30void Potential::init_PAW()
36 bool const is_global{
true};
39 paw_ae_exc_ = std::make_unique<Spheric_function_set<double, paw_atom_index_t>>(
"paw_ae_exc_",
unit_cell_,
40 unit_cell_.paw_atoms(), [
this](
int ia){
return lmax_t(2 * this->unit_cell_.atom(ia).type().indexr().lmax());});
42 paw_ps_exc_ = std::make_unique<Spheric_function_set<double, paw_atom_index_t>>(
"paw_ps_exc_",
unit_cell_,
43 unit_cell_.paw_atoms(), [
this](
int ia){
return lmax_t(2 * this->unit_cell_.atom(ia).type().indexr().lmax());});
54void Potential::generate_PAW_effective_potential(Density
const& density)
56 PROFILE(
"sirius::Potential::generate_PAW_effective_potential");
70 density.paw_ps_density(ia));
75 std::vector<Spheric_function_set<double, paw_atom_index_t>*> ae_comp;
76 std::vector<Spheric_function_set<double, paw_atom_index_t>*> ps_comp;
97 #pragma omp parallel for
100 calc_PAW_local_Dij(ia,
paw_dij_[it.i]);
108 #pragma omp parallel for
113 for (
int imagn = 0; imagn < ctx_.
num_mag_dims() + 1; imagn++) {
114 for (
int ib2 = 0; ib2 < atom.mt_basis_size(); ib2++) {
115 for (
int ib1 = 0; ib1 < atom.mt_basis_size(); ib1++) {
116 atom.d_mtrx(ib1, ib2, imagn) +=
paw_dij_[i](ib1, ib2, imagn);
123double xc_mt_paw(std::vector<XC_functional>
const& xc_func__,
int lmax__,
int num_mag_dims__, SHT
const& sht__,
124 Radial_grid<double>
const& rgrid__, std::vector<Flm const*> rho__, std::vector<double>
const& rho_core__,
125 std::vector<Flm>& vxc__, Flm& exclm__)
130 Flm rho0(
lmmax, rgrid__);
132 if (rho0.size(0) != rho__[0]->size(0)) {
134 s <<
"Sizes of rho0 and rho do not match" << std::endl
135 <<
" rho0.size(0) : " << rho0.size(0) << std::endl
136 <<
" rho__[0]->size(0) : " << rho__[0]->size(0) << std::endl
137 <<
" lmax : " << lmax__;
144 double invY00 = 1.0 /
y00;
147 for (
int ir = 0; ir < rgrid__.num_points(); ir++) {
148 rho0(0, ir) += invY00 * rho_core__[ir];
151 std::vector<Flm const*> rho;
152 rho.push_back(&rho0);
153 for (
int j = 0; j < num_mag_dims__; j++) {
154 rho.push_back(rho__[j + 1]);
157 std::vector<Flm*> vxc;
158 for (
int j = 0; j < num_mag_dims__ + 1; j++) {
159 vxc.push_back(&vxc__[j]);
162 sirius::xc_mt(rgrid__, sht__, xc_func__, num_mag_dims__, rho, vxc, &exclm__);
163 return inner(exclm__, rho0);
166double Potential::calc_PAW_hartree_potential(Atom& atom__, Flm
const& rho__, Flm& v_tot__)
168 auto lmmax = rho__.angular_domain_size();
170 auto& grid = rho__.radial_grid();
173 Flm v_ha(
lmmax, grid);
176 poisson_vmt<true>(atom__, rho__, v_ha);
181 return 0.5 *
inner(rho__, v_ha);
186 std::vector<Flm const*> ps_density__)
191 auto& ps_core = atom.
type().ps_core_charge_density();
192 auto& ae_core = atom.type().paw_ae_core_charge_density();
194 auto& rgrid = atom.type().radial_grid();
195 int l_max = 2 * atom.type().indexr().lmax();
197 std::vector<Flm> vxc;
199 vxc.emplace_back(
sf::lmmax(l_max), rgrid);
202 sirius::xc_mt_paw(xc_func_, l_max, ctx_.
num_mag_dims(), *sht_, rgrid, ae_density__, ae_core, vxc, (*
paw_ae_exc_)[ia__]);
207 sirius::xc_mt_paw(xc_func_, l_max, ctx_.
num_mag_dims(), *sht_, rgrid, ps_density__, ps_core, vxc, (*
paw_ps_exc_)[ia__]);
212 auto eha = calc_PAW_hartree_potential(atom, *ae_density__[0],
paw_potential_->ae_component(0)[ia__]) -
213 calc_PAW_hartree_potential(atom, *ps_density__[0],
paw_potential_->ps_component(0)[ia__]);
224 auto& atom_type = atom.
type();
226 auto& paw_ae_wfs = atom_type.ae_paw_wfs_array();
227 auto& paw_ps_wfs = atom_type.ps_paw_wfs_array();
230 int lmax = atom_type.indexr().lmax();
237 auto nbrf = atom_type.num_beta_radial_functions();
242 auto& rgrid = atom_type.radial_grid();
244 for (
int imagn = 0; imagn < ctx_.
num_mag_dims() + 1; imagn++) {
248 for (
int irb2 = 0; irb2 < nbrf; irb2++) {
249 for (
int irb1 = 0; irb1 <= irb2; irb1++) {
252 std::vector<double> intdata(rgrid.num_points());
255 for (
int lm3 = 0; lm3 <
lmmax; lm3++) {
257 for (
int irad = 0; irad < rgrid.num_points(); irad++) {
258 double ae_part = paw_ae_wfs(irad, irb1) * paw_ae_wfs(irad, irb2);
259 double ps_part = paw_ps_wfs(irad, irb1) * paw_ps_wfs(irad, irb2) +
260 atom_type.q_radial_function(irb1, irb2,
l_by_lm[lm3])(irad);
262 intdata[irad] = ae_atom_pot(lm3, irad) * ae_part - ps_atom_pot(lm3, irad) * ps_part;
266 integrals(lm3,
packed_index(irb1, irb2), imagn) = Spline<double>(rgrid, intdata).integrate(0);
273 for (
int ib2 = 0; ib2 < atom_type.mt_basis_size(); ib2++) {
274 for (
int ib1 = 0; ib1 <= ib2; ib1++) {
277 int lm1 = atom_type.indexb(ib1).lm;
278 int lm2 = atom_type.indexb(ib2).lm;
281 int irb1 = atom_type.indexb(ib1).idxrf;
282 int irb2 = atom_type.indexb(ib2).idxrf;
288 int num_non_zero_gk = GC.num_gaunt(lm1, lm2);
290 for (
int imagn = 0; imagn < ctx_.
num_mag_dims() + 1; imagn++) {
292 for (
int inz = 0; inz < num_non_zero_gk; inz++) {
293 auto& lm3coef = GC.gaunt(lm1, lm2, inz);
296 paw_dij__(ib1, ib2, imagn) += lm3coef.coef * integrals(lm3coef.lm3, iqij, imagn);
300 paw_dij__(ib2, ib1, imagn) = paw_dij__(ib1, ib2, imagn);
308Potential::calc_PAW_one_elec_energy(Atom
const& atom__, sddk::mdarray<double, 2>
const& density_matrix__,
309 sddk::mdarray<double, 3>
const& paw_dij__)
const
313 for (
int ib2 = 0; ib2 < atom__.mt_basis_size(); ib2++) {
314 for (
int ib1 = 0; ib1 < atom__.mt_basis_size(); ib1++) {
315 for (
int imagn = 0; imagn < ctx_.
num_mag_dims() + 1; imagn++) {
316 energy += density_matrix__(
packed_index(ib1, ib2), imagn) * paw_dij__(ib1, ib2, imagn);
Atom_type const & type() const
Return const reference to corresponding atom type object.
Compact storage of non-zero Gaunt coefficients .
mpi::Communicator const & comm_
Communicator of the simulation.
double paw_hartree_total_energy_
Hartree contribution to total energy from PAW atoms.
double calc_PAW_local_potential(typename atom_index_t::global ia__, std::vector< Flm const * > ae_density, std::vector< Flm const * > ps_density)
Calculate PAW potential for a given atom.
std::unique_ptr< Spheric_function_set< double, paw_atom_index_t > > paw_ae_exc_
Exchange-correlation energy density of PAW atoms all-electron density.
std::unique_ptr< PAW_field4D< double > > paw_potential_
All-electron and pseudopotential parts of PAW potential.
std::unique_ptr< Spheric_function_set< double, paw_atom_index_t > > paw_ps_exc_
Exchange-correlation energy density of PAW atoms pseudodensity.
Unit_cell & unit_cell_
Alias to unit cell.
std::vector< sddk::mdarray< double, 3 > > paw_dij_
Contribution to D-operator matrix from the PAW atoms.
static double gaunt_rrr(int l1, int l2, int l3, int m1, int m2, int m3)
Gaunt coefficent of three real spherical harmonics.
int num_mag_dims() const
Number of dimensions in the magnetization vector.
Atom const & atom(int id__) const
Return const atom instance by id.
int num_paw_atoms() const
Return number of atoms with PAW pseudopotential.
auto const & spl_num_paw_atoms() const
Get split index of PAW atoms.
auto paw_atom_index(paw_atom_index_t::global ipaw__) const
Return global index of atom by the index in the list of PAW atoms.
void bcast(T *buffer__, int count__, int root__) const
Perform buffer broadcast.
void allreduce(T *buffer__, int count__) const
Perform the in-place (the output buffer is used as the input buffer) all-to-all reduction.
void zero(memory_t mem__, size_t idx0__, size_t n__)
Zero n elements starting from idx0.
int lmax(int lmmax__)
Get maximum orbital quantum number by the maximum lm index.
int lmmax(int lmax)
Maximum number of combinations for a given .
std::vector< int > l_by_lm(int lmax__)
Get array of orbital quantum numbers for each lm component.
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > inner(::spla::Context &spla_ctx__, sddk::memory_t mem__, spin_range spins__, W const &wf_i__, band_range br_i__, Wave_functions< T > const &wf_j__, band_range br_j__, la::dmatrix< F > &result__, int irow0__, int jcol0__)
Compute inner product between the two sets of wave-functions.
Namespace of the SIRIUS library.
const double y00
First spherical harmonic .
int packed_index(int i__, int j__)
Pack two indices into one for symmetric matrices.
Contains declaration and partial implementation of sirius::Potential class.
Symmetrize muffin-tin spheric functions.