1+ #pragma once
2+ #include " module_lr/utils/gint_template.h"
3+ #include " module_psi/psi.h"
4+ #include " module_lr/Grad/dm_diff/dm_diff.h"
5+ #include " module_lr/utils/lr_util_hcontainer.h"
6+ #include " module_io/cube_io.h"
7+ namespace LR
8+ {
9+ template <typename T>
10+ class LR_Density
11+ {
12+ typename TGint<T>::type* gint_;
13+ const UnitCell& ucell_;
14+ const K_Vectors& kv_;
15+ const Grid_Driver& gd_;
16+ const psi::Psi<T>& psi_ks_;
17+ const std::vector<double >& orb_cutoff_;
18+ const Parallel_Grid& pgrid_;
19+ const int nspin_;
20+ const std::vector<int >& nocc_;
21+ const std::vector<int >& nvirt_;
22+ const int nao_;
23+ const int nk_;
24+ const std::vector<Parallel_2D>& pX_;
25+ const Parallel_2D& pc_;
26+ const Parallel_Orbitals& pmat_;
27+ const bool openshell_;
28+ const std::vector<std::string> spintype_;
29+
30+ inline void dm_to_density (elecstate::DensityMatrix<double , double >& dm, double ** density)
31+ {
32+ ModuleBase::TITLE (" LR_Density" , " dm_to_density" );
33+ this ->gint_ ->transfer_DM2DtoGrid (dm.get_DMR_vector ());
34+ Gint_inout inout_rho (density, Gint_Tools::job_type::rho, 1 , false );
35+ this ->gint_ ->cal_gint (&inout_rho);
36+ }
37+ inline void dm_to_density (elecstate::DensityMatrix<complex <double >, complex <double >>& dm, double ** density)
38+ {
39+ ModuleBase::TITLE (" LR_Density" , " dm_to_density" );
40+ auto dm_to_density_real = [&](const char & part) -> void
41+ {
42+ elecstate::DensityMatrix<std::complex <double >, double > dm_real (&pmat_, 1 , kv_.kvec_d , nk_);
43+ LR_Util::initialize_DMR<std::complex <double >, double >(dm_real, pmat_, ucell_, gd_, orb_cutoff_);
44+ LR_Util::get_DMR_real_imag_part (dm, dm_real, ucell_.nat , part);
45+ this ->gint_ ->transfer_DM2DtoGrid (dm_real.get_DMR_vector ());
46+ Gint_inout inout_rho (density, Gint_Tools::job_type::rho, 1 , false );
47+ this ->gint_ ->cal_gint (&inout_rho); // add-on
48+ };
49+ dm_to_density_real (' R' );
50+ dm_to_density_real (' I' );
51+ }
52+
53+ public:
54+ LR_Density (typename TGint<T>::type* gint,
55+ const UnitCell& ucell,
56+ const K_Vectors& kv,
57+ const Grid_Driver& gd,
58+ const psi::Psi<T>& psi_ks,
59+ const std::vector<double >& orb_cutoff,
60+ const Parallel_Grid& pgrid,
61+ const int & nspin,
62+ const std::vector<int >& nocc,
63+ const std::vector<int >& nvirt,
64+ const int & nao,
65+ const std::vector<Parallel_2D>& pX,
66+ const Parallel_2D& pc,
67+ const Parallel_Orbitals& pmat,
68+ const bool openshell = false ) :
69+ gint_ (gint), ucell_(ucell), kv_(kv), gd_(gd), psi_ks_(psi_ks),
70+ orb_cutoff_ (orb_cutoff), pgrid_(pgrid), nspin_(nspin), nk_(kv.get_nks() / nspin),
71+ nocc_ (nocc), nvirt_(nvirt), nao_(nao), pX_(pX), pc_(pc), pmat_(pmat),
72+ openshell_ (openshell), spintype_(openshell ? std::vector<std::string>({ " up" , " down" }) : std::vector<std::string>({ " singlet" , " triplet" }))
73+ {
74+ }
75+
76+ // / @brief calculate the electron density from the density matrix in 2d-block distribution
77+ void cal_eh_density_single_state (const T* const X_istate, const int ispin, double ** density)
78+ {
79+ ModuleBase::TITLE (" LR_Density" , " cal_eh_density_single_state" );
80+ ModuleBase::GlobalFunc::ZEROS (density[0 ], this ->pgrid_ .get_nrxx ());
81+ // 1. calculate the density matrix in AO basis
82+ auto c_spin = LR_Util::get_psi_spin (psi_ks_, ispin,nk_);
83+ const std::vector<ct::Tensor> dm_diff_k =
84+ cal_dm_diff_pblas<T>(X_istate, pX_[ispin], c_spin, pc_, nao_, nocc_[ispin], nvirt_[ispin], pmat_);
85+ // 2. calculate DM(R)
86+ elecstate::DensityMatrix<T, T> dm_diff=
87+ LR_Util::build_dm_from_dmk<T, T>(dm_diff_k,
88+ this ->pmat_ , this ->nk_ , this ->kv_ .kvec_d , this ->ucell_ , this ->gd_ , this ->orb_cutoff_ , /* symmetrize=*/ false );
89+ // 3. calculate electron density from DM(R)
90+ this ->dm_to_density (dm_diff, density);
91+ }
92+
93+ void write_density_single_state (const double * const * const density, const std::string& filepath)
94+ {
95+ ModuleIO::write_vdata_palgrid (pgrid_, density[0 ], 0 , 1 , 0 , filepath, 0.0 , &ucell_, PARAM.inp .out_chg [1 ], 0 );
96+ }
97+
98+ void output_eh_density_all_states (const T* const X, const int ispin, const int nstate)
99+ {
100+ ModuleBase::TITLE (" LR_Density" , " cal_eh_density_all_states" );
101+ const int offset_per_state = openshell_ ?
102+ this ->nk_ * (this ->pX_ [0 ].get_local_size () + this ->pX_ [1 ].get_local_size ())
103+ : this ->nk_ * this ->pX_ [ispin].get_local_size ();
104+ double ** density;
105+ LR_Util::_allocate_2order_nested_ptr (density, 1 , pgrid_.get_nrxx ());
106+ for (int istate = 0 ;istate < nstate;++istate)
107+ {
108+ int offset = istate * offset_per_state;
109+ if (openshell_)
110+ offset += ispin * this ->pX_ [0 ].get_local_size ();
111+ this ->cal_eh_density_single_state (X + offset, ispin, density);
112+ const std::string filepath = PARAM.globalv .global_out_dir + " LR_e-h_density_" + spintype_[ispin] + " _" + std::to_string (istate + 1 ) + " .cube" ;
113+ this ->write_density_single_state (density, filepath);
114+ }
115+ LR_Util::_deallocate_2order_nested_ptr (density, 1 );
116+ }
117+ };
118+
119+ }
0 commit comments