diff --git a/docs/advanced/elec_properties/wfc.md b/docs/advanced/elec_properties/wfc.md
index c4a661a3e0..a3f6d52f6c 100644
--- a/docs/advanced/elec_properties/wfc.md
+++ b/docs/advanced/elec_properties/wfc.md
@@ -14,9 +14,11 @@ The files are stored in `OUT.${suffix}/`. Their pattern is `wfk{k}[s{spin}][g{ge
With `out_freq_ion=0`, files are written only when the electronic calculation converges or reaches `scf_nmax`, and the names contain neither `g*` nor `e*`. During structural relaxation or molecular dynamics, each later ionic step overwrites the same files. With `out_freq_ion>0`, output is restricted to the ionic steps selected by `out_freq_ion` and occurs at multiples of `out_freq_elec`, at convergence, or at `scf_nmax`; both `g*` and `e*` are included in the file names. A static `calculation=scf` or `calculation=nscf` run also receives `g1e*` indices when `out_freq_ion>0`.
-The normal [`init_wfc=file`](../scf/initialization.md#wave-function) path reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Generate directly reusable files with `out_wfc_pw=2` and normally `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
+The [`init_wfc file binary`](../scf/initialization.md#wave-function) path reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Generate directly reusable files with `out_wfc_pw=2` and normally `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
-For `basis_type=lcao`, set [`out_wfc_lcao=1`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-lcao). Multi-k calculations generate `wfs{spin}k{k-point}_nao.txt`, while Gamma-only calculations generate `wfs{spin}_nao.txt`.
+For `basis_type=lcao`, [`out_wfc_lcao`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-lcao) controls the output of numerical-atomic-orbital coefficients: `1` writes text files with the `.txt` suffix and `2` writes binary files with the `.dat` suffix. Multi-k calculations generate `wfs{spin}k{k-point}_nao.txt` or `.dat`, while Gamma-only calculations generate `wfs{spin}_nao.txt` or `.dat`.
+
+To reuse LCAO coefficients, point `read_file_dir` to the coefficient files and set `init_wfc file txt` for text input or `init_wfc file binary` for binary input. The selected extension is required; there is no automatic format fallback. Only independent files without geometry-step indices are supported, not files accumulated with `out_app_flag`.
## Wave Function in Real Space
diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md
index 8a6922da9a..0c65dbdd3d 100644
--- a/docs/advanced/input_files/input-main.md
+++ b/docs/advanced/input_files/input-main.md
@@ -730,7 +730,7 @@
### init_wfc
-- **Type**: String
+- **Type**: Vector of string
- **Description**: The method used to initialize wavefunction coefficients. The available options and behavior depend on `basis_type`.
For `basis_type=pw`, the available options are:
@@ -740,13 +740,18 @@
- `random`: Initialize all bands with random coefficients.
- `nao`: Use numerical atomic orbitals. If the number of NAO states is smaller than `nbands`, the remaining bands are initialized randomly.
- `nao+random`: Apply an approximately 5% multiplicative random perturbation to the NAO initialization; any bands not covered by NAO states are first initialized randomly.
- - `file`: Read binary `wf*_pw.dat` files generated with `out_wfc_pw=2` from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice.
+ - `file binary`: Read binary `wf*_pw.dat` files generated with `out_wfc_pw=2` from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice. The `txt` format is not supported for PW wavefunctions.
+
+ For `basis_type=lcao`, the file options are:
+
+ - `file txt`: Read text `wf*_nao.txt` files generated with `out_wfc_lcao=1` from `read_file_dir`.
+ - `file binary`: Read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2` from `read_file_dir`.
- For `basis_type=lcao`, only `file` triggers reading existing wavefunctions. It reads text `wf*_nao.txt` files generated with `out_wfc_lcao=1` from `read_file_dir`; binary files generated with `out_wfc_lcao=2` are not supported. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. Normal `init_wfc=file` reading matches files written with the default `out_app_flag=true`, which have no geometry-step index. Files written under `WFC/` with a `g*` geometry-step index when `out_app_flag=false` are not matched automatically.
+ The selected format is required; ABACUS does not automatically detect or fall back to the other format. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. File initialization matches independent files without geometry-step indices. Files accumulated with `out_app_flag` or files under `WFC/` with a `g*` geometry-step index are not supported.
For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`.
- > Note: For `calculation=get_wf` or `calculation=get_pchg`, `init_wfc` is automatically set to `file`. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.
+ > Note: For `calculation=get_wf` or `calculation=get_pchg`, non-file initialization choices are automatically changed to the file option appropriate for the selected basis. An explicitly selected file format is preserved. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.
- **Default**: atomic
### init_chg
@@ -1954,7 +1959,7 @@
With `out_freq_ion=0`, files are written only when the electronic calculation converges or reaches `scf_nmax`; no `g*` or `e*` index is added. During structural relaxation or molecular dynamics, later ionic steps overwrite the same unindexed files. With `out_freq_ion` > 0, output is restricted to the ionic steps selected by `out_freq_ion` and is written when the electronic iteration is a multiple of `out_freq_elec`, when the calculation converges, or when it reaches `scf_nmax`. Both `g*` and `e*` indices are then added, including for a static `calculation=scf` or `calculation=nscf` run.
- For `init_wfc=file`, ABACUS automatically reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Such directly reusable files are normally generated with `out_wfc_pw=2` and `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
+ With `init_wfc file binary`, ABACUS reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Such directly reusable files are normally generated with `out_wfc_pw=2` and `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
> Note: In the 3.10-LTS version, the binary files are named `WAVEFUNC1.dat`, `WAVEFUNC2.dat`, etc.
- **Default**: 0
diff --git a/docs/advanced/scf/initialization.md b/docs/advanced/scf/initialization.md
index 8bd45c07c4..427146bf22 100644
--- a/docs/advanced/scf/initialization.md
+++ b/docs/advanced/scf/initialization.md
@@ -24,10 +24,10 @@ For `basis_type=pw`, the available options are:
* `random`: Initialize all bands with random coefficients.
* `nao`: Use numerical atomic orbitals. If the number of NAO states is smaller than `nbands`, the remaining bands are initialized randomly.
* `nao+random`: Apply an approximately 5% multiplicative random perturbation to the NAO initialization; any bands not covered by NAO states are first initialized randomly.
-* `file`: Read binary `wf*_pw.dat` files generated with [`out_wfc_pw=2`](../elec_properties/wfc.md) from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice.
+* `file binary`: Read binary `wf*_pw.dat` files generated with [`out_wfc_pw=2`](../elec_properties/wfc.md) from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice. The `txt` format is not supported for PW wavefunctions.
-For `basis_type=lcao`, only `init_wfc=file` triggers reading existing wavefunctions. LCAO wavefunctions initialize the density matrix and real-space charge density. ABACUS reads text `wf*_nao.txt` files generated with [`out_wfc_lcao=1`](../elec_properties/wfc.md) from `read_file_dir`; binary files generated with `out_wfc_lcao=2` are not supported. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. Normal `init_wfc=file` reading matches files written with the default `out_app_flag=true`, which have no geometry-step index. Files written under `WFC/` with a `g*` geometry-step index when `out_app_flag=false` are not matched automatically.
+For `basis_type=lcao`, use `init_wfc file txt` to read text `wf*_nao.txt` files generated with [`out_wfc_lcao=1`](../elec_properties/wfc.md), or `init_wfc file binary` to read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2`, from `read_file_dir`. LCAO wavefunctions initialize the density matrix and real-space charge density. The selected format is required; ABACUS does not automatically detect or fall back to the other format. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. Only independent files without geometry-step indices are supported, not files accumulated with `out_app_flag`.
For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`.
-For `calculation=get_wf` or `calculation=get_pchg`, `init_wfc` is automatically set to `file`. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.
+For `calculation=get_wf` or `calculation=get_pchg`, a non-file initialization choice is automatically changed to the file option appropriate for the selected basis. An explicitly selected file format is preserved. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.
diff --git a/docs/parameters.yaml b/docs/parameters.yaml
index f9fccde788..593a364924 100644
--- a/docs/parameters.yaml
+++ b/docs/parameters.yaml
@@ -161,7 +161,7 @@ parameters:
availability: ""
- name: init_wfc
category: System variables
- type: String
+ type: Vector of string
description: |
The method used to initialize wavefunction coefficients. The available options and behavior depend on `basis_type`.
@@ -171,13 +171,17 @@ parameters:
* `random`: Initialize all bands with random coefficients.
* `nao`: Use numerical atomic orbitals. If the number of NAO states is smaller than `nbands`, the remaining bands are initialized randomly.
* `nao+random`: Apply an approximately 5% multiplicative random perturbation to the NAO initialization; any bands not covered by NAO states are first initialized randomly.
- * `file`: Read binary `wf*_pw.dat` files generated with `out_wfc_pw=2` from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice.
+ * `file binary`: Read binary `wf*_pw.dat` files generated with `out_wfc_pw=2` from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice. The `txt` format is not supported for PW wavefunctions.
+
+ For `basis_type=lcao`, the file options are:
+ * `file txt`: Read text `wf*_nao.txt` files generated with `out_wfc_lcao=1` from `read_file_dir`.
+ * `file binary`: Read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2` from `read_file_dir`.
- For `basis_type=lcao`, only `file` triggers reading existing wavefunctions. It reads text `wf*_nao.txt` files generated with `out_wfc_lcao=1` from `read_file_dir`; binary files generated with `out_wfc_lcao=2` are not supported. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. Normal `init_wfc=file` reading matches files written with the default `out_app_flag=true`, which have no geometry-step index. Files written under `WFC/` with a `g*` geometry-step index when `out_app_flag=false` are not matched automatically.
+ The selected format is required; ABACUS does not automatically detect or fall back to the other format. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. File initialization matches independent files without geometry-step indices. Files accumulated with `out_app_flag` or files under `WFC/` with a `g*` geometry-step index are not supported.
For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`.
- [NOTE] For `calculation=get_wf` or `calculation=get_pchg`, `init_wfc` is automatically set to `file`. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.
+ [NOTE] For `calculation=get_wf` or `calculation=get_pchg`, non-file initialization choices are automatically changed to the file option appropriate for the selected basis. An explicitly selected file format is preserved. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.
default_value: atomic
unit: ""
availability: ""
@@ -3162,7 +3166,7 @@ parameters:
With `out_freq_ion=0`, files are written only when the electronic calculation converges or reaches `scf_nmax`; no `g*` or `e*` index is added. During structural relaxation or molecular dynamics, later ionic steps overwrite the same unindexed files. With `out_freq_ion` > 0, output is restricted to the ionic steps selected by `out_freq_ion` and is written when the electronic iteration is a multiple of `out_freq_elec`, when the calculation converges, or when it reaches `scf_nmax`. Both `g*` and `e*` indices are then added, including for a static `calculation=scf` or `calculation=nscf` run.
- For `init_wfc=file`, ABACUS automatically reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Such directly reusable files are normally generated with `out_wfc_pw=2` and `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
+ With `init_wfc file binary`, ABACUS reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Such directly reusable files are normally generated with `out_wfc_pw=2` and `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
[NOTE] In the 3.10-LTS version, the binary files are named `WAVEFUNC1.dat`, `WAVEFUNC2.dat`, etc.
default_value: "0"
diff --git a/source/source_esolver/esolver_ks_lcao_tddft.cpp b/source/source_esolver/esolver_ks_lcao_tddft.cpp
index f767c4b210..7324cbeb45 100644
--- a/source/source_esolver/esolver_ks_lcao_tddft.cpp
+++ b/source/source_esolver/esolver_ks_lcao_tddft.cpp
@@ -114,6 +114,7 @@ void ESolver_KS_LCAO_TDDFT
::before_all_runners(BaseCell& basecell, c
this->kv.ik2iktot,
this->kv.get_nkstot(),
this->inp_->nspin,
+ this->inp_->init_wfc_file_format == "binary",
0,
TD_info::estep_shift))
{
diff --git a/source/source_esolver/esolver_lr_lcao_tddft.cpp b/source/source_esolver/esolver_lr_lcao_tddft.cpp
index 52bd6ad0e8..0bb84df574 100644
--- a/source/source_esolver/esolver_lr_lcao_tddft.cpp
+++ b/source/source_esolver/esolver_lr_lcao_tddft.cpp
@@ -805,6 +805,7 @@ void ModuleESolver::ESolver_LR::read_ks_wfc()
this->kv.ik2iktot,
this->kv.get_nkstot(),
this->inp_->nspin,
+ this->inp_->init_wfc_file_format == "binary",
/*skip_bands=*/this->nocc_max - this->nocc_in)) {
ModuleBase::WARNING_QUIT("ESolver_LR", "read ground-state wavefunction failed.");
}
diff --git a/source/source_io/module_parameter/input_parameter.h b/source/source_io/module_parameter/input_parameter.h
index 96189eadf9..2f85d2b632 100644
--- a/source/source_io/module_parameter/input_parameter.h
+++ b/source/source_io/module_parameter/input_parameter.h
@@ -45,7 +45,8 @@ struct Input_para
double erf_height = 0; ///< the height of the energy step for reciprocal vectors
double erf_sigma = 0.1; ///< the width of the energy step for reciprocal vectors
int fft_mode = 0; ///< fftw mode 0: estimate, 1: measure, 2: patient, 3: exhaustive
- std::string init_wfc = "atomic"; ///< "file","atomic","random"
+ std::string init_wfc = "atomic"; ///< "file", "atomic", "random", etc.
+ std::string init_wfc_file_format = ""; ///< normalized file format: "txt" or "binary"
int pw_seed = 0; ///< random seed for initializing wave functions
std::string init_chg = "atomic"; ///< "file","atomic"
bool dm_to_rho = false; ///< read density matrix from npz format and calculate charge density
diff --git a/source/source_io/module_parameter/read_inp_out.cpp b/source/source_io/module_parameter/read_inp_out.cpp
index 3c47d07f21..3a0f68b9fb 100644
--- a/source/source_io/module_parameter/read_inp_out.cpp
+++ b/source/source_io/module_parameter/read_inp_out.cpp
@@ -259,7 +259,7 @@ The file-name pattern is `wfk{k}[s{spin}][g{geometry step}][e{electronic iterati
With `out_freq_ion=0`, files are written only when the electronic calculation converges or reaches `scf_nmax`; no `g*` or `e*` index is added. During structural relaxation or molecular dynamics, later ionic steps overwrite the same unindexed files. With `out_freq_ion` > 0, output is restricted to the ionic steps selected by `out_freq_ion` and is written when the electronic iteration is a multiple of `out_freq_elec`, when the calculation converges, or when it reaches `scf_nmax`. Both `g*` and `e*` indices are then added, including for a static `calculation=scf` or `calculation=nscf` run.
-For `init_wfc=file`, ABACUS automatically reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Such directly reusable files are normally generated with `out_wfc_pw=2` and `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
+With `init_wfc file binary`, ABACUS reads only unindexed binary `wf*_pw.dat` files from `read_file_dir`. Such directly reusable files are normally generated with `out_wfc_pw=2` and `out_freq_ion=0`. Text `wf*_pw.txt` files and files containing `g*` or `e*` indices are not matched automatically.
[NOTE] In the 3.10-LTS version, the binary files are named `WAVEFUNC1.dat`, `WAVEFUNC2.dat`, etc.)";
item.default_value = "0";
diff --git a/source/source_io/module_parameter/read_inp_sys.cpp b/source/source_io/module_parameter/read_inp_sys.cpp
index 73e8c12144..cc24e15fcf 100644
--- a/source/source_io/module_parameter/read_inp_sys.cpp
+++ b/source/source_io/module_parameter/read_inp_sys.cpp
@@ -9,6 +9,44 @@
namespace ModuleIO
{
+namespace
+{
+void parse_init_wfc(const std::vector& values, Input_para& input)
+{
+ if (values.empty() || values.size() > 2)
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", "init_wfc accepts one or two values");
+ }
+
+ const std::vector valid_methods
+ = {"atomic", "atomic+random", "random", "nao", "nao+random", "file"};
+ if (std::find(valid_methods.begin(), valid_methods.end(), values[0]) == valid_methods.end())
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", nofound_str(valid_methods, "init_wfc"));
+ }
+
+ input.init_wfc = values[0];
+ input.init_wfc_file_format.clear();
+ if (input.init_wfc != "file")
+ {
+ if (values.size() == 2)
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", "only init_wfc file accepts a second value");
+ }
+ return;
+ }
+
+ if (values.size() == 2)
+ {
+ if (values[1] != "txt" && values[1] != "binary")
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", "the init_wfc file format must be txt or binary");
+ }
+ input.init_wfc_file_format = values[1];
+ }
+}
+} // namespace
+
// There are some examples:
// Generallly:
// {
@@ -439,10 +477,9 @@ Theory: G. Makov and M. C. Payne, Phys. Rev. B 51, 4014 (1995).)";
}
{
Input_Item item("init_wfc");
- item.annotation = "start wave functions are from 'atomic', "
- "'atomic+random', 'random' or";
+ item.annotation = "atomic; atomic+random; random; nao; nao+random; file txt; file binary";
item.category = "System variables";
- item.type = "String";
+ item.type = "Vector of string";
item.description = R"(The method used to initialize wavefunction coefficients. The available options and behavior depend on `basis_type`.
For `basis_type=pw`, the available options are:
@@ -451,19 +488,28 @@ For `basis_type=pw`, the available options are:
* `random`: Initialize all bands with random coefficients.
* `nao`: Use numerical atomic orbitals. If the number of NAO states is smaller than `nbands`, the remaining bands are initialized randomly.
* `nao+random`: Apply an approximately 5% multiplicative random perturbation to the NAO initialization; any bands not covered by NAO states are first initialized randomly.
-* `file`: Read binary `wf*_pw.dat` files generated with `out_wfc_pw=2` from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice.
+* `file binary`: Read binary `wf*_pw.dat` files generated with `out_wfc_pw=2` from `read_file_dir`. The files must match the current k points, `nbands`, plane-wave layout, and lattice. The `txt` format is not supported for PW wavefunctions.
+
+For `basis_type=lcao`, the file options are:
+* `file txt`: Read text `wf*_nao.txt` files generated with `out_wfc_lcao=1` from `read_file_dir`.
+* `file binary`: Read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2` from `read_file_dir`.
-For `basis_type=lcao`, only `file` triggers reading existing wavefunctions. It reads text `wf*_nao.txt` files generated with `out_wfc_lcao=1` from `read_file_dir`; binary files generated with `out_wfc_lcao=2` are not supported. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. Normal `init_wfc=file` reading matches files written with the default `out_app_flag=true`, which have no geometry-step index. Files written under `WFC/` with a `g*` geometry-step index when `out_app_flag=false` are not matched automatically.
+The selected format is required; ABACUS does not automatically detect or fall back to the other format. The files must use a compatible NAO basis, match the current k-point and spin setup, and contain enough bands. File initialization matches independent files without geometry-step indices. Files accumulated with `out_app_flag` or files under `WFC/` with a `g*` geometry-step index are not supported.
For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`.
-[NOTE] For `calculation=get_wf` or `calculation=get_pchg`, `init_wfc` is automatically set to `file`. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.)";
+[NOTE] For `calculation=get_wf` or `calculation=get_pchg`, non-file initialization choices are automatically changed to the file option appropriate for the selected basis. An explicitly selected file format is preserved. If `basis_type=lcao_in_pw` is also used, the final value is `nao`.)";
item.default_value = "atomic";
item.unit = "";
+ item.read_value = [](const Input_Item& item, Parameter& para) {
+ parse_init_wfc(item.str_values, para.input);
+ };
item.reset_value = [](const Input_Item& item, Parameter& para) {
- if (para.input.calculation == "get_pchg" || para.input.calculation == "get_wf")
+ if ((para.input.calculation == "get_pchg" || para.input.calculation == "get_wf")
+ && para.input.init_wfc != "file")
{
para.input.init_wfc = "file";
+ para.input.init_wfc_file_format.clear();
}
if (para.input.basis_type == "lcao_in_pw")
{
@@ -474,9 +520,41 @@ For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`.
"basis_type is lcao_in_pw"
<< std::endl;
}
+ para.input.init_wfc_file_format.clear();
+ }
+ else if (para.input.init_wfc == "file" && para.input.init_wfc_file_format.empty())
+ {
+ para.input.init_wfc_file_format = para.input.basis_type == "lcao" ? "txt" : "binary";
+ }
+ };
+ item.get_final_value = [](Input_Item& item, const Parameter& para) {
+ item.final_value << para.input.init_wfc;
+ if (para.input.init_wfc == "file")
+ {
+ item.final_value << " " << para.input.init_wfc_file_format;
+ }
+ };
+ add_string_bcast(input.init_wfc);
+ add_string_bcast(input.init_wfc_file_format);
+ item.check_value = [](const Input_Item& item, const Parameter& para) {
+ const std::vector valid_methods
+ = {"atomic", "atomic+random", "random", "nao", "nao+random", "file"};
+ if (std::find(valid_methods.begin(), valid_methods.end(), para.input.init_wfc) == valid_methods.end())
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", nofound_str(valid_methods, "init_wfc"));
+ }
+ if (para.input.init_wfc == "file"
+ && para.input.init_wfc_file_format != "txt"
+ && para.input.init_wfc_file_format != "binary")
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", "the init_wfc file format must be txt or binary");
+ }
+ if (para.input.init_wfc == "file" && para.input.basis_type == "pw"
+ && para.input.init_wfc_file_format == "txt")
+ {
+ ModuleBase::WARNING_QUIT("ReadInput", "init_wfc file txt is not supported for basis_type=pw");
}
};
- read_sync_string(input.init_wfc);
this->add_item(item);
}
{
diff --git a/source/source_io/module_wf/read_wfc_nao.cpp b/source/source_io/module_wf/read_wfc_nao.cpp
index 330fa41947..712c4e513a 100644
--- a/source/source_io/module_wf/read_wfc_nao.cpp
+++ b/source/source_io/module_wf/read_wfc_nao.cpp
@@ -2,14 +2,76 @@
#include "source_base/parallel_common.h"
#include "source_base/timer.h"
-#include "source_io/module_wf/write_wfc_nao.h"
-
-#include "source_io/module_wf/write_wfc_nao.h"
#include "source_base/module_external/scalapack_connector.h"
#include "source_base/module_out/filename.h"
#include "source_base/tool_title.h" // use title
#include "source_base/global_function.h" // use READ_VALUE
+#include
+
+namespace
+{
+
+template
+bool read_binary_value(std::ifstream& ifs, T& value)
+{
+ ifs.read(reinterpret_cast(&value), sizeof(T));
+ return static_cast(ifs);
+}
+
+template
+bool read_record_value(std::ifstream& ifs, T& value, const bool binary)
+{
+ if (binary)
+ {
+ return read_binary_value(ifs, value);
+ }
+ ModuleBase::GlobalFunc::READ_VALUE(ifs, value);
+ return static_cast(ifs);
+}
+
+bool read_binary_wfc_data(std::ifstream& ifs, double& data)
+{
+ return read_binary_value(ifs, data);
+}
+
+bool read_binary_wfc_data(std::ifstream& ifs, float& data)
+{
+ double value = 0.0;
+ if (!read_binary_value(ifs, value))
+ {
+ return false;
+ }
+ data = static_cast(value);
+ return true;
+}
+
+bool read_binary_wfc_data(std::ifstream& ifs, std::complex& data)
+{
+ double real = 0.0;
+ double imag = 0.0;
+ if (!read_binary_value(ifs, real) || !read_binary_value(ifs, imag))
+ {
+ return false;
+ }
+ data = std::complex(real, imag);
+ return true;
+}
+
+bool read_binary_wfc_data(std::ifstream& ifs, std::complex& data)
+{
+ double real = 0.0;
+ double imag = 0.0;
+ if (!read_binary_value(ifs, real) || !read_binary_value(ifs, imag))
+ {
+ return false;
+ }
+ data = std::complex(static_cast(real), static_cast(imag));
+ return true;
+}
+
+} // namespace
+
// mohan add 2025-10-19
void ModuleIO::read_wfc_nao_one_data(std::ifstream& ifs, float& data)
{
@@ -47,6 +109,7 @@ bool ModuleIO::read_wfc_nao(
const std::vector &ik2iktot,
const int nkstot,
const int nspin,
+ const bool binary,
const int skip_band,
const int istep)
{
@@ -55,10 +118,23 @@ bool ModuleIO::read_wfc_nao(
const int nk = ekb.nr;
- const bool gamma_only = std::is_same::value;
- const int out_type = 1; // only support .txt file now
+ const bool gamma_only = std::is_same::value || std::is_same::value;
bool read_success = true;
int myrank = 0;
+#ifdef __MPI
+ MPI_Comm_rank(ParaV.comm(), &myrank);
+#endif
+ if (skip_band < 0)
+ {
+ if (myrank == 0)
+ {
+ std::cout << " Error in reading wave function files!\n"
+ << " skip_band should not be negative, but got " << skip_band << std::endl;
+ }
+ ModuleBase::timer::end("ModuleIO", "read_wfc_nao");
+ return false;
+ }
+
int nbands = ParaV.get_wfc_global_nbands(); // the global number of bands
int nlocal = ParaV.get_wfc_global_nbasis(); // the global number of basis functions
int nbands_local = ParaV.ncol_bands; // the number of bands in the local process
@@ -77,10 +153,6 @@ bool ModuleIO::read_wfc_nao(
psid.zero_out();
}
-#ifdef __MPI
- MPI_Comm_rank(ParaV.comm(), &myrank);
-#endif
-
// lambda function to read one file
auto read_one_file = [&](const std::string& ss,
std::stringstream& error_message,
@@ -88,7 +160,9 @@ bool ModuleIO::read_wfc_nao(
std::vector& ctot)
{
std::ifstream ifs;
- ifs.open(ss.c_str());
+ const std::ios_base::openmode mode
+ = binary ? (std::ios::in | std::ios::binary) : std::ios::in;
+ ifs.open(ss.c_str(), mode);
if (!ifs)
{
error_message << " Can't open file:" << ss << std::endl;
@@ -99,14 +173,39 @@ bool ModuleIO::read_wfc_nao(
std::cout << " Read NAO wave functions from " << ss << std::endl;
}
+ const auto incomplete_file = [&](const std::string& field) {
+ error_message << "The wave function file is incomplete or corrupted while reading "
+ << field << ": " << ss << std::endl;
+ ifs.close();
+ return false;
+ };
+
if (!gamma_only)
{
int ik_file = 0;
double kx = 0.0;
double ky = 0.0;
double kz = 0.0;
- ModuleBase::GlobalFunc::READ_VALUE(ifs, ik_file);
- ifs >> kx >> ky >> kz;
+ if (!read_record_value(ifs, ik_file, binary))
+ {
+ return incomplete_file("the k-point index");
+ }
+ if (binary)
+ {
+ if (!read_binary_value(ifs, kx) || !read_binary_value(ifs, ky)
+ || !read_binary_value(ifs, kz))
+ {
+ return incomplete_file("the k-point vector");
+ }
+ }
+ else
+ {
+ ifs >> kx >> ky >> kz;
+ if (!ifs)
+ {
+ return incomplete_file("the k-point vector");
+ }
+ }
if (ik_file != ik + 1)
{
error_message << "The k index read in from file do not match the k index generated by ABACUS!\n";
@@ -117,12 +216,16 @@ bool ModuleIO::read_wfc_nao(
}
}
int nbands_file = 0, nlocal_file = 0;
- ModuleBase::GlobalFunc::READ_VALUE(ifs, nbands_file);
- ModuleBase::GlobalFunc::READ_VALUE(ifs, nlocal_file);
- if (nbands > nbands_file)
+ if (!read_record_value(ifs, nbands_file, binary)
+ || !read_record_value(ifs, nlocal_file, binary))
+ {
+ return incomplete_file("the dimensions");
+ }
+ if (nbands_file < 0 || skip_band > nbands_file || nbands > nbands_file - skip_band)
{
error_message << "The number of bands to be read exceeds the number of bands in the file generated by ABACUS!\n";
error_message << " nbands in the existing file=" << nbands_file;
+ error_message << " skip_band=" << skip_band;
error_message << " nbands to be read into ABACUS=" << nbands << std::endl;
ifs.close();
return false;
@@ -140,9 +243,12 @@ bool ModuleIO::read_wfc_nao(
// the first skip_bands useless bands are read into 0th band to be overwritten
const int ib_read = std::max(i - skip_band, 0);
int ib = 0;
- ModuleBase::GlobalFunc::READ_VALUE(ifs, ib);
- ModuleBase::GlobalFunc::READ_VALUE(ifs, ekb(ik, ib_read));
- ModuleBase::GlobalFunc::READ_VALUE(ifs, wg(ik, ib_read));
+ if (!read_record_value(ifs, ib, binary)
+ || !read_record_value(ifs, ekb(ik, ib_read), binary)
+ || !read_record_value(ifs, wg(ik, ib_read), binary))
+ {
+ return incomplete_file("band " + std::to_string(i + 1) + " metadata");
+ }
if (i+1 != ib)
{
error_message << "The band index read in from file do not match the global parameter band index!\n";
@@ -153,7 +259,20 @@ bool ModuleIO::read_wfc_nao(
}
for (int j = 0; j < nlocal; j++)
{
- read_wfc_nao_one_data(ifs, ctot[ib_read * nlocal + j]);
+ bool data_read = false;
+ if (binary)
+ {
+ data_read = read_binary_wfc_data(ifs, ctot[ib_read * nlocal + j]);
+ }
+ else
+ {
+ read_wfc_nao_one_data(ifs, ctot[ib_read * nlocal + j]);
+ data_read = static_cast(ifs);
+ }
+ if (!data_read)
+ {
+ return incomplete_file("band " + std::to_string(i + 1) + " coefficients");
+ }
}
}
ifs.close();
@@ -184,8 +303,9 @@ bool ModuleIO::read_wfc_nao(
{
readin_dir = readin_dir + "WFC/";
}
+ const int read_type = binary ? 2 : 1;
std::string ss = ModuleIO::filename_output(readin_dir,"wf","nao",
- ik,ik2iktot,nspin,nkstot,out_type,out_app_flag,gamma_only,istep);
+ ik,ik2iktot,nspin,nkstot,read_type,out_app_flag,gamma_only,istep);
read_success = read_one_file(ss, error_message, ik, ctot);
errors = error_message.str();
@@ -236,8 +356,9 @@ template bool ModuleIO::read_wfc_nao(const std::string& global_readin_di
const std::vector &ik2iktot,
const int nkstot,
const int nspin,
- const int istep,
- const int skip_band);
+ const bool binary,
+ const int skip_band,
+ const int istep);
// mohan add 2025-10-19
template bool ModuleIO::read_wfc_nao(const std::string& global_readin_dir,
@@ -248,8 +369,9 @@ template bool ModuleIO::read_wfc_nao(const std::string& global_readin_dir
const std::vector &ik2iktot,
const int nkstot,
const int nspin,
- const int istep,
- const int skip_band);
+ const bool binary,
+ const int skip_band,
+ const int istep);
template bool ModuleIO::read_wfc_nao>(const std::string& global_readin_dir,
const Parallel_Orbitals& ParaV,
@@ -259,8 +381,9 @@ template bool ModuleIO::read_wfc_nao>(const std::string& gl
const std::vector &ik2iktot,
const int nkstot,
const int nspin,
- const int istep,
- const int skip_band);
+ const bool binary,
+ const int skip_band,
+ const int istep);
// mohan add 2025-10-19
template bool ModuleIO::read_wfc_nao>(const std::string& global_readin_dir,
@@ -271,5 +394,6 @@ template bool ModuleIO::read_wfc_nao>(const std::string& glo
const std::vector &ik2iktot,
const int nkstot,
const int nspin,
- const int istep,
- const int skip_band);
+ const bool binary,
+ const int skip_band,
+ const int istep);
diff --git a/source/source_io/module_wf/read_wfc_nao.h b/source/source_io/module_wf/read_wfc_nao.h
index 4abf06ae00..263b8de540 100644
--- a/source/source_io/module_wf/read_wfc_nao.h
+++ b/source/source_io/module_wf/read_wfc_nao.h
@@ -34,6 +34,7 @@ void read_wfc_nao_one_data(std::ifstream& ifs, std::complex& data);
* @param ParaV The parallel orbitals object.
* @param psid The Psi object to store the wavefunction coefficients.
* @param pelec Pointer to the ElecState object.
+ * @param binary Whether to read the binary format instead of the text format.
* @param skip_band From which band to start reading.
* @return True if the wavefunction coefficients are successfully read, false otherwise.
*/
@@ -47,6 +48,7 @@ bool read_wfc_nao(
const std::vector &ik2iktot,
const int nkstot,
const int nspin,
+ const bool binary,
const int skip_band = 0,
const int istep = -1);
diff --git a/source/source_io/test/CMakeLists.txt b/source/source_io/test/CMakeLists.txt
index 4849f0a662..0e31ae783c 100644
--- a/source/source_io/test/CMakeLists.txt
+++ b/source/source_io/test/CMakeLists.txt
@@ -242,7 +242,7 @@ add_test(
AddTest(
TARGET MODULE_IO_read_wfc_nao_test
LIBS parameter base device
- SOURCES read_wfc_nao_test.cpp ../module_wf/read_wfc_nao.cpp ../../source_psi/psi.cpp ../../source_basis/module_ao/parallel_orbitals.cpp
+ SOURCES read_wfc_nao_test.cpp ../module_wf/read_wfc_nao.cpp ../module_wf/write_wfc_nao.cpp ../../source_psi/psi.cpp ../../source_basis/module_ao/parallel_orbitals.cpp
)
add_test(
diff --git a/source/source_io/test/read_wfc_nao_test.cpp b/source/source_io/test/read_wfc_nao_test.cpp
index bf3c31adec..1e53b77900 100644
--- a/source/source_io/test/read_wfc_nao_test.cpp
+++ b/source/source_io/test/read_wfc_nao_test.cpp
@@ -7,6 +7,9 @@
#include "source_basis/module_ao/parallel_orbitals.h"
#include "source_io/module_wf/write_wfc_nao.h"
#include "source_base/module_out/filename.h"
+#include "source_base/global_function.h"
+
+#include
/************************************************
* unit test of functions in read_wfc_nao.cpp
@@ -23,6 +26,53 @@
class ReadWfcNaoTest : public ::testing::Test
{
protected:
+ int my_rank = 0;
+ int nproc = 1;
+ std::string binary_test_dir;
+
+ void SetUp() override
+ {
+#ifdef __MPI
+ MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+#endif
+ binary_test_dir = "./read_wfc_nao_binary_np" + std::to_string(nproc) + "/";
+ ModuleBase::GlobalFunc::MAKE_DIR(binary_test_dir);
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+ }
+
+ void TearDown() override
+ {
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+ if (my_rank == 0)
+ {
+ std::remove((binary_test_dir + "wf_nao.dat").c_str());
+ std::remove((binary_test_dir + "wf_nao.txt").c_str());
+ std::remove((binary_test_dir + "wfk1_nao.dat").c_str());
+ std::remove(binary_test_dir.substr(0, binary_test_dir.size() - 1).c_str());
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+ }
+
+ void initialize_parallel_orbitals(Parallel_Orbitals& para, const int nlocal, const int nbands)
+ {
+#ifdef __MPI
+ std::ofstream ofs_running, ofs_warning;
+ para.init(nlocal, nlocal, 1, MPI_COMM_WORLD);
+ para.set_nloc_wfc_Eij(nbands, ofs_running, ofs_warning);
+ para.set_desc_wfc_Eij(nlocal, nbands, para.nrow);
+#else
+ para.set_serial(nlocal, nlocal);
+ para.nrow_bands = nlocal;
+ para.ncol_bands = nbands;
+#endif
+ }
};
@@ -60,7 +110,7 @@ TEST_F(ReadWfcNaoTest,ReadWfcNao)
// Act
ModuleIO::read_wfc_nao(PARAM.sys.global_readin_dir, ParaV, psid,
- ekb, wg, ik2iktot, nkstot, nspin);
+ ekb, wg, ik2iktot, nkstot, nspin, false);
// Assert
EXPECT_NEAR(ekb(0,1),0.31482195194888534794941393,1e-5);
EXPECT_NEAR(wg(0,1),0.0,1e-5);
@@ -106,7 +156,7 @@ TEST_F(ReadWfcNaoTest, ReadWfcNaoPart)
// Act
ModuleIO::read_wfc_nao(PARAM.sys.global_readin_dir, ParaV, psid,
- ekb, wg, ik2iktot, nkstot, nspin, skip_band, nstep);
+ ekb, wg, ik2iktot, nkstot, nspin, false, skip_band, nstep);
// Assert
EXPECT_NEAR(ekb(0, 1), 7.4141254894954844445464914e-01, 1e-5);
@@ -116,6 +166,294 @@ TEST_F(ReadWfcNaoTest, ReadWfcNaoPart)
}
}
+TEST_F(ReadWfcNaoTest, ReadBinaryGamma)
+{
+ const int nbands = 2;
+ const int nlocal = 3;
+ Parallel_Orbitals para;
+ initialize_parallel_orbitals(para, nlocal, nbands);
+
+ const std::vector coefficients = {0.1, 0.2, 0.3, 1.1, 1.2, 1.3};
+ ModuleBase::matrix ekb_source(1, nbands);
+ ModuleBase::matrix wg_source(1, nbands);
+ ekb_source(0, 0) = -0.5;
+ ekb_source(0, 1) = 0.7;
+ wg_source(0, 0) = 2.0;
+ wg_source(0, 1) = 0.0;
+ if (my_rank == 0)
+ {
+ ModuleIO::wfc_nao_write2file(binary_test_dir + "wf_nao.dat",
+ coefficients.data(),
+ nlocal,
+ 0,
+ ekb_source,
+ wg_source,
+ true,
+ false);
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ psi::Psi psi_read;
+ ModuleBase::matrix ekb(1, nbands);
+ ModuleBase::matrix wg(1, nbands);
+ const std::vector ik2iktot = {0};
+ EXPECT_TRUE(ModuleIO::read_wfc_nao(binary_test_dir,
+ para,
+ psi_read,
+ ekb,
+ wg,
+ ik2iktot,
+ 1,
+ 1,
+ true));
+ EXPECT_DOUBLE_EQ(ekb(0, 0), ekb_source(0, 0));
+ EXPECT_DOUBLE_EQ(ekb(0, 1), ekb_source(0, 1));
+ EXPECT_DOUBLE_EQ(wg(0, 0), wg_source(0, 0));
+ EXPECT_DOUBLE_EQ(wg(0, 1), wg_source(0, 1));
+ if (my_rank == 0)
+ {
+ EXPECT_DOUBLE_EQ(psi_read(0, 0, 0), coefficients[0]);
+ }
+}
+
+TEST_F(ReadWfcNaoTest, ReadBinaryGammaFloat)
+{
+ const int nbands = 2;
+ const int nlocal = 3;
+ Parallel_Orbitals para;
+ initialize_parallel_orbitals(para, nlocal, nbands);
+
+ const std::vector coefficients = {0.1, 0.2, 0.3, 1.1, 1.2, 1.3};
+ ModuleBase::matrix ekb_source(1, nbands);
+ ModuleBase::matrix wg_source(1, nbands);
+ ekb_source(0, 0) = -0.5;
+ ekb_source(0, 1) = 0.7;
+ wg_source(0, 0) = 2.0;
+ wg_source(0, 1) = 0.0;
+ if (my_rank == 0)
+ {
+ ModuleIO::wfc_nao_write2file(binary_test_dir + "wf_nao.dat",
+ coefficients.data(),
+ nlocal,
+ 0,
+ ekb_source,
+ wg_source,
+ true,
+ false);
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ psi::Psi psi_read;
+ ModuleBase::matrix ekb(1, nbands);
+ ModuleBase::matrix wg(1, nbands);
+ const std::vector ik2iktot = {0};
+ EXPECT_TRUE(ModuleIO::read_wfc_nao(binary_test_dir,
+ para,
+ psi_read,
+ ekb,
+ wg,
+ ik2iktot,
+ 1,
+ 1,
+ true));
+ EXPECT_DOUBLE_EQ(ekb(0, 0), ekb_source(0, 0));
+ EXPECT_DOUBLE_EQ(ekb(0, 1), ekb_source(0, 1));
+ EXPECT_DOUBLE_EQ(wg(0, 0), wg_source(0, 0));
+ EXPECT_DOUBLE_EQ(wg(0, 1), wg_source(0, 1));
+ if (my_rank == 0)
+ {
+ EXPECT_FLOAT_EQ(psi_read(0, 0, 0), static_cast(coefficients[0]));
+ }
+}
+
+TEST_F(ReadWfcNaoTest, ReadBinaryComplex)
+{
+ const int nbands = 2;
+ const int nlocal = 3;
+ Parallel_Orbitals para;
+ initialize_parallel_orbitals(para, nlocal, nbands);
+
+ const std::vector> coefficients
+ = {{0.1, -0.1}, {0.2, -0.2}, {0.3, -0.3}, {1.1, 0.4}, {1.2, 0.5}, {1.3, 0.6}};
+ ModuleBase::matrix ekb_source(1, nbands);
+ ModuleBase::matrix wg_source(1, nbands);
+ ekb_source(0, 0) = -0.4;
+ ekb_source(0, 1) = 0.8;
+ wg_source(0, 0) = 1.0;
+ wg_source(0, 1) = 0.0;
+ if (my_rank == 0)
+ {
+ ModuleIO::wfc_nao_write2file_complex(binary_test_dir + "wfk1_nao.dat",
+ coefficients.data(),
+ nlocal,
+ 0,
+ ModuleBase::Vector3(0.25, 0.0, 0.0),
+ ekb_source,
+ wg_source,
+ true,
+ false);
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ psi::Psi> psi_read;
+ ModuleBase::matrix ekb(1, nbands);
+ ModuleBase::matrix wg(1, nbands);
+ const std::vector ik2iktot = {0};
+ EXPECT_TRUE(ModuleIO::read_wfc_nao(binary_test_dir,
+ para,
+ psi_read,
+ ekb,
+ wg,
+ ik2iktot,
+ 1,
+ 1,
+ true));
+ EXPECT_DOUBLE_EQ(ekb(0, 0), ekb_source(0, 0));
+ EXPECT_DOUBLE_EQ(ekb(0, 1), ekb_source(0, 1));
+ EXPECT_DOUBLE_EQ(wg(0, 0), wg_source(0, 0));
+ EXPECT_DOUBLE_EQ(wg(0, 1), wg_source(0, 1));
+ if (my_rank == 0)
+ {
+ EXPECT_DOUBLE_EQ(psi_read(0, 0, 0).real(), coefficients[0].real());
+ EXPECT_DOUBLE_EQ(psi_read(0, 0, 0).imag(), coefficients[0].imag());
+ }
+}
+
+TEST_F(ReadWfcNaoTest, ReadBinaryPart)
+{
+ const int nbands_file = 3;
+ const int nbands = 2;
+ const int skip_band = 1;
+ const int nlocal = 3;
+ Parallel_Orbitals para;
+ initialize_parallel_orbitals(para, nlocal, nbands);
+
+ const std::vector coefficients
+ = {0.1, 0.2, 0.3, 1.1, 1.2, 1.3, 2.1, 2.2, 2.3};
+ ModuleBase::matrix ekb_source(1, nbands_file);
+ ModuleBase::matrix wg_source(1, nbands_file);
+ for (int ib = 0; ib < nbands_file; ++ib)
+ {
+ ekb_source(0, ib) = -0.5 + ib;
+ wg_source(0, ib) = 2.0 - ib;
+ }
+ if (my_rank == 0)
+ {
+ ModuleIO::wfc_nao_write2file(binary_test_dir + "wf_nao.dat",
+ coefficients.data(),
+ nlocal,
+ 0,
+ ekb_source,
+ wg_source,
+ true,
+ false);
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ psi::Psi psi_read;
+ ModuleBase::matrix ekb(1, nbands);
+ ModuleBase::matrix wg(1, nbands);
+ const std::vector ik2iktot = {0};
+ EXPECT_TRUE(ModuleIO::read_wfc_nao(binary_test_dir,
+ para,
+ psi_read,
+ ekb,
+ wg,
+ ik2iktot,
+ 1,
+ 1,
+ true,
+ skip_band));
+ EXPECT_DOUBLE_EQ(ekb(0, 0), ekb_source(0, 1));
+ EXPECT_DOUBLE_EQ(ekb(0, 1), ekb_source(0, 2));
+ EXPECT_DOUBLE_EQ(wg(0, 0), wg_source(0, 1));
+ EXPECT_DOUBLE_EQ(wg(0, 1), wg_source(0, 2));
+ if (my_rank == 0)
+ {
+ EXPECT_DOUBLE_EQ(psi_read(0, 0, 0), coefficients[nlocal]);
+ }
+}
+
+TEST_F(ReadWfcNaoTest, BinaryDoesNotFallBackToText)
+{
+ const int nbands = 2;
+ const int nlocal = 2;
+ Parallel_Orbitals para;
+ initialize_parallel_orbitals(para, nlocal, nbands);
+
+ const std::vector coefficients = {0.25, 0.5, 0.75, 1.0};
+ ModuleBase::matrix ekb_source(1, nbands);
+ ModuleBase::matrix wg_source(1, nbands);
+ if (my_rank == 0)
+ {
+ ModuleIO::wfc_nao_write2file(binary_test_dir + "wf_nao.txt",
+ coefficients.data(),
+ nlocal,
+ 0,
+ ekb_source,
+ wg_source,
+ false,
+ false);
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ psi::Psi psi_read;
+ ModuleBase::matrix ekb(1, nbands);
+ ModuleBase::matrix wg(1, nbands);
+ const std::vector ik2iktot = {0};
+ EXPECT_FALSE(ModuleIO::read_wfc_nao(binary_test_dir,
+ para,
+ psi_read,
+ ekb,
+ wg,
+ ik2iktot,
+ 1,
+ 1,
+ true));
+}
+
+TEST_F(ReadWfcNaoTest, RejectTruncatedBinary)
+{
+ const int nbands = 2;
+ const int nlocal = 2;
+ Parallel_Orbitals para;
+ initialize_parallel_orbitals(para, nlocal, nbands);
+
+ if (my_rank == 0)
+ {
+ std::ofstream ofs(binary_test_dir + "wf_nao.dat", std::ios::binary);
+ ofs.write(reinterpret_cast(&nbands), sizeof(nbands));
+ ofs.write(reinterpret_cast(&nlocal), sizeof(nlocal));
+ }
+#ifdef __MPI
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ psi::Psi psi_read;
+ ModuleBase::matrix ekb(1, nbands);
+ ModuleBase::matrix wg(1, nbands);
+ const std::vector ik2iktot = {0};
+ EXPECT_FALSE(ModuleIO::read_wfc_nao(binary_test_dir,
+ para,
+ psi_read,
+ ekb,
+ wg,
+ ik2iktot,
+ 1,
+ 1,
+ true));
+}
+
#ifdef __MPI
diff --git a/source/source_io/test_serial/read_input_item_test.cpp b/source/source_io/test_serial/read_input_item_test.cpp
index c5815f858a..6b438a77fd 100644
--- a/source/source_io/test_serial/read_input_item_test.cpp
+++ b/source/source_io/test_serial/read_input_item_test.cpp
@@ -363,15 +363,105 @@ TEST_F(InputTest, Item_test)
}
{ // init_wfc
auto it = find_label("init_wfc", readinput.input_lists);
- param.input.init_wfc = "atomic";
+ ASSERT_NE(it, readinput.input_lists.end());
+ EXPECT_EQ(it->second.type, "Vector of string");
+ EXPECT_EQ(param.input.init_wfc, "atomic");
+ EXPECT_TRUE(param.input.init_wfc_file_format.empty());
+
+ param.input.basis_type = "lcao";
+ param.input.calculation = "scf";
+ it->second.str_values = {"file", "txt"};
+ it->second.read_value(it->second, param);
+ it->second.reset_value(it->second, param);
+ EXPECT_EQ(param.input.init_wfc, "file");
+ EXPECT_EQ(param.input.init_wfc_file_format, "txt");
+ EXPECT_NO_THROW(it->second.check_value(it->second, param));
+
+ it->second.str_values = {"file", "binary"};
+ it->second.read_value(it->second, param);
+ it->second.reset_value(it->second, param);
+ EXPECT_EQ(param.input.init_wfc, "file");
+ EXPECT_EQ(param.input.init_wfc_file_format, "binary");
+ EXPECT_NO_THROW(it->second.check_value(it->second, param));
+
+ it->second.str_values = {"file"};
+ it->second.read_value(it->second, param);
+ EXPECT_TRUE(param.input.init_wfc_file_format.empty());
+ it->second.reset_value(it->second, param);
+ EXPECT_EQ(param.input.init_wfc_file_format, "txt");
+ it->second.final_value.str("");
+ it->second.final_value.clear();
+ it->second.get_final_value(it->second, param);
+ EXPECT_EQ(it->second.final_value.str(), "file txt");
+
+ param.input.basis_type = "pw";
+ it->second.str_values = {"file"};
+ it->second.read_value(it->second, param);
+ it->second.reset_value(it->second, param);
+ EXPECT_EQ(param.input.init_wfc_file_format, "binary");
+ it->second.final_value.str("");
+ it->second.final_value.clear();
+ it->second.get_final_value(it->second, param);
+ EXPECT_EQ(it->second.final_value.str(), "file binary");
+
+ it->second.str_values = {"atomic"};
+ it->second.read_value(it->second, param);
param.input.calculation = "get_pchg";
+ param.input.basis_type = "lcao";
it->second.reset_value(it->second, param);
EXPECT_EQ(param.input.init_wfc, "file");
+ EXPECT_EQ(param.input.init_wfc_file_format, "txt");
- param.input.init_wfc = "atomic";
+ it->second.str_values = {"atomic"};
+ it->second.read_value(it->second, param);
+ param.input.calculation = "get_wf";
+ param.input.basis_type = "pw";
+ it->second.reset_value(it->second, param);
+ EXPECT_EQ(param.input.init_wfc, "file");
+ EXPECT_EQ(param.input.init_wfc_file_format, "binary");
+
+ it->second.str_values = {"file", "binary"};
+ it->second.read_value(it->second, param);
+ param.input.calculation = "get_wf";
+ param.input.basis_type = "lcao";
+ it->second.reset_value(it->second, param);
+ EXPECT_EQ(param.input.init_wfc_file_format, "binary");
+
+ it->second.str_values = {"file", "binary"};
+ it->second.read_value(it->second, param);
+ param.input.calculation = "scf";
param.input.basis_type = "lcao_in_pw";
it->second.reset_value(it->second, param);
EXPECT_EQ(param.input.init_wfc, "nao");
+ EXPECT_TRUE(param.input.init_wfc_file_format.empty());
+
+ for (const std::vector& invalid : {
+ std::vector{},
+ std::vector{"file", "txt", "extra"},
+ std::vector{"file", "json"},
+ std::vector{"atomic", "txt"},
+ std::vector{"invalid"}})
+ {
+ it->second.str_values = invalid;
+ EXPECT_EXIT(it->second.read_value(it->second, param), ::testing::ExitedWithCode(1), "");
+ }
+
+ param.input.basis_type = "pw";
+ it->second.str_values = {"file", "txt"};
+ it->second.read_value(it->second, param);
+ it->second.reset_value(it->second, param);
+ testing::internal::CaptureStdout();
+ EXPECT_EXIT(it->second.check_value(it->second, param), ::testing::ExitedWithCode(1), "");
+ output = testing::internal::GetCapturedStdout();
+ EXPECT_THAT(output, testing::HasSubstr("not supported for basis_type=pw"));
+
+ it->second.str_values = {"file", "binary"};
+ it->second.read_value(it->second, param);
+ it->second.reset_value(it->second, param);
+ EXPECT_NO_THROW(it->second.check_value(it->second, param));
+
+ EXPECT_EQ(find_label("read_wfc_lcao", readinput.input_lists), readinput.input_lists.end());
+ param.input.calculation = "get_wf";
}
{ // init_chg
auto it = find_label("init_chg", readinput.input_lists);
diff --git a/source/source_lcao/lcao_set.cpp b/source/source_lcao/lcao_set.cpp
index e2996b070b..d43f4e4907 100644
--- a/source/source_lcao/lcao_set.cpp
+++ b/source/source_lcao/lcao_set.cpp
@@ -27,7 +27,7 @@ void LCAO_domain::set_psi_occ_dm_chg(
{
if (!ModuleIO::read_wfc_nao(PARAM.globalv.global_readin_dir,
pv, *psi, pelec->ekb, pelec->wg, kv.ik2iktot,
- kv.get_nkstot(), inp.nspin))
+ kv.get_nkstot(), inp.nspin, inp.init_wfc_file_format == "binary"))
{
ModuleBase::WARNING_QUIT("set_psi_occ_dm_chg", "read electronic wave functions failed");
}