Skip to content

Commit c1621de

Browse files
Feature: Add INPUT parameter bands_to_print for LCAO basis set (#3934)
* Add INPUT param out_band_index * Add INPUT param out_band_index * Add INPUT param out_band_index * Fix extra spacing within in doc * Fix several bugs of band-decomposed charge densities using PW basis set * Change INPUT param from out_band_index to bands_to_print and modified the corresponding docs --------- Co-authored-by: Mohan Chen <[email protected]>
1 parent cc21a8d commit c1621de

File tree

11 files changed

+191
-107
lines changed

11 files changed

+191
-107
lines changed

docs/advanced/input_files/input-main.md

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
- [basis\_type](#basis_type)
6565
- [ks\_solver](#ks_solver)
6666
- [nbands](#nbands)
67-
- [nbands\_istate](#nbands_istate)
6867
- [nspin](#nspin)
6968
- [smearing\_method](#smearing_method)
7069
- [smearing\_sigma](#smearing_sigma)
@@ -148,12 +147,12 @@
148147
- [out\_app\_flag](#out_app_flag)
149148
- [out\_ndigits](#out_ndigits)
150149
- [out\_interval](#out_interval)
151-
- [band\_print\_num](#band_print_num)
152-
- [bands\_to\_print](#bands_to_print)
153150
- [out\_element\_info](#out_element_info)
154151
- [restart\_save](#restart_save)
155152
- [restart\_load](#restart_load)
156153
- [rpa](#rpa)
154+
- [nbands\_istate](#nbands_istate)
155+
- [bands\_to\_print](#bands_to_print)
157156
- [Density of states](#density-of-states)
158157
- [dos\_edelta\_ev](#dos_edelta_ev)
159158
- [dos\_sigma](#dos_sigma)
@@ -413,7 +412,7 @@ These variables are used to control general system parameters.
413412
- relax: do structure relaxation calculation, one can use `relax_nmax` to decide how many ionic relaxations you want
414413
- cell-relax: do variable-cell relaxation calculation
415414
- nscf: do the non self-consistent electronic structure calculations. For this option, you need a charge density file. For nscf calculations with planewave basis set, pw_diag_thr should be <= 1e-3
416-
- get_pchg: For LCAO basis. Please see the explanation for variable `nbands_istate`
415+
- get_pchg: For LCAO basis. Please see the explanation for variable `nbands_istate` and `bands_to_print`
417416
- get_wf: Envelope function for LCAO basis. Please see the explanation for variable `nbands_istate`
418417
- md: molecular dynamics
419418
- test_memory : checks memory required for the calculation. The number is not quite reliable, please use it with care
@@ -937,13 +936,6 @@ calculations.
937936
- nspin=2: max(1.2\*nelec_spin, nelec_spin + 10), in which nelec_spin = max(nelec_spin_up, nelec_spin_down)
938937
- nspin=4: max(1.2\*nelec, nelec + 20)
939938

940-
### nbands_istate
941-
942-
- **Type**: Integer
943-
- **Availability**: Only used when `calculation = get_wf` or `calculation = get_pchg`.
944-
- **Description**: The number of bands around the Fermi level you would like to calculate. `get_wf` means to calculate the envelope functions of wave functions $\Psi_{i}=\Sigma_{\mu}C_{i\mu}\Phi_{\mu}$, where $\Psi_{i}$ is the ith wave function with the band index $i$ and $\Phi_{\mu}$ is the localized atomic orbital set. `get_pchg` means to calculate the density of each wave function $|\Psi_{i}|^{2}$. Specifically, suppose we have highest occupied bands at 100th wave functions. And if you set this variable to 5, it will print five wave functions from 96th to 105th. But before all this can be carried out, the wave functions coefficients should be first calculated and written into a file by setting the flag `out_wfc_lcao = 1`.
945-
- **Default**: 5
946-
947939
### nspin
948940

949941
- **Type**: Integer
@@ -1635,20 +1627,6 @@ These variables are used to control the output of properties.
16351627
- **Description**: Control the interval for printing Mulliken population analysis, $r(R)$, $H(R)$, $S(R)$, $T(R)$, $dH(R)$, $H(k)$, $S(k)$ and $wfc(k)$ matrices during molecular dynamics calculations. Check input parameters [out_mul](#out_mul), [out_mat_r](#out_mat_r), [out_mat_hs2](#out_mat_hs2), [out_mat_t](#out_mat_t), [out_mat_dh](#out_mat_dh), [out_mat_hs](#out_mat_hs) and [out_wfc_lcao](#out_wfc_lcao) for more information, respectively.
16361628
- **Default**: 1
16371629

1638-
### band_print_num
1639-
1640-
- **Type**: Integer
1641-
- **Availability**: PW basis
1642-
- **Description**: If you want to plot a partial charge density contributed from some chosen bands. `band_print_num` define the number of band list. The result can be found in "band*.cube".
1643-
- **Default**: 0
1644-
1645-
### bands_to_print
1646-
1647-
- **Type**: vector
1648-
- **Availability**: band_print_num > 0
1649-
- **Description**: define which band you want to choose for partial charge density.
1650-
- **Default**: []
1651-
16521630
### out_element_info
16531631

16541632
- **Type**: Boolean
@@ -1681,6 +1659,20 @@ These variables are used to control the output of properties.
16811659
- **Description**: Generate output files used in rpa calculations.
16821660
- **Default**: False
16831661

1662+
### nbands_istate
1663+
1664+
- **Type**: Integer
1665+
- **Availability**: Only for LCAO, used when `calculation = get_wf` or `calculation = get_pchg`.
1666+
- **Description**: The number of bands around the Fermi level you would like to calculate. `get_wf` means to calculate the envelope functions of wave functions $\Psi_{i}=\Sigma_{\mu}C_{i\mu}\Phi_{\mu}$, where $\Psi_{i}$ is the ith wave function with the band index $i$ and $\Phi_{\mu}$ is the localized atomic orbital set. `get_pchg` means to calculate the density of each wave function $|\Psi_{i}|^{2}$. Specifically, suppose we have highest occupied bands at 100th wave functions. And if you set this variable to 5, it will print five wave functions from 96th to 105th. But before all this can be carried out, the wave functions coefficients should be first calculated and written into a file by setting the flag `out_wfc_lcao = 1`.
1667+
- **Default**: 5
1668+
1669+
### bands_to_print
1670+
1671+
- **Type**: String
1672+
- **Availability**: For both PW and LCAO. When `basis_type = lcao`, only used when `calculation = get_pchg`.
1673+
- **Description**: Specifies the bands to calculate the charge density for, using a space-separated string of 0s and 1s, providing a more flexible selection compared to `nbands_istate`. Each digit in the string corresponds to a band, starting from the first band. A `1` indicates that the charge density should be calculated for that band, while a `0` means the band will be ignored. The parameter allows a compact and flexible notation (similar to [`ocp_set`](#ocp_set)), for example the syntax `1 4*0 5*1 0` is used to denote the selection of bands: `1` means calculate for the first band, `4*0` skips the next four bands, `5*1` means calculate for the following five bands, and the final `0` skips the next band. It's essential that the total count of bands does not exceed the total number of bands (`nbands`); otherwise, it results in an error, and the process exits. The input string must contain only numbers and the asterisk (`*`) for repetition, ensuring correct format and intention of band selection.
1674+
- **Default**: none
1675+
16841676
[back to top](#full-list-of-input-keywords)
16851677

16861678
## Density of states

source/module_esolver/esolver_ks_lcao_elec.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ void ESolver_KS_LCAO<TK, TR>::others(const int istep)
408408
GlobalV::NBANDS,
409409
GlobalV::nelec,
410410
GlobalV::NSPIN,
411+
GlobalV::NLOCAL,
411412
GlobalV::global_out_dir,
412413
GlobalV::MY_RANK,
413414
GlobalV::ofs_warning);

source/module_esolver/esolver_ks_pw.cpp

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "module_io/write_istate_info.h"
88
#include "module_io/write_wfc_pw.h"
99
#include "module_io/output_log.h"
10+
#include "module_io/input_conv.h"
1011

1112
//--------------temporary----------------------------
1213
#include "module_elecstate/module_charge/symmetry_rho.h"
@@ -1023,36 +1024,81 @@ void ESolver_KS_PW<T, Device>::after_scf(const int istep)
10231024
this->psi[0].size());
10241025
}
10251026

1026-
if(INPUT.band_print_num > 0)
1027+
// Get bands_to_print through public function of INPUT (returns a const pointer to string)
1028+
std::string bands_to_print = *INPUT.get_bands_to_print();
1029+
if(!bands_to_print.empty())
10271030
{
1028-
std::complex<double> * wfcr = new std::complex<double>[this->pw_rho->nxyz];
1029-
double * rho_band = new double [this->pw_rho->nxyz];
1030-
for(int i = 0; i < this->pw_rho->nxyz; i++)
1031+
std::vector<double> out_band_kb;
1032+
Input_Conv::parse_expression(bands_to_print, out_band_kb);
1033+
1034+
// bands_picked is a vector of 0s and 1s, where 1 means the band is picked to output
1035+
std::vector<int> bands_picked;
1036+
bands_picked.resize(this->kspw_psi->get_nbands());
1037+
ModuleBase::GlobalFunc::ZEROS(bands_picked.data(), this->kspw_psi->get_nbands());
1038+
1039+
// Check if length of out_band_kb is valid
1040+
if (static_cast<int>(out_band_kb.size()) > this->kspw_psi->get_nbands())
1041+
{
1042+
ModuleBase::WARNING_QUIT(
1043+
"ESolver_KS_PW::after_scf",
1044+
"The number of bands specified by `bands_to_print` in the INPUT file exceeds `nbands`!");
1045+
}
1046+
1047+
// Check if all elements in bands_picked are 0 or 1
1048+
for (int value: out_band_kb)
1049+
{
1050+
if (value != 0 && value != 1)
1051+
{
1052+
ModuleBase::WARNING_QUIT(
1053+
"ESolver_KS_PW::after_scf",
1054+
"The elements of `bands_to_print` must be either 0 or 1. Invalid values found!");
1055+
}
1056+
}
1057+
1058+
// Fill bands_picked with values from out_band_kb, converting to int
1059+
// Remaining bands are already set to 0
1060+
int length = std::min(static_cast<int>(out_band_kb.size()), this->kspw_psi->get_nbands());
1061+
for (int i = 0; i < length; ++i)
10311062
{
1032-
rho_band[i] = 0.0;
1063+
// out_band_kb rely on function parse_expression from input_conv.cpp
1064+
// Initially designed for ocp_set, which can be double
1065+
bands_picked[i] = static_cast<int>(out_band_kb[i]);
10331066
}
10341067

1035-
for(int i = 0; i < INPUT.band_print_num; i++)
1068+
std::complex<double>* wfcr = new std::complex<double>[this->pw_rho->nxyz];
1069+
double* rho_band = new double[this->pw_rho->nxyz];
1070+
1071+
for (int ib = 0; ib < this->kspw_psi->get_nbands(); ++ib)
10361072
{
1037-
int ib = INPUT.bands_to_print[i];
1038-
for(int ik = 0; ik < this->kv.nks; ik++)
1073+
// Skip the loop iteration if bands_picked[ib] is 0
1074+
if (!bands_picked[ib])
1075+
{
1076+
continue;
1077+
}
1078+
1079+
for (int i = 0; i < this->pw_rho->nxyz; i++)
1080+
{
1081+
// Initialize rho_band to zero for each band
1082+
rho_band[i] = 0.0;
1083+
}
1084+
1085+
for (int ik = 0; ik < this->kv.nks; ik++)
10391086
{
10401087
this->psi->fix_k(ik);
1041-
this->pw_wfc->recip_to_real(this->ctx,&psi[0](ib,0),wfcr,ik);
1088+
this->pw_wfc->recip_to_real(this->ctx, &psi[0](ib, 0), wfcr, ik);
10421089

10431090
double w1 = static_cast<double>(this->kv.wk[ik] / GlobalC::ucell.omega);
10441091

1045-
for(int i = 0; i < this->pw_rho->nxyz; i++)
1092+
for (int i = 0; i < this->pw_rho->nxyz; i++)
10461093
{
10471094
rho_band[i] += std::norm(wfcr[i]) * w1;
10481095
}
10491096
}
10501097

10511098
std::stringstream ssc;
1052-
ssc << GlobalV::global_out_dir << "band" << ib << ".cube";
1099+
ssc << GlobalV::global_out_dir << "band" << ib + 1 << ".cube"; // band index starts from 1
10531100

1054-
ModuleIO::write_rho
1055-
(
1101+
ModuleIO::write_rho(
10561102
#ifdef __MPI
10571103
this->pw_big->bz,
10581104
this->pw_big->nbz,

source/module_io/input.cpp

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ void Input::Default(void)
162162
nbands_sto = 256;
163163
nbndsto_str = "256";
164164
nbands_istate = 5;
165+
bands_to_print_ = "";
165166
pw_seed = 1;
166167
emin_sto = 0.0;
167168
emax_sto = 0.0;
@@ -332,8 +333,6 @@ void Input::Default(void)
332333

333334
out_bandgap = 0; // QO added for bandgap printing
334335

335-
band_print_num = 0;
336-
337336
deepks_out_labels = 0; // caoyu added 2020-11-24, mohan added 2021-01-03
338337
deepks_scf = 0;
339338
deepks_bandgap = 0;
@@ -784,6 +783,10 @@ bool Input::Read(const std::string& fn)
784783
// if (nbands_istate < 0)
785784
// ModuleBase::WARNING_QUIT("Input", "NBANDS_ISTATE must > 0");
786785
}
786+
else if (strcmp("bands_to_print", word) == 0)
787+
{
788+
getline(ifs, bands_to_print_);
789+
}
787790
else if (strcmp("nche_sto", word) == 0) // Chebyshev expansion order
788791
{
789792
read_value(ifs, nche_sto);
@@ -1351,14 +1354,6 @@ bool Input::Read(const std::string& fn)
13511354
{
13521355
read_bool(ifs, out_chg);
13531356
}
1354-
else if (strcmp("band_print_num", word) == 0)
1355-
{
1356-
read_value(ifs, band_print_num);
1357-
}
1358-
else if (strcmp("bands_to_print", word) == 0)
1359-
{
1360-
ifs.ignore(150, '\n');
1361-
}
13621357
else if (strcmp("out_dm", word) == 0)
13631358
{
13641359
read_bool(ifs, out_dm);
@@ -2416,29 +2411,6 @@ bool Input::Read(const std::string& fn)
24162411
ModuleBase::WARNING_QUIT("Input", "The ntype in INPUT is not equal to the ntype counted in STRU, check it.");
24172412
}
24182413

2419-
if(band_print_num > 0)
2420-
{
2421-
bands_to_print.resize(band_print_num);
2422-
ifs.clear();
2423-
ifs.seekg(0); // move to the beginning of the file
2424-
ifs.rdstate();
2425-
while (ifs.good())
2426-
{
2427-
ifs >> word1;
2428-
if (ifs.eof() != 0)
2429-
break;
2430-
strtolower(word1, word); // convert uppercase std::string to lower case; word1 --> word
2431-
2432-
if (strcmp("bands_to_print", word) == 0)
2433-
{
2434-
for(int i = 0; i < band_print_num; i ++)
2435-
{
2436-
ifs >> bands_to_print[i];
2437-
}
2438-
}
2439-
}
2440-
}
2441-
24422414
//----------------------------------------------------------
24432415
// DFT+U Xin Qu added on 2020-10-29
24442416
//----------------------------------------------------------
@@ -3256,6 +3228,7 @@ void Input::Bcast()
32563228
Parallel_Common::bcast_int(nbands);
32573229
Parallel_Common::bcast_int(nbands_sto);
32583230
Parallel_Common::bcast_int(nbands_istate);
3231+
Parallel_Common::bcast_string(bands_to_print_);
32593232
for (int i = 0; i < 3; i++)
32603233
{
32613234
Parallel_Common::bcast_double(kspacing[i]);
@@ -3625,17 +3598,6 @@ void Input::Bcast()
36253598
Parallel_Common::bcast_bool(restart_save); // Peize Lin add 2020.04.04
36263599
Parallel_Common::bcast_bool(restart_load); // Peize Lin add 2020.04.04
36273600

3628-
Parallel_Common::bcast_int(band_print_num);
3629-
if(GlobalV::MY_RANK != 0)
3630-
{
3631-
bands_to_print.resize(band_print_num);
3632-
}
3633-
3634-
for(int i = 0; i < band_print_num; i++)
3635-
{
3636-
Parallel_Common::bcast_int(bands_to_print[i]);
3637-
}
3638-
36393601
//-----------------------------------------------------------------------------------
36403602
// DFT+U (added by Quxin 2020-10-29)
36413603
//-----------------------------------------------------------------------------------

source/module_io/input.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Input
4848
int ntype; // number of atom types
4949
int nbands; // number of bands
5050
int nbands_istate; // number of bands around fermi level for get_pchg calculation.
51+
5152
int pw_seed; // random seed for initializing wave functions qianrui 2021-8-12
5253

5354
bool init_vel; // read velocity from STRU or not liuyu 2021-07-14
@@ -262,8 +263,6 @@ class Input
262263
bool out_chg; // output charge density. 0: no; 1: yes
263264
bool out_dm; // output density matrix.
264265
bool out_dm1;
265-
int band_print_num;
266-
std::vector<int> bands_to_print;
267266
int out_pot; // yes or no
268267
int out_wfc_pw; // 0: no; 1: txt; 2: dat
269268
bool out_wfc_r; // 0: no; 1: yes
@@ -640,6 +639,8 @@ class Input
640639

641640
int count_ntype(const std::string &fn); // sunliang add 2022-12-06
642641

642+
std::string bands_to_print_; // specify the bands to be calculated in the get_pchg calculation, formalism similar to ocp_set.
643+
643644
public:
644645
template <class T> static void read_value(std::ifstream &ifs, T &var)
645646
{
@@ -697,6 +698,12 @@ class Input
697698
typename std::enable_if<std::is_same<T, std::string>::value, T>::type cast_string(const std::string& str) { return str; }
698699
void strtolower(char *sa, char *sb);
699700
void read_bool(std::ifstream &ifs, bool &var);
701+
702+
// Return the const string pointer of private member bands_to_print_
703+
const std::string* get_bands_to_print() const
704+
{
705+
return &bands_to_print_;
706+
}
700707
};
701708

702709
extern Input INPUT;

source/module_io/input_conv.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ void Input_Conv::Convert(void)
305305
GlobalV::MIN_DIST_COEF = INPUT.min_dist_coef;
306306
GlobalV::NBANDS = INPUT.nbands;
307307
GlobalV::NBANDS_ISTATE = INPUT.nbands_istate;
308+
308309
GlobalV::device_flag = psi::device::get_device_flag(INPUT.device, INPUT.ks_solver, INPUT.basis_type);
309310

310311
if (GlobalV::device_flag == "gpu")

0 commit comments

Comments
 (0)