33#include " source_base/kernels/math_kernel_op.h"
44#include " source_base/parallel_reduce.h"
55#include " source_base/timer.h"
6+ #include " source_hamilt/module_xc/xc_functional.h"
7+ #include " source_pw/module_pwdft/kernels/meta_op.h"
68namespace hamilt
79{
810
@@ -11,7 +13,10 @@ Velocity<FPTYPE, Device>::Velocity(const ModulePW::PW_Basis_K* wfcpw_in,
1113 const int * isk_in,
1214 pseudopot_cell_vnl* ppcell_in,
1315 const UnitCell* ucell_in,
14- const bool nonlocal_in)
16+ const bool nonlocal_in,
17+ const typename GetTypeReal<FPTYPE >::type* vtau_in,
18+ const int vtau_col_in,
19+ const int vtau_row_in)
1520{
1621 if (wfcpw_in == nullptr || isk_in == nullptr || ppcell_in == nullptr || ucell_in == nullptr )
1722 {
@@ -23,6 +28,9 @@ Velocity<FPTYPE, Device>::Velocity(const ModulePW::PW_Basis_K* wfcpw_in,
2328 this ->ucell = ucell_in;
2429 this ->nonlocal = nonlocal_in;
2530 this ->tpiba = ucell_in->tpiba ;
31+ this ->vtau_ = vtau_in;
32+ this ->vtau_col_ = vtau_col_in;
33+ this ->vtau_row_ = vtau_row_in;
2634 if (this ->nonlocal )
2735 {
2836 this ->ppcell ->initgradq_vnl (*this ->ucell );
@@ -37,6 +45,8 @@ Velocity<FPTYPE, Device>::~Velocity()
3745 delmem_var_op ()(this ->gz_ );
3846 delmem_complex_op ()(vkb_);
3947 delmem_complex_op ()(gradvkb_);
48+ delmem_complex_op ()(porter1_);
49+ delmem_complex_op ()(porter2_);
4050}
4151
4252template <typename FPTYPE , typename Device>
@@ -93,6 +103,7 @@ void Velocity<FPTYPE, Device>::act(const psi::Psi<std::complex<FPTYPE>, Device>*
93103 const int npw = this ->wfcpw ->npwk [this ->ik ];
94104 const int max_npw = this ->wfcpw ->npwk_max ;
95105 const int npol = psi_in->get_npol ();
106+ using Real = typename GetTypeReal<FPTYPE >::type;
96107
97108 std::vector<FPTYPE *> gtmp_ptr = {this ->gx_ , this ->gy_ , this ->gz_ };
98109 // -------------
@@ -110,6 +121,89 @@ void Velocity<FPTYPE, Device>::act(const psi::Psi<std::complex<FPTYPE>, Device>*
110121 }
111122 }
112123
124+ // ---------------------------------------------
125+ // meta-GGA velocity correction
126+ // V_tau = -(1/2) div(v_tau grad), whose plane-wave matrix element is
127+ // <k+G|V_tau|k+G'> = (1/2) v_tau(G-G') (k+G) dot (k+G').
128+ // Therefore
129+ // i[V_tau, r_\alpha]_{G,G'} =
130+ // (1/2) v_tau(G-G') [2k_alpha + G_alpha + G'_alpha].
131+ // In real space this is implemented as
132+ // -i/2 [\partial_\alpha(v_tau psi) + v_tau \partial_\alpha psi].
133+ // ---------------------------------------------
134+ if (this ->vtau_ != nullptr && this ->vtau_col_ > 0 && XC_Functional::get_ked_flag ())
135+ {
136+ if (this ->porter1_ == nullptr )
137+ {
138+ resmem_complex_op ()(this ->porter1_ , this ->wfcpw ->nmaxgr );
139+ }
140+ if (this ->porter2_ == nullptr )
141+ {
142+ resmem_complex_op ()(this ->porter2_ , this ->wfcpw ->nmaxgr );
143+ }
144+ int current_spin = 0 ;
145+ if (this ->vtau_row_ > 1 )
146+ {
147+ current_spin = this ->isk [this ->ik ];
148+ if (current_spin < 0 || current_spin >= this ->vtau_row_ )
149+ {
150+ ModuleBase::WARNING_QUIT (" Velocity" , " invalid spin index for meta-GGA velocity correction" );
151+ }
152+ }
153+ const Real* vtau_spin = this ->vtau_ + current_spin * this ->vtau_col_ ;
154+ Complex minus_half_i (0.0 , -0.5 );
155+ for (int ib = 0 ; ib < n_npwx; ++ib)
156+ {
157+ const Complex* bandpsi = psi0 + ib * max_npw;
158+ this ->wfcpw ->recip_to_real (this ->ctx , bandpsi, this ->porter1_ , this ->ik );
159+ ModuleBase::vector_mul_vector_op<Complex, Device>()(this ->vtau_col_ ,
160+ this ->porter1_ ,
161+ this ->porter1_ ,
162+ vtau_spin);
163+ this ->wfcpw ->real_to_recip (this ->ctx , this ->porter1_ , this ->porter1_ , this ->ik );
164+ for (int id = 0 ; id < 3 ; ++id)
165+ {
166+ // term1: partial_id (v_tau * psi)
167+ meta_pw_op<Real, Device>()(this ->ctx ,
168+ this ->ik ,
169+ id,
170+ npw,
171+ max_npw,
172+ this ->tpiba ,
173+ this ->wfcpw ->template get_gcar_data <Real>(),
174+ this ->wfcpw ->template get_kvec_c_data <Real>(),
175+ this ->porter1_ ,
176+ this ->porter2_ ,
177+ false );
178+ ModuleBase::scal_op<Real, Device>()(npw, &minus_half_i, this ->porter2_ , 1 );
179+ Complex* vpsi_slice = vpsi + id * n_npwx * max_npw + ib * max_npw;
180+ Complex one = 1.0 ;
181+ ModuleBase::axpy_op<Complex, Device>()(npw, &one, this ->porter2_ , 1 , vpsi_slice, 1 );
182+
183+ // term2: v_tau * partial_id psi
184+ meta_pw_op<Real, Device>()(this ->ctx ,
185+ this ->ik ,
186+ id,
187+ npw,
188+ max_npw,
189+ this ->tpiba ,
190+ this ->wfcpw ->template get_gcar_data <Real>(),
191+ this ->wfcpw ->template get_kvec_c_data <Real>(),
192+ bandpsi,
193+ this ->porter2_ ,
194+ false );
195+ this ->wfcpw ->recip_to_real (this ->ctx , this ->porter2_ , this ->porter2_ , this ->ik );
196+ ModuleBase::vector_mul_vector_op<Complex, Device>()(this ->vtau_col_ ,
197+ this ->porter2_ ,
198+ this ->porter2_ ,
199+ vtau_spin);
200+ this ->wfcpw ->real_to_recip (this ->ctx , this ->porter2_ , this ->porter2_ , this ->ik );
201+ ModuleBase::scal_op<Real, Device>()(npw, &minus_half_i, this ->porter2_ , 1 );
202+ ModuleBase::axpy_op<Complex, Device>()(npw, &one, this ->porter2_ , 1 , vpsi_slice, 1 );
203+ }
204+ }
205+ }
206+
113207 // ---------------------------------------------
114208 // i[V_NL, r] = (\nabla_q+\nabla_q')V_{NL}(q,q')
115209 // |\beta><\beta|\psi>
@@ -334,4 +428,4 @@ template class Velocity<double, base_device::DEVICE_GPU>;
334428template class Velocity <float , base_device::DEVICE_GPU >;
335429#endif
336430
337- } // namespace hamilt
431+ } // namespace hamilt
0 commit comments