From b9e83cb10d0c021e000f66d8e02b208d343ba0bd Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Wed, 14 May 2025 20:34:34 +0800 Subject: [PATCH 1/8] Feature: Support cube format real-space wave function output for Plane Wave basis set --- docs/advanced/input_files/input-main.md | 6 +- source/module_esolver/esolver_ks_pw.cpp | 37 +++- source/module_io/get_wf_lcao.cpp | 239 ++++++++++++------------ source/module_io/get_wf_pw.h | 221 ++++++++++++++++++++++ 4 files changed, 381 insertions(+), 122 deletions(-) create mode 100644 source/module_io/get_wf_pw.h diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index 182f569b16..298b761d24 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -1670,7 +1670,7 @@ These variables are used to control the output of properties. - 2: results are stored in binary files named `OUT.${suffix}/WAVEFUNC${K}.dat`. - **Default**: 0 -### out_wfc_r +### out_wfc_r (deprecated) - **Type**: Boolean - **Availability**: Plane wave basis or get_wf calculation in numerical atomic orbital basis @@ -1911,14 +1911,14 @@ The band (KS orbital) energy for each (k-point, spin, band) will be printed in t ### out_wfc_norm - **Type**: String -- **Availability**: For LCAO, used when `calculation = get_wf`. +- **Availability**: For both PW and LCAO. When `basis_type = lcao`, used when `calculation = get_wf`. - **Description**: Specifies the bands to calculate the real-space wave function modulus (norm, or known as the envelope function) $|\psi(r)|$. The syntax and band selection rules are identical to [`out_pchg`](#out_pchg), but the output is the norm of the wave function. - **Default**: none ### out_wfc_re_im - **Type**: String -- **Availability**: For LCAO, used when `calculation = get_wf`. +- **Availability**: For both PW and LCAO. When `basis_type = lcao`, used when `calculation = get_wf`. - **Description**: Specifies the bands to calculate the real and imaginary parts of the wave function $\text{Re}(\psi(r))$ and $\text{Im}(\psi(r))$. The syntax and band selection rules are identical to [`out_pchg`](#out_pchg), but the output contains both the real and imaginary components of the wave function. - **Default**: none diff --git a/source/module_esolver/esolver_ks_pw.cpp b/source/module_esolver/esolver_ks_pw.cpp index fd080070e8..c742133831 100644 --- a/source/module_esolver/esolver_ks_pw.cpp +++ b/source/module_esolver/esolver_ks_pw.cpp @@ -24,6 +24,7 @@ #include "module_io/berryphase.h" #include "module_io/cal_ldos.h" #include "module_io/get_pchg_pw.h" +#include "module_io/get_wf_pw.h" #include "module_io/numerical_basis.h" #include "module_io/numerical_descriptor.h" #include "module_io/to_wannier90_pw.h" @@ -933,9 +934,41 @@ void ESolver_KS_PW::after_all_runners(UnitCell& ucell) //---------------------------------------------------------- //! 5) Print out electronic wave functions in real space //---------------------------------------------------------- - if (PARAM.inp.out_wfc_r == 1) // Peize Lin add 2021.11.21 + + //---------------------------------------------------------- + //! The write_psi_r_1 interface will be removed in the very + //! near future. Don't use it! + //---------------------------------------------------------- + // if (PARAM.inp.out_wfc_r == 1) // Peize Lin add 2021.11.21 + // { + // ModuleIO::write_psi_r_1(ucell, this->psi[0], this->pw_wfc, "wfc_realspace", true, this->kv); + // } + + const std::vector out_wfc_norm = PARAM.inp.out_wfc_norm; + const std::vector out_wfc_re_im = PARAM.inp.out_wfc_re_im; + if (out_wfc_norm.size() > 0) { - ModuleIO::write_psi_r_1(ucell, this->psi[0], this->pw_wfc, "wfc_realspace", true, this->kv); + ModuleIO::get_wf_pw(out_wfc_norm, + out_wfc_re_im, + this->kspw_psi->get_nbands(), + PARAM.inp.nspin, + this->pw_rhod->nx, + this->pw_rhod->ny, + this->pw_rhod->nz, + this->pw_rhod->nxyz, + this->kv.get_nks(), + this->kv.isk, + this->kv.wk, + this->pw_big->bz, + this->pw_big->nbz, + this->chr.ngmc, + &ucell, + this->psi, + this->pw_rhod, + this->pw_wfc, + this->ctx, + this->Pgrid, + PARAM.globalv.global_out_dir); } //---------------------------------------------------------- diff --git a/source/module_io/get_wf_lcao.cpp b/source/module_io/get_wf_lcao.cpp index b62ac097ce..45e13f0abe 100644 --- a/source/module_io/get_wf_lcao.cpp +++ b/source/module_io/get_wf_lcao.cpp @@ -21,27 +21,27 @@ Get_wf_lcao::~Get_wf_lcao() // For gamma_only void Get_wf_lcao::begin(const UnitCell& ucell, - const psi::Psi* psid, - const ModulePW::PW_Basis* pw_rhod, - const ModulePW::PW_Basis_K* pw_wfc, - const ModulePW::PW_Basis_Big* pw_big, - const Parallel_Grid& pgrid, - const Parallel_Orbitals& para_orb, - Gint_Gamma& gg, - const int& out_wfc_pw, - const int& out_wfc_r, - const K_Vectors& kv, - const double nelec, - const int nbands_istate, - const std::vector& out_wfc_norm, - const std::vector& out_wfc_re_im, - const int nbands, - const int nspin, - const int nlocal, - const std::string& global_out_dir) + const psi::Psi* psid, + const ModulePW::PW_Basis* pw_rhod, + const ModulePW::PW_Basis_K* pw_wfc, + const ModulePW::PW_Basis_Big* pw_big, + const Parallel_Grid& pgrid, + const Parallel_Orbitals& para_orb, + Gint_Gamma& gg, + const int& out_wfc_pw, + const int& out_wfc_r, + const K_Vectors& kv, + const double nelec, + const int nbands_istate, + const std::vector& out_wfc_norm, + const std::vector& out_wfc_re_im, + const int nbands, + const int nspin, + const int nlocal, + const std::string& global_out_dir) { ModuleBase::TITLE("Get_wf_lcao", "begin"); - + int fermi_band = 0; prepare_get_wf(GlobalV::ofs_running, nelec, fermi_band); @@ -97,8 +97,8 @@ void Get_wf_lcao::begin(const UnitCell& ucell, #ifdef __MPI wfc_2d_to_grid(psid->get_pointer(), para_orb, wfc_gamma_grid[is], gg.gridt->trace_lo); #else - // if not MPI enabled, it is the case psid holds a global matrix. - // use fix_k to switch between different spin channels (actually kpoints, + // if not MPI enabled, it is the case psid holds a global matrix. + // use fix_k to switch between different spin channels (actually kpoints, // because now the same kpoint in different spin channels are treated // as distinct kpoints) @@ -117,17 +117,16 @@ void Get_wf_lcao::begin(const UnitCell& ucell, // pint out information std::stringstream ss_file; - ss_file << "wf" << ib + 1 << "s" << is + 1 << ".cube"; + ss_file << "wf" << ib + 1 << "s" << is + 1 << ".cube"; std::stringstream ss_out; ss_out << global_out_dir << ss_file.str(); std::stringstream ss_info; - ss_info << "Wave func. " << ib+1 << " spin " << is+1 << " saved in"; + ss_info << "Wave func. " << ib + 1 << " spin " << is + 1 << " saved in"; ModuleBase::GlobalFunc::OUT(GlobalV::ofs_running, ss_info.str(), ss_file.str()); - const double ef_tmp = this->pes_->eferm.get_efval(is); ModuleIO::write_vdata_palgrid(pgrid, pes_->charge->rho_save[is], @@ -268,24 +267,24 @@ void Get_wf_lcao::begin(const UnitCell& ucell, // For multi-k void Get_wf_lcao::begin(const UnitCell& ucell, - const psi::Psi>* psi, - const ModulePW::PW_Basis* pw_rhod, - const ModulePW::PW_Basis_K* pw_wfc, - const ModulePW::PW_Basis_Big* pw_big, - const Parallel_Grid& pgrid, - const Parallel_Orbitals& para_orb, - Gint_k& gk, - const int& out_wf, - const int& out_wf_r, - const K_Vectors& kv, - const double nelec, - const int nbands_istate, - const std::vector& out_wfc_norm, - const std::vector& out_wfc_re_im, - const int nbands, - const int nspin, - const int nlocal, - const std::string& global_out_dir) + const psi::Psi>* psi, + const ModulePW::PW_Basis* pw_rhod, + const ModulePW::PW_Basis_K* pw_wfc, + const ModulePW::PW_Basis_Big* pw_big, + const Parallel_Grid& pgrid, + const Parallel_Orbitals& para_orb, + Gint_k& gk, + const int& out_wf, + const int& out_wf_r, + const K_Vectors& kv, + const double nelec, + const int nbands_istate, + const std::vector& out_wfc_norm, + const std::vector& out_wfc_re_im, + const int nbands, + const int nspin, + const int nlocal, + const std::string& global_out_dir) { ModuleBase::TITLE("Get_wf_lcao", "begin"); @@ -343,7 +342,6 @@ void Get_wf_lcao::begin(const UnitCell& ucell, ModuleBase::GlobalFunc::ZEROS(pes_->charge->rho[ispin], pw_wfc->nrxx); // terrible, you make changes on another instance's data??? - // 2d-to-grid conversion is unified into `wfc_2d_to_grid`. psi->fix_k(ik); @@ -352,39 +350,35 @@ void Get_wf_lcao::begin(const UnitCell& ucell, #else for (int i = 0; i < nbands; ++i) { - for (int j = 0; j < nlocal; ++j) - { - wfc_k_grid[ik][i][j] = psi[0](i, j); - } + for (int j = 0; j < nlocal; ++j) + { + wfc_k_grid[ik][i][j] = psi[0](i, j); + } } #endif // deal with NSPIN=4 gk.cal_env_k(ik, wfc_k_grid[ik][ib], pes_->charge->rho[ispin], kv.kvec_c, kv.kvec_d, ucell); - - // ik0 is the real k-point index, starting from 0 - int ik0 = kv.ik2iktot[ik]; - if(nspin == 2) - { - const int half_k = kv.get_nkstot()/2; - if(ik0 >= half_k) - { - ik0 -= half_k; - } - } + // ik0 is the real k-point index, starting from 0 + int ik0 = kv.ik2iktot[ik]; + if (nspin == 2) + { + const int half_k = kv.get_nkstot() / 2; + if (ik0 >= half_k) + { + ik0 -= half_k; + } + } // pint out information std::stringstream ss_file; - ss_file << "wf" << ib+1 << "s" << ispin + 1 << "k" << ik0+1 << ".cube"; + ss_file << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << ".cube"; std::stringstream ss_out; ss_out << global_out_dir << ss_file.str(); std::stringstream ss_info; - ss_info << "Wave func. " << ib+1 - << " spin " << ispin+1 - << " k-point " << ik0+1 - << " saved in"; + ss_info << "Wave func. " << ib + 1 << " spin " << ispin + 1 << " k-point " << ik0 + 1 << " saved in"; ModuleBase::GlobalFunc::OUT(GlobalV::ofs_running, ss_info.str(), ss_file.str()); @@ -453,10 +447,20 @@ void Get_wf_lcao::begin(const UnitCell& ucell, wfc_imag[ir] = wfc_r[ir].imag(); } - // Output real part + // ik0 is the real k-point index, starting from 0 + int ik0 = kv.ik2iktot[ik]; + if (nspin == 2) + { + const int half_k = kv.get_nkstot() / 2; + if (ik0 >= half_k) + { + ik0 -= half_k; + } + } + // Output real part std::stringstream ss_real; - ss_real << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik+1 << "real.cube"; + ss_real << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << "real.cube"; const double ef_tmp = this->pes_->eferm.get_efval(ispin); ModuleIO::write_vdata_palgrid(pgrid, @@ -470,7 +474,7 @@ void Get_wf_lcao::begin(const UnitCell& ucell, // Output imaginary part std::stringstream ss_imag; - ss_imag << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik+1 << "imag.cube"; + ss_imag << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << "imag.cube"; ModuleIO::write_vdata_palgrid(pgrid, wfc_imag.data(), ispin, @@ -497,11 +501,11 @@ void Get_wf_lcao::begin(const UnitCell& ucell, } void Get_wf_lcao::select_bands(const int nbands_istate, - const std::vector& out_wfc_kb, - const int nbands, - const double nelec, - const int mode, - const int fermi_band) + const std::vector& out_wfc_kb, + const int nbands, + const double nelec, + const int mode, + const int fermi_band) { ModuleBase::TITLE("Get_wf_lcao", "select_bands"); @@ -610,11 +614,11 @@ void Get_wf_lcao::select_bands(const int nbands_istate, // for each band void Get_wf_lcao::set_pw_wfc(const ModulePW::PW_Basis_K* pw_wfc, - const int& ik, - const int& ib, - const int& nspin, - const double* const* const rho, - psi::Psi>& wfc_g) + const int& ik, + const int& ib, + const int& nspin, + const double* const* const rho, + psi::Psi>& wfc_g) { if (ib == 0) { @@ -640,14 +644,14 @@ void Get_wf_lcao::set_pw_wfc(const ModulePW::PW_Basis_K* pw_wfc, #ifdef __MPI template int Get_wf_lcao::set_wfc_grid(const int naroc[2], - const int nb, - const int dim0, - const int dim1, - const int iprow, - const int ipcol, - const T* in, - T** out, - const std::vector& trace_lo) + const int nb, + const int dim0, + const int dim1, + const int iprow, + const int ipcol, + const T* in, + T** out, + const std::vector& trace_lo) { ModuleBase::TITLE(" Local_Orbital_wfc", "set_wfc_grid"); if (!out) @@ -675,29 +679,29 @@ int Get_wf_lcao::set_wfc_grid(const int naroc[2], } template int Get_wf_lcao::set_wfc_grid(const int naroc[2], - const int nb, - const int dim0, - const int dim1, - const int iprow, - const int ipcol, - const double* in, - double** out, - const std::vector& trace_lo); + const int nb, + const int dim0, + const int dim1, + const int iprow, + const int ipcol, + const double* in, + double** out, + const std::vector& trace_lo); template int Get_wf_lcao::set_wfc_grid(const int naroc[2], - const int nb, - const int dim0, - const int dim1, - const int iprow, - const int ipcol, - const std::complex* in, - std::complex** out, - const std::vector& trace_lo); + const int nb, + const int dim0, + const int dim1, + const int iprow, + const int ipcol, + const std::complex* in, + std::complex** out, + const std::vector& trace_lo); template void Get_wf_lcao::wfc_2d_to_grid(const T* lowf_2d, - const Parallel_Orbitals& pv, - T** lowf_grid, - const std::vector& trace_lo) + const Parallel_Orbitals& pv, + T** lowf_grid, + const std::vector& trace_lo) { ModuleBase::TITLE(" Local_Orbital_wfc", "wfc_2d_to_grid"); ModuleBase::timer::tick("Local_Orbital_wfc", "wfc_2d_to_grid"); @@ -763,33 +767,36 @@ void Get_wf_lcao::wfc_2d_to_grid(const T* lowf_2d, } template void Get_wf_lcao::wfc_2d_to_grid(const double* lowf_2d, - const Parallel_Orbitals& pv, - double** lowf_grid, - const std::vector& trace_lo); + const Parallel_Orbitals& pv, + double** lowf_grid, + const std::vector& trace_lo); template void Get_wf_lcao::wfc_2d_to_grid(const std::complex* lowf_2d, - const Parallel_Orbitals& pv, - std::complex** lowf_grid, - const std::vector& trace_lo); + const Parallel_Orbitals& pv, + std::complex** lowf_grid, + const std::vector& trace_lo); #endif - -void Get_wf_lcao::prepare_get_wf(std::ofstream &ofs_running, const int nelec, int& fermi_band) +void Get_wf_lcao::prepare_get_wf(std::ofstream& ofs_running, const int nelec, int& fermi_band) { ofs_running << "\n\n"; ofs_running << " GET_WF CALCULATIONS BEGINS" << std::endl; ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" - ">>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl; + ">>>>>>>>>>>>>>>>>>>>>>>>>" + << std::endl; ofs_running << " | " - " |" << std::endl; + " |" + << std::endl; ofs_running << " | Here we use real-space (r) grid integral technique to calculate |" << std::endl; ofs_running << " | the electronic wave function psi(i,r) for each electronic state i. |" << std::endl; ofs_running << " | The |psi(i, r)|, Re[psi(i, r)], Im[psi(i, r)] are printed out |" << std::endl; ofs_running << " | using numerical atomic orbitals as basis set. |" << std::endl; ofs_running << " | " - " |" << std::endl; + " |" + << std::endl; ofs_running << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" - ">>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl; + ">>>>>>>>>>>>>>>>>>>>>>>>>" + << std::endl; ofs_running << "\n\n"; @@ -803,8 +810,6 @@ void Get_wf_lcao::prepare_get_wf(std::ofstream &ofs_running, const int nelec, in ModuleBase::GlobalFunc::OUT(ofs_running, "Number of occupied bands", fermi_band); } - - int Get_wf_lcao::globalIndex(int localindex, int nblk, int nprocs, int myproc) { const int iblock = localindex / nblk; diff --git a/source/module_io/get_wf_pw.h b/source/module_io/get_wf_pw.h new file mode 100644 index 0000000000..29b831f786 --- /dev/null +++ b/source/module_io/get_wf_pw.h @@ -0,0 +1,221 @@ +#ifndef GET_WF_PW_H +#define GET_WF_PW_H + +#include "cube_io.h" +#include "module_base/module_device/device.h" +#include "module_base/tool_quit.h" +#include "module_basis/module_pw/pw_basis.h" +#include "module_basis/module_pw/pw_basis_k.h" +#include "module_cell/unitcell.h" +#include "module_elecstate/elecstate.h" +#include "module_elecstate/module_charge/symmetry_rho.h" +#include "module_hamilt_pw/hamilt_pwdft/parallel_grid.h" +#include "module_psi/psi.h" + +#include +#include + +namespace ModuleIO +{ +template +void get_wf_pw(const std::vector& out_wfc_norm, + const std::vector& out_wfc_re_im, + const int nbands, + const int nspin, + const int nx, + const int ny, + const int nz, + const int nxyz, + const int nks, + const std::vector& isk, + const std::vector& wk, + const int pw_big_bz, + const int pw_big_nbz, + const int ngmc, + UnitCell* ucell, + const psi::Psi>* psi, + const ModulePW::PW_Basis* pw_rhod, + const ModulePW::PW_Basis_K* pw_wfc, + const Device* ctx, + const Parallel_Grid& pgrid, + const std::string& global_out_dir) +{ + // bands_picked is a vector of 0s and 1s, where 1 means the band is picked to output + std::vector bands_picked_norm(nbands, 0); + std::vector bands_picked_re_im(nbands, 0); + + // Check if length of out_wfc_norm and out_wfc_re_im is valid + if (static_cast(out_wfc_norm.size()) > nbands || static_cast(out_wfc_re_im.size()) > nbands) + { + ModuleBase::WARNING_QUIT("ModuleIO::get_wf_pw", + "The number of bands specified by `out_wfc_norm` or `out_wfc_re_im` in the " + "INPUT file exceeds `nbands`!"); + } + + // Check if all elements in bands_picked are 0 or 1 + for (int value: out_wfc_norm) + { + if (value != 0 && value != 1) + { + ModuleBase::WARNING_QUIT("ModuleIO::get_wf_pw", + "The elements of `out_wfc_norm` must be either 0 or 1. " + "Invalid values found!"); + } + } + for (int value: out_wfc_re_im) + { + if (value != 0 && value != 1) + { + ModuleBase::WARNING_QUIT("ModuleIO::get_wf_pw", + "The elements of `out_wfc_re_im` must be either 0 or 1. " + "Invalid values found!"); + } + } + + // Fill bands_picked with values from out_wfc_norm + // Remaining bands are already set to 0 + int length = std::min(static_cast(out_wfc_norm.size()), nbands); + for (int i = 0; i < length; ++i) + { + // out_wfc_norm rely on function parse_expression + bands_picked_norm[i] = static_cast(out_wfc_norm[i]); + } + length = std::min(static_cast(out_wfc_re_im.size()), nbands); + for (int i = 0; i < length; ++i) + { + bands_picked_re_im[i] = static_cast(out_wfc_re_im[i]); + } + + std::vector> wfcr_norm(nxyz); + std::vector> rho_band_norm(nspin, std::vector(nxyz)); + + for (int ib = 0; ib < nbands; ++ib) + { + // Skip the loop iteration if bands_picked[ib] is 0 + if (!bands_picked_norm[ib]) + { + continue; + } + + for (int is = 0; is < nspin; ++is) + { + std::fill(rho_band_norm[is].begin(), rho_band_norm[is].end(), 0.0); + } + for (int ik = 0; ik < nks; ++ik) + { + const int spin_index = isk[ik]; + std::cout << " Calculating wave function norm for band " << ib + 1 << ", k-point " << ik % (nks / nspin) + 1 + << ", spin " << spin_index + 1 << std::endl; + + psi->fix_k(ik); + pw_wfc->recip_to_real(ctx, &psi[0](ib, 0), wfcr_norm.data(), ik); + + // To ensure the normalization of charge density in multi-k calculation + double wg_sum_k = 0; + for (int ik_tmp = 0; ik_tmp < nks / nspin; ++ik_tmp) + { + wg_sum_k += wk[ik_tmp]; + } + + double w1 = static_cast(wg_sum_k / ucell->omega); + + for (int i = 0; i < nxyz; ++i) + { + rho_band_norm[spin_index][i] = std::abs(wfcr_norm[i]) * std::sqrt(w1); + } + + std::cout << " Writing cube files..."; + + std::stringstream ss_file; + ss_file << global_out_dir << "wf" << ib + 1 << "s" << spin_index + 1 << "k" << ik % (nks / nspin) + 1 + << ".cube"; + + ModuleIO::write_vdata_palgrid(pgrid, + rho_band_norm[spin_index].data(), + spin_index, + nspin, + 0, + ss_file.str(), + 0.0, + ucell); + + std::cout << " Complete!" << std::endl; + } + } + + std::vector> wfc_re_im(nxyz); + std::vector> rho_band_re(nspin, std::vector(nxyz)); + std::vector> rho_band_im(nspin, std::vector(nxyz)); + + for (int ib = 0; ib < nbands; ++ib) + { + // Skip the loop iteration if bands_picked[ib] is 0 + if (!bands_picked_re_im[ib]) + { + continue; + } + + for (int is = 0; is < nspin; ++is) + { + std::fill(rho_band_re[is].begin(), rho_band_re[is].end(), 0.0); + std::fill(rho_band_im[is].begin(), rho_band_im[is].end(), 0.0); + } + for (int ik = 0; ik < nks; ++ik) + { + const int spin_index = isk[ik]; + std::cout << " Calculating wave function real and imaginary part for band " << ib + 1 << ", k-point " + << ik % (nks / nspin) + 1 << ", spin " << spin_index + 1 << std::endl; + + psi->fix_k(ik); + pw_wfc->recip_to_real(ctx, &psi[0](ib, 0), wfc_re_im.data(), ik); + + // To ensure the normalization of charge density in multi-k calculation + double wg_sum_k = 0; + for (int ik_tmp = 0; ik_tmp < nks / nspin; ++ik_tmp) + { + wg_sum_k += wk[ik_tmp]; + } + + double w1 = static_cast(wg_sum_k / ucell->omega); + + for (int i = 0; i < nxyz; ++i) + { + rho_band_re[spin_index][i] = std::real(wfc_re_im[i]) * std::sqrt(w1); + rho_band_im[spin_index][i] = std::imag(wfc_re_im[i]) * std::sqrt(w1); + } + + std::cout << " Writing cube files..."; + + std::stringstream ss_real; + ss_real << global_out_dir << "wf" << ib + 1 << "s" << spin_index + 1 << "k" << ik % (nks / nspin) + 1 + << "real.cube"; + + ModuleIO::write_vdata_palgrid(pgrid, + rho_band_re[spin_index].data(), + spin_index, + nspin, + 0, + ss_real.str(), + 0.0, + ucell); + + std::stringstream ss_imag; + ss_imag << global_out_dir << "wf" << ib + 1 << "s" << spin_index + 1 << "k" << ik % (nks / nspin) + 1 + << "imag.cube"; + + ModuleIO::write_vdata_palgrid(pgrid, + rho_band_im[spin_index].data(), + spin_index, + nspin, + 0, + ss_imag.str(), + 0.0, + ucell); + + std::cout << " Complete!" << std::endl; + } + } +} +} // namespace ModuleIO + +#endif // GET_WF_PW_H \ No newline at end of file From 26a45eedac59a7316404097097d60241be280989 Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Wed, 14 May 2025 20:36:54 +0800 Subject: [PATCH 2/8] Keep out_wfc_r temporarily --- source/module_esolver/esolver_ks_pw.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/module_esolver/esolver_ks_pw.cpp b/source/module_esolver/esolver_ks_pw.cpp index c742133831..afbfe201c6 100644 --- a/source/module_esolver/esolver_ks_pw.cpp +++ b/source/module_esolver/esolver_ks_pw.cpp @@ -939,10 +939,10 @@ void ESolver_KS_PW::after_all_runners(UnitCell& ucell) //! The write_psi_r_1 interface will be removed in the very //! near future. Don't use it! //---------------------------------------------------------- - // if (PARAM.inp.out_wfc_r == 1) // Peize Lin add 2021.11.21 - // { - // ModuleIO::write_psi_r_1(ucell, this->psi[0], this->pw_wfc, "wfc_realspace", true, this->kv); - // } + if (PARAM.inp.out_wfc_r == 1) // Peize Lin add 2021.11.21 + { + ModuleIO::write_psi_r_1(ucell, this->psi[0], this->pw_wfc, "wfc_realspace", true, this->kv); + } const std::vector out_wfc_norm = PARAM.inp.out_wfc_norm; const std::vector out_wfc_re_im = PARAM.inp.out_wfc_re_im; From 5169e2821306372a83e9f7a4601b2291eecf69d0 Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Thu, 15 May 2025 20:14:17 +0800 Subject: [PATCH 3/8] Remove out_wfc_r from PW code --- source/module_esolver/esolver_ks_pw.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/module_esolver/esolver_ks_pw.cpp b/source/module_esolver/esolver_ks_pw.cpp index afbfe201c6..f41d5e88da 100644 --- a/source/module_esolver/esolver_ks_pw.cpp +++ b/source/module_esolver/esolver_ks_pw.cpp @@ -939,14 +939,14 @@ void ESolver_KS_PW::after_all_runners(UnitCell& ucell) //! The write_psi_r_1 interface will be removed in the very //! near future. Don't use it! //---------------------------------------------------------- - if (PARAM.inp.out_wfc_r == 1) // Peize Lin add 2021.11.21 - { - ModuleIO::write_psi_r_1(ucell, this->psi[0], this->pw_wfc, "wfc_realspace", true, this->kv); - } + // if (PARAM.inp.out_wfc_r == 1) // Peize Lin add 2021.11.21 + // { + // ModuleIO::write_psi_r_1(ucell, this->psi[0], this->pw_wfc, "wfc_realspace", true, this->kv); + // } const std::vector out_wfc_norm = PARAM.inp.out_wfc_norm; const std::vector out_wfc_re_im = PARAM.inp.out_wfc_re_im; - if (out_wfc_norm.size() > 0) + if (out_wfc_norm.size() > 0 || out_wfc_re_im.size() > 0) { ModuleIO::get_wf_pw(out_wfc_norm, out_wfc_re_im, From 73f862d61e5a855cd14d8bd27054058d4dd26f7f Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Thu, 15 May 2025 20:17:03 +0800 Subject: [PATCH 4/8] Remove out_wfc_r from LCAO code --- source/module_io/get_wf_lcao.cpp | 110 +++++++++++++------------------ 1 file changed, 46 insertions(+), 64 deletions(-) diff --git a/source/module_io/get_wf_lcao.cpp b/source/module_io/get_wf_lcao.cpp index 45e13f0abe..bd951c21c4 100644 --- a/source/module_io/get_wf_lcao.cpp +++ b/source/module_io/get_wf_lcao.cpp @@ -58,10 +58,9 @@ void Get_wf_lcao::begin(const UnitCell& ucell, // for pw_wfc in G space psi::Psi> psi_g; - if (out_wfc_pw || out_wfc_r) - { - psi_g.resize(nspin, nbands, kv.ngk[0]); - } + + // if (out_wfc_pw || out_wfc_r) + psi_g.resize(nspin, nbands, kv.ngk[0]); const double mem_size = sizeof(double) * double(gg.gridt->lgd) * double(nbands) * double(nspin) / 1024.0 / 1024.0; ModuleBase::Memory::record("Get_wf_lcao::begin", mem_size); @@ -158,84 +157,67 @@ void Get_wf_lcao::begin(const UnitCell& ucell, // Set this->bands_picked_ according to the mode this->select_bands(nbands_istate, out_wfc_re_im, nbands, nelec, mode_re_im, fermi_band); - if (out_wfc_pw || out_wfc_r) + // Calculate out_wfc_re_im + for (int ib = 0; ib < nbands; ++ib) { - // Calculate out_wfc_re_im - for (int ib = 0; ib < nbands; ++ib) + if (bands_picked_[ib]) { - if (bands_picked_[ib]) - { - std::cout << " Performing grid integral over real space grid for band " << ib + 1 << "..." << std::endl; + std::cout << " Performing grid integral over real space grid for band " << ib + 1 << "..." << std::endl; - for (int is = 0; is < nspin; ++is) - { - ModuleBase::GlobalFunc::ZEROS(pes_->charge->rho[is], pw_wfc->nrxx); + for (int is = 0; is < nspin; ++is) + { + ModuleBase::GlobalFunc::ZEROS(pes_->charge->rho[is], pw_wfc->nrxx); - psid->fix_k(is); + psid->fix_k(is); #ifdef __MPI - wfc_2d_to_grid(psid->get_pointer(), para_orb, wfc_gamma_grid[is], gg.gridt->trace_lo); + wfc_2d_to_grid(psid->get_pointer(), para_orb, wfc_gamma_grid[is], gg.gridt->trace_lo); #else - // if not MPI enabled, it is the case psid holds a global matrix. use fix_k to switch between - // different spin channels (actually kpoints, because now the same kpoint in different spin channels - // are treated as distinct kpoints) + // if not MPI enabled, it is the case psid holds a global matrix. use fix_k to switch between + // different spin channels (actually kpoints, because now the same kpoint in different spin channels + // are treated as distinct kpoints) - for (int i = 0; i < nbands; ++i) + for (int i = 0; i < nbands; ++i) + { + for (int j = 0; j < nlocal; ++j) { - for (int j = 0; j < nlocal; ++j) - { - wfc_gamma_grid[is][i][j] = psid[0](i, j); - } + wfc_gamma_grid[is][i][j] = psid[0](i, j); } + } #endif - gg.cal_env(wfc_gamma_grid[is][ib], pes_->charge->rho[is], ucell); + gg.cal_env(wfc_gamma_grid[is][ib], pes_->charge->rho[is], ucell); - pes_->charge->save_rho_before_sum_band(); + pes_->charge->save_rho_before_sum_band(); - const double ef_tmp = this->pes_->eferm.get_efval(is); + const double ef_tmp = this->pes_->eferm.get_efval(is); - // only for gamma_only now - psi_g.fix_k(is); - this->set_pw_wfc(pw_wfc, is, ib, nspin, pes_->charge->rho, psi_g); + // only for gamma_only now + psi_g.fix_k(is); + this->set_pw_wfc(pw_wfc, is, ib, nspin, pes_->charge->rho, psi_g); - // Calculate real-space wave functions - psi_g.fix_k(is); - std::vector> wfc_r(pw_wfc->nrxx); - pw_wfc->recip2real(&psi_g(ib, 0), wfc_r.data(), is); + // Calculate real-space wave functions + psi_g.fix_k(is); + std::vector> wfc_r(pw_wfc->nrxx); + pw_wfc->recip2real(&psi_g(ib, 0), wfc_r.data(), is); - // Extract real and imaginary parts - std::vector wfc_real(pw_wfc->nrxx); - std::vector wfc_imag(pw_wfc->nrxx); - for (int ir = 0; ir < pw_wfc->nrxx; ++ir) - { - wfc_real[ir] = wfc_r[ir].real(); - wfc_imag[ir] = wfc_r[ir].imag(); - } + // Extract real and imaginary parts + std::vector wfc_real(pw_wfc->nrxx); + std::vector wfc_imag(pw_wfc->nrxx); + for (int ir = 0; ir < pw_wfc->nrxx; ++ir) + { + wfc_real[ir] = wfc_r[ir].real(); + wfc_imag[ir] = wfc_r[ir].imag(); + } - // Output real part - std::stringstream ss_real; - ss_real << global_out_dir << "wf" << ib + 1 << "s" << is + 1 << "real.cube"; - ModuleIO::write_vdata_palgrid(pgrid, - wfc_real.data(), - is, - nspin, - 0, - ss_real.str(), - ef_tmp, - &(ucell)); + // Output real part + std::stringstream ss_real; + ss_real << global_out_dir << "wf" << ib + 1 << "s" << is + 1 << "real.cube"; + ModuleIO::write_vdata_palgrid(pgrid, wfc_real.data(), is, nspin, 0, ss_real.str(), ef_tmp, &(ucell)); - // Output imaginary part - std::stringstream ss_imag; - ss_imag << global_out_dir << "wf" << ib + 1 << "s" << is + 1 << "imag.cube"; - ModuleIO::write_vdata_palgrid(pgrid, - wfc_imag.data(), - is, - nspin, - 0, - ss_imag.str(), - ef_tmp, - &(ucell)); - } + // Output imaginary part + std::stringstream ss_imag; + ss_imag << global_out_dir << "wf" << ib + 1 << "s" << is + 1 << "imag.cube"; + ModuleIO::write_vdata_palgrid(pgrid, wfc_imag.data(), is, nspin, 0, ss_imag.str(), ef_tmp, &(ucell)); } } } From d6cde5cc59a391334d201e15fda5b259c61fdfd0 Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Fri, 16 May 2025 18:33:40 +0800 Subject: [PATCH 5/8] Add out_wfc_re_im integrate test for LCAO --- tests/02_NAO_Gamma/013_NO_GO_get_wf/INPUT | 1 + tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/tests/02_NAO_Gamma/013_NO_GO_get_wf/INPUT b/tests/02_NAO_Gamma/013_NO_GO_get_wf/INPUT index 7e1b539a1e..faf237933c 100644 --- a/tests/02_NAO_Gamma/013_NO_GO_get_wf/INPUT +++ b/tests/02_NAO_Gamma/013_NO_GO_get_wf/INPUT @@ -2,6 +2,7 @@ INPUT_PARAMETERS suffix autotest calculation get_wf out_wfc_norm 1 3*0 +out_wfc_re_im 0 1 2*0 nbands 4 latname sc stru_file STRU diff --git a/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref b/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref index df7490df6e..7900aaef64 100644 --- a/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref +++ b/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref @@ -1,3 +1,7 @@ wf1s1.cube -11.64684896 wf1s2.cube -11.64684895 +wf2s1imag.cube 0.08121948242 +wf2s1real.cube -11.61500843 +wf2s2imag.cube 0.08121948242 +wf2s2real.cube 0.1448579759 totaltimeref 0.36 From 97b932898e303feb20bc0094fa47b17d3d895b5b Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Fri, 16 May 2025 18:52:30 +0800 Subject: [PATCH 6/8] Remove the remaining out_wfc_r from ABACUS repo --- docs/advanced/elec_properties/wfc.md | 4 +- docs/advanced/input_files/input-main.md | 10 +- source/module_esolver/lcao_others.cpp | 2 - source/module_io/get_wf_lcao.cpp | 143 ++++++++------------ source/module_io/get_wf_lcao.h | 4 - source/module_io/read_input_item_output.cpp | 6 - source/module_io/test/read_input_ptest.cpp | 1 - source/module_io/test/support/INPUT | 1 - source/module_parameter/input_parameter.h | 1 - 9 files changed, 62 insertions(+), 110 deletions(-) diff --git a/docs/advanced/elec_properties/wfc.md b/docs/advanced/elec_properties/wfc.md index f77a448a71..51be1d8a31 100644 --- a/docs/advanced/elec_properties/wfc.md +++ b/docs/advanced/elec_properties/wfc.md @@ -9,8 +9,6 @@ In the LCAO basis case, several `WFC_NAO_K${k}.dat` files will be output in mult ## wave function in real space -One can also choose to output real-space wave function in PW basis calculation with the key word ***[out_wfc_r](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out_wfc_r)***. - -After calculation, an additional directory named `wfc_realspace` will appear in the `OUT.${system}` directory. +One can also choose to output real-space wave function in PW basis calculation with the key word ***[out_wfc_norm](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-norm)***. Notice: when the ***[basis_type](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#basis_type)*** is `lcao`, only `get_wf` ***[calculation](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#calculation)*** is effective. An example is [examples/wfc/lcao_ienvelope_Si2](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/wfc/lcao_ienvelope_Si2). \ No newline at end of file diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index 298b761d24..bd5d740f8d 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -136,7 +136,6 @@ - [out\_dm](#out_dm) - [out\_dm1](#out_dm1) - [out\_wfc\_pw](#out_wfc_pw) - - [out\_wfc\_r](#out_wfc_r) - [out\_wfc\_lcao](#out_wfc_lcao) - [out\_dos](#out_dos) - [out\_ldos](#out_ldos) @@ -1593,7 +1592,7 @@ These variables are used to control the output of properties. ### out_freq_elec - **Type**: Integer -- **Description**: Output the charge density (only binary format, controlled by [out_chg](#out_chg)), wavefunction (controlled by [out_wfc_pw](#out_wfc_pw) or [out_wfc_r](#out_wfc_r)) per `out_freq_elec` electronic iterations. Note that they are always output when converged or reach the maximum iterations [scf_nmax](#scf_nmax). +- **Description**: Output the charge density (only binary format, controlled by [out_chg](#out_chg)), wavefunction (controlled by [out_wfc_pw](#out_wfc_pw)) per `out_freq_elec` electronic iterations. Note that they are always output when converged or reach the maximum iterations [scf_nmax](#scf_nmax). - **Default**: [scf_nmax](#scf_nmax) ### out_chg @@ -1670,13 +1669,6 @@ These variables are used to control the output of properties. - 2: results are stored in binary files named `OUT.${suffix}/WAVEFUNC${K}.dat`. - **Default**: 0 -### out_wfc_r (deprecated) - -- **Type**: Boolean -- **Availability**: Plane wave basis or get_wf calculation in numerical atomic orbital basis -- **Description**: Whether to output real-space wave functions into `OUT.suffix/wfc_realspace/wfc_realspace_${K}_${B}`, where `${K}` is the index of k points, `${B}` is the index of bands. -- **Default**: False - ### out_wfc_lcao - **Type**: Integer diff --git a/source/module_esolver/lcao_others.cpp b/source/module_esolver/lcao_others.cpp index b13270d6dd..6390d59ddc 100644 --- a/source/module_esolver/lcao_others.cpp +++ b/source/module_esolver/lcao_others.cpp @@ -362,7 +362,6 @@ void ESolver_KS_LCAO::others(UnitCell& ucell, const int istep) this->pv, this->GG, PARAM.inp.out_wfc_pw, - PARAM.inp.out_wfc_r, this->kv, PARAM.inp.nelec, PARAM.inp.nbands_istate, @@ -384,7 +383,6 @@ void ESolver_KS_LCAO::others(UnitCell& ucell, const int istep) this->pv, this->GK, PARAM.inp.out_wfc_pw, - PARAM.inp.out_wfc_r, this->kv, PARAM.inp.nelec, PARAM.inp.nbands_istate, diff --git a/source/module_io/get_wf_lcao.cpp b/source/module_io/get_wf_lcao.cpp index bd951c21c4..60885ae9da 100644 --- a/source/module_io/get_wf_lcao.cpp +++ b/source/module_io/get_wf_lcao.cpp @@ -29,7 +29,6 @@ void Get_wf_lcao::begin(const UnitCell& ucell, const Parallel_Orbitals& para_orb, Gint_Gamma& gg, const int& out_wfc_pw, - const int& out_wfc_r, const K_Vectors& kv, const double nelec, const int nbands_istate, @@ -231,10 +230,10 @@ void Get_wf_lcao::begin(const UnitCell& ucell, ModuleIO::write_wfc_pw(ssw.str(), psi_g, kv, pw_wfc); } - if (out_wfc_r) - { - ModuleIO::write_psi_r_1(ucell, psi_g, pw_wfc, "wfc_realspace", false, kv); - } + // if (out_wfc_r) + // { + // ModuleIO::write_psi_r_1(ucell, psi_g, pw_wfc, "wfc_realspace", false, kv); + // } for (int is = 0; is < nspin; ++is) { @@ -257,7 +256,6 @@ void Get_wf_lcao::begin(const UnitCell& ucell, const Parallel_Orbitals& para_orb, Gint_k& gk, const int& out_wf, - const int& out_wf_r, const K_Vectors& kv, const double nelec, const int nbands_istate, @@ -292,10 +290,9 @@ void Get_wf_lcao::begin(const UnitCell& ucell, // for pw_wfc in G space psi::Psi> psi_g; - if (out_wf || out_wf_r) - { - psi_g.resize(nks, nbands, pw_wfc->npwk_max); - } + + // if (out_wf || out_wf_r) + psi_g.resize(nks, nbands, pw_wfc->npwk_max); int mode_norm = 0; if (nbands_istate > 0 && static_cast(out_wfc_norm.size()) == 0) @@ -377,95 +374,75 @@ void Get_wf_lcao::begin(const UnitCell& ucell, 3, 1); - if (out_wf || out_wf_r) - { - psi_g.fix_k(ik); - this->set_pw_wfc(pw_wfc, ik, ib, nspin, pes_->charge->rho, psi_g); - } + // if (out_wf || out_wf_r) + psi_g.fix_k(ik); + this->set_pw_wfc(pw_wfc, ik, ib, nspin, pes_->charge->rho, psi_g); } } } - if (out_wf || out_wf_r) + if (out_wf) { - if (out_wf) - { - std::stringstream ssw; - ssw << global_out_dir << "WAVEFUNC"; - std::cout << " write G-space wave functions into \"" << global_out_dir << "/" << ssw.str() << "\" files." - << std::endl; - ModuleIO::write_wfc_pw(ssw.str(), psi_g, kv, pw_wfc); - } - if (out_wf_r) - { - ModuleIO::write_psi_r_1(ucell, psi_g, pw_wfc, "wfc_realspace", false, kv); - } + std::stringstream ssw; + ssw << global_out_dir << "WAVEFUNC"; + std::cout << " write G-space wave functions into \"" << global_out_dir << "/" << ssw.str() << "\" files." + << std::endl; + ModuleIO::write_wfc_pw(ssw.str(), psi_g, kv, pw_wfc); + } + // if (out_wf_r) + // { + // ModuleIO::write_psi_r_1(ucell, psi_g, pw_wfc, "wfc_realspace", false, kv); + // } - std::cout << " Outputting real-space wave functions in cube format..." << std::endl; + std::cout << " Outputting real-space wave functions in cube format..." << std::endl; - for (int ib = 0; ib < nbands; ++ib) + for (int ib = 0; ib < nbands; ++ib) + { + if (bands_picked_[ib]) { - if (bands_picked_[ib]) + const int nspin0 = (nspin == 2) ? 2 : 1; + for (int ik = 0; ik < nks; ++ik) { - const int nspin0 = (nspin == 2) ? 2 : 1; - for (int ik = 0; ik < nks; ++ik) - { - const int ispin = kv.isk[ik]; - std::cout << " Processing band " << ib + 1 << ", k-point " << ik << ", spin " << ispin + 1 - << std::endl; + const int ispin = kv.isk[ik]; + std::cout << " Processing band " << ib + 1 << ", k-point " << ik << ", spin " << ispin + 1 << std::endl; - psi_g.fix_k(ik); + psi_g.fix_k(ik); - // Calculate real-space wave functions - std::vector> wfc_r(pw_wfc->nrxx); - pw_wfc->recip2real(&psi_g(ib, 0), wfc_r.data(), ik); + // Calculate real-space wave functions + std::vector> wfc_r(pw_wfc->nrxx); + pw_wfc->recip2real(&psi_g(ib, 0), wfc_r.data(), ik); - // Extract real and imaginary parts - std::vector wfc_real(pw_wfc->nrxx); - std::vector wfc_imag(pw_wfc->nrxx); - for (int ir = 0; ir < pw_wfc->nrxx; ++ir) - { - wfc_real[ir] = wfc_r[ir].real(); - wfc_imag[ir] = wfc_r[ir].imag(); - } + // Extract real and imaginary parts + std::vector wfc_real(pw_wfc->nrxx); + std::vector wfc_imag(pw_wfc->nrxx); + for (int ir = 0; ir < pw_wfc->nrxx; ++ir) + { + wfc_real[ir] = wfc_r[ir].real(); + wfc_imag[ir] = wfc_r[ir].imag(); + } - // ik0 is the real k-point index, starting from 0 - int ik0 = kv.ik2iktot[ik]; - if (nspin == 2) + // ik0 is the real k-point index, starting from 0 + int ik0 = kv.ik2iktot[ik]; + if (nspin == 2) + { + const int half_k = kv.get_nkstot() / 2; + if (ik0 >= half_k) { - const int half_k = kv.get_nkstot() / 2; - if (ik0 >= half_k) - { - ik0 -= half_k; - } + ik0 -= half_k; } - - // Output real part - std::stringstream ss_real; - ss_real << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << "real.cube"; - - const double ef_tmp = this->pes_->eferm.get_efval(ispin); - ModuleIO::write_vdata_palgrid(pgrid, - wfc_real.data(), - ispin, - nspin, - 0, - ss_real.str(), - ef_tmp, - &(ucell)); - - // Output imaginary part - std::stringstream ss_imag; - ss_imag << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << "imag.cube"; - ModuleIO::write_vdata_palgrid(pgrid, - wfc_imag.data(), - ispin, - nspin, - 0, - ss_imag.str(), - ef_tmp, - &(ucell)); } + + // Output real part + std::stringstream ss_real; + ss_real << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << "real.cube"; + + const double ef_tmp = this->pes_->eferm.get_efval(ispin); + ModuleIO::write_vdata_palgrid(pgrid, wfc_real.data(), ispin, nspin, 0, ss_real.str(), ef_tmp, &(ucell)); + + // Output imaginary part + std::stringstream ss_imag; + ss_imag << global_out_dir << "wf" << ib + 1 << "s" << ispin + 1 << "k" << ik0 + 1 << "imag.cube"; + ModuleIO::write_vdata_palgrid(pgrid, wfc_imag.data(), ispin, nspin, 0, ss_imag.str(), ef_tmp, &(ucell)); } } } diff --git a/source/module_io/get_wf_lcao.h b/source/module_io/get_wf_lcao.h index 164431a9ba..3485e208d5 100644 --- a/source/module_io/get_wf_lcao.h +++ b/source/module_io/get_wf_lcao.h @@ -26,7 +26,6 @@ class Get_wf_lcao const Parallel_Orbitals& para_orb, Gint_Gamma& gg, const int& out_wfc_pw, - const int& out_wfc_r, const K_Vectors& kv, const double nelec, const int nbands_istate, @@ -47,7 +46,6 @@ class Get_wf_lcao const Parallel_Orbitals& para_orb, Gint_k& gg, const int& out_wfc_pw, - const int& out_wfc_r, const K_Vectors& kv, const double nelec, const int nbands_istate, @@ -71,7 +69,6 @@ class Get_wf_lcao const Parallel_Orbitals& para_orb, Gint_k& gk, const int& out_wfc_pw, - const int& out_wfc_r, const K_Vectors& kv, const double nelec, const int nbands_istate, @@ -92,7 +89,6 @@ class Get_wf_lcao const Parallel_Orbitals& para_orb, Gint_Gamma& gk, const int& out_wfc_pw, - const int& out_wfc_r, const K_Vectors& kv, const double nelec, const int nbands_istate, diff --git a/source/module_io/read_input_item_output.cpp b/source/module_io/read_input_item_output.cpp index 467ceef5d1..d94d17b641 100644 --- a/source/module_io/read_input_item_output.cpp +++ b/source/module_io/read_input_item_output.cpp @@ -78,12 +78,6 @@ void ReadInput::item_output() read_sync_int(input.out_wfc_pw); this->add_item(item); } - { - Input_Item item("out_wfc_r"); - item.annotation = "output wave functions in realspace"; - read_sync_bool(input.out_wfc_r); - this->add_item(item); - } { Input_Item item("printe"); item.annotation = "Print out energy for each band for every printe steps"; diff --git a/source/module_io/test/read_input_ptest.cpp b/source/module_io/test/read_input_ptest.cpp index 6fa3ba34a5..572b709d60 100644 --- a/source/module_io/test/read_input_ptest.cpp +++ b/source/module_io/test/read_input_ptest.cpp @@ -197,7 +197,6 @@ TEST_F(InputParaTest, ParaRead) EXPECT_EQ(param.inp.deepks_out_unittest, 0); EXPECT_EQ(param.inp.out_pot, 2); EXPECT_EQ(param.inp.out_wfc_pw, 0); - EXPECT_EQ(param.inp.out_wfc_r, 0); EXPECT_EQ(param.inp.out_dos, 0); EXPECT_EQ(param.inp.out_ldos[0], 1); EXPECT_EQ(param.inp.out_ldos[1], 3); diff --git a/source/module_io/test/support/INPUT b/source/module_io/test/support/INPUT index 8f67cdbfd1..ca85427f70 100644 --- a/source/module_io/test/support/INPUT +++ b/source/module_io/test/support/INPUT @@ -63,7 +63,6 @@ chg_extrap atomic #atomic; first-order; second-order; dm:coe out_chg 0 #>0 output charge density for selected electron steps out_pot 2 #output realspace potential out_wfc_pw 0 #output wave functions -out_wfc_r 0 #output wave functions in realspace out_dos 0 #output energy and dos out_ldos 1 #output local density of states, second parameter controls the precision out_band 0 #output energy and band structure diff --git a/source/module_parameter/input_parameter.h b/source/module_parameter/input_parameter.h index 0aa358b985..3ab9c6e1b2 100644 --- a/source/module_parameter/input_parameter.h +++ b/source/module_parameter/input_parameter.h @@ -362,7 +362,6 @@ struct Input_para std::vector out_chg = {0, 3}; ///< output charge density. 0: no; 1: yes int out_pot = 0; ///< yes or no int out_wfc_pw = 0; ///< 0: no; 1: txt; 2: dat - bool out_wfc_r = false; ///< 0: no; 1: yes int printe = 0; ///< Print out energy for each band for every printe step, default is scf_nmax std::vector out_band = {0, 8}; ///< band calculation pengfei 2014-10-13 int out_dos = 0; ///< dos calculation. mohan add 20090909 From 455f8990c7a94fc879185e711ecd53c7e36df52f Mon Sep 17 00:00:00 2001 From: AsTonyshment Date: Fri, 16 May 2025 20:25:33 +0800 Subject: [PATCH 7/8] Add integration tests for PW get_wf and get_pchg and some bug fixes --- tests/01_PW/112_PW_get_wf/INPUT | 21 ++++ tests/01_PW/112_PW_get_wf/KPT | 4 + tests/01_PW/112_PW_get_wf/README | 1 + tests/01_PW/112_PW_get_wf/STRU | 19 ++++ tests/01_PW/112_PW_get_wf/result.ref | 9 ++ tests/01_PW/113_PW_get_pchg/INPUT | 20 ++++ tests/01_PW/113_PW_get_pchg/KPT | 4 + tests/01_PW/113_PW_get_pchg/README | 1 + tests/01_PW/113_PW_get_pchg/STRU | 19 ++++ tests/01_PW/113_PW_get_pchg/result.ref | 10 ++ tests/01_PW/CASES_CPU.txt | 2 + .../02_NAO_Gamma/013_NO_GO_get_wf/result.ref | 12 +- .../015_NO_GO_get_pchg/result.ref | 8 +- tests/03_NAO_multik/32_NO_KP_get_wf/INPUT | 3 + .../03_NAO_multik/32_NO_KP_get_wf/result.ref | 30 +++-- tests/integrate/tools/catch_properties.sh | 64 +++++------ tests/integrate/tools/sum_cube.cpp | 106 ++++++++++-------- tests/integrate/tools/sum_cube.exe | Bin 15072 -> 18128 bytes 18 files changed, 227 insertions(+), 106 deletions(-) create mode 100644 tests/01_PW/112_PW_get_wf/INPUT create mode 100644 tests/01_PW/112_PW_get_wf/KPT create mode 100644 tests/01_PW/112_PW_get_wf/README create mode 100644 tests/01_PW/112_PW_get_wf/STRU create mode 100644 tests/01_PW/112_PW_get_wf/result.ref create mode 100644 tests/01_PW/113_PW_get_pchg/INPUT create mode 100644 tests/01_PW/113_PW_get_pchg/KPT create mode 100644 tests/01_PW/113_PW_get_pchg/README create mode 100644 tests/01_PW/113_PW_get_pchg/STRU create mode 100644 tests/01_PW/113_PW_get_pchg/result.ref diff --git a/tests/01_PW/112_PW_get_wf/INPUT b/tests/01_PW/112_PW_get_wf/INPUT new file mode 100644 index 0000000000..cf8619c111 --- /dev/null +++ b/tests/01_PW/112_PW_get_wf/INPUT @@ -0,0 +1,21 @@ +INPUT_PARAMETERS +#Parameters (1.General) +suffix autotest +calculation scf + +nbands 6 +symmetry 1 +pseudo_dir ../../PP_ORB + +#Parameters (2.Iteration) +ecutwfc 20 +scf_thr 1e-9 +scf_nmax 100 + +#Parameters (3.Basis) +basis_type pw + +out_wfc_norm 1 3*0 +out_wfc_re_im 0 1 2*0 + +pw_seed 1 diff --git a/tests/01_PW/112_PW_get_wf/KPT b/tests/01_PW/112_PW_get_wf/KPT new file mode 100644 index 0000000000..c289c0158a --- /dev/null +++ b/tests/01_PW/112_PW_get_wf/KPT @@ -0,0 +1,4 @@ +K_POINTS +0 +Gamma +1 1 1 0 0 0 diff --git a/tests/01_PW/112_PW_get_wf/README b/tests/01_PW/112_PW_get_wf/README new file mode 100644 index 0000000000..f663a595df --- /dev/null +++ b/tests/01_PW/112_PW_get_wf/README @@ -0,0 +1 @@ +test the output of out_wfc_norm and out_wfc_re_im diff --git a/tests/01_PW/112_PW_get_wf/STRU b/tests/01_PW/112_PW_get_wf/STRU new file mode 100644 index 0000000000..0041740d12 --- /dev/null +++ b/tests/01_PW/112_PW_get_wf/STRU @@ -0,0 +1,19 @@ +ATOMIC_SPECIES +Si 14 Si_ONCV_PBE-1.0.upf upf201 + +LATTICE_CONSTANT +10.2 // add lattice constant + +LATTICE_VECTORS +0.0 0.5 0.5 +0.5 0.0 0.5 +0.5 0.5 0.0 + +ATOMIC_POSITIONS +Direct + +Si // Element type +0.0 // magnetism +2 +0.00 0.00 0.00 1 1 1 +0.25 0.25 0.25 1 1 1 diff --git a/tests/01_PW/112_PW_get_wf/result.ref b/tests/01_PW/112_PW_get_wf/result.ref new file mode 100644 index 0000000000..7709864b2f --- /dev/null +++ b/tests/01_PW/112_PW_get_wf/result.ref @@ -0,0 +1,9 @@ +etotref -197.1405644417785 +etotperatomref -98.5702822209 +wf1s1k1.cube 22.08506167 +wf2s1k1imag.cube 7.845633773e-07 +wf2s1k1real.cube 2.250475858e-07 +pointgroupref T_d +spacegroupref O_h +nksibzref 1 +totaltimeref 0.35 diff --git a/tests/01_PW/113_PW_get_pchg/INPUT b/tests/01_PW/113_PW_get_pchg/INPUT new file mode 100644 index 0000000000..1c319c8366 --- /dev/null +++ b/tests/01_PW/113_PW_get_pchg/INPUT @@ -0,0 +1,20 @@ +INPUT_PARAMETERS +#Parameters (1.General) +suffix autotest +calculation scf + +nbands 6 +symmetry 1 +pseudo_dir ../../PP_ORB + +#Parameters (2.Iteration) +ecutwfc 20 +scf_thr 1e-9 +scf_nmax 100 + +#Parameters (3.Basis) +basis_type pw + +out_pchg 4*1 + +pw_seed 1 diff --git a/tests/01_PW/113_PW_get_pchg/KPT b/tests/01_PW/113_PW_get_pchg/KPT new file mode 100644 index 0000000000..c289c0158a --- /dev/null +++ b/tests/01_PW/113_PW_get_pchg/KPT @@ -0,0 +1,4 @@ +K_POINTS +0 +Gamma +1 1 1 0 0 0 diff --git a/tests/01_PW/113_PW_get_pchg/README b/tests/01_PW/113_PW_get_pchg/README new file mode 100644 index 0000000000..013c7397e6 --- /dev/null +++ b/tests/01_PW/113_PW_get_pchg/README @@ -0,0 +1 @@ +test the output of out_pchg diff --git a/tests/01_PW/113_PW_get_pchg/STRU b/tests/01_PW/113_PW_get_pchg/STRU new file mode 100644 index 0000000000..0041740d12 --- /dev/null +++ b/tests/01_PW/113_PW_get_pchg/STRU @@ -0,0 +1,19 @@ +ATOMIC_SPECIES +Si 14 Si_ONCV_PBE-1.0.upf upf201 + +LATTICE_CONSTANT +10.2 // add lattice constant + +LATTICE_VECTORS +0.0 0.5 0.5 +0.5 0.0 0.5 +0.5 0.5 0.0 + +ATOMIC_POSITIONS +Direct + +Si // Element type +0.0 // magnetism +2 +0.00 0.00 0.00 1 1 1 +0.25 0.25 0.25 1 1 1 diff --git a/tests/01_PW/113_PW_get_pchg/result.ref b/tests/01_PW/113_PW_get_pchg/result.ref new file mode 100644 index 0000000000..8aefd98e99 --- /dev/null +++ b/tests/01_PW/113_PW_get_pchg/result.ref @@ -0,0 +1,10 @@ +etotref -197.1405644417787 +etotperatomref -98.5702822209 +BAND1_SPIN1_CHG.cube 2 +BAND2_SPIN1_CHG.cube 2 +BAND3_SPIN1_CHG.cube 2 +BAND4_SPIN1_CHG.cube 2 +pointgroupref T_d +spacegroupref O_h +nksibzref 1 +totaltimeref 0.35 diff --git a/tests/01_PW/CASES_CPU.txt b/tests/01_PW/CASES_CPU.txt index d8b269d929..c9ff35be2c 100644 --- a/tests/01_PW/CASES_CPU.txt +++ b/tests/01_PW/CASES_CPU.txt @@ -106,6 +106,8 @@ 109_PW_PBE0 110_PW_ONCV_skip 111_PW_CG_float +112_PW_get_wf +113_PW_get_pchg 801_PW_LT_sc 802_PW_LT_fcc 803_PW_LT_bcc diff --git a/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref b/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref index 7900aaef64..392cc84922 100644 --- a/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref +++ b/tests/02_NAO_Gamma/013_NO_GO_get_wf/result.ref @@ -1,7 +1,7 @@ -wf1s1.cube -11.64684896 -wf1s2.cube -11.64684895 -wf2s1imag.cube 0.08121948242 -wf2s1real.cube -11.61500843 -wf2s2imag.cube 0.08121948242 -wf2s2real.cube 0.1448579759 +wf1s1.cube -11.7665927 +wf1s2.cube -11.76659269 +wf2s1imag.cube 0 +wf2s1real.cube -11.76659269 +wf2s2imag.cube 0 +wf2s2real.cube 3.042711753e-14 totaltimeref 0.36 diff --git a/tests/02_NAO_Gamma/015_NO_GO_get_pchg/result.ref b/tests/02_NAO_Gamma/015_NO_GO_get_pchg/result.ref index 743bc19e5a..cb1f475e21 100644 --- a/tests/02_NAO_Gamma/015_NO_GO_get_pchg/result.ref +++ b/tests/02_NAO_Gamma/015_NO_GO_get_pchg/result.ref @@ -1,5 +1,5 @@ -BAND1_GAMMA_SPIN1_CHG.cube 2.060784687 -BAND2_GAMMA_SPIN1_CHG.cube 2.076249844 -BAND3_GAMMA_SPIN1_CHG.cube 2.070272135 -BAND4_GAMMA_SPIN1_CHG.cube 2.06983289 +BAND1_GAMMA_SPIN1_CHG.cube 2.000642408 +BAND2_GAMMA_SPIN1_CHG.cube 2.005076281 +BAND3_GAMMA_SPIN1_CHG.cube 2.003119785 +BAND4_GAMMA_SPIN1_CHG.cube 2.010880493 totaltimeref 0.17 diff --git a/tests/03_NAO_multik/32_NO_KP_get_wf/INPUT b/tests/03_NAO_multik/32_NO_KP_get_wf/INPUT index a1cc52840f..6c25a14814 100644 --- a/tests/03_NAO_multik/32_NO_KP_get_wf/INPUT +++ b/tests/03_NAO_multik/32_NO_KP_get_wf/INPUT @@ -16,6 +16,9 @@ basis_type lcao scf_thr 1e-10 read_file_dir ./ +out_wfc_norm 1 +out_wfc_re_im 1 + bx 2 by 2 bz 2 diff --git a/tests/03_NAO_multik/32_NO_KP_get_wf/result.ref b/tests/03_NAO_multik/32_NO_KP_get_wf/result.ref index a3eb036651..215fb3e07c 100644 --- a/tests/03_NAO_multik/32_NO_KP_get_wf/result.ref +++ b/tests/03_NAO_multik/32_NO_KP_get_wf/result.ref @@ -1,13 +1,19 @@ -wf1s1k1.cube -11.65179721 -wf1s1k2.cube -3.691662805 -wf1s1k3.cube -3.691662805 -wf1s2k1.cube -11.65179721 -wf1s2k2.cube -3.691662805 -wf1s2k3.cube -3.691662805 -wf2s1k1.cube 0.1128845215 -wf2s1k2.cube 0.06528930664 -wf2s1k3.cube 0.06528930664 -wf2s2k1.cube 0.1128845215 -wf2s2k2.cube 0.06528930664 -wf2s2k3.cube 0.06528930664 +wf1s1k1.cube -11.77152988 +wf1s1k1imag.cube 0 +wf1s1k1real.cube -11.77169544 +wf1s1k2.cube -3.753605249 +wf1s1k2imag.cube -6.240965225e-15 +wf1s1k2real.cube -3.753696262 +wf1s1k3.cube -3.753605249 +wf1s1k3imag.cube 1.793009931e-15 +wf1s1k3real.cube -3.753696262 +wf1s2k1.cube -11.77152988 +wf1s2k1imag.cube 0 +wf1s2k1real.cube -15.5253917 +wf1s2k2.cube -3.753605249 +wf1s2k2imag.cube 3.852845828e-14 +wf1s2k2real.cube -7.507392525 +wf1s2k3.cube -3.753605249 +wf1s2k3imag.cube -2.168256114e-14 +wf1s2k3real.cube -7.507392525 totaltimeref 0.46 diff --git a/tests/integrate/tools/catch_properties.sh b/tests/integrate/tools/catch_properties.sh index b2a32a5b8d..393904518f 100755 --- a/tests/integrate/tools/catch_properties.sh +++ b/tests/integrate/tools/catch_properties.sh @@ -499,43 +499,35 @@ if ! test -z "$out_mul" && [ $out_mul == 1 ]; then fi #-------------------------------------------- -# obtain wave functions for each electronic -# state +# Process .cube files for: +# 1. get_wf/get_pchg calculation tag (LCAO) +# 2. out_wfc_norm/out_wfc_re_im/out_pchg (PW) #-------------------------------------------- -if [ $calculation == "get_wf" ]; then - nfile=0 - cubefiles=`ls OUT.autotest/ | grep -E '.cube$'` - #echo "The cube files are $cubefiles" - if test -z "$cubefiles"; then - echo "Can't find $cubefiles files" - exit 1 - else - for cube in $cubefiles; - do - total_chg=`$SUM_CUBE_EXE OUT.autotest/$cube` - echo "$cube $total_chg" >>$1 - done - fi -fi - - -#-------------------------------------------- -# obtian electron charge density for each -# electronic state -#-------------------------------------------- -if [ $calculation == "get_pchg" ]; then - nfile=0 - cubefiles=`ls OUT.autotest/ | grep -E '.cube$'` - if test -z "$cubefiles"; then - echo "Can't find cube files" - exit 1 - else - for cube in $cubefiles; - do - total_chg=`$SUM_CUBE_EXE OUT.autotest/$cube` - echo "$cube $total_chg" >>$1 - done - fi +need_process_cube=false +# Check if this is a LCAO calculation with get_wf/get_pchg +if [ $calculation == "get_wf" ] || [ $calculation == "get_pchg" ]; then + need_process_cube=true +fi +# Check if this is a PW calculation with out_wfc_norm/out_wfc_re_im +out_wfc_norm=$(get_input_key_value "out_wfc_norm" "INPUT") +out_wfc_re_im=$(get_input_key_value "out_wfc_re_im" "INPUT") +out_pchg=$(get_input_key_value "out_pchg" "INPUT") +if [ -n "$out_wfc_norm" ] || [ -n "$out_wfc_re_im" ] || [ -n "$out_pchg" ]; then + need_process_cube=true +fi +# Process .cube files if needed +if [ "$need_process_cube" = true ]; then + cubefiles=$(ls OUT.autotest/ | grep -E '.cube$') + + if [ -z "$cubefiles" ]; then + echo "Error: No .cube files found in OUT.autotest/" + exit 1 + else + for cube in $cubefiles; do + total_chg=$($SUM_CUBE_EXE OUT.autotest/$cube) + echo "$cube $total_chg" >> $1 + done + fi fi #-------------------------------------------- diff --git a/tests/integrate/tools/sum_cube.cpp b/tests/integrate/tools/sum_cube.cpp index 2e10207bc9..c2773cbfed 100644 --- a/tests/integrate/tools/sum_cube.cpp +++ b/tests/integrate/tools/sum_cube.cpp @@ -1,60 +1,70 @@ -#include -#include -#include +#include #include #include -#include +#include +#include +#include using namespace std; -int main(int argc, char **argv) +int main(int argc, char** argv) { - string input_file = argv[1]; + string input_file = argv[1]; + + ifstream inp(input_file.c_str(), ios::in); + + if (!inp) + { + cout << "Can't find " << input_file << " !" << endl; + return 1; + } - ifstream inp(input_file.c_str(), ios::in); + // skip the first two lines + string tmpstring; + for (int i = 0; i < 2; i++) + { + getline(inp, tmpstring); + } + + // read the 3rd line: number of atoms + origin coordinates + int natom; + double origin_x, origin_y, origin_z; + inp >> natom >> origin_x >> origin_y >> origin_z; + getline(inp, tmpstring); + + // read the grid vectors (support non-orthogonal) + double v1[3], v2[3], v3[3]; + int nx, ny, nz; + inp >> nx >> v1[0] >> v1[1] >> v1[2]; + inp >> ny >> v2[0] >> v2[1] >> v2[2]; + inp >> nz >> v3[0] >> v3[1] >> v3[2]; + + // calculate the volume element |v1 · (v2 × v3)| + double volume = fabs(v1[0] * (v2[1] * v3[2] - v2[2] * v3[1]) - v1[1] * (v2[0] * v3[2] - v2[2] * v3[0]) + + v1[2] * (v2[0] * v3[1] - v2[1] * v3[0])); + + getline(inp, tmpstring); - if (!inp) - { - cout << "Can't find " << input_file << " !" << endl; - return 1; - } - else + // skip the atom coordinates + for (int i = 0; i < natom; ++i) { -// cout << "Find the " << input_file << endl; + getline(inp, tmpstring); } - int nx = 0; - int ny = 0; - int nz = 0; - int nr = 0; - double mx = 0.0; - double my = 0.0; - double mz = 0.0; - double tmp = 0.0; - std::string tmpstring; - getline(inp, tmpstring); - getline(inp, tmpstring); - getline(inp, tmpstring); - inp >> nx >> mx >> tmp >> tmp; - inp >> ny >> tmp >> my >> tmp; - inp >> nz >> tmp >> tmp >> mz; - getline(inp, tmpstring); - getline(inp, tmpstring); - - nr = nx * ny * nz; - - double sum = 0.0; - double env = 0.0; - for (int i=0; i< nr; i++) - { - inp >> env; - sum += env; - } - - double ne = 0.0; - - ne = sum * mx * my * mz; - std::cout<> env; + sum += env; + } + + double ne = 0.0; + + ne = sum * volume; + std::cout << setprecision(10) << ne << std::endl; + + return 0; } diff --git a/tests/integrate/tools/sum_cube.exe b/tests/integrate/tools/sum_cube.exe index a6928b21d63d30058a75476e42ce008ff83f16a8..e7c9a184bf2f6dc864a7d9075d571ad6d5a35663 100755 GIT binary patch literal 18128 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 literal 15072 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 Date: Sat, 17 May 2025 12:52:52 +0800 Subject: [PATCH 8/8] Remove sum_cube.exe from repo --- tests/integrate/tools/sum_cube.exe | Bin 18128 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 tests/integrate/tools/sum_cube.exe diff --git a/tests/integrate/tools/sum_cube.exe b/tests/integrate/tools/sum_cube.exe deleted file mode 100755 index e7c9a184bf2f6dc864a7d9075d571ad6d5a35663..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18128 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