SIRIUS 7.5.0
Electronic structure library and applications
wavefunction_strain_deriv.hpp
1#ifndef __WAVEFUNCTION_STRAIN_DERIV_HPP__
2#define __WAVEFUNCTION_STRAIN_DERIV_HPP__
3
5
6namespace sirius {
7
8void
9wavefunctions_strain_deriv(Simulation_context const& ctx__, K_point<double>& kp__, wf::Wave_functions<double>& dphi__,
10 sddk::mdarray<double, 2> const& rlm_g__, sddk::mdarray<double, 3> const& rlm_dg__,
11 int nu__, int mu__)
12{
13 auto num_ps_atomic_wf = ctx__.unit_cell().num_ps_atomic_wf();
14 PROFILE("sirius::wavefunctions_strain_deriv");
15 #pragma omp parallel for schedule(static)
16 for (int igkloc = 0; igkloc < kp__.num_gkvec_loc(); igkloc++) {
17 /* Cartesian coordinats of G-vector */
18 auto gvc = kp__.gkvec().gkvec_cart<index_domain_t::local>(igkloc);
19 /* vs = {r, theta, phi} */
20 auto gvs = r3::spherical_coordinates(gvc);
21
22 std::vector<sddk::mdarray<double, 1>> ri_values(ctx__.unit_cell().num_atom_types());
23 for (int iat = 0; iat < ctx__.unit_cell().num_atom_types(); iat++) {
24 ri_values[iat] = ctx__.ri().ps_atomic_wf_->values(iat, gvs[0]);
25 }
26
27 std::vector<sddk::mdarray<double, 1>> ridjl_values(ctx__.unit_cell().num_atom_types());
28 for (int iat = 0; iat < ctx__.unit_cell().num_atom_types(); iat++) {
29 ridjl_values[iat] = ctx__.ri().ps_atomic_wf_djl_->values(iat, gvs[0]);
30 }
31
32 const double p = (mu__ == nu__) ? 0.5 : 0.0;
33
34 for (int ia = 0; ia < ctx__.unit_cell().num_atoms(); ia++) {
35 auto& atom_type = ctx__.unit_cell().atom(ia).type();
36 // TODO: this can be optimized, check k_point::generate_atomic_wavefunctions()
37 auto phase = twopi * dot(kp__.gkvec().gkvec<index_domain_t::local>(igkloc),
38 ctx__.unit_cell().atom(ia).position());
39 auto phase_factor = std::exp(std::complex<double>(0.0, phase));
40 for (auto const& e: atom_type.indexb_wfs()) {
41 /* orbital quantum number of this atomic orbital */
42 int l = e.am.l();
43 /* composite l,m index */
44 int lm = e.lm;
45 /* index of the radial function */
46 int idxrf = e.idxrf;
47 int offset_in_wf = num_ps_atomic_wf.second[ia] + e.xi;
48
49 auto z = std::pow(std::complex<double>(0, -1), l) * fourpi / std::sqrt(ctx__.unit_cell().omega());
50
51 /* case |G+k| = 0 */
52 if (gvs[0] < 1e-10) {
53 if (l == 0) {
54 auto d1 = ri_values[atom_type.id()][idxrf] * p * y00;
55
56 dphi__.pw_coeffs(igkloc, wf::spin_index(0), wf::band_index(offset_in_wf)) = -z * d1 * phase_factor;
57 } else {
58 dphi__.pw_coeffs(igkloc, wf::spin_index(0), wf::band_index(offset_in_wf)) = 0.0;
59 }
60 } else {
61 auto d1 = ri_values[atom_type.id()][idxrf] *
62 (gvc[mu__] * rlm_dg__(lm, nu__, igkloc) + p * rlm_g__(lm, igkloc));
63 auto d2 =
64 ridjl_values[atom_type.id()][idxrf] * rlm_g__(lm, igkloc) * gvc[mu__] * gvc[nu__] / gvs[0];
65
66 dphi__.pw_coeffs(igkloc, wf::spin_index(0), wf::band_index(offset_in_wf)) = -z * (d1 + d2) * std::conj(phase_factor);
67 }
68 } // xi
69 }
70 }
71}
72
73
74}
75
76#endif
auto spherical_coordinates(vector< double > vc)
Transform Cartesian coordinates [x,y,z] to spherical coordinates [r,theta,phi].
Definition: r3.hpp:590
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
Definition: specfunc.hpp:50
Namespace of the SIRIUS library.
Definition: sirius.f90:5
const double y00
First spherical harmonic .
Definition: constants.hpp:51
const double twopi
Definition: constants.hpp:45
const double fourpi
Definition: constants.hpp:48
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
Definition: math_tools.hpp:165
Contains definition and implementation of Simulation_context class.