25#ifndef __DENSITY_HPP__
26#define __DENSITY_HPP__
32#include "function3d/spheric_function_set.hpp"
37#include "density_matrix.hpp"
40#if defined(SIRIUS_GPU)
44update_density_rg_1_real_gpu_float(
int size__,
float const* psi_rg__,
float wt__,
float* density_rg__);
47update_density_rg_1_real_gpu_double(
int size__,
double const* psi_rg__,
double wt__,
double* density_rg__);
50update_density_rg_1_complex_gpu_float(
int size__, std::complex<float>
const* psi_rg__,
float wt__,
54update_density_rg_1_complex_gpu_double(
int size__, std::complex<double>
const* psi_rg__,
double wt__,
double* density_rg__);
57update_density_rg_2_gpu_float(
int size__, std::complex<float>
const* psi_rg_up__, std::complex<float>
const* psi_rg_dn__,
58 float wt__,
float* density_x_rg__,
float* density_y_rg__);
61update_density_rg_2_gpu_double(
int size__, std::complex<double>
const* psi_rg_up__, std::complex<double>
const* psi_rg_dn__,
62 double wt__,
double* density_x_rg__,
double* density_y_rg__);
65generate_dm_pw_gpu(
int num_atoms__,
int num_gvec_loc__,
int num_beta__,
double const* atom_pos__,
66 int const* gvx__,
int const* gvy__,
int const* gvz__,
double* phase_factors__,
67 double const* dm__,
double* dm_pw__,
int stream_id__);
70sum_q_pw_dm_pw_gpu(
int num_gvec_loc__,
int nbf__,
double const* q_pw__,
int ldq__,
double const* dm_pw__,
int ldd__,
71 double const* sym_weight__, std::complex<double>* rho_pw__,
int stream_id__);
83 return std::make_pair<double, double>(0, 0);
87 if (num_mag_dims__ == 1) {
90 if (std::abs(mag) > rho__) {
91 mag =
sign(mag) * rho__;
95 mag = std::min(mag__.
length(), rho__);
98 return std::make_pair<double, double>(0.5 * (rho__ + mag), 0.5 * (rho__ - mag));
112 auto& ae_density(
int i__,
int ja__)
114 return this->ae_component(i__)[ja__];
117 auto const& ae_density(
int i__,
int ja__)
const
119 return this->ae_component(i__)[ja__];
122 auto& ps_density(
int i__,
int ja__)
124 return this->ps_component(i__)[ja__];
127 auto const& ps_density(
int i__,
int ja__)
const
129 return this->ps_component(i__)[ja__];
268 template <
int num_mag_dims>
300 template <
typename T,
typename F>
304 template <
typename T>
313 PROFILE(
"sirius::Density::generate_core_charge_density");
315 auto& spl_idx =
unit_cell_.spl_num_atom_symmetry_classes();
317 for (
auto it : spl_idx) {
321 for (
auto ic = begin_global(spl_idx); ic != end_global(spl_idx); ic++) {
322 auto rank = spl_idx.location(ic).ib;
327 void generate_pseudo_core_charge_density()
329 PROFILE(
"sirius::Density::generate_pseudo_core_charge_density");
332 auto q = ctx_.
gvec().shells_len();
334 auto const ff = ctx_.ri().ps_core_->values(q, ctx_.
comm());
336 auto v = make_periodic_function<index_domain_t::local>(ctx_.unit_cell(), ctx_.
gvec(),
337 ctx_.phase_factors_t(), ff);
345 Density(Simulation_context& ctx__);
356 void initial_density_pseudo();
358 void initial_density_full_pot();
370 template <
typename T>
371 void generate(K_point_set
const& ks__,
bool symmetrize__,
bool add_core__,
bool transform_to_rg__);
378 template <
typename T>
416 inline auto const&
rho()
const
424 return const_cast<Periodic_function<double>&
>(
static_cast<Density const&
>(*this).
rho());
427 inline auto& mag(
int i)
432 inline auto const& mag(
int i)
const
437 inline auto& rho_pseudo_core()
442 inline auto const& rho_pseudo_core()
const
447 inline auto const& density_mt(atom_index_t::local ialoc__)
const
449 auto ia = ctx_.unit_cell().spl_num_atoms().global_index(ialoc__);
450 return rho().mt()[ia];
459 std::vector<Flm const*> result(ctx_.
num_mag_dims() + 1);
469 std::vector<Flm const*> result(ctx_.
num_mag_dims() + 1);
486 inline auto const& density_matrix(
int ia__)
const
491 inline auto& density_matrix(
int ia__)
497 sddk::mdarray<double, 3>
500 sddk::mdarray<double, 2>
504 sddk::mdarray<double, 2>
511 std::tuple<std::array<double, 3>, std::array<double, 3>, std::vector<std::array<double, 3>>>
514 void print_info(std::ostream& out__)
const;
516 Occupation_matrix
const& occupation_matrix()
const
521 Occupation_matrix& occupation_matrix()
526 auto const& paw_density()
const
568 void save(std::string name__)
const
570 rho().hdf5_write(name__,
"density");
573 s <<
"magnetization/" << j;
574 mag(j).hdf5_write(name__, s.str());
576 ctx_.
comm().barrier();
579 void load(std::string name__)
581 HDF5_tree fin(name__, hdf5_access_t::read_only);
584 fin.read(
"/parameters/num_gvec", &ngv, 1);
585 if (ngv != ctx_.
gvec().num_gvec()) {
586 RTE_THROW(
"wrong number of G-vectors");
588 sddk::mdarray<int, 2> gv(3, ngv);
589 fin.read(
"/parameters/gvec", gv);
591 rho().hdf5_read(name__,
"density", gv);
592 rho().rg().fft_transform(1);
594 mag(j).hdf5_read(name__,
"magnetization/" + std::to_string(j), gv);
595 mag(j).rg().fft_transform(1);
746copy(Density
const& src__, Density& dest__)
748 for (
int j = 0; j < src__.ctx().num_mag_dims() + 1; j++) {
749 copy(src__.component(j).rg(), dest__.component(j).rg());
750 if (src__.ctx().full_potential()) {
751 copy(src__.component(j).mt(), dest__.component(j).mt());
754 for (
int ia = 0; ia < src__.ctx().unit_cell().num_atoms(); ia++) {
755 copy(src__.density_matrix(ia), dest__.density_matrix(ia));
757 if (src__.ctx().hubbard_correction()) {
758 copy(src__.occupation_matrix(), dest__.occupation_matrix());
762template <
bool add_pseudo_core__>
763inline std::array<std::unique_ptr<Smooth_periodic_function<double>>, 2>
764get_rho_up_dn(Density
const& density__,
double add_delta_rho_xc__ = 0.0,
double add_delta_mag_xc__ = 0.0)
766 PROFILE(
"sirius::get_rho_up_dn");
768 auto& ctx =
const_cast<Simulation_context&
>(density__.ctx());
769 int num_points = ctx.spfft<
double>().local_slice_size();
771 auto rho_up = std::make_unique<Smooth_periodic_function<double>>(ctx.spfft<
double>(), ctx.gvec_fft_sptr());
772 auto rho_dn = std::make_unique<Smooth_periodic_function<double>>(ctx.spfft<
double>(), ctx.gvec_fft_sptr());
776 #pragma omp parallel for reduction(min:rhomin)
777 for (
int ir = 0; ir < num_points; ir++) {
778 r3::vector<double> m;
779 for (
int j = 0; j < ctx.num_mag_dims(); j++) {
780 m[j] = density__.mag(j).rg().value(ir) * (1 + add_delta_mag_xc__);
783 double rho = density__.rho().rg().value(ir);
784 if (add_pseudo_core__) {
785 rho += density__.rho_pseudo_core().value(ir);
787 rho *= (1 + add_delta_rho_xc__);
788 rhomin = std::min(rhomin, rho);
791 rho_up->value(ir) = rud.first;
792 rho_dn->value(ir) = rud.second;
795 mpi::Communicator(ctx.spfft<
double>().communicator()).allreduce<double, mpi::op_t::min>(&rhomin, 1);
796 if (rhomin< 0.0 && ctx.comm().rank() == 0) {
798 s <<
"Interstitial charge density has negative values" << std::endl
799 <<
"most negatve value : " << rhomin;
802 std::array<std::unique_ptr<Smooth_periodic_function<double>>, 2> result;
803 result[0] = std::move(rho_up);
804 result[1] = std::move(rho_dn);
void generate_core_charge_density(relativity_t core_rel__)
Find core states and generate core density.
Defines the properties of atom type.
Generate charge density and magnetization from occupied spinor wave-functions.
auto & rho()
Return charge density (scalar functions).
sddk::mdarray< double, 2 > compute_atomic_mag_mom() const
Calculate approximate atomic magnetic moments in case of PP-PW.
auto paw_ps_density(int ia__) const
Return list of pointers to pseudo PAW density function for a given local index of atom with PAW poten...
std::unique_ptr< mixer::Mixer< Periodic_function< double >, Periodic_function< double >, Periodic_function< double >, Periodic_function< double >, density_matrix_t, PAW_density< double >, Hubbard_matrix > > mixer_
Density mixer.
double core_leakage() const
Find the total leakage of the core states out of the muffin-tins.
void generate_paw_density()
Generate and in lm components.
Unit_cell & unit_cell_
Alias to ctx_.unit_cell()
void mixer_init(config_t::mixer_t const &mixer_cfg__)
Initialize density mixer.
void update()
Update internal parameters after a change of lattice vectors or atomic coordinates.
double core_leakage(int ic) const
Return core leakage for a specific atom symmetry class.
std::unique_ptr< density_matrix_t > density_matrix_
Density matrix for all atoms.
void generate_core_charge_density()
Generate charge density of core states.
std::unique_ptr< PAW_density< double > > paw_density_
Local fraction of atoms with PAW correction.
sddk::mdarray< double, 3 > density_matrix_aux(Atom_type const &atom_type__) const
Return density matrix for all atoms of a given type in auxiliary form.
void augment()
Add augmentation charge Q(r).
bool check_num_electrons() const
Check total density for the correct number of electrons.
void reduce_density_matrix(Atom_type const &atom_type__, sddk::mdarray< std::complex< double >, 3 > const &zdens__, sddk::mdarray< double, 3 > &mt_density_matrix__)
Reduce complex density matrix over magnetic quantum numbers.
Density(Simulation_context &ctx__)
Constructor.
sddk::mdarray< std::complex< double >, 2 > generate_rho_aug() const
Generate augmentation charge density.
double mix()
Mix new density.
std::tuple< std::array< double, 3 >, std::array< double, 3 >, std::vector< std::array< double, 3 > > > get_magnetisation() const
Get total magnetization and also contributions from interstitial and muffin-tin parts.
auto const & rho() const
Return const reference to charge density (scalar functions).
void check_density_continuity_at_mt()
Check density at MT boundary.
void initial_density()
Generate initial charge density and magnetization.
void generate_valence_mt()
Generate valence density in the muffin-tins.
std::unique_ptr< Smooth_periodic_function< double > > rho_pseudo_core_
Pointer to pseudo core charge density.
std::unique_ptr< Occupation_matrix > occupation_matrix_
Occupation matrix of the LDA+U method.
void add_k_point_contribution_rg(K_point< T > *kp__, std::array< wf::Wave_functions_fft< T >, 2 > &wf_fft__)
Add k-point contribution to the density and magnetization defined on the regular FFT grid.
std::vector< int > l_by_lm_
Fast mapping between composite lm index and corresponding orbital quantum number.
std::array< std::unique_ptr< Smooth_periodic_function< double > >, 4 > rho_mag_coarse_
Density and magnetization on the coarse FFT mesh.
auto paw_ae_density(int ia__) const
Return list of pointers to all-electron PAW density function for a given local index of atom with PAW...
void generate_valence(K_point_set const &ks__)
Generate valence charge density and magnetization from the wave functions.
void init_density_matrix_for_paw()
Initialize PAW density matrix.
void add_k_point_contribution_dm(K_point< T > &kp__, sddk::mdarray< std::complex< double >, 4 > &density_matrix__)
Add k-point contribution to the density matrix in the canonical form.
void generate(K_point_set const &ks__, bool symmetrize__, bool add_core__, bool transform_to_rg__)
Generate full charge density (valence + core) and magnetization from the wave 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.
K-point related variables and methods.
PAW density and potential storage.
Representation of the periodical function on the muffin-tin geometry.
auto const & gvec() const
Return const reference to Gvec object.
mpi::Communicator const & comm() const
Total communicator of the simulation.
void core_relativity(std::string name__)
Set core relativity for the LAPW method.
int num_mag_dims() const
Number of dimensions in the magnetization vector.
Representation of a unit cell.
Atom_symmetry_class const & atom_symmetry_class(int id__) const
Return const symmetry class instance by class id.
double length() const
Return vector length (L2 norm).
Multidimensional array with the column-major (Fortran) order.
Wave-fucntions in the FFT-friendly distribution.
Base class for sirius::Density and sirius::Potential.
Contains declaration and partial implementation of sirius::K_point_set class.
Generate plane-wave coefficients of the periodic function from the form-factors.
Contains definition and implementation of sirius::Mixer base class.
void copy(T *target__, T const *source__, size_t n__)
Copy memory inside a device.
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.
int sign(T val)
Sign of the variable.
Occupation matrix of the LDA+U method.
Contains definition and implementation of PAW_field4D class.
Contains declaration and partial implementation of sirius::Periodic_function class.