SIRIUS 7.5.0
Electronic structure library and applications
potential.cpp
Go to the documentation of this file.
1// Copyright (c) 2013-2020 Anton Kozhevnikov, Ilia Sivkov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file potential.cpp
21 *
22 * \brief Generate effective potential.
23 */
24
25#include "potential.hpp"
26#include "xc_functional.hpp"
30
31namespace sirius {
32
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())
37 , comm_(ctx__.comm())
38 , hubbard_potential_(ctx__)
39{
40 PROFILE("sirius::Potential");
41
42 if (!ctx_.initialized()) {
43 RTE_THROW("Simulation_context is not initialized");
44 }
45
46 int lmax{-1};
47
48 if (ctx_.full_potential()) {
49 lmax = std::max(ctx_.lmax_rho(), ctx_.lmax_pot());
50 } else {
51 lmax = 2 * ctx_.unit_cell().lmax();
52 }
53
54 if (lmax >= 0) {
55 sht_ = std::make_unique<SHT>(ctx_.processing_unit(), lmax, ctx_.cfg().settings().sht_coverage());
56 if (ctx_.cfg().control().verification() >= 1) {
57 sht_->check();
58 }
59 l_by_lm_ = sf::l_by_lm(lmax);
60
61 /* precompute i^l */
62 zil_.resize(lmax + 1);
63 for (int l = 0; l <= lmax; l++) {
64 zil_[l] = std::pow(std::complex<double>(0, 1), l);
65 }
66
67 zilm_.resize(sf::lmmax(lmax));
68 for (int l = 0, lm = 0; l <= lmax; l++) {
69 for (int m = -l; m <= l; m++, lm++) {
70 zilm_[lm] = zil_[l];
71 }
72 }
73 }
74
75 /* create list of XC functionals */
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,
78 ctx_.num_spins()));
79 if (ctx_.cfg().parameters().xc_dens_tre() > 0) {
80 xc_func_.back().set_dens_threshold(ctx_.cfg().parameters().xc_dens_tre());
81 }
82 }
83
84 using pf = Periodic_function<double>;
85 using spf = Smooth_periodic_function<double>;
86
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());
94 } else {
95 hartree_potential_ = std::make_unique<pf>(ctx_);
96 xc_potential_ = std::make_unique<pf>(ctx_);
97 xc_energy_density_ = std::make_unique<pf>(ctx_);
98 }
99
100 if (this->is_gradient_correction()) {
101 int nsigma = (ctx_.num_spins() == 1) ? 1 : 3;
102 for (int i = 0; i < nsigma ; i++) {
103 vsigma_[i] = std::make_unique<spf>(ctx_.spfft<double>(), ctx_.gvec_fft_sptr());
104 }
105 }
106
107 if (!ctx_.full_potential()) {
108 local_potential_ = std::make_unique<spf>(ctx_.spfft<double>(), ctx_.gvec_fft_sptr());
109 dveff_ = std::make_unique<spf>(ctx_.spfft<double>(), ctx_.gvec_fft_sptr());
110 dveff_->zero();
111 }
112
113 vh_el_ = sddk::mdarray<double, 1>(unit_cell_.num_atoms());
114
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_");
117
118 switch (ctx_.valence_relativity()) {
119 case relativity_t::iora: {
120 rm2_inv_pw_ = sddk::mdarray<std::complex<double>, 1>(ctx_.gvec().num_gvec());
121 }
122 case relativity_t::zora: {
123 rm_inv_pw_ = sddk::mdarray<std::complex<double>, 1>(ctx_.gvec().num_gvec());
124 }
125 default: {
126 veff_pw_ = sddk::mdarray<std::complex<double>, 1>(ctx_.gvec().num_gvec());
127 }
128 }
129 }
130
131 aux_bf_ = sddk::mdarray<double, 2>(3, ctx_.unit_cell().num_atoms());
132 aux_bf_.zero();
133
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}) {
137 aux_bf_(x, ia) = 1;
138 }
139 }
140 }
141
142 /* in case of PAW */
143 init_PAW();
144
145 if (ctx_.hubbard_correction()) {
146 U_ = std::unique_ptr<Hubbard>(new Hubbard(ctx_));
147 }
148
149 update();
150}
151
153{
154 PROFILE("sirius::Potential::update");
155
156 if (!ctx_.full_potential()) {
157 local_potential_->zero();
159 } else {
160 gvec_ylm_ = generate_gvec_ylm(ctx_, ctx_.lmax_pot());
161
162 auto lmax = std::max(ctx_.lmax_rho(), ctx_.lmax_pot());
163 sbessel_mt_ = generate_sbessel_mt(ctx_, lmax + pseudo_density_order_ + 1);
164
165 /* compute moments of spherical Bessel functions
166 *
167 * In[]:= Integrate[SphericalBesselJ[l,G*x]*x^(2+l),{x,0,R},Assumptions->{R>0,G>0,l>=0}]
168 * Out[]= (Sqrt[\[Pi]/2] R^(3/2+l) BesselJ[3/2+l,G R])/G^(3/2)
169 *
170 * and use relation between Bessel and spherical Bessel functions:
171 * Subscript[j, n](z)=Sqrt[\[Pi]/2]/Sqrt[z]Subscript[J, n+1/2](z) */
172 sbessel_mom_ = sddk::mdarray<double, 3>(ctx_.lmax_rho() + 1,
173 ctx_.gvec().count(),
175 sddk::memory_t::host, "sbessel_mom_");
177 int ig0{0};
178 if (ctx_.comm().rank() == 0) {
179 /* for |G| = 0 */
180 for (int iat = 0; iat < unit_cell_.num_atom_types(); iat++) {
181 sbessel_mom_(0, 0, iat) = std::pow(unit_cell_.atom_type(iat).mt_radius(), 3) / 3.0;
182 }
183 ig0 = 1;
184 }
185 for (int iat = 0; iat < unit_cell_.num_atom_types(); iat++) {
186 #pragma omp parallel for schedule(static)
187 for (int igloc = ig0; igloc < ctx_.gvec().count(); igloc++) {
188 auto len = ctx_.gvec().gvec_cart<index_domain_t::local>(igloc).length();
189 for (int l = 0; l <= ctx_.lmax_rho(); l++) {
190 sbessel_mom_(l, igloc, iat) = std::pow(unit_cell_.atom_type(iat).mt_radius(), l + 2) *
191 sbessel_mt_(l + 1, igloc, iat) / len;
192 }
193 }
194 }
195
196 /* compute Gamma[5/2 + n + l] / Gamma[3/2 + l] / R^l
197 *
198 * use Gamma[1/2 + p] = (2p - 1)!!/2^p Sqrt[Pi] */
199 gamma_factors_R_ = sddk::mdarray<double, 2>(ctx_.lmax_rho() + 1, unit_cell_.num_atom_types(),
200 sddk::memory_t::host, "gamma_factors_R_");
201 for (int iat = 0; iat < unit_cell_.num_atom_types(); iat++) {
202 for (int l = 0; l <= ctx_.lmax_rho(); l++) {
203 long double Rl = std::pow(unit_cell_.atom_type(iat).mt_radius(), l);
204
205 int n_min = (2 * l + 3);
206 int n_max = (2 * l + 1) + (2 * pseudo_density_order_ + 2);
207 /* split factorial product into two parts to avoid overflow */
208 long double f1 = 1.0;
209 long double f2 = 1.0;
210 for (int n = n_min; n <= n_max; n += 2) {
211 if (f1 < Rl) {
212 f1 *= (n / 2.0);
213 } else {
214 f2 *= (n / 2.0);
215 }
216 }
217 gamma_factors_R_(l, iat) = static_cast<double>((f1 / Rl) * f2);
218 }
219 }
220 }
221
222 // VDWXC depends on unit cell, which might have changed.
223 for (auto& xc : xc_func_) {
224 if (xc.is_vdw()) {
225 xc.vdw_update_unit_cell(ctx_.spfft<double>(), ctx_.unit_cell().lattice_vectors());
226 }
227 }
228}
229
230bool Potential::is_gradient_correction() const
231{
232 bool is_gga{false};
233 for (auto& ixc : xc_func_) {
234 if (ixc.is_gga() || ixc.is_vdw()) {
235 is_gga = true;
236 }
237 }
238 return is_gga;
239}
240
241void Potential::generate(Density const& density__, bool use_symmetry__, bool transform_to_rg__)
242{
243 PROFILE("sirius::Potential::generate");
244
245 if (!ctx_.full_potential()) {
246 /* save current effective 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);
249 }
250 }
251
252 /* zero effective potential and magnetic field */
253 zero();
254
255 auto veff_callback = ctx_.veff_callback();
256 if (veff_callback) {
257 veff_callback();
258 //if (!ctx_.full_potential()) {
259 // /* add local ionic potential to the effective potential */
260 // effective_potential().add(local_potential());
261 //}
262 /* transform to real space */
263 //fft_transform(1);
264 } else {
265 /* solve Poisson equation */
266 poisson(density__.rho());
267
268 /* add Hartree potential to the total potential */
269 effective_potential() += hartree_potential();
270
271 if (env::print_hash()) {
272 auto h = effective_potential().rg().hash_f_rg();
273 print_hash("Vha", h, ctx_.out());
274 }
275
276 if (ctx_.full_potential()) {
277 xc(density__);
278 } else {
279 /* add local ionic potential to the effective potential */
280 effective_potential().rg() += local_potential();
281 /* construct XC potentials from rho + rho_core */
282 xc<true>(density__);
283 }
284 /* add XC potential to the effective potential */
285 effective_potential() += xc_potential();
286
287 if (env::print_hash()) {
288 auto h = effective_potential().rg().hash_f_rg();
289 print_hash("Vha+Vxc", h, ctx_.out());
290 }
291
292 if (ctx_.full_potential()) {
293 effective_potential().mt().sync(ctx_.unit_cell().spl_num_atoms());
294 for (int j = 0; j < ctx_.num_mag_dims(); j++) {
295 effective_magnetic_field(j).mt().sync(ctx_.unit_cell().spl_num_atoms());
296 }
297 }
298
299 /* get plane-wave coefficients of effective potential;
300 * they will be used in three places:
301 * 1) compute D-matrix
302 * 2) establish a mapping between fine and coarse FFT grid for the Hloc operator
303 * 3) symmetrize effective potential */
304 fft_transform(-1);
305 }
306
307 if (use_symmetry__) {
308 /* symmetrize potential and effective magnetic field */
309 symmetrize_field4d(*this);
310 if (transform_to_rg__) {
311 /* transform potential to real space after symmetrization */
312 this->fft_transform(1);
313 }
314 }
315
316 if (!ctx_.full_potential()) {
317 /* this is needed later to compute scf correction to forces */
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);
320 }
321 }
322
323 if (env::print_hash()) {
324 auto h = effective_potential().rg().hash_f_pw();
325 print_hash("V(G)", h, ctx_.out());
326 }
327
328 if (!ctx_.full_potential()) {
330 generate_PAW_effective_potential(density__);
331 if (ctx_.verbosity() >= 3) {
332 rte::ostream out(ctx_.out(), "potential");
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++) {
340 out << " ";
341 for (int ib1 = 0; ib1 < atom.mt_basis_size(); ib1++) {
342 out << ffmt(8, 3) << density__.density_matrix(ia)(ib1, ib2, imagn);
343 }
344 out << std::endl;
345 }
346 }
347 }
348
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++) {
356 out << " ";
357 for (int ib1 = 0; ib1 < atom.mt_basis_size(); ib1++) {
358 out << ffmt(8, 3) << atom.d_mtrx(ib1, ib2, imagn);
359 }
360 out << std::endl;
361 }
362 }
363 }
364 }
365 }
366
367 if (ctx_.hubbard_correction()) {
368 ::sirius::generate_potential(density__.occupation_matrix(), this->hubbard_potential());
369 }
370
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();
375 }
376 }
377 }
378}
379
380void Potential::save(std::string name__)
381{
382 effective_potential().hdf5_write(name__, "effective_potential");
383 for (int j = 0; j < ctx_.num_mag_dims(); j++) {
384 effective_magnetic_field(j).hdf5_write(name__, "effective_magnetic_field/" + std::to_string(j));
385 }
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());
391 }
392 }
393 }
394 comm_.barrier();
395}
396
397void Potential::load(std::string name__)
398{
399 HDF5_tree fin(name__, hdf5_access_t::read_only);
400
401 int ngv;
402 fin.read("/parameters/num_gvec", &ngv, 1);
403 if (ngv != ctx_.gvec().num_gvec()) {
404 RTE_THROW("wrong number of G-vectors");
405 }
406 sddk::mdarray<int, 2> gv(3, ngv);
407 fin.read("/parameters/gvec", gv);
408
409 effective_potential().hdf5_read(name__, "effective_potential", gv);
410
411 for (int j = 0; j < ctx_.num_mag_dims(); j++) {
412 effective_magnetic_field(j).hdf5_read(name__, "effective_magnetic_field/" + std::to_string(j), gv);
413 }
414
415 if (ctx_.full_potential()) {
416 update_atomic_potential();
417 }
418
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());
422 }
423 }
424}
425
426void Potential::update_atomic_potential()
427{
428 for (int ic = 0; ic < unit_cell_.num_atom_symmetry_classes(); ic++) {
429 int ia = unit_cell_.atom_symmetry_class(ic).atom_id(0);
430 int nmtp = unit_cell_.atom(ia).num_mt_points();
431
432 std::vector<double> veff(nmtp);
433
434 for (int ir = 0; ir < nmtp; ir++) {
435 veff[ir] = y00 * effective_potential().mt()[ia](0, ir);
436 }
437
439 }
440
441 for (int ia = 0; ia < unit_cell_.num_atoms(); ia++) {
442 double* veff = &effective_potential().mt()[ia](0, 0);
443
444 double* beff[] = {nullptr, nullptr, nullptr};
445 for (int i = 0; i < ctx_.num_mag_dims(); i++) {
446 beff[i] = &effective_magnetic_field(i).mt()[ia](0, 0);
447 }
448
450 }
451}
452
453}
454
void set_spherical_potential(std::vector< double > const &vs__)
Set the spherical component of the potential.
double mt_radius() const
Return muffin-tin radius.
Definition: atom_type.hpp:712
void set_nonspherical_potential(double *veff__, double *beff__[3])
Set muffin-tin potential and magnetic field.
Definition: atom.hpp:375
Generate charge density and magnetization from occupied spinor wave-functions.
Definition: density.hpp:214
auto const & rho() const
Return const reference to charge density (scalar functions).
Definition: density.hpp:416
Four-component function consisting of scalar and vector parts.
Definition: field4d.hpp:40
void generate(Density const &density__, bool use_sym__, bool transform_to_rg__)
Generate effective potential and magnetic field from charge density and magnetization.
Definition: potential.cpp:241
std::unique_ptr< Smooth_periodic_function< double > > dveff_
Used to compute SCF correction to forces.
Definition: potential.hpp:76
std::unique_ptr< Smooth_periodic_function< double > > local_potential_
Local part of pseudopotential.
Definition: potential.hpp:64
sddk::mdarray< std::complex< double >, 1 > rm_inv_pw_
Plane-wave coefficients of the inverse relativistic mass weighted by the unit step-function.
Definition: potential.hpp:109
mpi::Communicator const & comm_
Communicator of the simulation.
Definition: potential.hpp:52
std::unique_ptr< Periodic_function< double > > xc_energy_density_
XC energy per unit particle.
Definition: potential.hpp:61
void poisson(Periodic_function< double > const &rho)
Poisson solver.
Definition: poisson.cpp:158
std::unique_ptr< Periodic_function< double > > hartree_potential_
Hartree potential.
Definition: potential.hpp:55
sddk::mdarray< std::complex< double >, 1 > rm2_inv_pw_
Plane-wave coefficients of the squared inverse relativistic mass weighted by the unit step-function.
Definition: potential.hpp:112
Potential(Simulation_context &ctx__)
Constructor.
Definition: potential.cpp:33
void xc(Density const &rho__)
Generate XC potential and energy density.
Definition: xc.cpp:435
std::unique_ptr< Periodic_function< double > > xc_potential_
XC potential.
Definition: potential.hpp:58
std::unique_ptr< Hubbard > U_
Hubbard potential correction operator.
Definition: potential.hpp:132
Unit_cell & unit_cell_
Alias to unit cell.
Definition: potential.hpp:49
void generate_local_potential()
Generate local part of pseudo potential.
Definition: potential.hpp:248
void update()
Recompute some variables that depend on atomic positions or the muffin-tin radius.
Definition: potential.cpp:152
std::array< std::unique_ptr< Smooth_periodic_function< double > >, 3 > vsigma_
Derivative .
Definition: potential.hpp:72
sddk::mdarray< double, 1 > vh_el_
Electronic part of Hartree potential.
Definition: potential.hpp:101
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.
Definition: potential.hpp:106
sddk::mdarray< double, 3 > sbessel_mom_
Moments of the spherical Bessel functions.
Definition: potential.hpp:79
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.
Definition: unit_cell.hpp:344
int num_atom_symmetry_classes() const
Number of atom symmetry classes.
Definition: unit_cell.hpp:320
int num_atom_types() const
Number of atom types.
Definition: unit_cell.hpp:281
Atom_type & atom_type(int id__)
Return atom type instance by id.
Definition: unit_cell.hpp:288
int num_atoms() const
Number of atoms in the unit cell.
Definition: unit_cell.hpp:338
Atom_symmetry_class const & atom_symmetry_class(int id__) const
Return const symmetry class instance by class id.
Definition: unit_cell.hpp:326
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.
Definition: memory.hpp:1316
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.
Definition: specfunc.hpp:56
int lmmax(int lmax)
Maximum number of combinations for a given .
Definition: specfunc.hpp:44
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
Definition: specfunc.hpp:50
std::vector< int > l_by_lm(int lmax__)
Get array of orbital quantum numbers for each lm component.
Definition: specfunc.hpp:69
Namespace of the SIRIUS library.
Definition: sirius.f90:5
const double y00
First spherical harmonic .
Definition: constants.hpp:51
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.