25#ifndef __POTENTIAL_HPP__
26#define __POTENTIAL_HPP__
34void check_xc_potential(Density
const& rho__);
36double xc_mt(Radial_grid<double>
const& rgrid__, SHT
const& sht__, std::vector<XC_functional>
const& xc_func__,
37 int num_mag_dims__, std::vector<Flm const*> rho__, std::vector<Flm*> vxc__, Flm* exc__);
39double density_residual_hartree_energy(Density
const& rho1__, Density
const& rho2__);
72 std::array<std::unique_ptr<Smooth_periodic_function<double>>, 3>
vsigma_;
76 std::unique_ptr<Smooth_periodic_function<double>>
dveff_;
85 std::unique_ptr<SHT> sht_;
87 int pseudo_density_order_{9};
89 std::vector<std::complex<double>> zil_;
91 std::vector<std::complex<double>> zilm_;
93 std::vector<int> l_by_lm_;
97 double energy_vha_{0};
103 std::vector<XC_functional> xc_func_;
121 std::unique_ptr<Spheric_function_set<double, paw_atom_index_t>>
paw_ps_exc_;
124 std::unique_ptr<Spheric_function_set<double, paw_atom_index_t>>
paw_ae_exc_;
132 std::unique_ptr<Hubbard>
U_;
150 std::vector<Flm const*> ps_density);
154 double calc_PAW_hartree_potential(
Atom& atom,
Flm const& full_density,
Flm& full_potential);
162 PROFILE(
"sirius::Potential::poisson_vmt");
182 sddk::mdarray<std::complex<double>, 2>& qit__, std::complex<double>* rho_pw__);
250 PROFILE(
"sirius::Potential::generate_local_potential");
253 auto q = ctx_.
gvec().shells_len();
255 auto const ff = ctx_.ri().vloc_->values(q, ctx_.
comm());
257 auto v = make_periodic_function<index_domain_t::local>(ctx_.unit_cell(), ctx_.
gvec(),
258 ctx_.phase_factors_t(), ff);
264 if (env::print_checksum()) {
267 print_checksum(
"local_potential_pw", cs, ctx_.
out());
268 print_checksum(
"local_potential_rg", cs1, ctx_.
out());
276 template <
bool add_pseudo_core__>
280 template <
bool add_pseudo_core__>
291 template <
bool free_atom,
typename T>
292 inline std::vector<T>
296 const bool use_r_prefact{
false};
298 int lmmax_rho = rho_mt__.angular_domain_size();
299 int lmmax_pot = vha_mt__.angular_domain_size();
300 if ((
int)l_by_lm_.size() < lmmax_rho) {
302 s <<
"wrong size of l_by_lm array for atom of " << atom__.
type().symbol() << std::endl
303 <<
" lmmax_rho: " << lmmax_rho << std::endl
304 <<
" l_by_lm.size: " << l_by_lm_.size();
307 std::vector<T> qmt(lmmax_rho, 0);
309 double R = atom__.mt_radius();
310 int nmtp = atom__.num_mt_points();
318 for (
int lm = 0;
lm < lmmax_rho;
lm++) {
319 int l = l_by_lm_[
lm];
321 auto rholm = rho_mt__.component(
lm);
325 qmt[
lm] = rholm.integrate(g1, l + 2);
327 for (
int ir = 0; ir < nmtp; ir++) {
328 double r = atom__.radial_grid(ir);
329 rholm(ir) *= std::pow(r, l + 2);
331 qmt[
lm] = rholm.interpolate().integrate(g1, 0);
334 if (
lm < lmmax_pot) {
337 rholm.integrate(g2, 1 - l);
339 rholm = rho_mt__.component(
lm);
340 for (
int ir = 0; ir < nmtp; ir++) {
341 double r = atom__.radial_grid(ir);
342 rholm(ir) *= std::pow(r, 1 - l);
344 rholm.interpolate().integrate(g2, 0);
347 double fact =
fourpi / double(2 * l + 1);
349 for (
int ir = 0; ir < nmtp; ir++) {
350 double r = atom__.radial_grid(ir);
353 vha_mt__(
lm, ir) = g1[ir] / std::pow(r, l + 1) + (g2.back() - g2[ir]) * std::pow(r, l);
355 double d1 = 1.0 / std::pow(R, 2 * l + 1);
356 vha_mt__(
lm, ir) = (1.0 - std::pow(r / R, 2 * l + 1)) * g1[ir] / std::pow(r, l + 1) +
357 (g2.back() - g2[ir]) * std::pow(r, l) - (g1.back() - g1[ir]) * std::pow(r, l) * d1;
359 vha_mt__(
lm, ir) *= fact;
366 for (
int ir = 0; ir < nmtp; ir++) {
368 double r = atom__.radial_grid(ir);
369 vha_mt__(0, ir) += atom__.zn() * (1 / R - 1 / r) /
y00;
371 vha_mt__(0, ir) += atom__.zn() / R /
y00;
376 qmt[0] -= atom__.zn() *
y00;
601 template <
bool add_pseudo_core__ = false>
605 void generate(
Density const& density__,
bool use_sym__,
bool transform_to_rg__);
607 void save(std::string name__);
609 void load(std::string name__);
611 void update_atomic_potential();
613 template <sddk::device_t pu>
614 void add_mt_contribution_to_pw();
652 void generate_PAW_effective_potential(
Density const& density);
654 double PAW_xc_total_energy(
Density const& density__)
const
661 #pragma omp parallel for reduction(+:ecore)
667 auto& atom_type = atom.
type();
669 auto& ps_core = atom_type.ps_core_charge_density();
670 auto& ae_core = atom_type.paw_ae_core_charge_density();
672 Spline<double> s(atom_type.radial_grid());
673 auto y00inv = 1.0 /
y00;
674 for (
int ir = 0; ir < atom_type.num_mt_points(); ir++) {
675 s(ir) = y00inv * ((*paw_ae_exc_)[ia](0, ir) * ae_core[ir] - (*
paw_ps_exc_)[ia](0, ir) * ps_core[ir]) *
676 std::pow(atom_type.radial_grid(ir), 2);
678 ecore += s.interpolate().integrate(0);
686 double PAW_total_energy(Density
const& density__)
const
691 double PAW_one_elec_energy(Density
const& density__)
const
694 #pragma omp parallel for reduction(+:e)
697 auto dm = density__.density_matrix_aux(atom_index_t::global(ia));
704 void check_potential_continuity_at_mt();
706 auto& effective_potential()
711 auto const& effective_potential()
const
716 auto& local_potential()
721 auto const& local_potential()
const
731 auto const& effective_potential_mt(atom_index_t::local ialoc)
const
733 auto ia =
unit_cell_.spl_num_atoms().global_index(ialoc);
734 return this->
scalar().mt()[ia];
737 auto& effective_magnetic_field(
int i)
742 auto& effective_magnetic_field(
int i)
const
747 auto& hartree_potential()
752 auto const& hartree_potential_mt(atom_index_t::local ialoc)
const
754 auto ia =
unit_cell_.spl_num_atoms().global_index(ialoc);
763 auto const& xc_potential()
const
768 auto& xc_energy_density()
773 auto const& xc_energy_density()
const
778 inline auto vh_el(
int ia)
const
783 auto energy_vha()
const
788 auto const& veff_pw(
int ig__)
const
793 void set_veff_pw(std::complex<double>
const* veff_pw__)
798 auto const& rm_inv_pw(
int ig__)
const
803 void set_rm_inv_pw(std::complex<double>
const* rm_inv_pw__)
808 auto const& rm2_inv_pw(
int ig__)
const
813 inline void set_rm2_inv_pw(std::complex<double>
const* rm2_inv_pw__)
821 return inner(density__.
rho(), xc_potential());
827 return inner(density__.rho_pseudo_core(), xc_potential().rg());
834 if (!ctx_.full_potential()) {
840 bool is_gradient_correction()
const;
842 auto& vsigma(
int idx__)
844 RTE_ASSERT(idx__ >= 0 && idx__ < 3);
845 return (*
vsigma_[idx__].get());
848 inline void add_delta_rho_xc(
double d__)
853 inline void add_delta_mag_xc(
double d__)
863 auto& hubbard_potential()
868 auto const& hubbard_potential()
const
Data and methods specific to the actual atom in the unit cell.
Atom_type const & type() const
Return const reference to corresponding atom type object.
Generate charge density and magnetization from occupied spinor wave-functions.
auto const & rho() const
Return const reference to charge density (scalar functions).
Four-component function consisting of scalar and vector parts.
auto & scalar()
Return scalar part of the field.
auto & vector(int i)
Return component of the vector part of the field.
Describes Hubbard orbital occupancy or potential correction matrices.
Representation of the periodical function on the muffin-tin geometry.
auto & mt()
Return reference to spherical functions component.
Generate effective potential from charge density and magnetization.
void generate(Density const &density__, bool use_sym__, bool transform_to_rg__)
Generate effective potential and magnetic field from charge density and magnetization.
std::unique_ptr< Smooth_periodic_function< double > > dveff_
Used to compute SCF correction to forces.
std::unique_ptr< Smooth_periodic_function< double > > local_potential_
Local part of pseudopotential.
sddk::mdarray< std::complex< double >, 1 > rm_inv_pw_
Plane-wave coefficients of the inverse relativistic mass weighted by the unit step-function.
void xc_rg_magnetic(Density const &density__)
Generate magnetic XC potential on the regular real-space grid.
auto energy_vxc_core(Density const &density__) const
Integral of .
auto energy_vxc(Density const &density__) const
Integral of .
mpi::Communicator const & comm_
Communicator of the simulation.
std::unique_ptr< Periodic_function< double > > xc_energy_density_
XC energy per unit particle.
void poisson(Periodic_function< double > const &rho)
Poisson solver.
double add_delta_mag_xc_
Add extra charge to the density.
Hubbard_matrix hubbard_potential_
Hubbard potential correction matrix.
std::unique_ptr< Periodic_function< double > > hartree_potential_
Hartree potential.
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.
sddk::mdarray< std::complex< double >, 1 > rm2_inv_pw_
Plane-wave coefficients of the squared inverse relativistic mass weighted by the unit step-function.
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.
void xc_mt(Density const &density__)
Generate XC potential in the muffin-tins.
Potential(Simulation_context &ctx__)
Constructor.
void xc(Density const &rho__)
Generate XC potential and energy density.
std::unique_ptr< Periodic_function< double > > xc_potential_
XC potential.
std::vector< T > poisson_vmt(Atom const &atom__, Spheric_function< function_domain_t::spectral, T > const &rho_mt__, Spheric_function< function_domain_t::spectral, T > &vha_mt__) const
Solve Poisson equation for a single atom.
std::unique_ptr< Hubbard > U_
Hubbard potential correction operator.
auto energy_exc(Density const &density__) const
Integral of .
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.
void generate_local_potential()
Generate local part of pseudo potential.
void update()
Recompute some variables that depend on atomic positions or the muffin-tin radius.
std::array< std::unique_ptr< Smooth_periodic_function< double > >, 3 > vsigma_
Derivative .
sddk::mdarray< double, 1 > vh_el_
Electronic part of Hartree potential.
void generate_D_operator_matrix()
Calculate D operator from potential and augmentation charge.
void xc_rg_nonmagnetic(Density const &density__)
Generate non-magnetic XC potential on the regular real-space grid.
sddk::mdarray< std::complex< double >, 1 > veff_pw_
Plane-wave coefficients of the effective potential weighted by the unit step-function.
auto poisson_vmt(Periodic_function< double > const &rho__) const
Compute MT part of the potential and MT multipole moments.
sddk::mdarray< double, 3 > sbessel_mom_
Moments of the spherical Bessel functions.
void generate_pw_coefs()
Generate plane-wave coefficients of the potential in the interstitial region.
double add_delta_rho_xc_
Add extra charge to the density.
void poisson_add_pseudo_pw(sddk::mdarray< std::complex< double >, 2 > &qmt__, sddk::mdarray< std::complex< double >, 2 > &qit__, std::complex< double > *rho_pw__)
Add contribution from the pseudocharge to the plane-wave expansion.
static void convert(int lmax__, double const *f_rlm__, std::complex< double > *f_ylm__)
Convert form Rlm to Ylm representation.
Simulation context is a set of parameters and objects describing a single simulation.
auto const & gvec() const
Return const reference to Gvec object.
std::ostream & out() const
Return output stream.
mpi::Communicator const & comm() const
Total communicator of the simulation.
Function in spherical harmonics or spherical coordinates representation.
Representation of a unit cell.
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.
int num_atoms() const
Number of atoms in the unit cell.
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.
MPI communicator wrapper.
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.
size_t size() const
Return total size (number of elements) of the array.
Contains definition and partial implementation of sirius::Density class.
Contains declaration and partial implementation of sirius::Hubbard class.
void copy(T *target__, T const *source__, size_t n__)
Copy memory inside a device.
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
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 .
Contains implementation of sirius::XC_functional class.