11#include " cal_ldos.h"
22
33#include " cube_io.h"
4+ #include " module_base/blas_connector.h"
5+ #include " module_base/scalapack_connector.h"
6+
7+ #include < type_traits>
48
59namespace ModuleIO
610{
7- void cal_ldos (const elecstate::ElecStatePW<std::complex <double >>* pelec,
8- const psi::Psi<std::complex <double >>& psi,
9- const Parallel_Grid& pgrid,
10- const UnitCell& ucell)
11+ template <typename T>
12+ void Cal_ldos<T>::cal_ldos_pw(const elecstate::ElecStatePW<std::complex <double >>* pelec,
13+ const psi::Psi<std::complex <double >>& psi,
14+ const Parallel_Grid& pgrid,
15+ const UnitCell& ucell)
1116{
1217 // energy range for ldos (efermi as reference)
1318 const double emin = PARAM.inp .stm_bias < 0 ? PARAM.inp .stm_bias : 0 ;
@@ -19,13 +24,13 @@ void cal_ldos(const elecstate::ElecStatePW<std::complex<double>>* pelec,
1924 for (int ik = 0 ; ik < pelec->klist ->get_nks (); ++ik)
2025 {
2126 psi.fix_k (ik);
22- double efermi = pelec->eferm .get_efval (pelec->klist ->isk [ik]);
27+ const double efermi = pelec->eferm .get_efval (pelec->klist ->isk [ik]);
2328 int nbands = psi.get_nbands ();
2429
2530 for (int ib = 0 ; ib < nbands; ib++)
2631 {
2732 pelec->basis ->recip2real (&psi (ib, 0 ), wfcr.data (), ik);
28- double eigenval = (pelec->ekb (ik, ib) - efermi) * ModuleBase::Ry_to_eV;
33+ const double eigenval = (pelec->ekb (ik, ib) - efermi) * ModuleBase::Ry_to_eV;
2934 if (eigenval >= emin && eigenval <= emax)
3035 {
3136 for (int ir = 0 ; ir < pelec->basis ->nrxx ; ir++)
@@ -38,18 +43,90 @@ void cal_ldos(const elecstate::ElecStatePW<std::complex<double>>* pelec,
3843 fn << PARAM.globalv .global_out_dir << " LDOS_" << PARAM.inp .stm_bias << " eV"
3944 << " .cube" ;
4045
41- ModuleIO::write_vdata_palgrid (pgrid, ldos.data (), 0 , PARAM.inp .nspin , 0 , fn.str (), 0 , &ucell, 11 , 0 );
46+ const int precision = PARAM.inp .out_ldos [1 ];
47+ ModuleIO::write_vdata_palgrid (pgrid, ldos.data (), 0 , PARAM.inp .nspin , 0 , fn.str (), 0 , &ucell, precision, 0 );
4248}
4349
4450#ifdef __LCAO
45- // lcao multi-k case
46- // void cal_ldos(elecstate::ElecState* pelec, const psi::Psi<std::complex<double>>& psi, std::vector<double>& ldos)
47- // {
48- // }
49-
50- // // lcao Gamma_only case
51- // void cal_ldos(elecstate::ElecState* pelec, const psi::Psi<double>& psi, std::vector<double>& ldos)
52- // {
53- // }
51+ template <typename T>
52+ void Cal_ldos<T>::cal_ldos_lcao(const elecstate::ElecStateLCAO<T>* pelec,
53+ const psi::Psi<T>& psi,
54+ const Parallel_Grid& pgrid,
55+ const UnitCell& ucell)
56+ {
57+ // energy range for ldos (efermi as reference)
58+ const double emin = PARAM.inp .stm_bias < 0 ? PARAM.inp .stm_bias : 0 ;
59+ const double emax = PARAM.inp .stm_bias > 0 ? PARAM.inp .stm_bias : 0 ;
60+
61+ // calulate dm-like
62+ const int nbands_local = psi.get_nbands ();
63+ const int nbasis_local = psi.get_nbasis ();
64+
65+ // psi.T * wk * psi.conj()
66+ // result[ik](iw1,iw2) = \sum_{ib} psi[ik](ib,iw1).T * wk(k) * psi[ik](ib,iw2).conj()
67+ for (int ik = 0 ; ik < psi.get_nk (); ++ik)
68+ {
69+ psi.fix_k (ik);
70+ const double efermi = pelec->eferm .get_efval (pelec->klist ->isk [ik]);
71+
72+ // T* dmk_pointer = DM.get_DMK_pointer(ik);
73+
74+ psi::Psi<T> wk_psi (1 , psi.get_nbands (), psi.get_nbasis (), psi.get_nbasis (), true );
75+ const T* ppsi = psi.get_pointer ();
76+ T* pwk_psi = wk_psi.get_pointer ();
77+
78+ // #ifdef _OPENMP
79+ // #pragma omp parallel for schedule(static, 1024)
80+ // #endif
81+ // for (int i = 0; i < wk_psi.size(); ++i)
82+ // {
83+ // pwk_psi[i] = my_conj(ppsi[i]);
84+ // }
85+
86+ // int ib_global = 0;
87+ // for (int ib_local = 0; ib_local < nbands_local; ++ib_local)
88+ // {
89+ // while (ib_local != ParaV->global2local_col(ib_global))
90+ // {
91+ // ++ib_global;
92+ // if (ib_global >= wg.nc)
93+ // {
94+ // ModuleBase::WARNING_QUIT("cal_ldos", "please check global2local_col!");
95+ // }
96+ // }
97+
98+ // const double eigenval = (pelec->ekb(ik, ib_global) - efermi) * ModuleBase::Ry_to_eV;
99+ // if (eigenval >= emin && eigenval <= emax)
100+ // {
101+ // for (int ir = 0; ir < pelec->basis->nrxx; ir++)
102+ // ldos[ir] += pelec->klist->wk[ik] * norm(wfcr[ir]);
103+ // }
104+
105+ // double* wg_wfc_pointer = &(wk_psi(0, ib_local, 0));
106+ // BlasConnector::scal(nbasis_local, pelec->klist->wk[ik], wg_wfc_pointer, 1);
107+ // }
108+
109+ // // C++: dm(iw1,iw2) = psi(ib,iw1).T * wk_psi(ib,iw2)
110+ // #ifdef __MPI
111+ // psiMulPsiMpi(wk_psi, psi, dmk_pointer, ParaV->desc_wfc, ParaV->desc);
112+ // #else
113+ // psiMulPsi(wk_psi, psi, dmk_pointer);
114+ // #endif
115+ }
116+ }
117+
118+ double my_conj (double x)
119+ {
120+ return x;
121+ }
122+
123+ std::complex <double > my_conj (const std::complex <double >& z)
124+ {
125+ return {z.real (), -z.imag ()};
126+ }
127+
54128#endif
129+
130+ template class Cal_ldos <double >; // Gamma_only case
131+ template class Cal_ldos <std::complex <double >>; // multi-k case
55132} // namespace elecstate
0 commit comments