25#ifndef __INITIALIZE_SUBSPACE_HPP__
26#define __INITIALIZE_SUBSPACE_HPP__
36template <
typename T,
typename F>
40 PROFILE(
"sirius::initialize_subspace|kp");
42 auto& ctx = Hk__.H0().ctx();
44 if (ctx.cfg().control().verification() >= 2) {
45 auto eval = diag_S_davidson<T, F>(Hk__, kp__);
48 s <<
"S-operator matrix is not positive definite\n"
49 <<
" lowest eigen-value: " << eval[0];
53 s <<
"S-matrix is OK! Minimum eigen-value : " << eval[0];
54 RTE_OUT(ctx.out(1)) << s.str() << std::endl;
58 auto pcs = env::print_checksum();
61 const int num_sc = (ctx.num_mag_dims() == 3) ? 2 : 1;
67 int num_phi = std::max(num_ao__,
num_bands / num_sc);
69 int num_phi_tot = num_phi * num_sc;
71 auto& mp = get_memory_pool(ctx.host_memory_t());
73 print_memory_usage(ctx.out(), FILE_LINE);
79 for (
int ispn = 0; ispn < num_sc; ispn++) {
84 std::vector<int> atoms(ctx.unit_cell().num_atoms());
85 std::iota(atoms.begin(), atoms.end(), 0);
87 atoms, [&](
int iat) {
return &ctx.unit_cell().atom_type(iat).indexb_wfs(); }, *ctx.ri().ps_atomic_wf_, phi);
90 std::vector<T> tmp(4096);
92 for (
int i = 0; i < 4096; i++) {
93 tmp[i] = 1e-5 * random<T>();
95 PROFILE_START(
"sirius::initialize_subspace|kp|wf");
97 RTE_ASSERT(kp__.
num_gkvec() > num_phi + 10);
100 for (
int i = 0; i < num_phi - num_ao__; i++) {
101 #pragma omp for schedule(static) nowait
102 for (
int igk_loc = 0; igk_loc < kp__.
num_gkvec_loc(); igk_loc++) {
104 int igk = kp__.gkvec().offset() + igk_loc;
117 for (
int i = 0; i < num_phi; i++) {
118 #pragma omp for schedule(static) nowait
119 for (
int igk_loc = kp__.gkvec().skip_g0(); igk_loc < kp__.
num_gkvec_loc(); igk_loc++) {
121 int igk = kp__.gkvec().offset() + igk_loc;
127 if (ctx.num_mag_dims() == 3) {
132 PROFILE_STOP(
"sirius::initialize_subspace|kp|wf");
143 int bs = ctx.cyclic_block_size();
145 auto& gen_solver = ctx.gen_evp_solver();
147 la::dmatrix<F> hmlt(num_phi_tot, num_phi_tot, ctx.blacs_grid(), bs, bs, mp);
148 la::dmatrix<F> ovlp(num_phi_tot, num_phi_tot, ctx.blacs_grid(), bs, bs, mp);
149 la::dmatrix<F> evec(num_phi_tot, num_phi_tot, ctx.blacs_grid(), bs, bs, mp);
151 std::vector<real_type<F>> eval(
num_bands);
153 print_memory_usage(ctx.out(), FILE_LINE);
155 auto mem = ctx.processing_unit() == sddk::device_t::CPU ? sddk::memory_t::host : sddk::memory_t::device;
157 std::vector<wf::device_memory_guard> mg;
158 mg.emplace_back(kp__.spinor_wave_functions().memory_guard(mem, wf::copy_to::host));
159 mg.emplace_back(phi.
memory_guard(mem, wf::copy_to::device));
165 auto& mpd = get_memory_pool(mem);
171 print_memory_usage(ctx.out(), FILE_LINE);
174 for (
int ispn = 0; ispn < num_sc; ispn++) {
176 if (kp__.comm().rank() == 0) {
178 s <<
"initial_phi" << ispn;
179 print_checksum(s.str(), cs, RTE_OUT(std::cout));
184 for (
int ispn_step = 0; ispn_step < ctx.num_spinors(); ispn_step++) {
224 auto cs1 = hmlt.checksum(num_phi_tot, num_phi_tot);
225 auto cs2 = ovlp.checksum(num_phi_tot, num_phi_tot);
226 if (kp__.comm().rank() == 0) {
227 print_checksum(
"hmlt", cs1, RTE_OUT(std::cout));
228 print_checksum(
"ovlp", cs2, RTE_OUT(std::cout));
241 if (gen_solver.solve(num_phi_tot,
num_bands, hmlt, ovlp, eval.data(), evec)) {
242 RTE_THROW(
"error in diagonalization");
259 out <<
"eval[" << i <<
"]=" << eval[i] << std::endl;
265 for (
int ispn = 0; ispn < num_sc; ispn++) {
267 wf::band_range(0, num_phi_tot), 0.0, kp__.spinor_wave_functions(),
277 for (
int ispn = 0; ispn < ctx.num_spins(); ispn++) {
280 s <<
"initial_spinor_wave_functions_" << ispn;
281 if (kp__.comm().rank() == 0) {
282 print_checksum(s.str(), cs, RTE_OUT(std::cout));
292 PROFILE(
"sirius::initialize_subspace_kset");
296 auto& ctx = H0__.ctx();
298 if (ctx.cfg().iterative_solver().init_subspace() ==
"lcao") {
300 N = ctx.unit_cell().num_ps_atomic_wf().first;
303 for (
auto it : kset__.spl_num_kpoints()) {
304 auto kp = kset__.get<T>(it.i);
306 if (ctx.gamma_point() && (ctx.so_correction() ==
false)) {
307 initialize_subspace<T, T>(Hk, *kp, N);
309 initialize_subspace<T, std::complex<T>>(Hk, *kp, N);
314 for (
int ik = 0; ik < kset__.num_kpoints(); ik++) {
315 for (
int ispn = 0; ispn < ctx.num_spinors(); ispn++) {
316 for (
int i = 0; i < ctx.num_bands(); i++) {
317 kset__.get<T>(ik)->band_energy(i, ispn, 0);
318 kset__.get<T>(ik)->band_occupancy(i, ispn, ctx.max_occupancy());
Representation of Kohn-Sham Hamiltonian.
K-point related variables and methods.
void generate_atomic_wave_functions(std::vector< int > atoms__, std::function< basis_functions_index const *(int)> indexb__, Radial_integrals_atomic_wf< false > const &ri__, wf::Wave_functions< T > &wf__)
Generate plane-wave coefficients of the atomic wave-functions.
auto gkvec_sptr() const
Return shared pointer to gkvec object.
std::ostream & out(int level__) const
Return stdout stream for high verbosity output.
double band_energy(int j__, int ispn__) const
Get band energy.
int num_gkvec() const
Total number of G+k vectors within the cutoff distance.
int num_gkvec_loc() const
Local number of G+k vectors in case of flat distribution.
mdarray< T, N > & allocate(memory_t memory__)
Allocate memory for array.
auto memory_guard(sddk::memory_t mem__, wf::copy_to copy_to__=copy_to::none) const
Return an instance of the memory guard.
void zero(sddk::memory_t mem__, spin_index s__, band_range br__)
Zero a spin component of the wave-functions in a band range.
Wave-functions representation.
auto & pw_coeffs(int ig__, spin_index ispn__, band_index i__)
Return reference to the plane-wave coefficient for a given plane-wave, spin and band indices.
Describe a range of bands.
Describe a range of spins.
Diagonalize pseudo-potential Hamiltonian.
Contains declaration and partial implementation of sirius::K_point_set class.
bool is_device_memory(memory_t mem__)
Check if this is a valid device memory (memory, accessible by the device).
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > transform(::spla::Context &spla_ctx__, sddk::memory_t mem__, la::dmatrix< F > const &M__, int irow0__, int jcol0__, real_type< F > alpha__, Wave_functions< T > const &wf_in__, spin_index s_in__, band_range br_in__, real_type< F > beta__, Wave_functions< T > &wf_out__, spin_index s_out__, band_range br_out__)
Apply linear transformation to the wave-functions.
void copy(sddk::memory_t mem__, Wave_functions< T > const &in__, wf::spin_index s_in__, wf::band_range br_in__, Wave_functions< F > &out__, wf::spin_index s_out__, wf::band_range br_out__)
Copy wave-functions.
Namespace of the SIRIUS library.
uint32_t random_uint32(bool reset=false)
Simple random number generator.
void initialize_subspace(Hamiltonian_k< T > const &Hk__, K_point< T > &kp__, int num_ao__)
Initialize the wave-functions subspace at a given k-point.
void generate_subspace_matrix(Simulation_context &ctx__, int N__, int n__, int num_locked__, wf::Wave_functions< T > &phi__, wf::Wave_functions< T > &op_phi__, la::dmatrix< F > &mtrx__, la::dmatrix< F > *mtrx_old__=nullptr)
Generate subspace matrix for the iterative diagonalization.