1#ifndef __PSEUDOPOTENTIAL_HMATRIX_HPP__
2#define __PSEUDOPOTENTIAL_HMATRIX_HPP__
6inline dmatrix<T> pseudopotential_hmatrix(K_point& kp__,
10 PROFILE(
"sirius::pseudopotential_hmatrix");
13 H__.local_op().prepare(H__.potential());
14 if (!H__.ctx().gamma_point()) {
15 H__.prepare<double_complex>();
17 H__.prepare<
double>();
19 H__.local_op().prepare(kp__.gkvec_partition());
20 H__.ctx().fft_coarse().prepare(kp__.gkvec_partition());
21 kp__.beta_projectors().prepare();
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);
32 auto gen_solver = ctx.gen_evp_solver<T>();
34 for (
int ig = 0; ig < kp__.num_gkvec(); ig++) {
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++) {
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);
62 hmlt(igk_row, igk_col) +=
std::conj(veff[ig12.first]);
64 hmlt(igk_row, igk_col) += veff[ig12.first];
68 hmlt(igk_row, igk_col) +=
std::conj(beff[ig12.first]);
70 hmlt(igk_row, igk_col) += beff[ig12.first];
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());
79 mdarray<double_complex, 2> btmp(kp__.num_gkvec_row(), ctx.unit_cell().max_mt_basis_size());
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++) {
85 kp__.beta_projectors_row().generate(ichunk);
86 kp__.beta_projectors_col().generate(ichunk);
88 auto& beta_row = kp__.beta_projectors_row().pw_coeffs_a();
89 auto& beta_col = kp__.beta_projectors_col().pw_coeffs_a();
91 for (
int i = 0; i < kp__.beta_projectors_row().chunk(ichunk).num_atoms_; i++) {
97 const auto& augment_op = ctx.augmentation_op(ctx.unit_cell().atom(ia).type_id());
99 for (
int xi1 = 0; xi1 < nbf; xi1++) {
100 for (
int xi2 = 0; xi2 < nbf; xi2++) {
101 if (ctx.num_mag_dims() == 1) {
103 dop(xi1, xi2) = ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 0) + ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 1);
105 dop(xi1, xi2) = ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 0) - ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 1);
108 dop(xi1, xi2) = ctx.unit_cell().atom(ia).d_mtrx(xi1, xi2, 0);
110 if(augment_op.atom_type().augment()) {
111 qop(xi1, xi2) = augment_op.q_mtrx(xi1, xi2);
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());
139 kp__.beta_projectors_row().dismiss();
140 kp__.beta_projectors_col().dismiss();
143 kp__.beta_projectors().dismiss();
144 H__.local_op().dismiss();
145 H__.ctx().fft_coarse().dismiss();
Namespace of the SIRIUS library.
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
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.