35void xc_mt_nonmagnetic(Radial_grid<double>
const& rgrid__, SHT
const& sht__, std::vector<XC_functional>
const& xc_func__,
36 Flm
const& rho_lm__, Ftp& rho_tp__, Flm& vxc_lm__, Flm& exc_lm__)
39 for (
auto& ixc : xc_func__) {
40 if (ixc.is_gga() || ixc.is_vdw()) {
45 Ftp exc_tp(sht__.num_points(), rgrid__);
46 Ftp vxc_tp(sht__.num_points(), rgrid__);
48 RTE_ASSERT(rho_tp__.size() == vxc_tp.size());
49 RTE_ASSERT(rho_tp__.size() == exc_tp.size());
51 Ftp grad_rho_grad_rho_tp;
54 Spheric_vector_function<function_domain_t::spatial, double> grad_rho_tp;
61 auto grad_rho_lm =
gradient(rho_lm__);
62 grad_rho_tp = Spheric_vector_function<function_domain_t::spatial, double>(sht__.num_points(), rgrid__);
64 for (
int x = 0; x < 3; x++) {
65 transform(sht__, grad_rho_lm[x], grad_rho_tp[x]);
68 grad_rho_grad_rho_tp = grad_rho_tp * grad_rho_tp;
69 RTE_ASSERT(rho_tp__.size() == grad_rho_grad_rho_tp.size());
71 vsigma_tp = Ftp(sht__.num_points(), rgrid__);
72 RTE_ASSERT(rho_tp__.size() == vsigma_tp.size());
76 RTE_ASSERT(lapl_rho_tp.size() == rho_tp__.size());
80 for (
auto& ixc: xc_func__) {
83 ixc.get_lda(sht__.num_points() * rgrid__.num_points(), rho_tp__.at(sddk::memory_t::host),
84 vxc_tp.at(sddk::memory_t::host), exc_tp.at(sddk::memory_t::host));
90 ixc.get_gga(sht__.num_points() * rgrid__.num_points(), rho_tp__.at(sddk::memory_t::host),
91 grad_rho_grad_rho_tp.at(sddk::memory_t::host), vxc_tp.at(sddk::memory_t::host), vsigma_tp.at(sddk::memory_t::host),
92 exc_tp.at(sddk::memory_t::host));
95 vxc_tp -= 2.0 * vsigma_tp * lapl_rho_tp;
101 Spheric_vector_function<function_domain_t::spatial, double> grad_vsigma_tp(sht__.num_points(), rgrid__);
102 for (
int x = 0; x < 3; x++) {
103 transform(sht__, grad_vsigma_lm[x], grad_vsigma_tp[x]);
107 auto grad_vsigma_grad_rho_tp = grad_vsigma_tp * grad_rho_tp;
109 vxc_tp -= 2.0 * grad_vsigma_grad_rho_tp;
111 Spheric_vector_function<function_domain_t::spectral, double> vsigma_grad_rho_lm(sht__.lmmax(), rgrid__);
112 for (
int x: {0, 1, 2}) {
113 auto vsigma_grad_rho_tp = vsigma_tp * grad_rho_tp[x];
114 transform(sht__, vsigma_grad_rho_tp, vsigma_grad_rho_lm[x]);
118 vxc_tp -= 2.0 * div_vsigma_grad_rho_tp;
126void xc_mt_magnetic(Radial_grid<double>
const& rgrid__, SHT
const& sht__,
int num_mag_dims__,
127 std::vector<XC_functional>
const& xc_func__, std::vector<Ftp>
const& rho_tp__,
128 std::vector<Flm*> vxc__, Flm& exc__)
131 for (
auto& ixc : xc_func__) {
132 if (ixc.is_gga() || ixc.is_vdw()) {
137 Ftp exc_tp(sht__.num_points(), rgrid__);
138 Ftp vxc_tp(sht__.num_points(), rgrid__);
141 Ftp rho_dn_tp(sht__.num_points(), rgrid__);
142 Ftp rho_up_tp(sht__.num_points(), rgrid__);
144 for (
int ir = 0; ir < rgrid__.num_points(); ir++) {
146 for (
int itp = 0; itp < sht__.num_points(); itp++) {
147 r3::vector<double> m;
148 for (
int j = 0; j < num_mag_dims__; j++) {
149 m[j] = rho_tp__[1 + j](itp, ir);
151 auto rud =
get_rho_up_dn(num_mag_dims__, rho_tp__[0](itp, ir), m);
154 rho_up_tp(itp, ir) = rud.first;
155 rho_dn_tp(itp, ir) = rud.second;
159 auto rho_up_lm =
transform(sht__, rho_up_tp);
160 auto rho_dn_lm =
transform(sht__, rho_dn_tp);
162 std::vector<Ftp> bxc_tp(num_mag_dims__);
164 Ftp vxc_up_tp(sht__.num_points(), rgrid__);
165 Ftp vxc_dn_tp(sht__.num_points(), rgrid__);
166 for (
int j = 0; j < num_mag_dims__; j++) {
167 bxc_tp[j] = Ftp(sht__.num_points(), rgrid__);
170 Ftp grad_rho_up_grad_rho_up_tp;
171 Ftp grad_rho_up_grad_rho_dn_tp;
172 Ftp grad_rho_dn_grad_rho_dn_tp;
176 Spheric_vector_function<function_domain_t::spatial, double> grad_rho_up_tp;
177 Spheric_vector_function<function_domain_t::spatial, double> grad_rho_dn_tp;
178 Spheric_vector_function<function_domain_t::spatial, double> grad_rho_up_vsigma_tp;
179 Spheric_vector_function<function_domain_t::spatial, double> grad_rho_dn_vsigma_tp;
183 auto grad_rho_up_lm =
gradient(rho_up_lm);
184 auto grad_rho_dn_lm =
gradient(rho_dn_lm);
185 grad_rho_up_tp = Spheric_vector_function<function_domain_t::spatial, double>(sht__.num_points(), rgrid__);
186 grad_rho_dn_tp = Spheric_vector_function<function_domain_t::spatial, double>(sht__.num_points(), rgrid__);
187 grad_rho_up_vsigma_tp = Spheric_vector_function<function_domain_t::spatial, double>(sht__.num_points(), rgrid__);
188 grad_rho_dn_vsigma_tp = Spheric_vector_function<function_domain_t::spatial, double>(sht__.num_points(), rgrid__);
191 for (
int x = 0; x < 3; x++) {
192 transform(sht__, grad_rho_up_lm[x], grad_rho_up_tp[x]);
193 transform(sht__, grad_rho_dn_lm[x], grad_rho_dn_tp[x]);
196 grad_rho_up_grad_rho_up_tp = grad_rho_up_tp * grad_rho_up_tp;
197 grad_rho_up_grad_rho_dn_tp = grad_rho_up_tp * grad_rho_dn_tp;
198 grad_rho_dn_grad_rho_dn_tp = grad_rho_dn_tp * grad_rho_dn_tp;
200 vsigma_uu_tp = Ftp(sht__.num_points(), rgrid__);
201 vsigma_ud_tp = Ftp(sht__.num_points(), rgrid__);
202 vsigma_dd_tp = Ftp(sht__.num_points(), rgrid__);
205 for (
auto& ixc: xc_func__) {
207 ixc.get_lda(sht__.num_points() * rgrid__.num_points(), rho_up_tp.at(sddk::memory_t::host),
208 rho_dn_tp.at(sddk::memory_t::host), vxc_up_tp.at(sddk::memory_t::host), vxc_dn_tp.at(sddk::memory_t::host),
209 exc_tp.at(sddk::memory_t::host));
213 ixc.get_gga(sht__.num_points() * rgrid__.num_points(), rho_up_tp.at(sddk::memory_t::host),
214 rho_dn_tp.at(sddk::memory_t::host), grad_rho_up_grad_rho_up_tp.at(sddk::memory_t::host),
215 grad_rho_up_grad_rho_dn_tp.at(sddk::memory_t::host), grad_rho_dn_grad_rho_dn_tp.at(sddk::memory_t::host),
216 vxc_up_tp.at(sddk::memory_t::host), vxc_dn_tp.at(sddk::memory_t::host), vsigma_uu_tp.at(sddk::memory_t::host),
217 vsigma_ud_tp.at(sddk::memory_t::host), vsigma_dd_tp.at(sddk::memory_t::host), exc_tp.at(sddk::memory_t::host));
220 for (
int x: {0, 1, 2}) {
221 grad_rho_up_vsigma_tp[x] = (2.0 * vsigma_uu_tp * grad_rho_up_tp[x] + vsigma_ud_tp * grad_rho_dn_tp[x]);
222 grad_rho_dn_vsigma_tp[x] = (2.0 * vsigma_dd_tp * grad_rho_dn_tp[x] + vsigma_ud_tp * grad_rho_up_tp[x]);
225 Spheric_vector_function<function_domain_t::spectral, double> grad_rho_up_vsigma_lm(sht__.lmmax(), rgrid__);
226 Spheric_vector_function<function_domain_t::spectral, double> grad_rho_dn_vsigma_lm(sht__.lmmax(), rgrid__);
228 for (
int x: {0, 1, 2}) {
229 grad_rho_up_vsigma_lm[x] =
transform(sht__, grad_rho_up_vsigma_tp[x]);
230 grad_rho_dn_vsigma_lm[x] =
transform(sht__, grad_rho_dn_vsigma_tp[x]);
233 auto div_grad_rho_up_vsigma_lm =
divergence(grad_rho_up_vsigma_lm);
234 auto div_grad_rho_dn_vsigma_lm =
divergence(grad_rho_dn_vsigma_lm);
237 vxc_up_tp -=
transform(sht__, div_grad_rho_up_vsigma_lm) ;
238 vxc_dn_tp -=
transform(sht__, div_grad_rho_dn_vsigma_lm);
241 for (
int ir = 0; ir < rgrid__.num_points(); ir++) {
242 for (
int itp = 0; itp < sht__.num_points(); itp++) {
244 vxc_tp(itp, ir) = 0.5 * (vxc_up_tp(itp, ir) + vxc_dn_tp(itp, ir));
246 double bxc = 0.5 * (vxc_up_tp(itp, ir) - vxc_dn_tp(itp, ir));
248 auto s =
sign((rho_up_tp(itp, ir) - rho_dn_tp(itp, ir)) * bxc);
250 r3::vector<double> m;
251 for (
int j = 0; j < num_mag_dims__; j++) {
252 m[j] = rho_tp__[1 + j](itp, ir);
254 auto m_len = m.length();
256 for (
int j = 0; j < num_mag_dims__; j++) {
257 bxc_tp[j](itp, ir) = std::abs(bxc) * s * m[j] / m_len;
260 for (
int j = 0; j < num_mag_dims__; j++) {
261 bxc_tp[j](itp, ir) = 0.0;
267 for (
int j = 0; j < num_mag_dims__; j++) {
268 *vxc__[j + 1] +=
transform(sht__, bxc_tp[j]);
276double xc_mt(Radial_grid<double>
const& rgrid__, SHT
const& sht__, std::vector<XC_functional>
const& xc_func__,
277 int num_mag_dims__, std::vector<Flm const*> rho__, std::vector<Flm*> vxc__, Flm* exc__)
281 for (
int j = 0; j < num_mag_dims__ + 1; j++) {
285 std::vector<Ftp> rho_tp(num_mag_dims__ + 1);
286 for (
int j = 0; j < num_mag_dims__ + 1; j++) {
293 for (
int ir = 0; ir < rgrid__.num_points(); ir++) {
294 for (
int itp = 0; itp < sht__.num_points(); itp++) {
295 rhomin = std::min(rhomin, rho_tp[0](itp, ir));
297 if (rho_tp[0](itp, ir) < 0.0) {
298 for (
int j = 0; j < num_mag_dims__ + 1; j++) {
299 rho_tp[j](itp, ir) = 0.0;
305 if (num_mag_dims__ == 0) {
306 xc_mt_nonmagnetic(rgrid__, sht__, xc_func__, *rho__[0], rho_tp[0], *vxc__[0], *exc__);
308 xc_mt_magnetic(rgrid__, sht__, num_mag_dims__, xc_func__, rho_tp, vxc__, *exc__);
316 PROFILE(
"sirius::Potential::xc_mt");
318 #pragma omp parallel for
323 rho[0] = &density__.
rho().mt()[it.i];
326 rho[j + 1] = &density__.mag(j).mt()[it.i];
327 vxc[j + 1] = &effective_magnetic_field(j).mt()[it.i];
333 s <<
"[xc_mt] negative charge density " << rhomin <<
" for atom " << it.i << std::endl
334 <<
" current Rlm expansion of the charge density may be not sufficient, try to increase lmax" << std::endl
335 <<
" sht.lmax : " << sht_->lmax() << std::endl
336 <<
" sht.num_points : " << sht_->num_points();
341 std::array<int, 3> comp_map = {2, 0, 1};
344 for (
int ir = 0; ir < rgrid.num_points(); ir++) {
345 effective_magnetic_field(j).mt()[it.i](0, ir) -=
346 aux_bf_(j, it.i) * ctx_.unit_cell().atom(it.i).vector_field()[comp_map[j]];
Generate charge density and magnetization from occupied spinor wave-functions.
auto const & rho() const
Return const reference to charge density (scalar functions).
std::unique_ptr< Periodic_function< double > > xc_energy_density_
XC energy per unit particle.
void xc_mt(Density const &density__)
Generate XC potential in the muffin-tins.
std::unique_ptr< Periodic_function< double > > xc_potential_
XC potential.
Unit_cell & unit_cell_
Alias to unit cell.
int num_mag_dims() const
Number of dimensions in the magnetization vector.
Atom const & atom(int id__) const
Return const atom instance by id.
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.
Namespace of the SIRIUS library.
auto get_rho_up_dn(int num_mag_dims__, double rho__, r3::vector< double > mag__)
Use Kuebler's trick to get rho_up and rho_dn from density and magnetisation.
Smooth_periodic_vector_function< T > gradient(Smooth_periodic_function< T > &f__)
Gradient of the function in the plane-wave domain.
Smooth_periodic_function< T > laplacian(Smooth_periodic_function< T > &f__)
Laplacian of the function in the plane-wave domain.
Smooth_periodic_function< T > divergence(Smooth_periodic_vector_function< T > &g__)
Divergence of the vecor function.
int sign(T val)
Sign of the variable.
Add or substitute OMP functions.
Contains declaration and partial implementation of sirius::Potential class.
Contains typedefs, enums and simple descriptors.
Contains implementation of sirius::XC_functional class.