34 :
Field4D(ctx__,
lmax_t(ctx__.lmax_pot()), {ctx__.periodic_function_ptr(
"veff"), ctx__.periodic_function_ptr(
"bz"),
35 ctx__.periodic_function_ptr(
"bx"), ctx__.periodic_function_ptr(
"by")})
36 , unit_cell_(ctx__.unit_cell())
38 , hubbard_potential_(ctx__)
40 PROFILE(
"sirius::Potential");
42 if (!ctx_.initialized()) {
43 RTE_THROW(
"Simulation_context is not initialized");
48 if (ctx_.full_potential()) {
49 lmax = std::max(ctx_.lmax_rho(), ctx_.lmax_pot());
51 lmax = 2 * ctx_.unit_cell().lmax();
55 sht_ = std::make_unique<SHT>(ctx_.processing_unit(),
lmax, ctx_.cfg().settings().sht_coverage());
56 if (ctx_.cfg().control().verification() >= 1) {
62 zil_.resize(
lmax + 1);
63 for (
int l = 0; l <=
lmax; l++) {
64 zil_[l] = std::pow(std::complex<double>(0, 1), l);
68 for (
int l = 0,
lm = 0; l <=
lmax; l++) {
69 for (
int m = -l; m <= l; m++,
lm++) {
76 for (
auto& xc_label : ctx_.xc_functionals()) {
77 xc_func_.emplace_back(XC_functional(ctx_.spfft<
double>(), ctx_.unit_cell().lattice_vectors(), xc_label,
79 if (ctx_.cfg().parameters().xc_dens_tre() > 0) {
80 xc_func_.back().set_dens_threshold(ctx_.cfg().parameters().xc_dens_tre());
84 using pf = Periodic_function<double>;
85 using spf = Smooth_periodic_function<double>;
87 if (ctx_.full_potential()) {
88 hartree_potential_ = std::make_unique<pf>(ctx_, [&](
int ia){
return lmax_t(ctx_.lmax_pot());},
89 &ctx_.unit_cell().spl_num_atoms());
90 xc_potential_ = std::make_unique<pf>(ctx_, [&](
int ia){
return lmax_t(ctx_.lmax_pot());},
91 &ctx_.unit_cell().spl_num_atoms());
92 xc_energy_density_ = std::make_unique<pf>(ctx_, [&](
int ia){
return lmax_t(ctx_.lmax_pot());},
93 &ctx_.unit_cell().spl_num_atoms());
100 if (this->is_gradient_correction()) {
101 int nsigma = (ctx_.
num_spins() == 1) ? 1 : 3;
102 for (
int i = 0; i < nsigma ; i++) {
107 if (!ctx_.full_potential()) {
115 if (ctx_.full_potential()) {
116 gvec_ylm_ = sddk::mdarray<std::complex<double>, 2>(ctx_.lmmax_pot(), ctx_.
gvec().count(), sddk::memory_t::host,
"gvec_ylm_");
119 case relativity_t::iora: {
120 rm2_inv_pw_ = sddk::mdarray<std::complex<double>, 1>(ctx_.
gvec().num_gvec());
122 case relativity_t::zora: {
123 rm_inv_pw_ = sddk::mdarray<std::complex<double>, 1>(ctx_.
gvec().num_gvec());
126 veff_pw_ = sddk::mdarray<std::complex<double>, 1>(ctx_.
gvec().num_gvec());
131 aux_bf_ = sddk::mdarray<double, 2>(3, ctx_.unit_cell().num_atoms());
134 if (ctx_.cfg().parameters().reduce_aux_bf() > 0 && ctx_.cfg().parameters().reduce_aux_bf() < 1) {
135 for (
int ia = 0; ia < ctx_.unit_cell().num_atoms(); ia++) {
136 for (
int x : {0, 1, 2}) {
145 if (ctx_.hubbard_correction()) {
146 U_ = std::unique_ptr<Hubbard>(
new Hubbard(ctx_));
154 PROFILE(
"sirius::Potential::update");
156 if (!ctx_.full_potential()) {
162 auto lmax = std::max(ctx_.lmax_rho(), ctx_.lmax_pot());
175 sddk::memory_t::host,
"sbessel_mom_");
186 #pragma omp parallel for schedule(static)
187 for (
int igloc = ig0; igloc < ctx_.
gvec().count(); igloc++) {
189 for (
int l = 0; l <= ctx_.lmax_rho(); l++) {
191 sbessel_mt_(l + 1, igloc, iat) / len;
200 sddk::memory_t::host,
"gamma_factors_R_");
202 for (
int l = 0; l <= ctx_.lmax_rho(); l++) {
205 int n_min = (2 * l + 3);
206 int n_max = (2 * l + 1) + (2 * pseudo_density_order_ + 2);
208 long double f1 = 1.0;
209 long double f2 = 1.0;
210 for (
int n = n_min; n <= n_max; n += 2) {
217 gamma_factors_R_(l, iat) =
static_cast<double>((f1 / Rl) * f2);
223 for (
auto&
xc : xc_func_) {
225 xc.vdw_update_unit_cell(ctx_.spfft<
double>(), ctx_.unit_cell().lattice_vectors());
230bool Potential::is_gradient_correction()
const
233 for (
auto& ixc : xc_func_) {
234 if (ixc.is_gga() || ixc.is_vdw()) {
243 PROFILE(
"sirius::Potential::generate");
245 if (!ctx_.full_potential()) {
247 for (
size_t ig = 0; ig < effective_potential().rg().f_pw_local().size(); ig++) {
248 dveff_->f_pw_local(ig) = effective_potential().rg().f_pw_local(ig);
255 auto veff_callback = ctx_.veff_callback();
269 effective_potential() += hartree_potential();
271 if (env::print_hash()) {
272 auto h = effective_potential().rg().hash_f_rg();
273 print_hash(
"Vha", h, ctx_.
out());
276 if (ctx_.full_potential()) {
280 effective_potential().rg() += local_potential();
285 effective_potential() += xc_potential();
287 if (env::print_hash()) {
288 auto h = effective_potential().rg().hash_f_rg();
289 print_hash(
"Vha+Vxc", h, ctx_.
out());
292 if (ctx_.full_potential()) {
293 effective_potential().mt().sync(ctx_.unit_cell().spl_num_atoms());
295 effective_magnetic_field(j).mt().sync(ctx_.unit_cell().spl_num_atoms());
307 if (use_symmetry__) {
309 symmetrize_field4d(*
this);
310 if (transform_to_rg__) {
312 this->fft_transform(1);
316 if (!ctx_.full_potential()) {
318 for (
size_t ig = 0; ig < effective_potential().rg().f_pw_local().size(); ig++) {
319 dveff_->f_pw_local(ig) = effective_potential().rg().f_pw_local(ig) -
dveff_->f_pw_local(ig);
323 if (env::print_hash()) {
324 auto h = effective_potential().rg().hash_f_pw();
325 print_hash(
"V(G)", h, ctx_.
out());
328 if (!ctx_.full_potential()) {
330 generate_PAW_effective_potential(density__);
331 if (ctx_.verbosity() >= 3) {
333 out <<
"density matrix" << std::endl;
334 for (
int ia = 0; ia < ctx_.unit_cell().num_atoms(); ia++) {
335 auto& atom = ctx_.unit_cell().atom(ia);
336 out <<
"atom : " << ia << std::endl;
337 for (
int imagn = 0; imagn < ctx_.
num_mag_comp(); imagn++) {
338 out <<
" imagn : " << imagn << std::endl;
339 for (
int ib2 = 0; ib2 < atom.mt_basis_size(); ib2++) {
341 for (
int ib1 = 0; ib1 < atom.mt_basis_size(); ib1++) {
342 out <<
ffmt(8, 3) << density__.density_matrix(ia)(ib1, ib2, imagn);
349 out <<
"D operator matrix" << std::endl;
350 for (
int ia = 0; ia < ctx_.unit_cell().num_atoms(); ia++) {
351 auto& atom = ctx_.unit_cell().atom(ia);
352 out <<
"atom : " << ia << std::endl;
353 for (
int imagn = 0; imagn < ctx_.
num_mag_dims() + 1; imagn++) {
354 out <<
" imagn : " << imagn << std::endl;
355 for (
int ib2 = 0; ib2 < atom.mt_basis_size(); ib2++) {
357 for (
int ib1 = 0; ib1 < atom.mt_basis_size(); ib1++) {
358 out <<
ffmt(8, 3) << atom.d_mtrx(ib1, ib2, imagn);
367 if (ctx_.hubbard_correction()) {
368 ::sirius::generate_potential(density__.occupation_matrix(), this->hubbard_potential());
371 if (ctx_.cfg().parameters().reduce_aux_bf() > 0 && ctx_.cfg().parameters().reduce_aux_bf() < 1) {
372 for (
int ia = 0; ia < ctx_.unit_cell().num_atoms(); ia++) {
373 for (
int x : {0, 1, 2}) {
374 aux_bf_(x, ia) *= ctx_.cfg().parameters().reduce_aux_bf();
380void Potential::save(std::string name__)
382 effective_potential().hdf5_write(name__,
"effective_potential");
384 effective_magnetic_field(j).hdf5_write(name__,
"effective_magnetic_field/" + std::to_string(j));
386 if (ctx_.
comm().
rank() == 0 && !ctx_.full_potential()) {
387 HDF5_tree fout(name__, hdf5_access_t::read_write);
388 for (
int j = 0; j < ctx_.unit_cell().num_atoms(); j++) {
389 if (ctx_.unit_cell().atom(j).mt_basis_size() != 0) {
390 fout[
"unit_cell"][
"atoms"][j].write(
"D_operator", ctx_.unit_cell().atom(j).d_mtrx());
397void Potential::load(std::string name__)
399 HDF5_tree fin(name__, hdf5_access_t::read_only);
402 fin.read(
"/parameters/num_gvec", &ngv, 1);
403 if (ngv != ctx_.
gvec().num_gvec()) {
404 RTE_THROW(
"wrong number of G-vectors");
406 sddk::mdarray<int, 2> gv(3, ngv);
407 fin.read(
"/parameters/gvec", gv);
409 effective_potential().hdf5_read(name__,
"effective_potential", gv);
412 effective_magnetic_field(j).hdf5_read(name__,
"effective_magnetic_field/" + std::to_string(j), gv);
415 if (ctx_.full_potential()) {
416 update_atomic_potential();
419 if (!ctx_.full_potential()) {
420 for (
int j = 0; j < ctx_.unit_cell().num_atoms(); j++) {
421 fin[
"unit_cell"][
"atoms"][j].read(
"D_operator", ctx_.unit_cell().atom(j).d_mtrx());
426void Potential::update_atomic_potential()
432 std::vector<double> veff(nmtp);
434 for (
int ir = 0; ir < nmtp; ir++) {
435 veff[ir] =
y00 * effective_potential().mt()[ia](0, ir);
442 double* veff = &effective_potential().mt()[ia](0, 0);
444 double* beff[] = {
nullptr,
nullptr,
nullptr};
446 beff[i] = &effective_magnetic_field(i).mt()[ia](0, 0);
void set_spherical_potential(std::vector< double > const &vs__)
Set the spherical component of the potential.
double mt_radius() const
Return muffin-tin radius.
void set_nonspherical_potential(double *veff__, double *beff__[3])
Set muffin-tin potential and magnetic field.
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.
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.
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.
std::unique_ptr< Periodic_function< double > > hartree_potential_
Hartree potential.
sddk::mdarray< std::complex< double >, 1 > rm2_inv_pw_
Plane-wave coefficients of the squared inverse relativistic mass weighted by the unit step-function.
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::unique_ptr< Hubbard > U_
Hubbard potential correction operator.
Unit_cell & unit_cell_
Alias to unit cell.
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.
sddk::mdarray< std::complex< double >, 1 > veff_pw_
Plane-wave coefficients of the effective potential weighted by the unit step-function.
sddk::mdarray< double, 3 > sbessel_mom_
Moments of the spherical Bessel functions.
Simulation context is a set of parameters and objects describing a single simulation.
auto const & gvec() const
Return const reference to Gvec object.
auto gvec_fft_sptr() const
Return shared pointer to Gvec_fft object.
std::ostream & out() const
Return output stream.
mpi::Communicator const & comm() const
Total communicator of the simulation.
int num_spins() const
Number of spin components.
int num_mag_comp() const
Number of components in the complex density matrix.
int num_mag_dims() const
Number of dimensions in the magnetization vector.
void valence_relativity(std::string name__)
Set valence relativity for the LAPW method.
Atom const & atom(int id__) const
Return const atom instance by id.
int num_atom_symmetry_classes() const
Number of atom symmetry classes.
int num_atom_types() const
Number of atom types.
Atom_type & atom_type(int id__)
Return atom type instance by id.
int num_atoms() const
Number of atoms in the unit cell.
Atom_symmetry_class const & atom_symmetry_class(int id__) const
Return const symmetry class instance by class id.
Floating-point formatting (precision and width).
int rank() const
Rank of MPI process inside communicator.
void zero(memory_t mem__, size_t idx0__, size_t n__)
Zero n elements starting from idx0.
Generate complex spherical harmonics for the local set of G-vectors.
Generate spherical Bessel functions at the muffin-tin boundary for the local set of G-vectors.
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 .
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
std::vector< int > l_by_lm(int lmax__)
Get array of orbital quantum numbers for each lm component.
Namespace of the SIRIUS library.
const double y00
First spherical harmonic .
auto generate_sbessel_mt(Simulation_context const &ctx__, int lmax__)
Compute values of spherical Bessel functions at MT boundary.
auto generate_gvec_ylm(Simulation_context const &ctx__, int lmax__)
Generate complex spherical harmonics for the local set of G-vectors.
Contains declaration and partial implementation of sirius::Potential class.
Symmetrize density and potential fields (scalar + vector).
Contains implementation of sirius::XC_functional class.