SIRIUS 7.5.0
Electronic structure library and applications
pseudopotential_hmatrix.hpp
1#ifndef __PSEUDOPOTENTIAL_HMATRIX_HPP__
2#define __PSEUDOPOTENTIAL_HMATRIX_HPP__
3
4namespace sirius {
5template <typename T>
6inline dmatrix<T> pseudopotential_hmatrix(K_point& kp__,
7 int ispn__,
8 Hamiltonian& H__)
9{
10 PROFILE("sirius::pseudopotential_hmatrix");
11
12 //
13 H__.local_op().prepare(H__.potential());
14 if (!H__.ctx().gamma_point()) {
15 H__.prepare<double_complex>();
16 } else {
17 H__.prepare<double>();
18 }
19 H__.local_op().prepare(kp__.gkvec_partition());
20 H__.ctx().fft_coarse().prepare(kp__.gkvec_partition());
21 kp__.beta_projectors().prepare();
22
23
24 auto& ctx = H__.ctx();
25 const int bs = ctx.cyclic_block_size();
26 dmatrix<T> hmlt(kp__.num_gkvec(), kp__.num_gkvec(), ctx.blacs_grid(), bs, bs);
27 // dmatrix<T> ovlp(kp__.num_gkvec(), kp__.num_gkvec(), ctx.blacs_grid(), bs, bs);
28
29 hmlt.zero();
30 // ovlp.zero();
31
32 auto gen_solver = ctx.gen_evp_solver<T>();
33
34 for (int ig = 0; ig < kp__.num_gkvec(); ig++) {
35 hmlt.set(ig, ig, 0.5 * std::pow(kp__.gkvec().gkvec_cart<index_domain_t::global>(ig).length(), 2));
36 // ovlp.set(ig, ig, 1);
37 }
38
39 auto veff = H__.potential().effective_potential().gather_f_pw();
40 std::vector<double_complex> beff;
41 if (ctx.num_mag_dims() == 1) {
42 beff = H__.potential().effective_magnetic_field(0).gather_f_pw();
43 for (int ig = 0; ig < ctx.gvec().num_gvec(); ig++) {
44 auto z1 = veff[ig];
45 auto z2 = beff[ig];
46 veff[ig] = z1 + z2;
47 beff[ig] = z1 - z2;
48 }
49 }
50
51 #pragma omp parallel for schedule(static)
52 for (int igk_col = 0; igk_col < kp__.num_gkvec_col(); igk_col++) {
53 int ig_col = kp__.igk_col(igk_col);
54 auto gvec_col = kp__.gkvec().gvec(ig_col);
55 for (int igk_row = 0; igk_row < kp__.num_gkvec_row(); igk_row++) {
56 int ig_row = kp__.igk_row(igk_row);
57 auto gvec_row = kp__.gkvec().gvec(ig_row);
58 auto ig12 = ctx.gvec().index_g12_safe(gvec_row, gvec_col);
59
60 if (ispn__ == 0) {
61 if (ig12.second) {
62 hmlt(igk_row, igk_col) += std::conj(veff[ig12.first]);
63 } else {
64 hmlt(igk_row, igk_col) += veff[ig12.first];
65 }
66 } else {
67 if (ig12.second) {
68 hmlt(igk_row, igk_col) += std::conj(beff[ig12.first]);
69 } else {
70 hmlt(igk_row, igk_col) += beff[ig12.first];
71 }
72 }
73 }
74 }
75
76 mdarray<double_complex, 2> dop(ctx.unit_cell().max_mt_basis_size(), ctx.unit_cell().max_mt_basis_size());
77 mdarray<double_complex, 2> qop(ctx.unit_cell().max_mt_basis_size(), ctx.unit_cell().max_mt_basis_size());
78
79 mdarray<double_complex, 2> btmp(kp__.num_gkvec_row(), ctx.unit_cell().max_mt_basis_size());
80
81 kp__.beta_projectors_row().prepare();
82 kp__.beta_projectors_col().prepare();
83 for (int ichunk = 0; ichunk < kp__.beta_projectors_row().num_chunks(); ichunk++) {
84 /* generate beta-projectors for a block of atoms */
85 kp__.beta_projectors_row().generate(ichunk);
86 kp__.beta_projectors_col().generate(ichunk);
87
88 auto& beta_row = kp__.beta_projectors_row().pw_coeffs_a();
89 auto& beta_col = kp__.beta_projectors_col().pw_coeffs_a();
90
91 for (int i = 0; i < kp__.beta_projectors_row().chunk(ichunk).num_atoms_; i++) {
92 /* number of beta functions for a given atom */
93 int nbf = kp__.beta_projectors_row().chunk(ichunk).desc_(beta_desc_idx::nbf, i);
94 int offs = kp__.beta_projectors_row().chunk(ichunk).desc_(beta_desc_idx::offset, i);
95 int ia = kp__.beta_projectors_row().chunk(ichunk).desc_(beta_desc_idx::ia, i);
96
97 const auto& augment_op = ctx.augmentation_op(ctx.unit_cell().atom(ia).type_id());
98
99 for (int xi1 = 0; xi1 < nbf; xi1++) {
100 for (int xi2 = 0; xi2 < nbf; xi2++) {
101 if (ctx.num_mag_dims() == 1) {
102 if (ispn__ == 0) {
103 dop(xi1, xi2) = ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 0) + ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 1);
104 } else {
105 dop(xi1, xi2) = ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 0) - ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 1);
106 }
107 } else {
108 dop(xi1, xi2) = ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 0);
109 }
110 if(augment_op.atom_type().augment()) {
111 qop(xi1, xi2) = augment_op.q_mtrx(xi1, xi2);
112 }
113 }
114 }
115 linalg<device_t::CPU>::gemm(0, 0, kp__.num_gkvec_row(), nbf, nbf,
116 &beta_row(0, offs), beta_row.ld(),
117 &dop(0, 0), dop.ld(),
118 &btmp(0, 0), btmp.ld());
119 linalg<device_t::CPU>::gemm(0, 2, kp__.num_gkvec_row(), kp__.num_gkvec_col(), nbf,
120 linalg_const<double_complex>::one(),
121 &btmp(0, 0), btmp.ld(),
122 &beta_col(0, offs), beta_col.ld(),
123 linalg_const<double_complex>::one(),
124 &hmlt(0, 0), hmlt.ld());
125 // if(augment_op.atom_type().augment()) {
126 // linalg<device_t::CPU>::gemm(0, 0, kp__.num_gkvec_row(), nbf, nbf,
127 // &beta_row(0, offs), beta_row.ld(),
128 // &qop(0, 0), qop.ld(),
129 // &btmp(0, 0), btmp.ld());
130 // }
131 // linalg<device_t::CPU>::gemm(0, 2, kp__.num_gkvec_row(), kp__.num_gkvec_col(), nbf,
132 // linalg_const<double_complex>::one(),
133 // &btmp(0, 0), btmp.ld(),
134 // &beta_col(0, offs), beta_col.ld(),
135 // linalg_const<double_complex>::one(),
136 // &ovlp(0, 0), ovlp.ld());
137 }
138 }
139 kp__.beta_projectors_row().dismiss();
140 kp__.beta_projectors_col().dismiss();
141
142 //
143 kp__.beta_projectors().dismiss();
144 H__.local_op().dismiss();
145 H__.ctx().fft_coarse().dismiss();
146
147 return hmlt;
148}
149} // sirius
150
151#endif /* __PSEUDOPOTENTIAL_HMATRIX_HPP__ */
Namespace of the SIRIUS library.
Definition: sirius.f90:5
@ global
Global index.
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
Definition: math_tools.hpp:165
static const int ia
Global index of atom.
static const int nbf
Number of beta-projector functions for this atom.
static const int offset
Offset of beta-projectors in this chunk.