From 001af6e3957f3fe82343b1b8cf56b84acc9b328f Mon Sep 17 00:00:00 2001 From: haochong zhang Date: Wed, 26 Aug 2026 12:33:18 +0800 Subject: [PATCH 1/2] feat: support binary LCAO wavefunction input --- docs/advanced/elec_properties/wfc.md | 10 +- docs/advanced/input_files/input-main.md | 17 +- docs/advanced/scf/initialization.md | 2 +- docs/parameters.yaml | 16 +- .../source_esolver/esolver_ks_lcao_tddft.cpp | 1 + .../source_esolver/esolver_lr_lcao_tddft.cpp | 1 + .../module_parameter/input_parameter.h | 1 + .../module_parameter/read_inp_sys.cpp | 26 +- source/source_io/module_wf/read_wfc_nao.cpp | 190 ++++++++-- source/source_io/module_wf/read_wfc_nao.h | 2 + source/source_io/test/CMakeLists.txt | 2 +- source/source_io/test/read_wfc_nao_test.cpp | 342 +++++++++++++++++- .../test_serial/read_input_item_test.cpp | 22 ++ source/source_lcao/lcao_set.cpp | 2 +- 14 files changed, 594 insertions(+), 40 deletions(-) diff --git a/docs/advanced/elec_properties/wfc.md b/docs/advanced/elec_properties/wfc.md index dc96eb88844..ef43e834c7a 100644 --- a/docs/advanced/elec_properties/wfc.md +++ b/docs/advanced/elec_properties/wfc.md @@ -7,12 +7,14 @@ ABACUS is able to output electron wave functions in both PW and LCAO basis calcu To output wave functions in G-space, add one of the following keywords to the `INPUT` file while performing SCF calculation: - **PW basis**: Set [`out_wfc_pw`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-pw) to `1`. Output file format: `wfs[spin]k[kpoint]_pw.txt`, where `[spin]` is the spin channel index, and `[kpoint]` the k-point index. -- **LCAO basis**: Set [`out_wfc_lcao`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-lcao) to `1`. - - **Multi-k calculations**: Generates multiple files `wfs[spin]k[kpoint]_nao.txt`. - - **Gamma-only calculations**: `wfs[spin]_nao.txt` instead. +- **LCAO basis**: Set [`out_wfc_lcao`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-lcao) to `1` for text or `2` for binary output. + - **Multi-k calculations**: Generates multiple files `wfs[spin]k[kpoint]_nao.txt` or `.dat`. + - **Gamma-only calculations**: Generates `wfs[spin]_nao.txt` or `.dat` instead. + +To reuse LCAO coefficients, set `init_wfc file`, point `read_file_dir` to the coefficient files, and set `read_wfc_lcao` to `1` for text or `2` for binary input. The selected extension is required; there is no automatic format fallback. ## Wave Function in Real Space One can also choose to output real-space wave functions with the keyword [`out_wfc_norm`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-norm) or [`out_wfc_re_im`](https://abacus-rtd.readthedocs.io/en/latest/advanced/input_files/input-main.html#out-wfc-re-im). -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/11_wfc/lcao_ienvelope_Si2](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/11_wfc/lcao_ienvelope_Si2). \ No newline at end of file +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/11_wfc/lcao_ienvelope_Si2](https://github.com/deepmodeling/abacus-develop/tree/develop/examples/11_wfc/lcao_ienvelope_Si2). diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index e4b44876ca4..9cd943b7cff 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -19,6 +19,7 @@ - [latname](#latname) - [assume\_isolated](#assume_isolated) - [init\_wfc](#init_wfc) + - [read\_wfc\_lcao](#read_wfc_lcao) - [init\_chg](#init_chg) - [init\_vel](#init_vel) - [mem\_saver](#mem_saver) @@ -737,7 +738,7 @@ - atomic: from atomic pseudo wave functions. If they are not enough, other wave functions are initialized with random numbers. - atomic+random: add small random numbers on atomic pseudo-wavefunctions - - file: from binary files wf*.dat, which are output by setting out_wfc_pw to 2. + - file: from wave function coefficient files. For PW calculations, binary `wf*.dat` files are generated by setting `out_wfc_pw` to 2. For LCAO calculations, the text or binary format is selected by `read_wfc_lcao` and generated by setting `out_wfc_lcao` to the corresponding value. - random: random numbers - nao: from numerical atomic orbitals. If they are not enough, other wave functions are initialized with random numbers. - nao+random: add small random numbers on numerical atomic orbitals @@ -745,6 +746,20 @@ > Note: Only the file option is useful for the lcao basis set, which is mostly used when calculation is set to get_wf and get_pchg. - **Default**: atomic +### read_wfc_lcao + +- **Type**: Integer +- **Availability**: *[`basis_type`](#basis_type)==lcao* +- **Description**: The file format used when reading LCAO wave function coefficients. + + Available options are: + + - 1: text files (`.txt`) generated by setting `out_wfc_lcao` to 1. + - 2: binary files (`.dat`) generated by setting `out_wfc_lcao` to 2. + + The selected format is used directly; ABACUS does not automatically detect or fall back to the other format. Only independent wave function files are supported, not files accumulated with `out_app_flag`. +- **Default**: 1 + ### init_chg - **Type**: String diff --git a/docs/advanced/scf/initialization.md b/docs/advanced/scf/initialization.md index c01d1f2bb8a..bead5975127 100644 --- a/docs/advanced/scf/initialization.md +++ b/docs/advanced/scf/initialization.md @@ -21,4 +21,4 @@ Atomic wave function is read from pseudopotential file under keyword `PP_PSWFC`, When `basis_type=lcao`, we further support reading of initial wavefunction by setting `init_wfc` to `file`. In LCAO code, wave function is used to initialize density matrix and real-space charge density. -For such purpose, a file containing wavefunction must be prepared. Such files can be generated from previous calculations with [`out_wfc_lcao 1`](../elec_properties/wfc.md). +For such purpose, files containing wavefunction coefficients must be prepared. They can be generated by a previous calculation with [`out_wfc_lcao 1`](../elec_properties/wfc.md) for text files or `out_wfc_lcao 2` for binary files. Set `read_wfc_lcao` to the same value when reading them; ABACUS does not automatically switch between formats. diff --git a/docs/parameters.yaml b/docs/parameters.yaml index 2df3f8fc18d..b792e87458c 100644 --- a/docs/parameters.yaml +++ b/docs/parameters.yaml @@ -168,7 +168,7 @@ parameters: Available options are: * atomic: from atomic pseudo wave functions. If they are not enough, other wave functions are initialized with random numbers. * atomic+random: add small random numbers on atomic pseudo-wavefunctions - * file: from binary files wf*.dat, which are output by setting out_wfc_pw to 2. + * file: from wave function coefficient files. For PW calculations, binary `wf*.dat` files are generated by setting `out_wfc_pw` to 2. For LCAO calculations, the text or binary format is selected by `read_wfc_lcao` and generated by setting `out_wfc_lcao` to the corresponding value. * random: random numbers * nao: from numerical atomic orbitals. If they are not enough, other wave functions are initialized with random numbers. * nao+random: add small random numbers on numerical atomic orbitals @@ -177,6 +177,20 @@ parameters: default_value: atomic unit: "" availability: "" + - name: read_wfc_lcao + category: System variables + type: Integer + description: | + The file format used when reading LCAO wave function coefficients. + + Available options are: + * 1: text files (`.txt`) generated by setting `out_wfc_lcao` to 1. + * 2: binary files (`.dat`) generated by setting `out_wfc_lcao` to 2. + + The selected format is used directly; ABACUS does not automatically detect or fall back to the other format. Only independent wave function files are supported, not files accumulated with `out_app_flag`. + default_value: "1" + unit: "" + availability: basis_type==lcao - name: init_chg category: System variables type: String diff --git a/source/source_esolver/esolver_ks_lcao_tddft.cpp b/source/source_esolver/esolver_ks_lcao_tddft.cpp index f767c4b2107..f7f9ca0f560 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_->read_wfc_lcao, 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 52bd6ad0e89..fbfd735ace3 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_->read_wfc_lcao, /*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 196b11fad9f..7b0ed8cf0e2 100644 --- a/source/source_io/module_parameter/input_parameter.h +++ b/source/source_io/module_parameter/input_parameter.h @@ -46,6 +46,7 @@ struct Input_para 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" + int read_wfc_lcao = 1; ///< LCAO wavefunction input format: 1 text, 2 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_sys.cpp b/source/source_io/module_parameter/read_inp_sys.cpp index 3c9bff3935a..03037d0fb12 100644 --- a/source/source_io/module_parameter/read_inp_sys.cpp +++ b/source/source_io/module_parameter/read_inp_sys.cpp @@ -448,7 +448,7 @@ Theory: G. Makov and M. C. Payne, Phys. Rev. B 51, 4014 (1995).)"; Available options are: * atomic: from atomic pseudo wave functions. If they are not enough, other wave functions are initialized with random numbers. * atomic+random: add small random numbers on atomic pseudo-wavefunctions -* file: from binary files wf*.dat, which are output by setting out_wfc_pw to 2. +* file: from wave function coefficient files. For PW calculations, binary `wf*.dat` files are generated by setting `out_wfc_pw` to 2. For LCAO calculations, the text or binary format is selected by `read_wfc_lcao` and generated by setting `out_wfc_lcao` to the corresponding value. * random: random numbers * nao: from numerical atomic orbitals. If they are not enough, other wave functions are initialized with random numbers. * nao+random: add small random numbers on numerical atomic orbitals @@ -474,6 +474,30 @@ Available options are: read_sync_string(input.init_wfc); this->add_item(item); } + { + Input_Item item("read_wfc_lcao"); + item.annotation = "LCAO wave function input format: 1 text, 2 binary"; + item.category = "System variables"; + item.type = "Integer"; + item.description = R"(The file format used when reading LCAO wave function coefficients. + +Available options are: +* 1: text files (`.txt`) generated by setting `out_wfc_lcao` to 1. +* 2: binary files (`.dat`) generated by setting `out_wfc_lcao` to 2. + +The selected format is used directly; ABACUS does not automatically detect or fall back to the other format. Only independent wave function files are supported, not files accumulated with `out_app_flag`.)"; + item.default_value = "1"; + item.unit = ""; + item.set_availability("basis_type==lcao"); + read_sync_int(input.read_wfc_lcao); + item.check_value = [](const Input_Item& item, const Parameter& para) { + if (para.input.read_wfc_lcao != 1 && para.input.read_wfc_lcao != 2) + { + ModuleBase::WARNING_QUIT("ReadInput", "read_wfc_lcao should be 1 or 2"); + } + }; + this->add_item(item); + } { Input_Item item("init_chg"); item.annotation = "start charge is from 'atomic' or file"; diff --git a/source/source_io/module_wf/read_wfc_nao.cpp b/source/source_io/module_wf/read_wfc_nao.cpp index 662b39778d2..1e318bb2922 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 int read_type, const int skip_band, const int istep) { @@ -55,10 +118,34 @@ 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; + const bool binary = (read_type == 2); bool read_success = true; int myrank = 0; +#ifdef __MPI + MPI_Comm_rank(ParaV.comm(), &myrank); +#endif + if (read_type != 1 && read_type != 2) + { + if (myrank == 0) + { + std::cout << " Error in reading wave function files!\n" + << " read_wfc_lcao should be 1 or 2, but got " << read_type << std::endl; + } + ModuleBase::timer::end("ModuleIO", "read_wfc_nao"); + return false; + } + 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 @@ -72,10 +159,6 @@ bool ModuleIO::read_wfc_nao( } psid.resize(nk, nbands_local, nlocal_local); -#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, @@ -83,7 +166,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; @@ -94,14 +179,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"; @@ -112,12 +222,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; @@ -135,9 +249,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"; @@ -148,7 +265,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(); @@ -180,7 +310,7 @@ bool ModuleIO::read_wfc_nao( readin_dir = readin_dir + "WFC/"; } 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(); @@ -231,8 +361,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 int read_type, + const int skip_band, + const int istep); // mohan add 2025-10-19 template bool ModuleIO::read_wfc_nao(const std::string& global_readin_dir, @@ -243,8 +374,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 int read_type, + const int skip_band, + const int istep); template bool ModuleIO::read_wfc_nao>(const std::string& global_readin_dir, const Parallel_Orbitals& ParaV, @@ -254,8 +386,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 int read_type, + const int skip_band, + const int istep); // mohan add 2025-10-19 template bool ModuleIO::read_wfc_nao>(const std::string& global_readin_dir, @@ -266,5 +399,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 int read_type, + 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 4abf06ae007..80c27e33ef4 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 read_type The input file type: 1 for text and 2 for binary. * @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 int read_type, 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 4849f0a6621..0e31ae783ce 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 bf3c31adec1..71165948e4c 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, 1); // 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, 1, 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, + 2)); + 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, + 2)); + 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, + 2)); + 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, + 2, + 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, + 2)); +} + +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, + 2)); +} + #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 c5815f858ae..5e3d74a6500 100644 --- a/source/source_io/test_serial/read_input_item_test.cpp +++ b/source/source_io/test_serial/read_input_item_test.cpp @@ -373,6 +373,28 @@ TEST_F(InputTest, Item_test) it->second.reset_value(it->second, param); EXPECT_EQ(param.input.init_wfc, "nao"); } + { // read_wfc_lcao + auto it = find_label("read_wfc_lcao", readinput.input_lists); + EXPECT_NE(it, readinput.input_lists.end()); + EXPECT_EQ(param.input.read_wfc_lcao, 1); + EXPECT_EQ(it->second.get_availability(), "basis_type==lcao"); + + it->second.str_values = {"2"}; + it->second.read_value(it->second, param); + EXPECT_EQ(param.input.read_wfc_lcao, 2); + + param.input.read_wfc_lcao = 0; + testing::internal::CaptureStdout(); + EXPECT_EXIT(it->second.check_value(it->second, param), ::testing::ExitedWithCode(1), ""); + output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, testing::HasSubstr("NOTICE")); + + param.input.read_wfc_lcao = 3; + testing::internal::CaptureStdout(); + EXPECT_EXIT(it->second.check_value(it->second, param), ::testing::ExitedWithCode(1), ""); + output = testing::internal::GetCapturedStdout(); + EXPECT_THAT(output, testing::HasSubstr("NOTICE")); + } { // init_chg auto it = find_label("init_chg", readinput.input_lists); param.input.init_chg = "get_pchg"; diff --git a/source/source_lcao/lcao_set.cpp b/source/source_lcao/lcao_set.cpp index dda20f80580..206409b0d8f 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.read_wfc_lcao)) { ModuleBase::WARNING_QUIT("set_psi_occ_dm_chg", "read electronic wave functions failed"); } From a8d6970b5f7d6a3da1c62aed3418f677abf8046b Mon Sep 17 00:00:00 2001 From: haochong zhang Date: Sat, 29 Aug 2026 20:50:13 +0800 Subject: [PATCH 2/2] feat: select wavefunction file format via init_wfc --- docs/advanced/elec_properties/wfc.md | 4 +- docs/advanced/input_files/input-main.md | 30 ++--- docs/advanced/scf/initialization.md | 6 +- docs/parameters.yaml | 28 ++--- .../source_esolver/esolver_ks_lcao_tddft.cpp | 2 +- .../source_esolver/esolver_lr_lcao_tddft.cpp | 2 +- .../module_parameter/input_parameter.h | 4 +- .../module_parameter/read_inp_out.cpp | 2 +- .../module_parameter/read_inp_sys.cpp | 110 +++++++++++++----- source/source_io/module_wf/read_wfc_nao.cpp | 22 +--- source/source_io/module_wf/read_wfc_nao.h | 4 +- source/source_io/test/read_wfc_nao_test.cpp | 16 +-- .../test_serial/read_input_item_test.cpp | 104 ++++++++++++++--- source/source_lcao/lcao_set.cpp | 2 +- 14 files changed, 214 insertions(+), 122 deletions(-) diff --git a/docs/advanced/elec_properties/wfc.md b/docs/advanced/elec_properties/wfc.md index d9f6fddbdb9..a3f6d52f6c8 100644 --- a/docs/advanced/elec_properties/wfc.md +++ b/docs/advanced/elec_properties/wfc.md @@ -14,11 +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`, [`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, set `init_wfc=file`, point `read_file_dir` to the coefficient files, and set `read_wfc_lcao=1` for text or `read_wfc_lcao=2` 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`. +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 4309303efb7..0c65dbdd3da 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -19,7 +19,6 @@ - [latname](#latname) - [assume\_isolated](#assume_isolated) - [init\_wfc](#init_wfc) - - [read\_wfc\_lcao](#read_wfc_lcao) - [init\_chg](#init_chg) - [init\_vel](#init_vel) - [mem\_saver](#mem_saver) @@ -731,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: @@ -741,28 +740,19 @@ - `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`, only `file` triggers reading existing wavefunctions. Set `read_wfc_lcao=1` to read text `wf*_nao.txt` files generated with `out_wfc_lcao=1`, or set `read_wfc_lcao=2` to read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2`, from `read_file_dir`. 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. Normal `init_wfc=file` reading 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`, the file options are: - For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`. + - `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`. - > 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`. -- **Default**: atomic + 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. -### read_wfc_lcao - -- **Type**: Integer -- **Availability**: *[`basis_type`](#basis_type)==lcao* -- **Description**: The file format used when reading LCAO wave function coefficients. - - Available options are: - - - 1: text files (`.txt`) generated by setting `out_wfc_lcao` to 1. - - 2: binary files (`.dat`) generated by setting `out_wfc_lcao` to 2. + For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`. - The selected format is used directly; ABACUS does not automatically detect or fall back to the other format. Only independent wave function files are supported, not files accumulated with `out_app_flag`. -- **Default**: 1 + > 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 @@ -1969,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 cc23a33a1aa..427146bf223 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. Set `read_wfc_lcao=1` to read text `wf*_nao.txt` files generated with [`out_wfc_lcao=1`](../elec_properties/wfc.md), or set `read_wfc_lcao=2` to read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2`, from `read_file_dir`. 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`, 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 a458accd26d..593a3649240 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,30 +171,20 @@ 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. Set `read_wfc_lcao=1` to read text `wf*_nao.txt` files generated with `out_wfc_lcao=1`, or set `read_wfc_lcao=2` to read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2`, from `read_file_dir`. 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. Normal `init_wfc=file` reading 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. + 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: "" - - name: read_wfc_lcao - category: System variables - type: Integer - description: | - The file format used when reading LCAO wave function coefficients. - - Available options are: - * 1: text files (`.txt`) generated by setting `out_wfc_lcao` to 1. - * 2: binary files (`.dat`) generated by setting `out_wfc_lcao` to 2. - - The selected format is used directly; ABACUS does not automatically detect or fall back to the other format. Only independent wave function files are supported, not files accumulated with `out_app_flag`. - default_value: "1" - unit: "" - availability: basis_type==lcao - name: init_chg category: System variables type: String @@ -3176,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 f7f9ca0f560..7324cbeb453 100644 --- a/source/source_esolver/esolver_ks_lcao_tddft.cpp +++ b/source/source_esolver/esolver_ks_lcao_tddft.cpp @@ -114,7 +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_->read_wfc_lcao, + 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 fbfd735ace3..0bb84df574e 100644 --- a/source/source_esolver/esolver_lr_lcao_tddft.cpp +++ b/source/source_esolver/esolver_lr_lcao_tddft.cpp @@ -805,7 +805,7 @@ void ModuleESolver::ESolver_LR::read_ks_wfc() this->kv.ik2iktot, this->kv.get_nkstot(), this->inp_->nspin, - this->inp_->read_wfc_lcao, + 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 619b3e9a174..2f85d2b6323 100644 --- a/source/source_io/module_parameter/input_parameter.h +++ b/source/source_io/module_parameter/input_parameter.h @@ -45,8 +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" - int read_wfc_lcao = 1; ///< LCAO wavefunction input format: 1 text, 2 binary + 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 3c47d07f213..3a0f68b9fb7 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 55fbf36cab6..cc24e15fcfa 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. Set `read_wfc_lcao=1` to read text `wf*_nao.txt` files generated with `out_wfc_lcao=1`, or set `read_wfc_lcao=2` to read binary `wf*_nao.dat` files generated with `out_wfc_lcao=2`, from `read_file_dir`. 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. Normal `init_wfc=file` reading 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. +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,31 +520,39 @@ 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"; } }; - read_sync_string(input.init_wfc); - this->add_item(item); - } - { - Input_Item item("read_wfc_lcao"); - item.annotation = "LCAO wave function input format: 1 text, 2 binary"; - item.category = "System variables"; - item.type = "Integer"; - item.description = R"(The file format used when reading LCAO wave function coefficients. - -Available options are: -* 1: text files (`.txt`) generated by setting `out_wfc_lcao` to 1. -* 2: binary files (`.dat`) generated by setting `out_wfc_lcao` to 2. - -The selected format is used directly; ABACUS does not automatically detect or fall back to the other format. Only independent wave function files are supported, not files accumulated with `out_app_flag`.)"; - item.default_value = "1"; - item.unit = ""; - item.set_availability("basis_type==lcao"); - read_sync_int(input.read_wfc_lcao); + 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) { - if (para.input.read_wfc_lcao != 1 && para.input.read_wfc_lcao != 2) + 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", "read_wfc_lcao should be 1 or 2"); + ModuleBase::WARNING_QUIT("ReadInput", "init_wfc file txt is not supported for basis_type=pw"); } }; 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 bfbdbbd4454..712c4e513ae 100644 --- a/source/source_io/module_wf/read_wfc_nao.cpp +++ b/source/source_io/module_wf/read_wfc_nao.cpp @@ -109,7 +109,7 @@ bool ModuleIO::read_wfc_nao( const std::vector &ik2iktot, const int nkstot, const int nspin, - const int read_type, + const bool binary, const int skip_band, const int istep) { @@ -119,22 +119,11 @@ bool ModuleIO::read_wfc_nao( const int nk = ekb.nr; const bool gamma_only = std::is_same::value || std::is_same::value; - const bool binary = (read_type == 2); bool read_success = true; int myrank = 0; #ifdef __MPI MPI_Comm_rank(ParaV.comm(), &myrank); #endif - if (read_type != 1 && read_type != 2) - { - if (myrank == 0) - { - std::cout << " Error in reading wave function files!\n" - << " read_wfc_lcao should be 1 or 2, but got " << read_type << std::endl; - } - ModuleBase::timer::end("ModuleIO", "read_wfc_nao"); - return false; - } if (skip_band < 0) { if (myrank == 0) @@ -314,6 +303,7 @@ 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,read_type,out_app_flag,gamma_only,istep); @@ -366,7 +356,7 @@ template bool ModuleIO::read_wfc_nao(const std::string& global_readin_di const std::vector &ik2iktot, const int nkstot, const int nspin, - const int read_type, + const bool binary, const int skip_band, const int istep); @@ -379,7 +369,7 @@ template bool ModuleIO::read_wfc_nao(const std::string& global_readin_dir const std::vector &ik2iktot, const int nkstot, const int nspin, - const int read_type, + const bool binary, const int skip_band, const int istep); @@ -391,7 +381,7 @@ template bool ModuleIO::read_wfc_nao>(const std::string& gl const std::vector &ik2iktot, const int nkstot, const int nspin, - const int read_type, + const bool binary, const int skip_band, const int istep); @@ -404,6 +394,6 @@ template bool ModuleIO::read_wfc_nao>(const std::string& glo const std::vector &ik2iktot, const int nkstot, const int nspin, - const int read_type, + 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 80c27e33ef4..263b8de5403 100644 --- a/source/source_io/module_wf/read_wfc_nao.h +++ b/source/source_io/module_wf/read_wfc_nao.h @@ -34,7 +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 read_type The input file type: 1 for text and 2 for binary. + * @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. */ @@ -48,7 +48,7 @@ bool read_wfc_nao( const std::vector &ik2iktot, const int nkstot, const int nspin, - const int read_type, + const bool binary, const int skip_band = 0, const int istep = -1); diff --git a/source/source_io/test/read_wfc_nao_test.cpp b/source/source_io/test/read_wfc_nao_test.cpp index 71165948e4c..1e53b779003 100644 --- a/source/source_io/test/read_wfc_nao_test.cpp +++ b/source/source_io/test/read_wfc_nao_test.cpp @@ -110,7 +110,7 @@ TEST_F(ReadWfcNaoTest,ReadWfcNao) // Act ModuleIO::read_wfc_nao(PARAM.sys.global_readin_dir, ParaV, psid, - ekb, wg, ik2iktot, nkstot, nspin, 1); + 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); @@ -156,7 +156,7 @@ TEST_F(ReadWfcNaoTest, ReadWfcNaoPart) // Act ModuleIO::read_wfc_nao(PARAM.sys.global_readin_dir, ParaV, psid, - ekb, wg, ik2iktot, nkstot, nspin, 1, skip_band, nstep); + ekb, wg, ik2iktot, nkstot, nspin, false, skip_band, nstep); // Assert EXPECT_NEAR(ekb(0, 1), 7.4141254894954844445464914e-01, 1e-5); @@ -207,7 +207,7 @@ TEST_F(ReadWfcNaoTest, ReadBinaryGamma) ik2iktot, 1, 1, - 2)); + 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)); @@ -259,7 +259,7 @@ TEST_F(ReadWfcNaoTest, ReadBinaryGammaFloat) ik2iktot, 1, 1, - 2)); + 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)); @@ -313,7 +313,7 @@ TEST_F(ReadWfcNaoTest, ReadBinaryComplex) ik2iktot, 1, 1, - 2)); + 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)); @@ -370,7 +370,7 @@ TEST_F(ReadWfcNaoTest, ReadBinaryPart) ik2iktot, 1, 1, - 2, + true, skip_band)); EXPECT_DOUBLE_EQ(ekb(0, 0), ekb_source(0, 1)); EXPECT_DOUBLE_EQ(ekb(0, 1), ekb_source(0, 2)); @@ -419,7 +419,7 @@ TEST_F(ReadWfcNaoTest, BinaryDoesNotFallBackToText) ik2iktot, 1, 1, - 2)); + true)); } TEST_F(ReadWfcNaoTest, RejectTruncatedBinary) @@ -451,7 +451,7 @@ TEST_F(ReadWfcNaoTest, RejectTruncatedBinary) ik2iktot, 1, 1, - 2)); + true)); } 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 5e3d74a6500..6b438a77fd0 100644 --- a/source/source_io/test_serial/read_input_item_test.cpp +++ b/source/source_io/test_serial/read_input_item_test.cpp @@ -363,37 +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"); - } - { // read_wfc_lcao - auto it = find_label("read_wfc_lcao", readinput.input_lists); - EXPECT_NE(it, readinput.input_lists.end()); - EXPECT_EQ(param.input.read_wfc_lcao, 1); - EXPECT_EQ(it->second.get_availability(), "basis_type==lcao"); + 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), ""); + } - it->second.str_values = {"2"}; + param.input.basis_type = "pw"; + it->second.str_values = {"file", "txt"}; it->second.read_value(it->second, param); - EXPECT_EQ(param.input.read_wfc_lcao, 2); - - param.input.read_wfc_lcao = 0; + 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("NOTICE")); + EXPECT_THAT(output, testing::HasSubstr("not supported for basis_type=pw")); - param.input.read_wfc_lcao = 3; - testing::internal::CaptureStdout(); - EXPECT_EXIT(it->second.check_value(it->second, param), ::testing::ExitedWithCode(1), ""); - output = testing::internal::GetCapturedStdout(); - EXPECT_THAT(output, testing::HasSubstr("NOTICE")); + 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 fdb5caa5276..d43f4e4907c 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, inp.read_wfc_lcao)) + kv.get_nkstot(), inp.nspin, inp.init_wfc_file_format == "binary")) { ModuleBase::WARNING_QUIT("set_psi_occ_dm_chg", "read electronic wave functions failed"); }