diff --git a/docs/advanced/elec_properties/hs_matrix.md b/docs/advanced/elec_properties/hs_matrix.md index 5adf14e3971..6e4aa48423b 100644 --- a/docs/advanced/elec_properties/hs_matrix.md +++ b/docs/advanced/elec_properties/hs_matrix.md @@ -39,7 +39,7 @@ The output filenames depend on the k-point algorithm and `nspin`: Here `${k}` is the one-based k-point index. For `nspin = 2`, the overlap matrix is spin-independent, so only one overlap file is written for each physical k point. The gamma-only algorithm does not support `nspin = 4`; use the multi-k algorithm with an explicit Gamma-only `KPT` file for a noncollinear calculation at Gamma. -When `out_app_flag` is false, `g${step}` is inserted before `_nao`, where `${step}` is the one-based ionic-step index. For example, the first spin channel at the first k point and first ionic step is written to `hk1s1g1_nao.txt`. +When `out_app_flag` is not 1, `g${step}` is inserted before `_nao`, where `${step}` is the one-based ionic-step index. For example, the first spin channel at the first k point and first ionic step is written to `hk1s1g1_nao.txt`. Each output block starts with a comment header containing the one-based ionic-step index, filename, `gamma only` flag, and matrix dimensions. It is followed by `Row 1`, `Row 2`, and so on. Each row contains the matrix elements from the diagonal through the upper triangle. @@ -57,7 +57,7 @@ For `out_hsk 2`, the filenames in the table above use `.dat` instead of `.txt`. The file therefore contains `sizeof(int) + N(N+1)/2 * sizeof(double)` bytes for a gamma-only record and `sizeof(int) + N(N+1) * sizeof(double)` bytes for a multi-k or spinor record. The format uses the host integer representation and byte order and is intended for readers using a compatible ABI. -When `out_app_flag` is true, the first ionic step truncates the shared file and every later step appends another complete record. When it is false, each ionic step has a separate filename containing `g${step}` before `_nao`. +When `out_app_flag` is 1, the first ionic step truncates the shared file and every later step appends another complete record. When it is not 1, each ionic step has a separate filename containing `g${step}` before `_nao`. ## out_hsr @@ -95,7 +95,7 @@ In gamma-only mode, every generated file reports one Bravais lattice vector and ### Native Binary CSR Format -Set `out_hsr 2` to write the same H(R) and S(R) matrix sets with a `.dat` suffix. For example, an `nspin = 2` calculation writes `hrs1_nao.dat`, `hrs2_nao.dat`, and `sr_nao.dat`. When `out_app_flag` is false, the one-based ionic step is included before `_nao`, for example `hrs1g1_nao.dat` and `srg1_nao.dat`. +Set `out_hsr 2` to write the same H(R) and S(R) matrix sets with a `.dat` suffix. For example, an `nspin = 2` calculation writes `hrs1_nao.dat`, `hrs2_nao.dat`, and `sr_nao.dat`. When `out_app_flag` is not 1, the one-based ionic step is included before `_nao`, for example `hrs1g1_nao.dat` and `srg1_nao.dat`. Each ionic step is a complete record with no padding or self-describing header: @@ -107,7 +107,7 @@ Each ionic step is a complete record with no padding or self-describing header: All R blocks stored by the internal HContainer are present, including blocks with zero nonzero values. The sparse threshold is `1e-10`, matching text CSR output. The format uses the host integer representation and byte order and therefore requires a compatible ABI. It does not contain unit-cell, spin, or matrix-label metadata; those are determined by the calculation input and filename. -When `out_app_flag` is true, the first ionic step truncates the shared file and later ionic steps append complete records. Otherwise every ionic step is written to its own file. +When `out_app_flag` is 1, the first ionic step truncates the shared file and later ionic steps append complete records. Otherwise every ionic step is written to its own file. ### NPZ Format diff --git a/docs/advanced/elec_properties/position_matrix.md b/docs/advanced/elec_properties/position_matrix.md index c504a866b64..38743d5b65b 100644 --- a/docs/advanced/elec_properties/position_matrix.md +++ b/docs/advanced/elec_properties/position_matrix.md @@ -18,7 +18,7 @@ Each file or each section of the appended file starts with "STEP: " followed by Each block here contains the matrix for the corresponding cell. There are three columns in each block, giving the matrix elements in x, y, z directions, respectively. There are altogether nbasis * nbasis lines in each block, which emulates the matrix elements. -In molecular dynamics (MD) calculations, if [out_app_flag](../input_files/input-main.md#out_app_flag) is set to true, then `data-rR-tr` is written in an append manner. Otherwise, output files will be put in a separate directory, `matrix`, and named as `$x`_data-rR-tr, where `$x` is the number of MD step. In addition, the output frequency is controlled by [out_freq_ion](../input_files/input-main.md#out_freq_ion). For example, if we are running a 10-step MD with out_freq_ion = 3, then `$x` will be 0, 3, 6, and 9. +In molecular dynamics (MD) calculations, if [out_app_flag](../input_files/input-main.md#out_app_flag) is set to 1, then `data-rR-tr` is written in an append manner. Otherwise, output files will be put in a separate directory, `matrix`, and named as `$x`_data-rR-tr, where `$x` is the number of MD step. In addition, the output frequency is controlled by [out_freq_ion](../input_files/input-main.md#out_freq_ion). For example, if we are running a 10-step MD with out_freq_ion = 3, then `$x` will be 0, 3, 6, and 9. ## get_s We also offer the option of only calculating the position matrix without running SCF. For that purpose, in `INPUT` file we need to set the keyword [calculation](../input_files/input-main.md#calculation) to `get_s`, and [out_mat_r](../input_files/input-main.md#out_mat_r) to `true`. diff --git a/docs/advanced/elec_properties/wfc.md b/docs/advanced/elec_properties/wfc.md index 354d8844fc4..562b0c4b32b 100644 --- a/docs/advanced/elec_properties/wfc.md +++ b/docs/advanced/elec_properties/wfc.md @@ -18,7 +18,7 @@ The [`init_wfc file binary`](../scf/initialization.md#wavefunction) path reads o 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`. +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=1`. ## Wave Function in Real Space diff --git a/docs/advanced/scf/initialization.md b/docs/advanced/scf/initialization.md index 427146bf223..4517b691b44 100644 --- a/docs/advanced/scf/initialization.md +++ b/docs/advanced/scf/initialization.md @@ -26,7 +26,7 @@ For `basis_type=pw`, the available options are: * `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 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`, 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`, 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=1`. For `basis_type=lcao_in_pw`, `init_wfc` is automatically set to `nao`. diff --git a/examples/17_relax/04_relax_with_output_lcao/INPUT b/examples/17_relax/04_relax_with_output_lcao/INPUT index 05125b6fa1e..155b3ecc32c 100644 --- a/examples/17_relax/04_relax_with_output_lcao/INPUT +++ b/examples/17_relax/04_relax_with_output_lcao/INPUT @@ -34,7 +34,6 @@ out_dmr 1 out_dos 1 out_band 1 out_stru 1 -out_app_flag 0 out_mat_l 1 out_mat_r 1 @@ -42,3 +41,5 @@ out_mat_t 1 #out_mat_dh 1 out_freq_ion 2 + +out_app_flag 2 diff --git a/examples/18_md/02_lcao_output/INPUT b/examples/18_md/02_lcao_output/INPUT index 7c29d6e1355..c8333b2f0e8 100644 --- a/examples/18_md/02_lcao_output/INPUT +++ b/examples/18_md/02_lcao_output/INPUT @@ -36,3 +36,5 @@ md_tchain 1 dft_functional hse restart_save 1 + +out_app_flag 0 diff --git a/source/source_base/global_file.cpp b/source/source_base/global_file.cpp index 76a16036be7..1889357c2c8 100644 --- a/source/source_base/global_file.cpp +++ b/source/source_base/global_file.cpp @@ -30,7 +30,6 @@ void ModuleBase::Global_File::make_dir_out( const bool &restart, const bool out_alllog, const std::string &global_out_dir, - const std::string &global_stru_dir, const std::string &global_matrix_dir, const std::string &global_wfc_dir, const std::string &global_mlkedf_descriptor_dir, @@ -84,45 +83,6 @@ void ModuleBase::Global_File::make_dir_out( MPI_Barrier(MPI_COMM_WORLD); #endif - if(calculation == "md") - { - int make_dir_stru = 0; - - times = 0; - while(times0) { break; -} - ++times; - } - -#ifdef __MPI - if(make_dir_stru==0) - { - std::cout << " CAN NOT MAKE THE STRU DIR......." << std::endl; - ModuleBase::QUIT(); - } - MPI_Barrier(MPI_COMM_WORLD); -#endif - } - // make dir for HS matrix output in md calculation if((out_dir) && calculation == "md") { diff --git a/source/source_base/global_file.h b/source/source_base/global_file.h index d051b5e81c4..4ce5adb18d3 100644 --- a/source/source_base/global_file.h +++ b/source/source_base/global_file.h @@ -28,7 +28,6 @@ namespace Global_File const bool &restart, const bool out_alllog, const std::string &global_out_dir, - const std::string &global_stru_dir, const std::string &global_matrix_dir, const std::string &global_wfc_dir, const std::string &global_mlkedf_descriptor_dir, diff --git a/source/source_base/module_out/filename.cpp b/source/source_base/module_out/filename.cpp index 4dd86dc2bea..c7fa58fb9eb 100644 --- a/source/source_base/module_out/filename.cpp +++ b/source/source_base/module_out/filename.cpp @@ -14,7 +14,7 @@ std::string filename_output( const int nspin, const int nkstot, const int out_type, - const bool out_app_flag, + const int out_app_flag, const bool gamma_only, const int istep, const int iter) @@ -97,14 +97,14 @@ std::string filename_output( } std::string istep_block - = (istep >= 0 && (!out_app_flag)) + = (istep >= 0 && (out_app_flag != 1)) ? "g" + std::to_string(istep + 1) // istep starts from 0 - : ""; // only when istep >= 0 and out_app_flag is false will write each wfc to a separate file + : ""; // only when istep >= 0 and out_app_flag is not append mode will write each wfc to a separate file std::string iter_block - = (iter >= 0 && (!out_app_flag)) + = (iter >= 0 && (out_app_flag != 1)) ? "e" + std::to_string(iter) // iter starts from 1 - : ""; // only when istep >= 0 and out_app_flag is false will write each wfc to a separate file + : ""; // only when istep >= 0 and out_app_flag is not append mode will write each wfc to a separate file std::string suffix_block; if (out_type == 1) diff --git a/source/source_base/module_out/filename.h b/source/source_base/module_out/filename.h index d76970c769f..d4c351e3a1e 100644 --- a/source/source_base/module_out/filename.h +++ b/source/source_base/module_out/filename.h @@ -16,7 +16,7 @@ namespace ModuleIO * @param nspin: number of spin channels, 1,2 or 4 * @param nkstot: number of total k-points * @param out_type: two types of output file format, 1 for .txt and 2 for .dat (binary) - * @param out_app_flag: whether to append to existing file. + * @param out_app_flag: 0=no append, 1=append to same file, 2=write to subdirectory. * @param gamma_only: gamma_only algorithm or not. * @param istep: index of the ion step starting from 0. If < 0, the step number is not included in the file name. * @param iter: index of the electronic step starting from 0. If < 0, the step number is not included in the file name. @@ -31,7 +31,7 @@ std::string filename_output( const int nspin, const int nkstot, const int out_type, - const bool out_app_flag, + const int out_app_flag, const bool gamma_only, const int istep=-1, const int iter=-1); diff --git a/source/source_base/test/global_file_test.cpp b/source/source_base/test/global_file_test.cpp index 07184237553..fe7bdac7446 100644 --- a/source/source_base/test/global_file_test.cpp +++ b/source/source_base/test/global_file_test.cpp @@ -25,7 +25,6 @@ class GlobalFile : public testing::Test { protected: std::string global_out_dir; - std::string global_stru_dir; std::string global_matrix_dir; std::string global_wfc_dir; std::string global_mlkedf_descriptor_dir; @@ -34,7 +33,6 @@ class GlobalFile : public testing::Test { const std::string suffix = "Si"; global_out_dir = "OUT." + suffix + "/"; - global_stru_dir = global_out_dir + "STRU/"; global_matrix_dir = global_out_dir + "matrix/"; global_wfc_dir = global_out_dir + "WFC/"; global_mlkedf_descriptor_dir = global_out_dir + "MLKEDF_Descriptors/"; @@ -47,7 +45,7 @@ TEST_F(GlobalFile,mkdirout) std::string output; testing::internal::CaptureStdout(); ModuleBase::Global_File::make_dir_out("Si","m",false,false,0,true,true, - global_out_dir, global_stru_dir, global_matrix_dir, global_wfc_dir, + global_out_dir, global_matrix_dir, global_wfc_dir, global_mlkedf_descriptor_dir, global_deepks_label_elec_dir, "running_m_1.log", false, false); output = testing::internal::GetCapturedStdout(); @@ -58,22 +56,9 @@ TEST_F(GlobalFile,mkdirout) std::string dd = "OUT.Si/running_m_1.log"; remove(dd.c_str()); - testing::internal::CaptureStdout(); - ModuleBase::Global_File::make_dir_out("Si","md",false,false,0,true,false, - global_out_dir, global_stru_dir, global_matrix_dir, global_wfc_dir, - global_mlkedf_descriptor_dir, global_deepks_label_elec_dir, - "running_md.log", false, false); - output = testing::internal::GetCapturedStdout(); - EXPECT_THAT(output,testing::HasSubstr("MAKE THE STRU DIR")); - EXPECT_TRUE(GlobalV::ofs_running.is_open()); - GlobalV::ofs_running.close(); - GlobalV::ofs_warning.close(); - std::string bb = "OUT.Si/running_md.log"; - remove(bb.c_str()); - testing::internal::CaptureStdout(); ModuleBase::Global_File::make_dir_out("Si","md",true,false,0,true,true, - global_out_dir, global_stru_dir, global_matrix_dir, global_wfc_dir, + global_out_dir, global_matrix_dir, global_wfc_dir, global_mlkedf_descriptor_dir, global_deepks_label_elec_dir, "running_md_1.log", false, false); output = testing::internal::GetCapturedStdout(); @@ -84,7 +69,6 @@ TEST_F(GlobalFile,mkdirout) remove(cc.c_str()); std::string aa = "OUT.Si/warning.log"; remove(aa.c_str()); - rmdir(global_stru_dir.c_str()); rmdir(global_matrix_dir.c_str()); rmdir(global_out_dir.c_str()); } diff --git a/source/source_io/module_ctrl/ctrl_output_fp.cpp b/source/source_io/module_ctrl/ctrl_output_fp.cpp index 05bc5e6f6af..8e673e4fb4b 100644 --- a/source/source_io/module_ctrl/ctrl_output_fp.cpp +++ b/source/source_io/module_ctrl/ctrl_output_fp.cpp @@ -32,10 +32,14 @@ void ctrl_output_fp(UnitCell& ucell, ModuleBase::TITLE("ModuleIO", "ctrl_output_fp"); ModuleBase::timer::start("ModuleIO", "ctrl_output_fp"); - const bool out_app_flag = inp.out_app_flag; + const int out_app_flag = inp.out_app_flag; const bool gamma_only = PARAM.globalv.gamma_only_local; const int nspin = inp.nspin; const std::string global_out_dir = PARAM.globalv.global_out_dir; + const std::string global_chg_dir = PARAM.globalv.global_chg_dir; + const std::string global_pot_dir = PARAM.globalv.global_pot_dir; + const std::string global_elf_dir = PARAM.globalv.global_elf_dir; + const std::string global_dip_dir = PARAM.globalv.global_dip_dir; const int output_frequency = inp.esolver_type == "tddft" ? inp.out_freq_td : inp.out_freq_ion; // Print the global electronic step for TDDFT and the ionic step otherwise. @@ -61,7 +65,7 @@ void ctrl_output_fp(UnitCell& ucell, { for (int is = 0; is < nspin; ++is) { - std::string fn = PARAM.globalv.global_out_dir + "chg"; + std::string fn = global_chg_dir + "chg"; std::string spin_block; if (nspin == 2 || nspin == 4) @@ -94,7 +98,7 @@ void ctrl_output_fp(UnitCell& ucell, if (XC_Functional::get_ked_flag()) { - fn = PARAM.globalv.global_out_dir + "tau"; + fn = global_chg_dir + "tau"; fn += spin_block + geom_block + ".cube"; @@ -123,7 +127,7 @@ void ctrl_output_fp(UnitCell& ucell, { for (int is = 0; is < nspin; is++) { - std::string fn = PARAM.globalv.global_out_dir + "pot"; + std::string fn = global_pot_dir + "pot"; std::string spin_block; if (nspin == 2 || nspin == 4) @@ -157,7 +161,7 @@ void ctrl_output_fp(UnitCell& ucell, } else if (inp.out_pot[0] == 2 && should_output) { - std::string fn = PARAM.globalv.global_out_dir + "potes"; + std::string fn = global_pot_dir + "potes"; fn += geom_block + ".cube"; const std::vector* pcc_potential = pelec->pot->pcc_electron_potential(); @@ -189,7 +193,7 @@ void ctrl_output_fp(UnitCell& ucell, module_charge::cal_rhog_symm(is, chr, pw_rhod, ucell.symm); } - std::string out_dir = PARAM.globalv.global_out_dir; + std::string out_dir = global_elf_dir; ModuleIO::write_elf(out_dir, istep, nspin, @@ -226,7 +230,7 @@ void ctrl_output_fp(UnitCell& ucell, for (int is = 0; is < nspin; ++is) { std::stringstream ss_dipole; - ss_dipole << global_out_dir << "dipole_s" << is + 1 << ".txt"; + ss_dipole << global_dip_dir << "dipole_s" << is + 1 << ".txt"; ModuleIO::write_dipole(ucell, chr.rho[is], pw_rhod, istep, ss_dipole.str(), ofs_running); } } diff --git a/source/source_io/module_ctrl/ctrl_output_pw.cpp b/source/source_io/module_ctrl/ctrl_output_pw.cpp index 8294d7cbae6..6856a49458e 100644 --- a/source/source_io/module_ctrl/ctrl_output_pw.cpp +++ b/source/source_io/module_ctrl/ctrl_output_pw.cpp @@ -74,7 +74,7 @@ void ModuleIO::ctrl_iter_pw(const int istep, GlobalV::NPROC_IN_POOL, inp.out_wfc_pw, inp.ecutwfc, - PARAM.globalv.global_out_dir, + PARAM.globalv.global_psi_dir, stp.psi_cpu[0], kv, pw_wfc, @@ -174,7 +174,7 @@ void ModuleIO::ctrl_scf_pw(const int istep, PARAM.globalv.two_fermi, inp.out_app_flag, inp.bndpar, - PARAM.globalv.global_out_dir, + PARAM.globalv.global_dos_dir, ofs_running); } } @@ -294,7 +294,7 @@ void ModuleIO::ctrl_runner_pw(UnitCell& ucell, inp.out_ldos, inp.stm_bias, inp.nspin, - PARAM.globalv.global_out_dir, + PARAM.globalv.global_dos_dir, PARAM.globalv.two_fermi, inp.nbands, inp.dos_edelta_ev, diff --git a/source/source_io/module_ctrl/ctrl_runner_lcao.cpp b/source/source_io/module_ctrl/ctrl_runner_lcao.cpp index 5ceec5f9165..55a21bce7f7 100644 --- a/source/source_io/module_ctrl/ctrl_runner_lcao.cpp +++ b/source/source_io/module_ctrl/ctrl_runner_lcao.cpp @@ -54,7 +54,7 @@ void ctrl_runner_lcao(UnitCell& ucell, // unitcell { ModuleIO::Cal_ldos::cal_ldos_lcao(pelec->eferm, chr, dmat, kv, pelec->ekb, pelec->wg, psi[0], pgrid, pv, gd, ucell, - inp.stm_bias, inp.nspin, PARAM.globalv.global_out_dir, + inp.stm_bias, inp.nspin, PARAM.globalv.global_dos_dir, PARAM.globalv.two_fermi, inp.out_ldos[1], ofs_running); } diff --git a/source/source_io/module_ctrl/ctrl_scf_lcao.cpp b/source/source_io/module_ctrl/ctrl_scf_lcao.cpp index b7533f0325d..12f9067348f 100644 --- a/source/source_io/module_ctrl/ctrl_scf_lcao.cpp +++ b/source/source_io/module_ctrl/ctrl_scf_lcao.cpp @@ -136,10 +136,11 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, //***** - const bool out_app_flag = inp.out_app_flag; + const int out_app_flag = inp.out_app_flag; const bool gamma_only = PARAM.globalv.gamma_only_local; const int nspin = inp.nspin; const std::string global_out_dir = PARAM.globalv.global_out_dir; + const std::string global_mat_dir = PARAM.globalv.global_mat_dir; //------------------------------------------------------------------ //! 1) print out density of states (DOS) @@ -168,7 +169,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, inp.dos_emin_ev, PARAM.globalv.two_fermi, inp.bndpar, - PARAM.globalv.global_out_dir, + PARAM.globalv.global_dos_dir, ofs_running); } @@ -178,9 +179,10 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, if (inp.out_dmr[0]) { const int precision = inp.out_dmr[1]; + const bool append_dmr = (out_app_flag == 1); - ModuleIO::write_dmr(dm->get_dmr_vec(), &ucell, precision, pv, out_app_flag, - ucell.get_iat2iwt(), ucell.nat, istep, ofs_running); + ModuleIO::write_dmr(dm->get_dmr_vec(), &ucell, precision, pv, append_dmr, + ucell.get_iat2iwt(), ucell.nat, global_mat_dir, istep, ofs_running); } //------------------------------------------------------------------ @@ -195,7 +197,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, } const int precision = inp.out_dmk[1]; - ModuleIO::write_dmk(dm->get_dmk_vec(), kv, precision, efermis, &(ucell), pv, global_out_dir, istep, ofs_running); + ModuleIO::write_dmk(dm->get_dmk_vec(), kv, precision, efermis, &(ucell), pv, global_mat_dir, istep, ofs_running); } //------------------------------------------------------------------ @@ -279,7 +281,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, const hamilt::HContainer* sr = p_hamilt->getSR(); ModuleIO::write_hsr(hr_vec, sr, &ucell, inp.out_hsr[0], precision, pv, - out_app_flag, gamma_only, ucell.get_iat2iwt(), ucell.nat, istep, + (out_app_flag == 1), gamma_only, ucell.get_iat2iwt(), ucell.nat, istep, PARAM.globalv.global_out_dir, pelec->eferm, ofs_running); } @@ -399,7 +401,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, dh_params.nspin = inp.nspin; dh_params.istep = istep; dh_params.gamma_only = gamma_only; - dh_params.append = out_app_flag; + dh_params.append = (out_app_flag == 1); dh_params.ofs_running = &ofs_running; if (PARAM.inp.nspin == 1 || PARAM.inp.nspin == 2) { @@ -442,7 +444,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, h_params.nrxx = pw_rho->nrxx; h_params.nspin = nspin; h_params.istep = istep; - h_params.append = out_app_flag; + h_params.append = (out_app_flag == 1); h_params.iat2iwt = ucell.get_iat2iwt(); h_params.nat = ucell.nat; h_params.nlocal = PARAM.globalv.nlocal; @@ -527,7 +529,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, false, // bit inp.out_mat_tk[1], 1, // true for upper triangle matrix - inp.out_app_flag, + (inp.out_app_flag == 1), t_fn, pv, GlobalV::DRANK, @@ -558,7 +560,7 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, PARAM.globalv.gamma_only_local, &ofs_running, GlobalV::MY_RANK); - mylcalculator.calculate(inp.suffix, global_out_dir, ucell, inp.out_mat_l[1], GlobalV::MY_RANK, istep_in); + mylcalculator.calculate(inp.suffix, global_mat_dir, ucell, inp.out_mat_l[1], GlobalV::MY_RANK, istep_in); } //------------------------------------------------------------------ diff --git a/source/source_io/module_dhs/write_dh.cpp b/source/source_io/module_dhs/write_dh.cpp index 9a61cf3dee9..e0d99fde3ee 100644 --- a/source/source_io/module_dhs/write_dh.cpp +++ b/source/source_io/module_dhs/write_dh.cpp @@ -44,9 +44,9 @@ void write_dh_perI(WriteDHParams& params, const int nks = params.kv->get_nks() / nspin_k; const int nlocal = PARAM.globalv.nlocal; const std::string global_out_dir = PARAM.globalv.global_out_dir; - const bool out_app_flag = PARAM.inp.out_app_flag; + const int out_app_flag = PARAM.inp.out_app_flag; const std::string r_dir - = (PARAM.inp.calculation == "md" && !out_app_flag) ? PARAM.globalv.global_matrix_dir : global_out_dir; + = (PARAM.inp.calculation == "md" && (out_app_flag != 1)) ? PARAM.globalv.global_matrix_dir : global_out_dir; #ifdef __MPI Parallel_Orbitals serialV; @@ -129,7 +129,7 @@ void write_dh_perI(WriteDHParams& params, false, 8, false, - out_app_flag, + (out_app_flag == 1), fk, pv, GlobalV::DRANK, diff --git a/source/source_io/module_dm/write_dmr.cpp b/source/source_io/module_dm/write_dmr.cpp index 6b95e726a31..58bdd2ec16a 100644 --- a/source/source_io/module_dm/write_dmr.cpp +++ b/source/source_io/module_dm/write_dmr.cpp @@ -1,7 +1,7 @@ #include "write_dmr.h" #include "source_io/module_output/spin_tag.h" -#include "source_io/module_parameter/parameter.h" +#include "source_base/global_variable.h" #include "source_hamilt/module_hcontainer/hcontainer_funcs.h" #include "source_hamilt/module_hcontainer/output_hcontainer.h" #include "source_cell/ucell_io.h" @@ -85,6 +85,7 @@ void write_dmr(const std::vector*> dmr, const bool append, const int* iat2iwt, const int nat, + const std::string& dmr_dir, const int istep, std::ofstream& ofs_running) { @@ -110,7 +111,7 @@ void write_dmr(const std::vector*> dmr, // out_type = 1, csr format; // out_type = 2, npz format (currently not support) const int out_type = 1; - std::string fname = PARAM.globalv.global_out_dir + dmr_gen_fname(out_type, ispin, append, istep); + std::string fname = dmr_dir + dmr_gen_fname(out_type, ispin, append, istep); write_dmr_csr(fname, ucell, precision, &dm_serial, istep, ispin, nspin); const std::string spin_tag = ModuleIO::make_spin_tag(ispin, nspin); ofs_running << " Write DM(R)" << spin_tag << " matrix in NAO basis to file: " << fname << std::endl; diff --git a/source/source_io/module_dm/write_dmr.h b/source/source_io/module_dm/write_dmr.h index 644e2828b52..957553242e8 100644 --- a/source/source_io/module_dm/write_dmr.h +++ b/source/source_io/module_dm/write_dmr.h @@ -54,6 +54,7 @@ void write_dmr_csr(std::string& fname, * @param ispin The spin index, starting from 0. * @param append Whether to append the data to an existing file or create a new file. The file name is related to this * flag. + * @param dmr_dir The directory the DM(R) files are written into. * @param istep The ION step, starting from 0. */ void write_dmr(const std::vector*> dmr, @@ -63,6 +64,7 @@ void write_dmr(const std::vector*> dmr, const bool append, const int* iat2iwt, const int nat, + const std::string& dmr_dir, const int istep, std::ofstream& ofs_running); } // namespace ModuleIO diff --git a/source/source_io/module_dos/cal_dos.cpp b/source/source_io/module_dos/cal_dos.cpp index 7975c5e6ded..79f5dd7d65a 100644 --- a/source/source_io/module_dos/cal_dos.cpp +++ b/source/source_io/module_dos/cal_dos.cpp @@ -108,7 +108,7 @@ bool ModuleIO::cal_dos(const int& is, // index for spin const ModuleBase::matrix& ekb, // energy for each k point and each band const ModuleBase::matrix& wg, // weight of k-points and bands const int istep, // ionic step - const bool out_app_flag, + const int out_app_flag, const int bndpar) { ModuleBase::TITLE("ModuleIO", "cal_dos"); @@ -117,7 +117,7 @@ bool ModuleIO::cal_dos(const int& is, // index for spin if (GlobalV::MY_RANK == 0) { - if(out_app_flag==true) + if(out_app_flag == 1) { ofs_dos.open(fn.c_str(), std::ios::app); } diff --git a/source/source_io/module_dos/cal_dos.h b/source/source_io/module_dos/cal_dos.h index d133c4e9423..e8f305b685b 100644 --- a/source/source_io/module_dos/cal_dos.h +++ b/source/source_io/module_dos/cal_dos.h @@ -37,7 +37,7 @@ namespace ModuleIO const ModuleBase::matrix &ekb, //store energy for each k point and each band const ModuleBase::matrix &wg, //weight of (kpoint,bands)) const int istep_in, // ionic_step - const bool out_app_flag, // whether to append output + const int out_app_flag, // 0: no append, 1: append, 2: subdirectory const int bndpar); // number of band parallel groups } diff --git a/source/source_io/module_dos/unittests/test_cal_dos.cpp b/source/source_io/module_dos/unittests/test_cal_dos.cpp index abcf942bad4..3fe5d410600 100644 --- a/source/source_io/module_dos/unittests/test_cal_dos.cpp +++ b/source/source_io/module_dos/unittests/test_cal_dos.cpp @@ -37,7 +37,7 @@ TEST_F(DosTest,Dos) EXPECT_EQ(dosp.is,0); const int istep = 1; - const bool out_app_flag = false; + const int out_app_flag = 0; const int bndpar = 1; ModuleIO::cal_dos(dosp.is, dosp.fa, @@ -124,7 +124,7 @@ TEST_F(DosTest,DosW1) GlobalV::ofs_warning.open("warning1.log"); const int istep = 1; - const bool out_app_flag = false; + const int out_app_flag = 0; const int bndpar = 1; EXPECT_NO_THROW(ModuleIO::cal_dos(dosp.is, dosp.fa, @@ -171,7 +171,7 @@ TEST_F(DosTest,DosW2) GlobalV::ofs_warning.open("warning2.log"); const int istep = 1; - const bool out_app_flag = false; + const int out_app_flag = 0; const int bndpar = 1; EXPECT_NO_THROW(ModuleIO::cal_dos(dosp.is, dosp.fa, diff --git a/source/source_io/module_dos/unittests/test_write_dos_pw.cpp b/source/source_io/module_dos/unittests/test_write_dos_pw.cpp index 384af45ac63..b866c0b24d6 100644 --- a/source/source_io/module_dos/unittests/test_write_dos_pw.cpp +++ b/source/source_io/module_dos/unittests/test_write_dos_pw.cpp @@ -67,7 +67,7 @@ TEST_F(DosPWTest,Dos1) const bool dos_setemax = true; const bool dos_setemin = true; const bool two_fermi = false; - const bool out_app_flag = false; + const int out_app_flag = 0; const int bndpar = 1; const std::string global_out_dir = "./"; @@ -144,7 +144,7 @@ TEST_F(DosPWTest,Dos2) const int nspin = 1; const int out_dos = 1; const bool two_fermi = false; - const bool out_app_flag = false; + const int out_app_flag = 0; const int bndpar = 1; const std::string global_out_dir = "./"; const bool dos_setemax = false; diff --git a/source/source_io/module_dos/write_dos_lcao.cpp b/source/source_io/module_dos/write_dos_lcao.cpp index 926d94bd4e5..20ef0799aae 100644 --- a/source/source_io/module_dos/write_dos_lcao.cpp +++ b/source/source_io/module_dos/write_dos_lcao.cpp @@ -20,7 +20,7 @@ void write_dos_lcao( const double& dos_edelta_ev, const double& dos_scale, const double& bcoeff, - const bool out_app_flag, + const int out_app_flag, const int istep, const int nspin, const int nlocal, @@ -125,7 +125,7 @@ template void write_dos_lcao( const double& dos_edelta_ev, const double& dos_scale, const double& bcoeff, - const bool out_app_flag, + const int out_app_flag, const int istep, const int nspin, const int nlocal, @@ -152,7 +152,7 @@ template void write_dos_lcao( const double& dos_edelta_ev, const double& dos_scale, const double& bcoeff, - const bool out_app_flag, + const int out_app_flag, const int istep, const int nspin, const int nlocal, diff --git a/source/source_io/module_dos/write_dos_lcao.h b/source/source_io/module_dos/write_dos_lcao.h index 0e9017149a4..25e8b6d14a6 100644 --- a/source/source_io/module_dos/write_dos_lcao.h +++ b/source/source_io/module_dos/write_dos_lcao.h @@ -28,7 +28,7 @@ namespace ModuleIO const double& dos_edelta_ev, // Delta energy const double& dos_scale, const double& bcoeff, - const bool out_app_flag, + const int out_app_flag, const int istep, const int nspin, const int nlocal, diff --git a/source/source_io/module_dos/write_dos_pw.cpp b/source/source_io/module_dos/write_dos_pw.cpp index 1ce707f59de..3564a78f275 100644 --- a/source/source_io/module_dos/write_dos_pw.cpp +++ b/source/source_io/module_dos/write_dos_pw.cpp @@ -20,7 +20,7 @@ void ModuleIO::write_dos_pw( const bool dos_setemin, const double dos_emin_ev, const bool two_fermi, - const bool out_app_flag, + const int out_app_flag, const int bndpar, const std::string& global_out_dir, std::ofstream& ofs_running) diff --git a/source/source_io/module_dos/write_dos_pw.h b/source/source_io/module_dos/write_dos_pw.h index 4b2417d8f42..2491c7d303a 100644 --- a/source/source_io/module_dos/write_dos_pw.h +++ b/source/source_io/module_dos/write_dos_pw.h @@ -27,7 +27,7 @@ namespace ModuleIO const bool dos_setemin, const double dos_emin_ev, const bool two_fermi, - const bool out_app_flag, + const int out_app_flag, const int bndpar, const std::string& global_out_dir, std::ofstream& ofs_running); diff --git a/source/source_io/module_energy/write_bands.cpp b/source/source_io/module_energy/write_bands.cpp index f796b19f07a..e5d229f00c0 100644 --- a/source/source_io/module_energy/write_bands.cpp +++ b/source/source_io/module_energy/write_bands.cpp @@ -89,7 +89,7 @@ void ModuleIO::nscf_bands(const int& is, const int band_group = Parallel::make_band_world().rank(); if (GlobalV::MY_RANK == 0) { - if (PARAM.inp.out_app_flag == true) + if (PARAM.inp.out_app_flag == 1) { // do nothing } @@ -149,7 +149,7 @@ void ModuleIO::nscf_bands(const int& is, if (GlobalV::MY_RANK == 0) { - if (PARAM.inp.out_app_flag == true) + if (PARAM.inp.out_app_flag == 1) { ofs.open(eig_file.c_str(), std::ios::app); } diff --git a/source/source_io/module_hs/dhs_sparse_writer.cpp b/source/source_io/module_hs/dhs_sparse_writer.cpp index 5c4a049546f..557adfa59e7 100644 --- a/source/source_io/module_hs/dhs_sparse_writer.cpp +++ b/source/source_io/module_hs/dhs_sparse_writer.cpp @@ -21,10 +21,9 @@ void ModuleIO::save_dH_sparse(const int& istep, const bool& binary, const std::string& fileflag, const int precision, - const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nspin, const int nlocal, std::ofstream& ofs_running) { @@ -112,20 +111,19 @@ void ModuleIO::save_dH_sparse(const int& istep, } } - const bool md_no_append = (calculation == "md") && !out_app_flag; for (auto& comp: comps) { for (int ispin = 0; ispin < 2; ++ispin) { if (istep >= 0) { - comp.fname[ispin] << (md_no_append ? global_matrix_dir : global_out_dir) + comp.fname[ispin] << global_matrix_dir << "d" << fileflag << "r" << comp.axis << "s" << (ispin + 1) << "g" << (istep + 1) << "_nao.csr"; } else { - comp.fname[ispin] << global_out_dir + comp.fname[ispin] << global_matrix_dir << "d" << fileflag << "r" << comp.axis << "s" << (ispin + 1) << "_nao.csr"; } @@ -134,7 +132,7 @@ void ModuleIO::save_dH_sparse(const int& istep, if (GlobalV::DRANK == 0) { - const bool open_in_append = (calculation == "md") && out_app_flag && istep >= 0; + const bool open_in_append = (calculation == "md") && (out_app_flag == 1) && istep >= 0; for (auto& comp: comps) { const std::string label = std::string("dH") + comp.axis; diff --git a/source/source_io/module_hs/dhs_sparse_writer.h b/source/source_io/module_hs/dhs_sparse_writer.h index 8aab9c8007e..59677d8f6ce 100644 --- a/source/source_io/module_hs/dhs_sparse_writer.h +++ b/source/source_io/module_hs/dhs_sparse_writer.h @@ -17,10 +17,9 @@ void save_dH_sparse(const int& istep, const bool& binary, const std::string& fileflag, const int precision, - const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nspin, const int nlocal, std::ofstream& ofs_running); diff --git a/source/source_io/module_hs/hs_sparse_io.cpp b/source/source_io/module_hs/hs_sparse_io.cpp index f645893164e..580903839cc 100644 --- a/source/source_io/module_hs/hs_sparse_io.cpp +++ b/source/source_io/module_hs/hs_sparse_io.cpp @@ -33,7 +33,7 @@ void open_sparse_file(std::ofstream& ofs, const ModuleIO::SparseWriteOptions& op { mode |= std::ios::binary; } - const bool append_on_restart = (options.calculation == "md") && options.out_app_flag && options.istep >= 0; + const bool append_on_restart = (options.calculation == "md") && (options.out_app_flag == 1) && options.istep >= 0; if (append_on_restart) { mode |= std::ios::app; diff --git a/source/source_io/module_hs/hs_sparse_io.h b/source/source_io/module_hs/hs_sparse_io.h index d8bdb089989..3371e78628f 100644 --- a/source/source_io/module_hs/hs_sparse_io.h +++ b/source/source_io/module_hs/hs_sparse_io.h @@ -31,7 +31,7 @@ struct SparseWriteOptions // Runtime flags that decide file-open mode (append on md restart). // Must be provided explicitly by the caller instead of reading PARAM. std::string calculation; - bool out_app_flag = false; + int out_app_flag = 0; }; template diff --git a/source/source_io/module_hs/hsk_writer.cpp b/source/source_io/module_hs/hsk_writer.cpp index 263635b573b..0faa1ba1aa7 100644 --- a/source/source_io/module_hs/hsk_writer.cpp +++ b/source/source_io/module_hs/hsk_writer.cpp @@ -14,7 +14,7 @@ void ModuleIO::write_hsk( hamilt::Hamilt* p_hamilt, const Parallel_Orbitals &pv, const bool gamma_only, - const bool out_app_flag, + const int out_app_flag, const int istep, const int out_type, const int precision, @@ -96,11 +96,11 @@ template void ModuleIO::write_hsk( const std::string&, const int, const int, const int, const std::vector&, const std::vector&, hamilt::Hamilt*, const Parallel_Orbitals&, - const bool, const bool, const int, const int, const int, + const bool, const int, const int, const int, const int, const int, const std::string&, const int, std::ofstream&); template void ModuleIO::write_hsk>( const std::string&, const int, const int, const int, const std::vector&, const std::vector&, hamilt::Hamilt>*, const Parallel_Orbitals&, - const bool, const bool, const int, const int, const int, + const bool, const int, const int, const int, const int, const int, const std::string&, const int, std::ofstream&); diff --git a/source/source_io/module_hs/hsk_writer.h b/source/source_io/module_hs/hsk_writer.h index af2bb6a8540..d80a5eb8839 100644 --- a/source/source_io/module_hs/hsk_writer.h +++ b/source/source_io/module_hs/hsk_writer.h @@ -25,7 +25,7 @@ void write_hsk(const std::string& global_out_dir, hamilt::Hamilt* p_hamilt, const Parallel_Orbitals& pv, const bool gamma_only, - const bool out_app_flag, + const int out_app_flag, const int istep, const int out_type, const int precision, diff --git a/source/source_io/module_hs/hsr_legacy.cpp b/source/source_io/module_hs/hsr_legacy.cpp index 0f1e37daa3e..8b3fc5a4dfc 100644 --- a/source/source_io/module_hs/hsr_legacy.cpp +++ b/source/source_io/module_hs/hsr_legacy.cpp @@ -40,7 +40,7 @@ void ModuleIO::output_dSR(const int& istep, // mohan update 2024-04-01 const std::string fileflag_s = "s"; ModuleIO::save_dH_sparse(istep, pv, HS_Arrays, options.sparse_threshold, options.binary, - fileflag_s, options.precision, options.global_out_dir, + fileflag_s, options.precision, options.global_matrix_dir, options.calculation, options.out_app_flag, options.nspin, nlocal, ofs_running); @@ -86,7 +86,7 @@ void ModuleIO::output_dHR(const int& istep, // mohan update 2024-04-01 const std::string fileflag_h = "h"; ModuleIO::save_dH_sparse(istep, pv, HS_Arrays, options.sparse_threshold, options.binary, - fileflag_h, options.precision, options.global_out_dir, + fileflag_h, options.precision, options.global_matrix_dir, options.calculation, options.out_app_flag, options.nspin, nlocal, ofs_running); @@ -107,7 +107,7 @@ void ModuleIO::output_SR(Parallel_Orbitals& pv, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nspin, std::ofstream& ofs_running) { @@ -174,17 +174,16 @@ void ModuleIO::output_TR(const int istep, ModuleBase::timer::start("ModuleIO", "output_TR"); std::stringstream sst; - const bool md_no_append = (options.calculation == "md") && !options.out_app_flag; if (istep >= 0) { // insert the 1-indexed ionic-step suffix right after the "tr" prefix, // i.e. tr_nao.csr -> trg{step+1}_nao.csr (aligned with lxg/rrg naming) const std::string base = TR_filename.substr(0, TR_filename.size() - std::string("_nao.csr").size()); - sst << (md_no_append ? options.global_matrix_dir : options.global_out_dir) << base << "g" << (istep + 1) << "_nao.csr"; + sst << options.global_matrix_dir << base << "g" << (istep + 1) << "_nao.csr"; } else { - sst << options.global_out_dir << TR_filename; + sst << options.global_matrix_dir << TR_filename; } ofs_running << " Write T(R) matrix in NAO basis to file: " << sst.str() << std::endl; sparse_format::cal_TR(ucell, pv, HS_Arrays, grid, two_center_bundle, orb, options.sparse_threshold); @@ -220,7 +219,7 @@ template void ModuleIO::output_SR(Parallel_Orbitals& pv, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nspin, std::ofstream& ofs_running); template void ModuleIO::output_SR>(Parallel_Orbitals& pv, @@ -233,6 +232,6 @@ template void ModuleIO::output_SR>(Parallel_Orbitals& pv, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nspin, std::ofstream& ofs_running); diff --git a/source/source_io/module_hs/hsr_legacy.h b/source/source_io/module_hs/hsr_legacy.h index 334374125e1..cddd93aed3f 100644 --- a/source/source_io/module_hs/hsr_legacy.h +++ b/source/source_io/module_hs/hsr_legacy.h @@ -29,7 +29,7 @@ struct MatROutputOptions std::string global_out_dir; std::string global_matrix_dir; std::string calculation; - bool out_app_flag = false; + int out_app_flag = 0; int nspin = 1; }; @@ -82,7 +82,7 @@ void output_SR(Parallel_Orbitals& pv, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nspin, std::ofstream& ofs_running); diff --git a/source/source_io/module_hs/hterm_writer.cpp b/source/source_io/module_hs/hterm_writer.cpp index a4be8399b56..95910677d11 100644 --- a/source/source_io/module_hs/hterm_writer.cpp +++ b/source/source_io/module_hs/hterm_writer.cpp @@ -78,9 +78,6 @@ static void gather_and_write(const std::string& prefix, const bool append, const int* iat2iwt, const int nat, - const std::string& calculation, - const bool out_app_flag, - const std::string& global_out_dir, const std::string& global_matrix_dir, std::ofstream* ofs_running) { @@ -94,9 +91,7 @@ static void gather_and_write(const std::string& prefix, if (GlobalV::MY_RANK == 0) #endif { - const bool md_no_append = (calculation == "md") && !out_app_flag; - const std::string& out_dir = md_no_append ? global_matrix_dir : global_out_dir; - const std::string fname = out_dir + hsr_gen_fname(prefix, ispin, append, istep); + const std::string fname = global_matrix_dir + hsr_gen_fname(prefix, ispin, append, istep); // H(R) component terms (T, V^NL, V^L, V^H, V^XC, V^EXX) are parts of // the Hamiltonian, not the full H(R): they do not carry the Fermi annotation const double no_efermi = 0.0; @@ -127,7 +122,7 @@ static void write_hk_common(hamilt::HContainer& hR, const int nlocal, const bool gamma_only, const std::string& global_out_dir, - const bool out_app_flag, + const int out_app_flag, const std::string& ks_solver, const int drank) { @@ -200,7 +195,7 @@ static void write_h_term(WriteHParams& params, const HTermSpec& spec) const int nlocal = params.nlocal; const bool gamma_only = params.gamma_only_local; const std::string& global_out_dir = params.global_out_dir; - const bool out_app_flag = params.out_app_flag; + const int out_app_flag = params.out_app_flag; const int nspin_out = (nspin == 2 ? 2 : 1); @@ -215,8 +210,8 @@ static void write_h_term(WriteHParams& params, const HTermSpec& spec) if (also_hR) { gather_and_write(spec.r_prefix, spec.r_label, spec.term_name, hR_tmp, ucell, pv, nspin, ispin, - istep, append, iat2iwt, nat, params.calculation, params.out_app_flag, - params.global_out_dir, params.global_matrix_dir, params.ofs_running); + istep, append, iat2iwt, nat, + params.global_matrix_dir, params.ofs_running); } } @@ -378,7 +373,7 @@ static void write_h_exx_impl(const UnitCell& ucell, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const std::string& ks_solver, const int drank, const Exx_Info& exx_info, @@ -402,7 +397,7 @@ static void write_h_exx_impl(const UnitCell& ucell, if (also_hR) { gather_and_write("vexx", "V^EXX", "exx", hR_tmp, ucell, pv, nspin, ispin, istep, append, - iat2iwt, nat, calculation, out_app_flag, global_out_dir, global_matrix_dir, + iat2iwt, nat, global_matrix_dir, ofs_running); } } diff --git a/source/source_io/module_hs/hterm_writer.h b/source/source_io/module_hs/hterm_writer.h index 7aa2f721fc6..2cc9599548e 100644 --- a/source/source_io/module_hs/hterm_writer.h +++ b/source/source_io/module_hs/hterm_writer.h @@ -46,7 +46,7 @@ struct WriteHParams bool domag = false; bool domag_z = false; int gga_grad = 0; // used by the XC term - bool out_app_flag = false; + int out_app_flag = 0; std::string calculation; std::string global_out_dir; std::string global_matrix_dir; diff --git a/source/source_io/module_hs/output_mat_sparse.cpp b/source/source_io/module_hs/output_mat_sparse.cpp index 5179bd5477e..59e133574e7 100644 --- a/source/source_io/module_hs/output_mat_sparse.cpp +++ b/source/source_io/module_hs/output_mat_sparse.cpp @@ -25,7 +25,7 @@ void output_mat_sparse(const MatSparseOutputOptions& options, const std::string& global_out_dir = PARAM.globalv.global_out_dir; const std::string& global_matrix_dir = PARAM.globalv.global_matrix_dir; const std::string& calculation = PARAM.inp.calculation; - const bool out_app_flag = PARAM.inp.out_app_flag; + const int out_app_flag = PARAM.inp.out_app_flag; const int nspin = PARAM.inp.nspin; const bool gamma_only_local = PARAM.globalv.gamma_only_local; const int npol = PARAM.globalv.npol; diff --git a/source/source_io/module_hs/pos_op_mat.cpp b/source/source_io/module_hs/pos_op_mat.cpp index 04ec8d45e85..e37c7f1245e 100644 --- a/source/source_io/module_hs/pos_op_mat.cpp +++ b/source/source_io/module_hs/pos_op_mat.cpp @@ -89,7 +89,7 @@ void Position_op::out_rR(const UnitCell& ucell, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nlocal, const int npol, std::ofstream& ofs_running) diff --git a/source/source_io/module_hs/pos_op_mat.h b/source/source_io/module_hs/pos_op_mat.h index 96a6513c23e..d76d71e0c3e 100644 --- a/source/source_io/module_hs/pos_op_mat.h +++ b/source/source_io/module_hs/pos_op_mat.h @@ -76,7 +76,7 @@ class Position_op const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - const bool out_app_flag, + const int out_app_flag, const int nlocal, const int npol, std::ofstream& ofs_running); diff --git a/source/source_io/module_hs/pos_op_writer.cpp b/source/source_io/module_hs/pos_op_writer.cpp index 15e1fa201ea..8f75d52ed72 100644 --- a/source/source_io/module_hs/pos_op_writer.cpp +++ b/source/source_io/module_hs/pos_op_writer.cpp @@ -22,7 +22,7 @@ void PosOpWriter::out_lat_r(const UnitCell& ucell, const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - bool out_app_flag, + int out_app_flag, int nlocal, int npol, double sparse_threshold, @@ -216,18 +216,17 @@ void PosOpWriter::out_lat_r(const UnitCell& ucell, if (GlobalV::DRANK == 0) { std::stringstream ssr; - const bool md_no_append = (calculation == "md") && !out_app_flag; if (step >= 0) { - ssr << (md_no_append ? global_matrix_dir : global_out_dir) << "rrg" << (step + 1) << "_nao.txt"; + ssr << global_matrix_dir << "rrg" << (step + 1) << "_nao.txt"; } else { - ssr << global_out_dir << "rr_nao.txt"; + ssr << global_matrix_dir << "rr_nao.txt"; } ofs_tem1.close(); - const bool open_in_append = (calculation == "md") && out_app_flag && step >= 0; + const bool open_in_append = (calculation == "md") && (out_app_flag == 1) && step >= 0; const int header_step = std::max(step, 0); ModuleIO::detail::assemble_csr(ssr.str(), tem1.str(), diff --git a/source/source_io/module_hs/pos_op_writer.h b/source/source_io/module_hs/pos_op_writer.h index 1fd22bcfc81..d2996e43890 100644 --- a/source/source_io/module_hs/pos_op_writer.h +++ b/source/source_io/module_hs/pos_op_writer.h @@ -35,7 +35,7 @@ class PosOpWriter const std::string& global_out_dir, const std::string& global_matrix_dir, const std::string& calculation, - bool out_app_flag, + int out_app_flag, int nlocal, int npol, double sparse_threshold, diff --git a/source/source_io/module_hs/unittests/test_dhs_sparse_writer.cpp b/source/source_io/module_hs/unittests/test_dhs_sparse_writer.cpp index 3885c7c9472..c667523e075 100644 --- a/source/source_io/module_hs/unittests/test_dhs_sparse_writer.cpp +++ b/source/source_io/module_hs/unittests/test_dhs_sparse_writer.cpp @@ -40,7 +40,7 @@ TEST(DhsSparseWriter, TextCountsOnlyValuesAboveThreshold) arrays.dHRx_sparse[0][r_vector][1][0] = 0.0; arrays.dHRx_sparse[0][r_vector][1][1] = -2.0; - ModuleIO::save_dH_sparse(5, pv, arrays, 1e-10, false, "h", 8, "./", "./", "scf", false, 1, 2, ofs_running); + ModuleIO::save_dH_sparse(5, pv, arrays, 1e-10, false, "h", 8, "./", "scf", false, 1, 2, ofs_running); const std::vector lines = read_lines("dhrxs1g6_nao.csr"); ASSERT_GE(lines.size(), 7); @@ -91,7 +91,7 @@ TEST(DhsSparseWriter, BinaryCountsOnlyValuesAboveThreshold) arrays.dHRx_sparse[0][r_vector][1][0] = 0.0; arrays.dHRx_sparse[0][r_vector][1][1] = -2.0; - ModuleIO::save_dH_sparse(6, pv, arrays, 1e-10, true, "h", 8, "./", "./", "scf", false, 1, 2, ofs_running); + ModuleIO::save_dH_sparse(6, pv, arrays, 1e-10, true, "h", 8, "./", "scf", false, 1, 2, ofs_running); std::ifstream ifs("dhrxs1g7_nao.csr", std::ios::binary); ASSERT_TRUE(ifs.is_open()); @@ -127,7 +127,7 @@ TEST(DhsSparseWriter, SocWritesAllDirections) arrays.dHRy_soc_sparse[r_vector][0][1] = std::complex(2.0, -1.0); arrays.dHRz_soc_sparse[r_vector][1][1] = std::complex(-3.0, 0.5); - ModuleIO::save_dH_sparse(7, pv, arrays, 1e-10, false, "s", 8, "./", "./", "scf", false, 4, 2, ofs_running); + ModuleIO::save_dH_sparse(7, pv, arrays, 1e-10, false, "s", 8, "./", "scf", false, 4, 2, ofs_running); const std::string x_output = read_file("dsrxs1g8_nao.csr"); const std::string y_output = read_file("dsrys1g8_nao.csr"); diff --git a/source/source_io/module_hs/vxc_op_lip.cpp b/source/source_io/module_hs/vxc_op_lip.cpp index fcee73b6cd4..094015992d4 100644 --- a/source/source_io/module_hs/vxc_op_lip.cpp +++ b/source/source_io/module_hs/vxc_op_lip.cpp @@ -197,7 +197,7 @@ void write_Vxc_LIP(int nspin, // add-up and write const int istep = -1; const int out_label = 1; // 1 means .txt while 2 means .dat - const bool out_app_flag = 0; + const int out_app_flag = 0; std::string vxc_file = ModuleIO::filename_output( global_out_dir, "vxc", "nao", ik, kv.ik2iktot, nspin, kv.get_nkstot(), diff --git a/source/source_io/module_hs/vxc_op_mat.cpp b/source/source_io/module_hs/vxc_op_mat.cpp index c7a0b8fe2b4..b749e110b5a 100644 --- a/source/source_io/module_hs/vxc_op_mat.cpp +++ b/source/source_io/module_hs/vxc_op_mat.cpp @@ -115,7 +115,7 @@ void write_Vxc(const int nspin, // write const int istep = -1; const int out_label = 1; // 1 means .txt while 2 means .dat - const bool out_app_flag = 0; + const int out_app_flag = 0; std::string vxc_file = ModuleIO::filename_output( global_out_dir, "vxc", "nao", ik, kv.ik2iktot, nspin, kv.get_nkstot(), diff --git a/source/source_io/module_parameter/input_parameter.h b/source/source_io/module_parameter/input_parameter.h index d86993b63d9..dde1c933695 100644 --- a/source/source_io/module_parameter/input_parameter.h +++ b/source/source_io/module_parameter/input_parameter.h @@ -483,8 +483,9 @@ struct Input_para bool out_hr_npz = false; ///< output H(R) matrix in npz format bool out_hsr_npz = false; ///< output H(R) and S(R) matrices in npz format bool out_dm_npz = false; ///< output DM(R) matrix in npz format - bool out_app_flag = true; ///< whether output r(R), H(R), S(R), T(R), and dH(R) matrices - ///< in an append manner during MD liuyu 2023-03-20 + int out_app_flag = 1; ///< 0: no append, no subdirectory; 1: append to same file; + ///< 2: write to subdirectory (PSI/, CHG/, POT/, ELF/, DOS/, DIP/, MAT/) + ///< liuyu 2023-03-20, modified 2025-10-16 int out_ndigits = 8; ///< Assuming 8 digits precision is needed for matrices output std::vector out_mat_t = {0, 8}; ///< output T(R) matrix with precision bool out_element_info = false; ///< output information of all elements diff --git a/source/source_io/module_parameter/read_inp_out.cpp b/source/source_io/module_parameter/read_inp_out.cpp index 80a55319466..5d172868e6d 100644 --- a/source/source_io/module_parameter/read_inp_out.cpp +++ b/source/source_io/module_parameter/read_inp_out.cpp @@ -456,7 +456,7 @@ Note: values 2 and 3 are no longer supported. Setting out_dos to 2 or 3 will rai item.annotation = "output the structure files per ion step"; item.category = "Output information"; item.type = "Integer"; - item.description = "Controls the output of structure files per ionic step. The files are written to the OUT.{suffix}/ directory. Each file corresponds to the structure at RELAX STEP ${istep} (for scf/nscf this is the single step), i.e., the structure for which that step's energy was computed (before the relax move), and includes a header comment with the ABACUS version, timestamp, energy, and stress tensor. When out_freq_ion is positive, the numbered files STRU{istep} (or STRU{istep}.cif) are written every out_freq_ion steps during geometry relaxation; when out_freq_ion is 0, no numbered files are output. This parameter is effective for scf/nscf/relax/cell-relax; for scf/nscf only STRU_FINAL (or STRU_FINAL.cif) is written, and structure output is disabled by default unless out_stru is set explicitly. Molecular dynamics structure output is instead controlled by md_restartfreq (STRU_MD_*).\n" + item.description = "Controls the output of structure files per ionic step. The files are written to the OUT.{suffix}/ directory. Each file corresponds to the structure at the current ionic step, and includes a header comment with the ABACUS version, timestamp, energy, and stress tensor. When out_freq_ion is positive, the numbered files STRU{istep} (or STRU{istep}.cif) are written every out_freq_ion steps; when out_freq_ion is 0, no numbered files are output. This parameter is effective for scf/nscf/relax/cell-relax and md. For scf/nscf only STRU_FINAL (or STRU_FINAL.cif) is written. For MD, structure output follows the same out_freq_ion frequency as the restart file.\n" " - 0: No structure files are output.\n" " - 1: ABACUS STRU format files are output. The latest structure is written to STRU_NOW (overwritten each step), the numbered file STRU{istep} (e.g., STRU1, STRU2) is written every out_freq_ion steps (when out_freq_ion is positive), and the final converged structure is written to STRU_FINAL. No CIF files are output.\n" " - 2: CIF format files are output. The latest structure is written to STRU_NOW.cif (overwritten each step), the numbered file STRU{istep}.cif (e.g., STRU1.cif, STRU2.cif) is written every out_freq_ion steps (when out_freq_ion is positive), and the final converged structure is written to STRU_FINAL.cif. No non-CIF files are output.\n" @@ -1394,12 +1394,22 @@ The circle order of the charge density on real space grids is: x is the outer lo item.annotation = "whether output r(R), H(R), S(R), T(R), and dH(R) " "matrices in an append manner during MD"; item.category = "Output information"; - item.type = "Boolean"; - item.description = "Whether to output r(R), H(R), S(R), T(R), dH(R), dS(R), and wfc matrices in an append manner during molecular dynamics calculations. Check input parameters out_mat_r, out_hsr, out_mat_t, out_mat_dh, out_hsk and out_wfc_lcao for more information."; - item.default_value = "true"; + item.type = "Integer"; + item.description = R"(Controls output file organization during multi-step calculations (MD, relax, RT-TDDFT). +* 0: Write to OUT directory directly, no append (files overwritten each step) +* 1: Append to same file (default, backward compatible) +* 2: Write to subdirectory (PSI/, CHG/, POT/, ELF/, DOS/, DIP/, MAT/) +For more information, refer to the documentation of out_mat_r, out_hsr, out_mat_t, out_mat_dh, out_hsk, out_wfc_lcao, out_chg, out_pot, out_elf, out_dos, out_dipole.)"; + item.default_value = "1"; item.unit = ""; item.set_availability("basis_type==lcao and gamma_only==0"); - read_sync_bool(input.out_app_flag); + read_sync_int(input.out_app_flag); + item.check_value = [](const Input_Item& item, const Parameter& para) { + if (para.input.out_app_flag < 0 || para.input.out_app_flag > 2) + { + ModuleBase::WARNING_QUIT("ReadInput", "out_app_flag should be 0, 1, or 2"); + } + }; this->add_item(item); } { diff --git a/source/source_io/module_parameter/read_input.cpp b/source/source_io/module_parameter/read_input.cpp index 2de46279d8b..56b4b750146 100644 --- a/source/source_io/module_parameter/read_input.cpp +++ b/source/source_io/module_parameter/read_input.cpp @@ -13,6 +13,7 @@ #include #include #include "source_base/formatter.h" +#include "source_base/fs_compat.h" #include "source_base/global_file.h" #include "source_base/global_function.h" #include "source_base/tool_quit.h" @@ -276,7 +277,7 @@ void ReadInput::create_directory(const Parameter& param) // NAME : Run::make_dir( dir name : OUT.suffix) //---------------------------------------------------------- bool out_dir = false; - if (!param.input.out_app_flag + if (param.input.out_app_flag == 0 && ((param.input.out_hsr[0] == 1 || param.input.out_hsr[0] == 2) || param.input.out_mat_r[0] || param.input.out_mat_t[0] || param.input.out_mat_dh[0] || param.input.out_mat_ds[0])) @@ -284,7 +285,7 @@ void ReadInput::create_directory(const Parameter& param) out_dir = true; } bool out_wfc_dir = false; - if (param.input.out_wfc_lcao && !param.input.out_app_flag) + if (param.input.out_wfc_lcao && param.input.out_app_flag == 0) { out_wfc_dir = true; } @@ -298,7 +299,6 @@ void ReadInput::create_directory(const Parameter& param) param.input.mdp.md_restart, param.input.out_alllog, param.globalv.global_out_dir, - param.globalv.global_stru_dir, param.globalv.global_matrix_dir, param.globalv.global_wfc_dir, param.globalv.global_mlkedf_descriptor_dir, @@ -306,6 +306,40 @@ void ReadInput::create_directory(const Parameter& param) param.globalv.log_file, param.input.of_ml_gene_data, param.input.deepks_out_freq_elec > 0); // xiaohui add 2013-09-01 + + // Create unified subdirectories when out_app_flag == 2, only for outputs the user actually requested + if (param.input.out_app_flag == 2) + { + const std::vector> subdir_flags = { + {param.input.out_stru > 0, param.globalv.global_stru_dir}, + {param.input.out_wfc_lcao > 0 || param.input.out_wfc_pw > 0, param.globalv.global_psi_dir}, + {param.input.out_chg[0] > 0, param.globalv.global_chg_dir}, + {param.input.out_pot[0] > 0 || param.input.out_elf[0] > 0, param.globalv.global_pot_dir}, + {param.input.out_elf[0] > 0, param.globalv.global_elf_dir}, + {param.input.out_dos > 0 || !param.input.out_band.empty() && param.input.out_band[0] > 0, param.globalv.global_dos_dir}, + {param.input.out_dipole, param.globalv.global_dip_dir}, + {param.input.out_dmk[0] > 0 || param.input.out_dmr[0] > 0 || param.input.out_hsk[0] > 0 + || param.input.out_mat_hs2[0] > 0 || param.input.out_mat_r[0] > 0 || param.input.out_mat_t[0] > 0 + || param.input.out_mat_tk[0] > 0 || param.input.out_mat_l[0] > 0 + || param.input.out_mat_dh[0] > 0 || param.input.out_mat_ds[0] > 0 + || param.input.out_mat_xc || param.input.out_mat_xc2[0] > 0 || param.input.out_hr_npz + || param.input.out_dm_npz, param.globalv.global_mat_dir} + }; + for (const auto& flag_dir : subdir_flags) + { + const bool need_create = flag_dir.first; + const std::string& dir = flag_dir.second; + if (need_create && !dir.empty() && dir != param.globalv.global_out_dir) + { + int ret = ModuleBase::make_directory(dir); + if (ret != 0 && errno != EEXIST) + { + std::cout << " CAN NOT MAKE THE DIR: " << dir << std::endl; + } + } + } + } + //const std::string ss = "test -d " + PARAM.inp.read_file_dir; struct stat st; if (stat(PARAM.inp.read_file_dir.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) diff --git a/source/source_io/module_parameter/read_input_item_md.cpp b/source/source_io/module_parameter/read_input_item_md.cpp index d5f6dc6bd67..eb6ac3db167 100644 --- a/source/source_io/module_parameter/read_input_item_md.cpp +++ b/source/source_io/module_parameter/read_input_item_md.cpp @@ -169,7 +169,9 @@ Note that md_tlast is only used in NVT/NPT simulations. If md_tlast is unset or item.annotation = "The period to output MD restart information"; item.category = "Molecular dynamics"; item.type = "Integer"; - item.description = "The output frequency of OUT.{suffix}/STRU_MD_*, which are used to restart molecular dynamics calculations, see md_restart in detail. Set to 0 to disable MD restart output."; + item.description = "Deprecated: use out_freq_ion to control MD output frequency instead. " + "This parameter is kept for backward compatibility as a fallback when " + "out_freq_ion is not set (0)."; item.default_value = "5"; item.unit = ""; read_sync_int(input.mdp.md_restartfreq); diff --git a/source/source_io/module_parameter/read_set_globalv.cpp b/source/source_io/module_parameter/read_set_globalv.cpp index 3b395e6b8f5..5a74f8b41b8 100644 --- a/source/source_io/module_parameter/read_set_globalv.cpp +++ b/source/source_io/module_parameter/read_set_globalv.cpp @@ -3,6 +3,35 @@ #include "source_base/global_variable.h" #include "source_base/tool_quit.h" #include "source_io/module_parameter/parameter.h" + +namespace +{ +/// @brief Find the structure file for restarting a molecular dynamics run. +/// @param stru_dir directory where the previous run wrote its structure files +/// @param istep number of completed ionic steps recorded in Restart_md.txt +/// @return path of the first existing structure file, empty if none exists +/// @details Two naming schemes are accepted, in order: +/// - "STRU{istep + 1}": written by run_md since the ionic-step numbering +/// was unified with relax (1-based); +/// - "STRU_MD_{istep}": written by older ABACUS versions. +std::string find_md_restart_stru(const std::string& stru_dir, const int istep) +{ + const std::string stru_new = stru_dir + "STRU" + std::to_string(istep + 1); + std::ifstream file_new(stru_new.c_str()); + if (file_new.good()) + { + return stru_new; + } + const std::string stru_old = stru_dir + "STRU_MD_" + std::to_string(istep); + std::ifstream file_old(stru_old.c_str()); + if (file_old.good()) + { + return stru_old; + } + return ""; +} +} // namespace + namespace ModuleIO { /// @note Here para.inp has been synchronized of all ranks. @@ -85,17 +114,36 @@ void ReadInput::set_global_dir(const Input_para& inp, System_para& sys) sys.global_out_dir = prefix + inp.suffix + "/"; sys.global_out_dir = to_dir(sys.global_out_dir); - /// get the global output directory - sys.global_stru_dir = sys.global_out_dir + "STRU/"; - sys.global_stru_dir = to_dir(sys.global_stru_dir); - - /// get the global output directory - sys.global_matrix_dir = sys.global_out_dir + "matrix/"; - sys.global_matrix_dir = to_dir(sys.global_matrix_dir); + /// Set subdirectories based on out_app_flag + /// out_app_flag == 2: use unified uppercase subdirectories + /// otherwise: keep backward-compatible behavior (all point to global_out_dir) + if (inp.out_app_flag == 2) + { + sys.global_stru_dir = sys.global_out_dir + "STRU/"; + sys.global_psi_dir = sys.global_out_dir + "PSI/"; + sys.global_chg_dir = sys.global_out_dir + "CHG/"; + sys.global_pot_dir = sys.global_out_dir + "POT/"; + sys.global_elf_dir = sys.global_out_dir + "ELF/"; + sys.global_dos_dir = sys.global_out_dir + "DOS/"; + sys.global_dip_dir = sys.global_out_dir + "DIP/"; + sys.global_mat_dir = sys.global_out_dir + "MAT/"; + } + else + { + sys.global_stru_dir = sys.global_out_dir; + sys.global_psi_dir = sys.global_out_dir; + sys.global_chg_dir = sys.global_out_dir; + sys.global_pot_dir = sys.global_out_dir; + sys.global_elf_dir = sys.global_out_dir; + sys.global_dos_dir = sys.global_out_dir; + sys.global_dip_dir = sys.global_out_dir; + sys.global_mat_dir = sys.global_out_dir; + } - /// get the global output directory - sys.global_wfc_dir = sys.global_out_dir + "WFC/"; - sys.global_wfc_dir = to_dir(sys.global_wfc_dir); + /// Map legacy directory names to new unified names + /// WFC -> PSI, matrix -> MAT + sys.global_wfc_dir = sys.global_psi_dir; + sys.global_matrix_dir = sys.global_mat_dir; /// get the global ML KEDF descriptor directory sys.global_mlkedf_descriptor_dir = sys.global_out_dir + "MLKEDF_Descriptors/"; @@ -112,15 +160,36 @@ void ReadInput::set_global_dir(const Input_para& inp, System_para& sys) /// get the stru file for md restart case if (inp.calculation == "md" && inp.mdp.md_restart) { - int istep = current_md_step(sys.global_readin_dir); + const int istep = current_md_step(sys.global_readin_dir); if (inp.read_file_dir == to_dir("OUT." + inp.suffix)) { - sys.global_in_stru = sys.global_stru_dir + "STRU_MD_" + std::to_string(istep); + // Restart from the default output directory: search the current + // STRU output directory, which follows out_app_flag. + const std::string stru_dir = sys.global_stru_dir; + sys.global_in_stru = find_md_restart_stru(stru_dir, istep); + if (sys.global_in_stru.empty()) + { + // Releases before the out_app_flag rework always wrote + // STRU_MD_{istep} into a fixed STRU/ subdirectory of the + // output directory; keep those outputs restartable. + const std::string legacy_dir = sys.global_out_dir + "STRU/"; + sys.global_in_stru = find_md_restart_stru(legacy_dir, istep); + } } else { - sys.global_in_stru = inp.read_file_dir + "STRU_MD_" + std::to_string(istep); + // Restart from a user-provided directory: the previous run may + // have written either naming scheme there. + const std::string stru_dir = inp.read_file_dir; + sys.global_in_stru = find_md_restart_stru(stru_dir, istep); + } + + if (sys.global_in_stru.empty()) + { + const std::string message = "no STRU file found for MD restart in " + sys.global_readin_dir + + "; expected STRU_MD_{step} or STRU{step+1}"; + ModuleBase::WARNING_QUIT("ReadInput::set_global_dir", message); } } else @@ -154,6 +223,13 @@ void ReadInput::set_global_dir(const Input_para& inp, System_para& sys) Parallel_Common::bcast_string(sys.global_stru_dir); Parallel_Common::bcast_string(sys.global_matrix_dir); Parallel_Common::bcast_string(sys.global_wfc_dir); + Parallel_Common::bcast_string(sys.global_psi_dir); + Parallel_Common::bcast_string(sys.global_chg_dir); + Parallel_Common::bcast_string(sys.global_pot_dir); + Parallel_Common::bcast_string(sys.global_elf_dir); + Parallel_Common::bcast_string(sys.global_dos_dir); + Parallel_Common::bcast_string(sys.global_dip_dir); + Parallel_Common::bcast_string(sys.global_mat_dir); Parallel_Common::bcast_string(sys.global_in_stru); #endif } diff --git a/source/source_io/module_parameter/system_parameter.h b/source/source_io/module_parameter/system_parameter.h index 438bd32c145..4705c33f4ea 100644 --- a/source/source_io/module_parameter/system_parameter.h +++ b/source/source_io/module_parameter/system_parameter.h @@ -53,8 +53,16 @@ struct System_para std::string global_stru_dir = ""; ///< global structure directory std::string global_matrix_dir = ""; ///< global matrix directory std::string global_wfc_dir = ""; ///< global wavefunction directory + // Subdirectories used when out_app_flag == 2 + std::string global_psi_dir = ""; ///< wavefunction directory (PSI/) + std::string global_chg_dir = ""; ///< charge density directory (CHG/) + std::string global_pot_dir = ""; ///< potential directory (POT/) + std::string global_elf_dir = ""; ///< ELF directory (ELF/) + std::string global_dos_dir = ""; ///< DOS directory (DOS/) + std::string global_dip_dir = ""; ///< dipole directory (DIP/) + std::string global_mat_dir = ""; ///< matrix directory (MAT/) std::string global_mlkedf_descriptor_dir = ""; ///< global ML KEDF descriptor directory - std::string global_deepks_label_elec_dir = ""; ///< global directory for DeePKS labels during electronic steps + std::string global_deepks_label_elec_dir = ""; ///< global directory for DeePKS labels during electronic steps std::string log_file = "log"; ///< log file name bool deepks_setorb = false; ///< true if "deepks" is set diff --git a/source/source_io/module_wf/read_wf2rho_pw.cpp b/source/source_io/module_wf/read_wf2rho_pw.cpp index 50e31e733a3..298334607db 100644 --- a/source/source_io/module_wf/read_wf2rho_pw.cpp +++ b/source/source_io/module_wf/read_wf2rho_pw.cpp @@ -129,7 +129,7 @@ void ModuleIO::read_wf2rho_pw_impl(const ModulePW::PW_Basis_K* pw_wfc, // mohan add 2025-05-17 // .dat file const int out_type = 2; - const bool out_app_flag = false; + const int out_app_flag = 0; const bool gamma_only = false; const int istep = -1; diff --git a/source/source_io/module_wf/read_wfc_nao.cpp b/source/source_io/module_wf/read_wfc_nao.cpp index 3148e2c0e2f..58599769d4c 100644 --- a/source/source_io/module_wf/read_wfc_nao.cpp +++ b/source/source_io/module_wf/read_wfc_nao.cpp @@ -296,7 +296,7 @@ bool ModuleIO::read_wfc_nao( { if (myrank == 0) { - const bool out_app_flag = false; + const int out_app_flag = 0; std::stringstream error_message; std::string readin_dir = global_readin_dir; if(istep >= 0) diff --git a/source/source_io/module_wf/write_wfc_nao.cpp b/source/source_io/module_wf/write_wfc_nao.cpp index 2d28e96e60d..b468cc4c6c1 100644 --- a/source/source_io/module_wf/write_wfc_nao.cpp +++ b/source/source_io/module_wf/write_wfc_nao.cpp @@ -202,7 +202,7 @@ void wfc_nao_write2file_complex(const std::string& name, template void write_wfc_nao(const int out_type, - const bool out_app_flag, + const int out_app_flag, const psi::Psi& psi, const ModuleBase::matrix& ekb, const ModuleBase::matrix& wg, @@ -270,7 +270,7 @@ void write_wfc_nao(const int out_type, if (myid == 0) { std::string wfc_dir; - if(out_app_flag) + if(out_app_flag == 1) { wfc_dir = PARAM.globalv.global_out_dir; } @@ -281,7 +281,7 @@ void write_wfc_nao(const int out_type, std::string fn = filename_output(wfc_dir,"wf","nao",ik,ik2iktot,nspin,nkstot, out_type,out_app_flag,gamma_only,istep); - bool append_flag = (istep > 0 && out_app_flag); + bool append_flag = (istep > 0 && out_app_flag == 1); if (std::is_same::value) { wfc_nao_write2file(fn, @@ -311,7 +311,7 @@ void write_wfc_nao(const int out_type, } template void write_wfc_nao(const int out_type, - const bool out_app_flag, + const int out_app_flag, const psi::Psi& psi, const ModuleBase::matrix& ekb, const ModuleBase::matrix& wg, @@ -323,7 +323,7 @@ template void write_wfc_nao(const int out_type, const int istep); template void write_wfc_nao>(const int out_type, - const bool out_app_flag, + const int out_app_flag, const psi::Psi>& psi, const ModuleBase::matrix& ekb, const ModuleBase::matrix& wg, diff --git a/source/source_io/module_wf/write_wfc_nao.h b/source/source_io/module_wf/write_wfc_nao.h index 152723b5109..70dde0ae6fb 100644 --- a/source/source_io/module_wf/write_wfc_nao.h +++ b/source/source_io/module_wf/write_wfc_nao.h @@ -25,7 +25,7 @@ namespace ModuleIO */ template void write_wfc_nao(const int out_type, - const bool out_app_flag, + const int out_app_flag, const psi::Psi& psi, const ModuleBase::matrix& ekb, const ModuleBase::matrix& wg, diff --git a/source/source_io/module_wf/write_wfc_pw.cpp b/source/source_io/module_wf/write_wfc_pw.cpp index 450bb596988..d90f7f5d645 100644 --- a/source/source_io/module_wf/write_wfc_pw.cpp +++ b/source/source_io/module_wf/write_wfc_pw.cpp @@ -43,7 +43,7 @@ void ModuleIO::write_wfc_pw( assert(nkstot>0); assert(nks>0); - bool out_app_flag = false; // need to modify later, mohan 2025-05-17 + int out_app_flag = 0; // need to modify later, mohan 2025-05-17 bool gamma_only = false; // need to modify later, mohan 2025-05-17 std::string* wfilename = new std::string[nks]; diff --git a/source/source_io/test/write_wfc_nao_test.cpp b/source/source_io/test/write_wfc_nao_test.cpp index b5a64f2a336..8d7bc6b6a48 100644 --- a/source/source_io/test/write_wfc_nao_test.cpp +++ b/source/source_io/test/write_wfc_nao_test.cpp @@ -35,9 +35,9 @@ TEST(GenWfcLcaoFnameTest, OutType1GammaOnlyOutAppFlagTrue) const int nspin = 1; const int nkstot = 1; const int out_type = 1; - const bool out_app_flag = true; + const int out_app_flag = 1; const bool gamma_only = true; - // if out_app_flag = true, then the 'g' label will not show up + // if out_app_flag = 1 (append), then the 'g' label will not show up const int istep = 0; std::string result = ModuleIO::filename_output( @@ -60,9 +60,9 @@ TEST(GenWfcLcaoFnameTest, OutType2GammaOnlyOutAppFlagFalse) const int nspin = 2; const int nkstot = 2; const int out_type = 2; - const bool out_app_flag = false; + const int out_app_flag = 0; const bool gamma_only = true; - // if out_app_flag = false, then the 'g' label appears + // if out_app_flag = 0 (no append), then the 'g' label appears const int istep = 2; std::string result = ModuleIO::filename_output( @@ -84,7 +84,7 @@ TEST(GenWfcLcaoFnameTest, OutTypeInvalid) const int nspin = 1; const int nkstot = 3; const int out_type = 3; - const bool out_app_flag = true; + const int out_app_flag = 1; const bool gamma_only = false; const int istep = 3; @@ -151,7 +151,7 @@ class WriteWfcLcaoTest : public testing::Test // mohan add 2025-05-11 std::vector ik2iktot = {0,1}; int nkstot = 2; - bool out_app_flag = true; + int out_app_flag = 1; void SetUp() override { diff --git a/source/source_io/test_serial/io_sys_var_test.cpp b/source/source_io/test_serial/io_sys_var_test.cpp index 678ee6a81b4..21257b96694 100644 --- a/source/source_io/test_serial/io_sys_var_test.cpp +++ b/source/source_io/test_serial/io_sys_var_test.cpp @@ -5,6 +5,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "source_base/fs_compat.h" #include "source_base/tool_quit.h" #include "source_io/module_parameter/input_parameter.h" #define private public @@ -67,8 +68,18 @@ TEST_F(InputTest, Item_test) TestParameters::set_global_dir(readinput, input, sys); EXPECT_EQ(sys.global_out_dir, "OUT.test/"); - EXPECT_EQ(sys.global_stru_dir, "OUT.test/STRU/"); - EXPECT_EQ(sys.global_matrix_dir, "OUT.test/matrix/"); + // out_app_flag defaults to 1, so stru dir maps to global out dir + EXPECT_EQ(sys.global_stru_dir, "OUT.test/"); + // out_app_flag defaults to 1, so matrix dir maps to global out dir + EXPECT_EQ(sys.global_matrix_dir, "OUT.test/"); + EXPECT_EQ(sys.global_wfc_dir, "OUT.test/"); + EXPECT_EQ(sys.global_psi_dir, "OUT.test/"); + EXPECT_EQ(sys.global_chg_dir, "OUT.test/"); + EXPECT_EQ(sys.global_pot_dir, "OUT.test/"); + EXPECT_EQ(sys.global_elf_dir, "OUT.test/"); + EXPECT_EQ(sys.global_dos_dir, "OUT.test/"); + EXPECT_EQ(sys.global_dip_dir, "OUT.test/"); + EXPECT_EQ(sys.global_mat_dir, "OUT.test/"); TestParameters::set_globalv(readinput, input, sys); @@ -100,3 +111,55 @@ TEST_F(InputTest, Item_test) EXPECT_EQ(sys.npol, 1); } } + +TEST_F(InputTest, SetGlobalDirMdRestart) +{ + readinput.check_ntype_flag = false; + + const std::string case_dir = testing::TempDir() + "/abacus_md_restart_io/"; + ModuleBase::make_directory(case_dir); + + // Restart from a user-provided read_file_dir holding the legacy + // "STRU_MD_{istep}" naming: the structure file must be picked up. + const std::string legacy_dir = case_dir + "legacy/"; + ModuleBase::make_directory(legacy_dir); + const std::string restart_txt = legacy_dir + "Restart_md.txt"; + std::ofstream restart_file(restart_txt.c_str()); + restart_file << 5 << std::endl; + restart_file << 0.03 << std::endl; + restart_file.close(); + const std::string stru_legacy = legacy_dir + "STRU_MD_5"; + std::ofstream stru_file_legacy(stru_legacy.c_str()); + stru_file_legacy << "ATOMIC_SPECIES" << std::endl; + stru_file_legacy.close(); + + input.suffix = "autotest"; + input.calculation = "md"; + input.mdp.md_restart = true; + input.read_file_dir = legacy_dir; + TestParameters::set_global_dir(readinput, input, sys); + EXPECT_EQ(sys.global_in_stru, stru_legacy); + + // Restart from a read_file_dir holding the current "STRU{istep + 1}" + // naming written by run_md (1-based, unified with relax). + const std::string newnaming_dir = case_dir + "newnaming/"; + ModuleBase::make_directory(newnaming_dir); + const std::string restart_txt_new = newnaming_dir + "Restart_md.txt"; + std::ofstream restart_file_new(restart_txt_new.c_str()); + restart_file_new << 5 << std::endl; + restart_file_new << 0.03 << std::endl; + restart_file_new.close(); + const std::string stru_new = newnaming_dir + "STRU6"; + std::ofstream stru_file_new(stru_new.c_str()); + stru_file_new << "ATOMIC_SPECIES" << std::endl; + stru_file_new.close(); + + input.read_file_dir = newnaming_dir; + TestParameters::set_global_dir(readinput, input, sys); + EXPECT_EQ(sys.global_in_stru, stru_new); + + // restore the shared input state so other tests are not affected + input.calculation = "scf"; + input.mdp.md_restart = false; + input.read_file_dir = "OUT.$suffix"; +} diff --git a/source/source_io/test_serial/read_input_test.cpp b/source/source_io/test_serial/read_input_test.cpp index 236b8e8f87d..b948aa9116c 100644 --- a/source/source_io/test_serial/read_input_test.cpp +++ b/source/source_io/test_serial/read_input_test.cpp @@ -39,7 +39,6 @@ void make_dir_out(const std::string& suffix, const bool& restart, const bool out_alllog, const std::string& global_out_dir, - const std::string& global_stru_dir, const std::string& global_matrix_dir, const std::string& global_wfc_dir, const std::string& global_mlkedf_descriptor_dir, diff --git a/source/source_md/run_md.cpp b/source/source_md/run_md.cpp index 114f9cbb3a5..1e92c2e9556 100644 --- a/source/source_md/run_md.cpp +++ b/source/source_md/run_md.cpp @@ -188,6 +188,13 @@ void md_line(MDCell& mdcell, apply_plumed_forces(mdcell, plumed_forces); }; + /// Effective ionic-step output frequency. + /// Prefer out_freq_ion; fall back to md_restartfreq for backward + /// compatibility when out_freq_ion is not set. + const int eff_output_freq = (param_in.inp.out_freq_ion > 0) + ? param_in.inp.out_freq_ion + : param_in.mdp.md_restartfreq; + /// md cycle, mohan update 2026-01-04, change '<=' to '<' while ((mdrun->step_ + mdrun->step_rst_) < param_in.mdp.md_nstep && !mdrun->stop) { @@ -280,16 +287,22 @@ void md_line(MDCell& mdcell, mdrun->virial); } - if (param_in.mdp.md_restartfreq > 0 - && (mdrun->step_ + mdrun->step_rst_) % param_in.mdp.md_restartfreq == 0) + const int current_step = mdrun->step_ + mdrun->step_rst_; + const bool do_output_step = eff_output_freq > 0 + && current_step % eff_output_freq == 0; + if (do_output_step) { if (mdcell.has_backing_unitcell()) { mdcell.sync_backing_unitcell(); } - std::stringstream file; - file << PARAM.globalv.global_stru_dir << "STRU_MD_" << mdrun->step_ + mdrun->step_rst_; - mdcell::print_stru_file(mdcell, mdcell.stru_meta(), file.str()); + if (param_in.inp.out_stru > 0) + { + const int stru_step = current_step + 1; + std::stringstream file; + file << PARAM.globalv.global_stru_dir << "STRU" << stru_step; + mdcell::print_stru_file(mdcell, mdcell.stru_meta(), file.str()); + } mdrun->write_restart(PARAM.globalv.global_out_dir); } diff --git a/source/source_psi/psi_init_file.cpp b/source/source_psi/psi_init_file.cpp index 29a8619e30b..cc7086d8c8f 100644 --- a/source/source_psi/psi_init_file.cpp +++ b/source/source_psi/psi_init_file.cpp @@ -52,7 +52,7 @@ void psi_init_file::init_psig(T* psig, const int& ik) // mohan update, this is for plane wave, 2025-05-17 const int out_type = 2; - const bool out_app_flag = false; + const int out_app_flag = 0; const bool gamma_only = false; const int istep = -1; diff --git a/source/source_relax/relax_driver.cpp b/source/source_relax/relax_driver.cpp index 7497fc8e1c9..3c3d5c9273f 100644 --- a/source/source_relax/relax_driver.cpp +++ b/source/source_relax/relax_driver.cpp @@ -21,7 +21,7 @@ void Relax_Driver::relax_driver( // Cache global configuration once so downstream helpers do not each reach // into PARAM / GlobalV. - out_dir_ = PARAM.globalv.global_out_dir; + out_dir_ = PARAM.globalv.global_stru_dir; deepks_setorb_ = PARAM.globalv.deepks_setorb; my_rank_ = GlobalV::MY_RANK; @@ -186,7 +186,7 @@ bool Relax_Driver::relax_step(std::vector& steps, void Relax_Driver::stru_out(const int istep, UnitCell& ucell, const Input_para& inp, const double etot, const ModuleBase::matrix& stress, const ModuleBase::matrix& force) { - // out_stru is effective for scf/nscf/relax/cell-relax (md writes STRU_MD_* via md_restartfreq) + // out_stru is effective for scf/nscf/relax/cell-relax; md handles STRU output in run_md.cpp if (inp.calculation != "relax" && inp.calculation != "cell-relax" && inp.calculation != "scf" && inp.calculation != "nscf") { diff --git a/tests/integrate/validation_tools/props_cube.sh b/tests/integrate/validation_tools/props_cube.sh index 1dfd83270ff..2b1b78526b5 100644 --- a/tests/integrate/validation_tools/props_cube.sh +++ b/tests/integrate/validation_tools/props_cube.sh @@ -154,7 +154,7 @@ if ! test -z "$has_lowf" && [ "$has_lowf" == 1 ]; then else # multi-k point case if ! test -z "$out_app_flag" && [ $out_app_flag == 0 ]; then wfc_name=wfk1g3_nao - input_file=WFC/wfk1g3_nao + input_file=wfk1g3_nao else wfc_name=wfk2_nao input_file=wfk2_nao