From ed5d6cee9446955796f22ca19e3919fd3b30cd2e Mon Sep 17 00:00:00 2001 From: haochong zhang Date: Tue, 23 Jun 2026 04:09:41 +0000 Subject: [PATCH 1/3] fix: align module hs sparse output with threshold --- source/source_io/module_hs/single_R_io.cpp | 10 +- .../source_io/module_hs/write_HS_sparse.cpp | 13 +- .../module_restart/restart_exx_csr.hpp | 6 +- source/source_io/test/CMakeLists.txt | 9 ++ .../source_io/test/restart_exx_csr_test.cpp | 51 +++++++ source/source_io/test/single_R_io_test.cpp | 59 ++++++++ .../source_io/test/write_hs_r_compat_test.cpp | 136 ++++++++++++++++++ 7 files changed, 279 insertions(+), 5 deletions(-) create mode 100644 source/source_io/test/restart_exx_csr_test.cpp diff --git a/source/source_io/module_hs/single_R_io.cpp b/source/source_io/module_hs/single_R_io.cpp index f5e52a0c21..d901e0ab0a 100644 --- a/source/source_io/module_hs/single_R_io.cpp +++ b/source/source_io/module_hs/single_R_io.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -15,7 +16,8 @@ inline void write_data(std::ofstream& ofs, const double& data) } inline void write_data(std::ofstream& ofs, const std::complex& data) { - ofs << " (" << data.real() << "," << data.imag() << ")"; + ofs << " (" << std::fixed << std::scientific << std::setprecision(16) + << data.real() << "," << data.imag() << ")"; } template @@ -65,6 +67,12 @@ void ModuleIO::output_single_R(std::ofstream& ofs, { for (auto &value : iter->second) { + if (value.first >= static_cast(nlocal)) + { + std::cerr << "Sparse column index out of range." << std::endl; + ModuleBase::WARNING_QUIT("ModuleIO::output_single_R", + "Sparse column index out of range."); + } line[value.first] = value.second; } } diff --git a/source/source_io/module_hs/write_HS_sparse.cpp b/source/source_io/module_hs/write_HS_sparse.cpp index ed4a738741..3ea1367ccf 100644 --- a/source/source_io/module_hs/write_HS_sparse.cpp +++ b/source/source_io/module_hs/write_HS_sparse.cpp @@ -8,6 +8,8 @@ #include "single_R_io.h" #include +#include +#include #include namespace @@ -16,6 +18,7 @@ template std::vector count_nonzeros_by_R( const ModuleIO::SparseRMatrix& smat, const std::set& all_R_coor, + const double threshold, const bool reduce) { std::vector nonzero_num(all_R_coor.size(), 0); @@ -27,7 +30,13 @@ std::vector count_nonzeros_by_R( { for (const auto& row_loop: iter->second) { - nonzero_num[count] += row_loop.second.size(); + for (const auto& col_value: row_loop.second) + { + if (std::abs(col_value.second) > threshold) + { + ++nonzero_num[count]; + } + } } } ++count; @@ -499,7 +508,7 @@ void ModuleIO::save_sparse( } const std::vector nonzero_num - = count_nonzeros_by_R(smat, all_R_coor, options.reduce); + = count_nonzeros_by_R(smat, all_R_coor, options.threshold, options.reduce); const int output_R_number = count_output_R(nonzero_num); std::ofstream ofs; if (!options.reduce || GlobalV::DRANK == 0) diff --git a/source/source_io/module_restart/restart_exx_csr.hpp b/source/source_io/module_restart/restart_exx_csr.hpp index 99ff25382e..568ed952fc 100644 --- a/source/source_io/module_restart/restart_exx_csr.hpp +++ b/source/source_io/module_restart/restart_exx_csr.hpp @@ -99,8 +99,10 @@ namespace ModuleIO Abfs::Vector3_Order dR(R[0], R[1], R[2]); for (int i = 0;i < nw1;++i) { for (int j = 0;j < nw2;++j) { - target[dR][start1 + i][start2 + j] = - ((std::abs(matrix(i, j)) > sparse_threshold) ? matrix(i, j) : static_cast(0)); + if (std::abs(matrix(i, j)) > sparse_threshold) + { + target[dR][start1 + i][start2 + j] = matrix(i, j); + } } } } diff --git a/source/source_io/test/CMakeLists.txt b/source/source_io/test/CMakeLists.txt index 6dd2324747..5e200d99be 100644 --- a/source/source_io/test/CMakeLists.txt +++ b/source/source_io/test/CMakeLists.txt @@ -302,6 +302,15 @@ AddTest( ) endif() +if(ENABLE_LIBRI) +AddTest( + TARGET MODULE_IO_restart_exx_csr_test + LIBS parameter base ${math_libs} device cell_info + SOURCES + restart_exx_csr_test.cpp +) +endif() + AddTest( TARGET MODULE_IO_write_elf_logic_test SOURCES write_elf_logic_test.cpp diff --git a/source/source_io/test/restart_exx_csr_test.cpp b/source/source_io/test/restart_exx_csr_test.cpp new file mode 100644 index 0000000000..af023a7ef4 --- /dev/null +++ b/source/source_io/test/restart_exx_csr_test.cpp @@ -0,0 +1,51 @@ +#include "gtest/gtest.h" + +#include "source_io/module_restart/restart_exx_csr.h" + +#include + +namespace +{ +void init_unitcell_for_ri(UnitCell& ucell) +{ + ucell.ntype = 1; + ucell.nat = 1; + ucell.atoms = new Atom[1]; + ucell.set_atom_flag = true; + ucell.atoms[0].na = 1; + ucell.atoms[0].nw = 2; + ucell.atoms[0].stapos_wf = 0; + ucell.itia2iat(0, 0) = 0; + ucell.set_iat2itia(); + ucell.set_iat2iwt(1); +} +} // namespace + +TEST(RestartExxCsr, CalculateRITensorSparseDropsBelowThresholdEntries) +{ + UnitCell ucell; + init_unitcell_for_ri(ucell); + + RI::Tensor matrix({2, 2}); + matrix(0, 0) = 1.0; + matrix(0, 1) = 1e-12; + matrix(1, 0) = 0.0; + matrix(1, 1) = -2.0; + + std::map>> Hexxs; + Hexxs[0][ModuleIO::TAC{0, ModuleIO::TC{0, 0, 0}}] = matrix; + + const auto sparse = ModuleIO::calculate_RI_Tensor_sparse(1e-10, Hexxs, ucell); + + const Abfs::Vector3_Order r_vector(0, 0, 0); + ASSERT_EQ(sparse.count(r_vector), 1); + const auto& block = sparse.at(r_vector); + ASSERT_EQ(block.count(0), 1); + EXPECT_EQ(block.at(0).count(0), 1); + EXPECT_EQ(block.at(0).at(0), 1.0); + EXPECT_EQ(block.at(0).count(1), 0); + ASSERT_EQ(block.count(1), 1); + EXPECT_EQ(block.at(1).count(0), 0); + EXPECT_EQ(block.at(1).count(1), 1); + EXPECT_EQ(block.at(1).at(1), -2.0); +} diff --git a/source/source_io/test/single_R_io_test.cpp b/source/source_io/test/single_R_io_test.cpp index 092da754b9..8ce4531d47 100644 --- a/source/source_io/test/single_R_io_test.cpp +++ b/source/source_io/test/single_R_io_test.cpp @@ -6,6 +6,11 @@ #include "source_io/module_hs/single_R_io.h" #include "source_base/global_variable.h" #include "source_basis/module_ao/parallel_orbitals.h" +#include +#include +#include +#include +#include /************************************************ * unit test of output_single_R ***********************************************/ @@ -116,6 +121,60 @@ TEST(ModuleIOTest, OutputSingleR) std::remove("test_output_single_R_0.dat"); } +TEST(ModuleIOTest, OutputSingleRComplexKeepsHighPrecision) +{ + const std::string filename = "test_output_single_R_complex.dat"; + std::remove(filename.c_str()); + GlobalV::DRANK = 0; + std::ofstream ofs(filename); + + Parallel_Orbitals pv; + pv.set_serial(5, 5); + ModuleIO::SparseRBlock> XR = { + {0, {{1, std::complex(1.234567890123456, -2.345678901234567)}}} + }; + ModuleIO::SparseWriteOptions options; + options.threshold = 1e-12; + options.binary = false; + options.reduce = false; + options.temp_dir = "./"; + + ModuleIO::output_single_R(ofs, XR, pv, options); + ofs.close(); + + std::ifstream ifs(filename); + const std::string output((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + EXPECT_THAT(output, testing::HasSubstr("(1.2345678901234560e+00,-2.3456789012345669e+00)")); + EXPECT_THAT(output, testing::Not(testing::HasSubstr("(1.23457,-2.34568)"))); + + std::remove(filename.c_str()); +} + +TEST(ModuleIOTest, OutputSingleRRejectsOutOfRangeColumn) +{ + const char* filename = "/tmp/test_output_single_R_invalid.dat"; + std::remove(filename); + EXPECT_EXIT( + { + GlobalV::DRANK = 0; + std::ofstream ofs(filename); + Parallel_Orbitals pv; + pv.set_serial(5, 5); + ModuleIO::SparseRBlock XR = { + {0, {{5, 1.0}}} + }; + ModuleIO::SparseWriteOptions options; + options.threshold = 1e-12; + options.binary = false; + options.reduce = false; + options.temp_dir = "/tmp/"; + ModuleIO::output_single_R(ofs, XR, pv, options); + }, + ::testing::ExitedWithCode(1), + "Sparse column index out of range"); + std::remove(filename); +} + int main(int argc, char **argv) { diff --git a/source/source_io/test/write_hs_r_compat_test.cpp b/source/source_io/test/write_hs_r_compat_test.cpp index 392bafb68d..f8d714a7d2 100644 --- a/source/source_io/test/write_hs_r_compat_test.cpp +++ b/source/source_io/test/write_hs_r_compat_test.cpp @@ -115,6 +115,26 @@ std::vector read_binary_ints(const std::string& filename, const size_t coun return values; } +template +T read_binary_value(std::ifstream& ifs) +{ + T value{}; + ifs.read(reinterpret_cast(&value), sizeof(T)); + return value; +} + +std::vector read_lines(const std::string& filename) +{ + std::ifstream ifs(filename.c_str()); + std::vector lines; + std::string line; + while (std::getline(ifs, line)) + { + lines.push_back(line); + } + return lines; +} + int count_substr(const std::string& text, const std::string& pattern) { int count = 0; @@ -309,6 +329,73 @@ TEST(WriteHsRCompatibility, LegacySparseHeaderKeepsStepStyle) std::remove(filename.c_str()); } +TEST(WriteHsRCompatibility, LegacySparseTextCountsOnlyValuesAboveThreshold) +{ + const std::string filename = "write_hs_r_threshold_s.csr"; + std::remove(filename.c_str()); + + GlobalV::DRANK = 0; + PARAM.sys.global_out_dir = "./"; + + Parallel_Orbitals pv; + init_serial_orbitals(pv); + const Abfs::Vector3_Order r_vector(0, 0, 0); + std::set> all_R_coor; + all_R_coor.insert(r_vector); + std::map, std::map>> sparse_matrix; + sparse_matrix[r_vector][0][0] = 1.0; + sparse_matrix[r_vector][0][1] = 1e-12; + sparse_matrix[r_vector][1][0] = 0.0; + sparse_matrix[r_vector][1][1] = -2.0; + + ModuleIO::SparseWriteOptions options; + options.filename = filename; + options.label = "S"; + options.threshold = 1e-10; + options.binary = false; + options.istep = 2; + options.reduce = false; + options.temp_dir = "./"; + ModuleIO::save_sparse(sparse_matrix, all_R_coor, pv, options); + + const std::vector lines = read_lines(filename); + ASSERT_GE(lines.size(), 6); + EXPECT_EQ(lines[0], "STEP: 2"); + EXPECT_EQ(lines[1], "Matrix Dimension of S(R): 2"); + EXPECT_EQ(lines[2], "Matrix number of S(R): 1"); + EXPECT_EQ(lines[3], "0 0 0 2"); + + std::istringstream value_stream(lines[4]); + std::vector values; + double value = 0.0; + while (value_stream >> value) + { + values.push_back(value); + } + EXPECT_THAT(values, testing::ElementsAre(1.0, -2.0)); + + std::istringstream column_stream(lines[5]); + std::vector columns; + int column = 0; + while (column_stream >> column) + { + columns.push_back(column); + } + EXPECT_THAT(columns, testing::ElementsAre(0, 1)); + + ASSERT_GE(lines.size(), 7); + std::istringstream indptr_stream(lines[6]); + std::vector indptr; + long long ptr = 0; + while (indptr_stream >> ptr) + { + indptr.push_back(ptr); + } + EXPECT_THAT(indptr, testing::ElementsAre(0, 1, 2)); + + std::remove(filename.c_str()); +} + TEST(WriteHsRCompatibility, LegacySparseBinaryHeaderWritesConcreteStep) { const std::string filename = "write_hs_r_legacy_binary_s.csr"; @@ -343,6 +430,55 @@ TEST(WriteHsRCompatibility, LegacySparseBinaryHeaderWritesConcreteStep) std::remove(filename.c_str()); } +TEST(WriteHsRCompatibility, LegacySparseBinaryCountsOnlyValuesAboveThreshold) +{ + const std::string filename = "write_hs_r_threshold_binary_s.csr"; + std::remove(filename.c_str()); + + GlobalV::DRANK = 0; + PARAM.sys.global_out_dir = "./"; + + Parallel_Orbitals pv; + init_serial_orbitals(pv); + const Abfs::Vector3_Order r_vector(0, 0, 0); + std::set> all_R_coor; + all_R_coor.insert(r_vector); + std::map, std::map>> sparse_matrix; + sparse_matrix[r_vector][0][0] = 1.0; + sparse_matrix[r_vector][0][1] = 1e-12; + sparse_matrix[r_vector][1][0] = 0.0; + sparse_matrix[r_vector][1][1] = -2.0; + + ModuleIO::SparseWriteOptions options; + options.filename = filename; + options.label = "S"; + options.threshold = 1e-10; + options.binary = true; + options.istep = 4; + options.reduce = false; + options.temp_dir = "./"; + ModuleIO::save_sparse(sparse_matrix, all_R_coor, pv, options); + + std::ifstream ifs(filename.c_str(), std::ios::binary); + ASSERT_TRUE(ifs.is_open()); + EXPECT_EQ(read_binary_value(ifs), 4); + EXPECT_EQ(read_binary_value(ifs), 2); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 2); + EXPECT_DOUBLE_EQ(read_binary_value(ifs), 1.0); + EXPECT_DOUBLE_EQ(read_binary_value(ifs), -2.0); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 2); + + std::remove(filename.c_str()); +} + TEST(WriteHsRCompatibility, HeaderStyleSamplesRemainDistinct) { EXPECT_TRUE(starts_with(" --- Ionic Step 1 ---", " --- Ionic Step")); From a67d9fd5fc6176cb397804d9ca9522cd9f5d59b0 Mon Sep 17 00:00:00 2001 From: haochong zhang Date: Tue, 23 Jun 2026 05:29:00 +0000 Subject: [PATCH 2/3] fix: stabilize module hs sparse output controls --- docs/advanced/input_files/input-main.md | 10 +- docs/parameters.yaml | 10 +- source/source_esolver/esolver_gets.cpp | 7 +- source/source_io/CMakeLists.txt | 1 + .../source_io/module_ctrl/ctrl_scf_lcao.cpp | 15 +- .../source_io/module_hs/cal_r_overlap_R.cpp | 183 +++++------ source/source_io/module_hs/cal_r_overlap_R.h | 7 +- .../source_io/module_hs/output_mat_sparse.cpp | 105 +++++- .../source_io/module_hs/output_mat_sparse.h | 28 ++ .../source_io/module_hs/rr_sparse_writer.cpp | 64 ++++ source/source_io/module_hs/rr_sparse_writer.h | 23 ++ source/source_io/module_hs/single_R_io.cpp | 25 +- source/source_io/module_hs/write_HS.hpp | 17 + source/source_io/module_hs/write_HS_R.cpp | 30 +- source/source_io/module_hs/write_HS_R.h | 12 +- .../source_io/module_hs/write_HS_sparse.cpp | 181 +++++------ source/source_io/module_hs/write_HS_sparse.h | 4 +- source/source_io/module_hs/write_vxc_r.hpp | 8 - .../read_input_item_output.cpp | 10 +- source/source_io/test/CMakeLists.txt | 1 + source/source_io/test/single_R_io_test.cpp | 30 ++ .../source_io/test/write_hs_r_compat_test.cpp | 305 ++++++++++++++++++ 22 files changed, 803 insertions(+), 273 deletions(-) create mode 100644 source/source_io/module_hs/rr_sparse_writer.cpp create mode 100644 source/source_io/module_hs/rr_sparse_writer.h diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index e9dd89d779..b90929a6e9 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -1964,7 +1964,7 @@ - **Type**: Boolean \[Integer\](optional) - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md. +- **Description**: Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. The optional second parameter controls text output precision. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md. > Note: In the 3.10-LTS version, the file name is data-rR-sparse.csr. - **Default**: False 8 @@ -1974,7 +1974,7 @@ - **Type**: Boolean \[Integer\](optional) - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Generate files containing the kinetic energy matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. +- **Description**: Generate files containing the kinetic energy matrix. The optional second parameter controls text output precision. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. > Note: In the 3.10-LTS version, the file name is data-TR-sparse_SPIN0.csr. - **Default**: False 8 @@ -1982,9 +1982,9 @@ ### out_mat_dh -- **Type**: Integer +- **Type**: Boolean \[Integer\](optional) - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print files containing the derivatives of the Hamiltonian matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. +- **Description**: Whether to print files containing the derivatives of the Hamiltonian matrix. The optional second parameter controls text output precision. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. > Note: In the 3.10-LTS version, the file name is data-dHRx-sparse_SPIN0.csr and so on. - **Default**: 0 8 @@ -1994,7 +1994,7 @@ - **Type**: Boolean \[Integer\](optional) - **Availability**: *Numerical atomic orbital basis (not gamma-only algorithm)* -- **Description**: Whether to print files containing the derivatives of the overlap matrix. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s. +- **Description**: Whether to print files containing the derivatives of the overlap matrix. The optional second parameter controls text output precision. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s. > Note: In the 3.10-LTS version, the file name is data-dSRx-sparse_SPIN0.csr and so on. - **Default**: False 8 diff --git a/docs/parameters.yaml b/docs/parameters.yaml index 255d4b78c9..1b59094a57 100644 --- a/docs/parameters.yaml +++ b/docs/parameters.yaml @@ -3058,7 +3058,7 @@ parameters: category: Output information type: "Boolean \\[Integer\\](optional)" description: | - Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md. + Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. The optional second parameter controls text output precision. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md. [NOTE] In the 3.10-LTS version, the file name is data-rR-sparse.csr. default_value: False 8 @@ -3068,7 +3068,7 @@ parameters: category: Output information type: "Boolean \\[Integer\\](optional)" description: | - Generate files containing the kinetic energy matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. + Generate files containing the kinetic energy matrix. The optional second parameter controls text output precision. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. [NOTE] In the 3.10-LTS version, the file name is data-TR-sparse_SPIN0.csr. default_value: False 8 @@ -3076,9 +3076,9 @@ parameters: availability: Numerical atomic orbital basis (not gamma-only algorithm) - name: out_mat_dh category: Output information - type: Integer + type: "Boolean \\[Integer\\](optional)" description: | - Whether to print files containing the derivatives of the Hamiltonian matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. + Whether to print files containing the derivatives of the Hamiltonian matrix. The optional second parameter controls text output precision. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. [NOTE] In the 3.10-LTS version, the file name is data-dHRx-sparse_SPIN0.csr and so on. default_value: 0 8 @@ -3088,7 +3088,7 @@ parameters: category: Output information type: "Boolean \\[Integer\\](optional)" description: | - Whether to print files containing the derivatives of the overlap matrix. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s. + Whether to print files containing the derivatives of the overlap matrix. The optional second parameter controls text output precision. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s. [NOTE] In the 3.10-LTS version, the file name is data-dSRx-sparse_SPIN0.csr and so on. default_value: False 8 diff --git a/source/source_esolver/esolver_gets.cpp b/source/source_esolver/esolver_gets.cpp index c66e33bce6..6a4e4f9c23 100644 --- a/source/source_esolver/esolver_gets.cpp +++ b/source/source_esolver/esolver_gets.cpp @@ -135,7 +135,7 @@ void ESolver_GetS::runner(UnitCell& ucell, const int istep) { cal_r_overlap_R r_matrix; r_matrix.init(ucell, pv, orb_); - r_matrix.out_rR(ucell, gd, istep); + r_matrix.out_rR(ucell, gd, istep, PARAM.inp.out_mat_r[1]); } if (PARAM.inp.out_mat_ds[0]) @@ -149,7 +149,10 @@ void ESolver_GetS::runner(UnitCell& ucell, const int istep) gd, // mohan add 2024-04-06 two_center_bundle_, orb_, - kv); + kv, + false, + 1e-10, + PARAM.inp.out_mat_ds[1]); } ModuleBase::timer::end("ESolver_GetS", "runner"); diff --git a/source/source_io/CMakeLists.txt b/source/source_io/CMakeLists.txt index 6073f10a7d..093ec8d59f 100644 --- a/source/source_io/CMakeLists.txt +++ b/source/source_io/CMakeLists.txt @@ -88,6 +88,7 @@ if(ENABLE_LCAO) module_hs/write_HS_R.cpp module_hs/write_HS_sparse.cpp module_hs/single_R_io.cpp + module_hs/rr_sparse_writer.cpp module_hs/cal_r_overlap_R.cpp module_hs/output_mat_sparse.cpp module_ctrl/ctrl_scf_lcao.cpp diff --git a/source/source_io/module_ctrl/ctrl_scf_lcao.cpp b/source/source_io/module_ctrl/ctrl_scf_lcao.cpp index 95b0bcb6e4..5bf15cf135 100644 --- a/source/source_io/module_ctrl/ctrl_scf_lcao.cpp +++ b/source/source_io/module_ctrl/ctrl_scf_lcao.cpp @@ -232,10 +232,17 @@ void ModuleIO::ctrl_scf_lcao(UnitCell& ucell, //------------------------------------------------------------------ hamilt::Hamilt* p_ham_tk = static_cast*>(p_hamilt); - ModuleIO::output_mat_sparse(inp.out_mat_dh[0], - inp.out_mat_ds[0], - inp.out_mat_t[0], - inp.out_mat_r[0], + ModuleIO::MatSparseOutputOptions mat_sparse_options; + mat_sparse_options.out_mat_dh = inp.out_mat_dh[0]; + mat_sparse_options.out_mat_ds = inp.out_mat_ds[0]; + mat_sparse_options.out_mat_t = inp.out_mat_t[0]; + mat_sparse_options.out_mat_r = inp.out_mat_r[0]; + mat_sparse_options.dh_precision = inp.out_mat_dh[1]; + mat_sparse_options.ds_precision = inp.out_mat_ds[1]; + mat_sparse_options.t_precision = inp.out_mat_t[1]; + mat_sparse_options.r_precision = inp.out_mat_r[1]; + + ModuleIO::output_mat_sparse(mat_sparse_options, istep, pelec->pot->get_eff_v(), pv, diff --git a/source/source_io/module_hs/cal_r_overlap_R.cpp b/source/source_io/module_hs/cal_r_overlap_R.cpp index 541d57b9ee..57d6eb2297 100644 --- a/source/source_io/module_hs/cal_r_overlap_R.cpp +++ b/source/source_io/module_hs/cal_r_overlap_R.cpp @@ -1,9 +1,11 @@ #include "cal_r_overlap_R.h" +#include "rr_sparse_writer.h" #include "single_R_io.h" #include "source_io/module_parameter/parameter.h" #include "source_base/parallel_reduce.h" #include "source_base/timer.h" +#include "source_base/tool_quit.h" #include "source_cell/module_neighbor/sltk_grid_driver.h" #include "source_base/mathzone_add1.h" @@ -635,7 +637,7 @@ void cal_r_overlap_R::get_psi_r_beta(const UnitCell& ucell, } -void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const int& istep) +void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const int& istep, const int precision) { ModuleBase::TITLE("cal_r_overlap_R", "out_rR"); ModuleBase::timer::start("cal_r_overlap_R", "out_rR"); @@ -671,13 +673,13 @@ void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const ModuleIO::SparseWriteOptions single_R_options; single_R_options.threshold = sparse_threshold; single_R_options.binary = binary; + single_R_options.precision = precision; single_R_options.reduce = true; single_R_options.temp_dir = PARAM.globalv.global_out_dir; std::stringstream tem1; tem1 << PARAM.globalv.global_out_dir << "tmp-rr.csr"; std::ofstream ofs_tem1; - std::ifstream ifs_tem1; if (GlobalV::DRANK == 0) { @@ -689,6 +691,11 @@ void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const { ofs_tem1.open(tem1.str().c_str()); } + if (!ofs_tem1.is_open()) + { + ModuleBase::WARNING_QUIT("cal_r_overlap_R::out_rR", + "Cannot open temporary sparse matrix file: " + tem1.str()); + } } for (auto& R_coor: all_R_coor) @@ -801,19 +808,22 @@ void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const Parallel_Reduce::reduce_all(rR_nonzero_num, 3); - if (rR_nonzero_num[0] || rR_nonzero_num[1] || rR_nonzero_num[2]) + if (ModuleIO::detail::rr_sparse_has_payload(rR_nonzero_num)) { output_R_number++; - if (binary) - { - ofs_tem1.write(reinterpret_cast(&dRx), sizeof(int)); - ofs_tem1.write(reinterpret_cast(&dRy), sizeof(int)); - ofs_tem1.write(reinterpret_cast(&dRz), sizeof(int)); - } - else + if (GlobalV::DRANK == 0) { - ofs_tem1 << dRx << " " << dRy << " " << dRz << std::endl; + if (binary) + { + ofs_tem1.write(reinterpret_cast(&dRx), sizeof(int)); + ofs_tem1.write(reinterpret_cast(&dRy), sizeof(int)); + ofs_tem1.write(reinterpret_cast(&dRz), sizeof(int)); + } + else + { + ofs_tem1 << dRx << " " << dRy << " " << dRz << std::endl; + } } for (int direction = 0; direction < 3; ++direction) @@ -847,7 +857,6 @@ void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const if (GlobalV::DRANK == 0) { - std::ofstream out_r; std::stringstream ssr; if (PARAM.inp.calculation == "md" && !PARAM.inp.out_app_flag) { @@ -859,47 +868,15 @@ void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const ssr << PARAM.globalv.global_out_dir << "rr.csr"; } - if (binary) // .dat - { - ofs_tem1.close(); - int nlocal = PARAM.globalv.nlocal; - if (PARAM.inp.calculation == "md" && PARAM.inp.out_app_flag && step) - { - out_r.open(ssr.str().c_str(), std::ios::binary | std::ios::app); - } - else - { - out_r.open(ssr.str().c_str(), std::ios::binary); - } - out_r.write(reinterpret_cast(&step), sizeof(int)); - out_r.write(reinterpret_cast(&nlocal), sizeof(int)); - out_r.write(reinterpret_cast(&output_R_number), sizeof(int)); - - ifs_tem1.open(tem1.str().c_str(), std::ios::binary); - out_r << ifs_tem1.rdbuf(); - ifs_tem1.close(); - out_r.close(); - } - else // .txt - { - ofs_tem1.close(); - if (PARAM.inp.calculation == "md" && PARAM.inp.out_app_flag && step) - { - out_r.open(ssr.str().c_str(), std::ios::app); - } - else - { - out_r.open(ssr.str().c_str()); - } - out_r << "STEP: " << step << std::endl; - out_r << "Matrix Dimension of r(R): " << PARAM.globalv.nlocal << std::endl; - out_r << "Matrix number of r(R): " << output_R_number << std::endl; - - ifs_tem1.open(tem1.str().c_str()); - out_r << ifs_tem1.rdbuf(); - ifs_tem1.close(); - out_r.close(); - } + ofs_tem1.close(); + ModuleIO::detail::finalize_rr_sparse_file(ssr.str(), + tem1.str(), + step, + PARAM.globalv.nlocal, + output_R_number, + binary, + PARAM.inp.calculation == "md" && PARAM.inp.out_app_flag && step, + "cal_r_overlap_R::out_rR"); std::remove(tem1.str().c_str()); } @@ -908,7 +885,10 @@ void cal_r_overlap_R::out_rR(const UnitCell& ucell, const Grid_Driver& gd, const return; } -void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, const int& istep, const std::set>& output_R_coor) +void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, + const int& istep, + const std::set>& output_R_coor, + const int precision) { ModuleBase::TITLE("cal_r_overlap_R", "out_rR_other"); ModuleBase::timer::start("cal_r_overlap_R", "out_rR_other"); @@ -917,15 +897,35 @@ void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, const int& istep, cons ModuleBase::Vector3 tau1, tau2, dtau; ModuleBase::Vector3 origin_point(0.0, 0.0, 0.0); double factor = sqrt(ModuleBase::FOUR_PI / 3.0); - int output_R_number = output_R_coor.size(); + int output_R_number = 0; int step = istep; ModuleIO::SparseWriteOptions single_R_options; single_R_options.threshold = sparse_threshold; single_R_options.binary = binary; + single_R_options.precision = precision; single_R_options.reduce = true; single_R_options.temp_dir = PARAM.globalv.global_out_dir; - std::ofstream out_r; + std::stringstream tem1; + tem1 << PARAM.globalv.global_out_dir << "tmp-rr-other.csr"; + std::ofstream ofs_tem1; + if (GlobalV::DRANK == 0) + { + if (binary) + { + ofs_tem1.open(tem1.str().c_str(), std::ios::binary); + } + else + { + ofs_tem1.open(tem1.str().c_str()); + } + if (!ofs_tem1.is_open()) + { + ModuleBase::WARNING_QUIT("cal_r_overlap_R::out_rR_other", + "Cannot open temporary sparse matrix file: " + tem1.str()); + } + } + std::stringstream ssr; if (PARAM.inp.calculation == "md" && !PARAM.inp.out_app_flag) { @@ -937,39 +937,6 @@ void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, const int& istep, cons ssr << PARAM.globalv.global_out_dir << "rr.csr"; } - if (GlobalV::DRANK == 0) - { - if (binary) - { - int nlocal = PARAM.globalv.nlocal; - if (PARAM.inp.calculation == "md" && PARAM.inp.out_app_flag && step) - { - out_r.open(ssr.str().c_str(), std::ios::binary | std::ios::app); - } - else - { - out_r.open(ssr.str().c_str(), std::ios::binary); - } - out_r.write(reinterpret_cast(&step), sizeof(int)); - out_r.write(reinterpret_cast(&nlocal), sizeof(int)); - out_r.write(reinterpret_cast(&output_R_number), sizeof(int)); - } - else - { - if (PARAM.inp.calculation == "md" && PARAM.inp.out_app_flag && step) - { - out_r.open(ssr.str().c_str(), std::ios::app); - } - else - { - out_r.open(ssr.str().c_str()); - } - out_r << "STEP: " << step << std::endl; - out_r << "Matrix Dimension of r(R): " << PARAM.globalv.nlocal << std::endl; - out_r << "Matrix number of r(R): " << output_R_number << std::endl; - } - } - for (auto& R_coor: output_R_coor) { std::map> psi_r_psi_sparse[3]; @@ -1081,15 +1048,24 @@ void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, const int& istep, cons Parallel_Reduce::reduce_all(rR_nonzero_num, 3); - if (binary) // .dat + if (!ModuleIO::detail::rr_sparse_has_payload(rR_nonzero_num)) { - out_r.write(reinterpret_cast(&dRx), sizeof(int)); - out_r.write(reinterpret_cast(&dRy), sizeof(int)); - out_r.write(reinterpret_cast(&dRz), sizeof(int)); + continue; } - else // .txt + output_R_number++; + + if (GlobalV::DRANK == 0) { - out_r << dRx << " " << dRy << " " << dRz << std::endl; + if (binary) // .dat + { + ofs_tem1.write(reinterpret_cast(&dRx), sizeof(int)); + ofs_tem1.write(reinterpret_cast(&dRy), sizeof(int)); + ofs_tem1.write(reinterpret_cast(&dRz), sizeof(int)); + } + else // .txt + { + ofs_tem1 << dRx << " " << dRy << " " << dRz << std::endl; + } } for (int direction = 0; direction < 3; ++direction) @@ -1098,17 +1074,17 @@ void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, const int& istep, cons { if (binary) { - out_r.write(reinterpret_cast(&rR_nonzero_num[direction]), sizeof(int)); + ofs_tem1.write(reinterpret_cast(&rR_nonzero_num[direction]), sizeof(int)); } else { - out_r << rR_nonzero_num[direction] << std::endl; + ofs_tem1 << rR_nonzero_num[direction] << std::endl; } } if (rR_nonzero_num[direction]) { - ModuleIO::output_single_R(out_r, + ModuleIO::output_single_R(ofs_tem1, psi_r_psi_sparse[direction], *(this->ParaV), single_R_options); @@ -1122,7 +1098,16 @@ void cal_r_overlap_R::out_rR_other(const UnitCell& ucell, const int& istep, cons if (GlobalV::DRANK == 0) { - out_r.close(); + ofs_tem1.close(); + ModuleIO::detail::finalize_rr_sparse_file(ssr.str(), + tem1.str(), + step, + PARAM.globalv.nlocal, + output_R_number, + binary, + PARAM.inp.calculation == "md" && PARAM.inp.out_app_flag && step, + "cal_r_overlap_R::out_rR_other"); + std::remove(tem1.str().c_str()); } ModuleBase::timer::end("cal_r_overlap_R", "out_rR_other"); diff --git a/source/source_io/module_hs/cal_r_overlap_R.h b/source/source_io/module_hs/cal_r_overlap_R.h index 0f7d51e149..543bf248fa 100644 --- a/source/source_io/module_hs/cal_r_overlap_R.h +++ b/source/source_io/module_hs/cal_r_overlap_R.h @@ -70,8 +70,11 @@ class cal_r_overlap_R const ModuleBase::Vector3& R2, const int& T2 ); - void out_rR(const UnitCell& ucell, const Grid_Driver& gd, const int& istep); - void out_rR_other(const UnitCell& ucell, const int& istep, const std::set>& output_R_coor); + void out_rR(const UnitCell& ucell, const Grid_Driver& gd, const int& istep, const int precision = 16); + void out_rR_other(const UnitCell& ucell, + const int& istep, + const std::set>& output_R_coor, + const int precision = 16); private: void initialize_orb_table(const UnitCell& ucell, const LCAO_Orbitals& orb); diff --git a/source/source_io/module_hs/output_mat_sparse.cpp b/source/source_io/module_hs/output_mat_sparse.cpp index 9f31352b43..d55409ba48 100644 --- a/source/source_io/module_hs/output_mat_sparse.cpp +++ b/source/source_io/module_hs/output_mat_sparse.cpp @@ -6,10 +6,7 @@ namespace ModuleIO { template -void output_mat_sparse(const bool& out_mat_dh, - const bool& out_mat_ds, - const bool& out_mat_t, - const bool& out_mat_r, +void output_mat_sparse(const MatSparseOutputOptions& options, const int& istep, const ModuleBase::matrix& v_eff, const Parallel_Orbitals& pv, @@ -24,13 +21,23 @@ void output_mat_sparse(const bool& out_mat_dh, LCAO_HS_Arrays HS_Arrays; // store sparse arrays //! generate a file containing the kinetic energy matrix - if (out_mat_t) + if (options.out_mat_t) { - output_TR(istep, ucell, pv, HS_Arrays, grid, two_center_bundle, orb); + output_TR(istep, + ucell, + pv, + HS_Arrays, + grid, + two_center_bundle, + orb, + "trs1_nao.csr", + options.binary, + options.sparse_threshold, + options.t_precision); } //! generate a file containing the derivatives of the Hamiltonian matrix (in Ry/Bohr) - if (out_mat_dh) + if (options.out_mat_dh) { output_dHR(istep, v_eff, @@ -40,10 +47,13 @@ void output_mat_sparse(const bool& out_mat_dh, grid, two_center_bundle, orb, - kv); + kv, + options.binary, + options.sparse_threshold, + options.dh_precision); } //! generate a file containing the derivatives of the overlap matrix (in Ry/Bohr) - if (out_mat_ds) + if (options.out_mat_ds) { output_dSR(istep, ucell, @@ -52,20 +62,59 @@ void output_mat_sparse(const bool& out_mat_dh, grid, two_center_bundle, orb, - kv); + kv, + options.binary, + options.sparse_threshold, + options.ds_precision); } // add by jingan for out r_R matrix 2019.8.14 - if (out_mat_r) + if (options.out_mat_r) { cal_r_overlap_R r_matrix; + r_matrix.binary = options.binary; + r_matrix.sparse_threshold = options.sparse_threshold; r_matrix.init(ucell, pv, orb); - r_matrix.out_rR(ucell, grid, istep); + r_matrix.out_rR(ucell, grid, istep, options.r_precision); } return; } +template +void output_mat_sparse(const bool& out_mat_dh, + const bool& out_mat_ds, + const bool& out_mat_t, + const bool& out_mat_r, + const int& istep, + const ModuleBase::matrix& v_eff, + const Parallel_Orbitals& pv, + const TwoCenterBundle& two_center_bundle, + const LCAO_Orbitals& orb, + UnitCell& ucell, + const Grid_Driver& grid, + const K_Vectors& kv, + hamilt::Hamilt* p_ham, + Plus_U* p_dftu) +{ + MatSparseOutputOptions options; + options.out_mat_dh = out_mat_dh; + options.out_mat_ds = out_mat_ds; + options.out_mat_t = out_mat_t; + options.out_mat_r = out_mat_r; + output_mat_sparse(options, + istep, + v_eff, + pv, + two_center_bundle, + orb, + ucell, + grid, + kv, + p_ham, + p_dftu); +} + template void output_mat_sparse(const bool& out_mat_dh, const bool& out_mat_ds, const bool& out_mat_t, @@ -78,8 +127,8 @@ template void output_mat_sparse(const bool& out_mat_dh, UnitCell& ucell, const Grid_Driver& grid, const K_Vectors& kv, - hamilt::Hamilt* p_ham, - Plus_U* p_dftu); + hamilt::Hamilt* p_ham, + Plus_U* p_dftu); template void output_mat_sparse>(const bool& out_mat_dh, const bool& out_mat_ds, @@ -93,7 +142,31 @@ template void output_mat_sparse>(const bool& out_mat_dh, UnitCell& ucell, const Grid_Driver& grid, const K_Vectors& kv, - hamilt::Hamilt>* p_ham, - Plus_U* p_dftu); + hamilt::Hamilt>* p_ham, + Plus_U* p_dftu); + +template void output_mat_sparse(const MatSparseOutputOptions& options, + const int& istep, + const ModuleBase::matrix& v_eff, + const Parallel_Orbitals& pv, + const TwoCenterBundle& two_center_bundle, + const LCAO_Orbitals& orb, + UnitCell& ucell, + const Grid_Driver& grid, + const K_Vectors& kv, + hamilt::Hamilt* p_ham, + Plus_U* p_dftu); + +template void output_mat_sparse>(const MatSparseOutputOptions& options, + const int& istep, + const ModuleBase::matrix& v_eff, + const Parallel_Orbitals& pv, + const TwoCenterBundle& two_center_bundle, + const LCAO_Orbitals& orb, + UnitCell& ucell, + const Grid_Driver& grid, + const K_Vectors& kv, + hamilt::Hamilt>* p_ham, + Plus_U* p_dftu); } // namespace ModuleIO diff --git a/source/source_io/module_hs/output_mat_sparse.h b/source/source_io/module_hs/output_mat_sparse.h index 028211cf78..cfea51ca73 100644 --- a/source/source_io/module_hs/output_mat_sparse.h +++ b/source/source_io/module_hs/output_mat_sparse.h @@ -10,8 +10,36 @@ namespace ModuleIO { +struct MatSparseOutputOptions +{ + bool out_mat_dh = false; + bool out_mat_ds = false; + bool out_mat_t = false; + bool out_mat_r = false; + int dh_precision = 16; + int ds_precision = 16; + int t_precision = 16; + int r_precision = 16; + double sparse_threshold = 1e-10; + bool binary = false; +}; + /// @brief the output interface to write the sparse matrix of dH, dS, T, and r template +void output_mat_sparse(const MatSparseOutputOptions& options, + const int& istep, + const ModuleBase::matrix& v_eff, + const Parallel_Orbitals& pv, + const TwoCenterBundle& two_center_bundle, + const LCAO_Orbitals& orb, + UnitCell& ucell, + const Grid_Driver& grid, + const K_Vectors& kv, + hamilt::Hamilt* p_ham, + Plus_U* p_dftu); + +/// @brief legacy bool-only interface kept for source compatibility +template void output_mat_sparse(const bool& out_mat_dh, const bool& out_mat_ds, const bool& out_mat_t, diff --git a/source/source_io/module_hs/rr_sparse_writer.cpp b/source/source_io/module_hs/rr_sparse_writer.cpp new file mode 100644 index 0000000000..ed5dadb996 --- /dev/null +++ b/source/source_io/module_hs/rr_sparse_writer.cpp @@ -0,0 +1,64 @@ +#include "rr_sparse_writer.h" + +#include "source_base/tool_quit.h" + +#include + +namespace ModuleIO +{ +namespace detail +{ +bool rr_sparse_has_payload(const int nonzero_num[3]) +{ + return nonzero_num[0] != 0 || nonzero_num[1] != 0 || nonzero_num[2] != 0; +} + +void finalize_rr_sparse_file(const std::string& output_filename, + const std::string& payload_filename, + const int step, + const int nlocal, + const int output_R_number, + const bool binary, + const bool append, + const std::string& context) +{ + std::ios_base::openmode output_mode = std::ios::out; + std::ios_base::openmode payload_mode = std::ios::in; + if (binary) + { + output_mode |= std::ios::binary; + payload_mode |= std::ios::binary; + } + if (append) + { + output_mode |= std::ios::app; + } + + std::ofstream out_r(output_filename.c_str(), output_mode); + if (!out_r.is_open()) + { + ModuleBase::WARNING_QUIT(context, "Cannot open r(R) output file: " + output_filename); + } + + if (binary) + { + out_r.write(reinterpret_cast(&step), sizeof(int)); + out_r.write(reinterpret_cast(&nlocal), sizeof(int)); + out_r.write(reinterpret_cast(&output_R_number), sizeof(int)); + } + else + { + out_r << "STEP: " << step << std::endl; + out_r << "Matrix Dimension of r(R): " << nlocal << std::endl; + out_r << "Matrix number of r(R): " << output_R_number << std::endl; + } + + std::ifstream payload(payload_filename.c_str(), payload_mode); + if (!payload.is_open()) + { + ModuleBase::WARNING_QUIT(context, "Cannot read temporary sparse matrix file: " + payload_filename); + } + out_r << payload.rdbuf(); +} +} // namespace detail +} // namespace ModuleIO diff --git a/source/source_io/module_hs/rr_sparse_writer.h b/source/source_io/module_hs/rr_sparse_writer.h new file mode 100644 index 0000000000..78e17462d4 --- /dev/null +++ b/source/source_io/module_hs/rr_sparse_writer.h @@ -0,0 +1,23 @@ +#ifndef RR_SPARSE_WRITER_H +#define RR_SPARSE_WRITER_H + +#include + +namespace ModuleIO +{ +namespace detail +{ +bool rr_sparse_has_payload(const int nonzero_num[3]); + +void finalize_rr_sparse_file(const std::string& output_filename, + const std::string& payload_filename, + int step, + int nlocal, + int output_R_number, + bool binary, + bool append, + const std::string& context); +} // namespace detail +} // namespace ModuleIO + +#endif diff --git a/source/source_io/module_hs/single_R_io.cpp b/source/source_io/module_hs/single_R_io.cpp index d901e0ab0a..174742dc99 100644 --- a/source/source_io/module_hs/single_R_io.cpp +++ b/source/source_io/module_hs/single_R_io.cpp @@ -10,13 +10,13 @@ #include #include -inline void write_data(std::ofstream& ofs, const double& data) +inline void write_data(std::ofstream& ofs, const double& data, const int precision) { - ofs << " " << std::fixed << std::scientific << std::setprecision(16) << data; + ofs << " " << std::fixed << std::scientific << std::setprecision(precision) << data; } -inline void write_data(std::ofstream& ofs, const std::complex& data) +inline void write_data(std::ofstream& ofs, const std::complex& data, const int precision) { - ofs << " (" << std::fixed << std::scientific << std::setprecision(16) + ofs << " (" << std::fixed << std::scientific << std::setprecision(precision) << data.real() << "," << data.imag() << ")"; } @@ -53,6 +53,11 @@ void ModuleIO::output_single_R(std::ofstream& ofs, { ofs_tem1.open(tem1.str().c_str()); } + if (!ofs_tem1.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::output_single_R", + "Cannot open temporary sparse index file: " + tem1.str()); + } } std::vector line(nlocal); @@ -97,7 +102,7 @@ void ModuleIO::output_single_R(std::ofstream& ofs, } else { - write_data(ofs, line[col]); + write_data(ofs, line[col], options.precision); ofs_tem1 << " " << col; } @@ -117,6 +122,11 @@ void ModuleIO::output_single_R(std::ofstream& ofs, { ofs_tem1.close(); ifs_tem1.open(tem1.str().c_str(), std::ios::binary); + if (!ifs_tem1.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::output_single_R", + "Cannot read temporary sparse index file: " + tem1.str()); + } ofs << ifs_tem1.rdbuf(); ifs_tem1.close(); for (auto &i : indptr) @@ -130,6 +140,11 @@ void ModuleIO::output_single_R(std::ofstream& ofs, ofs_tem1 << std::endl; ofs_tem1.close(); ifs_tem1.open(tem1.str().c_str()); + if (!ifs_tem1.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::output_single_R", + "Cannot read temporary sparse index file: " + tem1.str()); + } ofs << ifs_tem1.rdbuf(); ifs_tem1.close(); for (auto &i : indptr) diff --git a/source/source_io/module_hs/write_HS.hpp b/source/source_io/module_hs/write_HS.hpp index 58e18a0755..04c677f98b 100644 --- a/source/source_io/module_hs/write_HS.hpp +++ b/source/source_io/module_hs/write_HS.hpp @@ -3,6 +3,7 @@ #include "source_io/module_parameter/parameter.h" #include "source_base/parallel_reduce.h" #include "source_base/timer.h" +#include "source_base/tool_quit.h" #include "source_cell/module_neighbor/sltk_grid_driver.h" #include "source_io/module_output/filename.h" // use filename_output function @@ -122,6 +123,10 @@ void ModuleIO::save_mat(const int istep, if (drank == 0) { out_matrix = fopen(filename.c_str(), "wb"); + if (out_matrix == nullptr) + { + ModuleBase::WARNING_QUIT("ModuleIO::save_mat", "Cannot open matrix file: " + filename); + } fwrite(&dim, sizeof(int), 1, out_matrix); } @@ -179,6 +184,10 @@ void ModuleIO::save_mat(const int istep, // write .dat file without MPI #else FILE* out_matrix = fopen(filename.c_str(), "wb"); + if (out_matrix == nullptr) + { + ModuleBase::WARNING_QUIT("ModuleIO::save_mat", "Cannot open matrix file: " + filename); + } fwrite(&dim, sizeof(int), 1, out_matrix); @@ -207,6 +216,10 @@ void ModuleIO::save_mat(const int istep, { out_matrix.open(filename.c_str()); } + if (!out_matrix.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::save_mat", "Cannot open matrix file: " + filename); + } out_matrix << "#------------------------------------------------------------------------" << std::endl; out_matrix << "# ionic step " << istep+1 << std::endl; // istep starts from 0 out_matrix << "# filename " << filename << std::endl; @@ -286,6 +299,10 @@ void ModuleIO::save_mat(const int istep, { out_matrix.open(filename.c_str()); } + if (!out_matrix.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::save_mat", "Cannot open matrix file: " + filename); + } out_matrix << dim; out_matrix << std::setprecision(precision); diff --git a/source/source_io/module_hs/write_HS_R.cpp b/source/source_io/module_hs/write_HS_R.cpp index be69653eac..f9ebe893ec 100644 --- a/source/source_io/module_hs/write_HS_R.cpp +++ b/source/source_io/module_hs/write_HS_R.cpp @@ -1,6 +1,7 @@ #include "write_HS_R.h" #include "source_base/timer.h" +#include "source_base/tool_quit.h" #include "source_io/module_parameter/parameter.h" #include "source_lcao/LCAO_HS_arrays.hpp" #include "source_lcao/spar_dh.h" @@ -22,7 +23,8 @@ void ModuleIO::output_dSR(const int& istep, const LCAO_Orbitals& orb, const K_Vectors& kv, const bool& binary, - const double& sparse_thr) + const double& sparse_thr, + const int precision) { ModuleBase::TITLE("ModuleIO", "output_dSR"); ModuleBase::timer::start("ModuleIO", "output_dSR"); @@ -30,7 +32,7 @@ void ModuleIO::output_dSR(const int& istep, sparse_format::cal_dS(ucell, pv, HS_Arrays, grid, two_center_bundle, orb, sparse_thr); // mohan update 2024-04-01 - ModuleIO::save_dH_sparse(istep, pv, HS_Arrays, sparse_thr, binary, "s"); + ModuleIO::save_dH_sparse(istep, pv, HS_Arrays, sparse_thr, binary, "s", precision); sparse_format::destroy_dH_R_sparse(HS_Arrays); @@ -48,7 +50,8 @@ void ModuleIO::output_dHR(const int& istep, const LCAO_Orbitals& orb, const K_Vectors& kv, const bool& binary, - const double& sparse_thr) + const double& sparse_thr, + const int precision) { ModuleBase::TITLE("ModuleIO", "output_dHR"); ModuleBase::timer::start("ModuleIO", "output_dHR"); @@ -76,7 +79,7 @@ void ModuleIO::output_dHR(const int& istep, } } // mohan update 2024-04-01 - ModuleIO::save_dH_sparse(istep, pv, HS_Arrays, sparse_thr, binary); + ModuleIO::save_dH_sparse(istep, pv, HS_Arrays, sparse_thr, binary, "h", precision); sparse_format::destroy_dH_R_sparse(HS_Arrays); @@ -90,7 +93,8 @@ void ModuleIO::output_SR(Parallel_Orbitals& pv, hamilt::Hamilt* p_ham, const std::string& SR_filename, const bool& binary, - const double& sparse_thr) + const double& sparse_thr, + const int precision) { ModuleBase::TITLE("ModuleIO", "output_SR"); ModuleBase::timer::start("ModuleIO", "output_SR"); @@ -120,6 +124,7 @@ void ModuleIO::output_SR(Parallel_Orbitals& pv, options.label = "S"; options.threshold = sparse_thr; options.binary = binary; + options.precision = precision; options.istep = istep; options.reduce = true; options.temp_dir = PARAM.globalv.global_out_dir; @@ -154,7 +159,8 @@ void ModuleIO::output_TR(const int istep, const LCAO_Orbitals& orb, const std::string& TR_filename, const bool& binary, - const double& sparse_thr) + const double& sparse_thr, + const int precision) { ModuleBase::TITLE("ModuleIO", "output_TR"); ModuleBase::timer::start("ModuleIO", "output_TR"); @@ -183,6 +189,7 @@ void ModuleIO::output_TR(const int istep, options.label = "T"; options.threshold = sparse_thr; options.binary = binary; + options.precision = precision; options.istep = istep; options.reduce = true; options.temp_dir = PARAM.globalv.global_out_dir; @@ -203,13 +210,15 @@ template void ModuleIO::output_SR(Parallel_Orbitals& pv, hamilt::Hamilt* p_ham, const std::string& SR_filename, const bool& binary, - const double& sparse_thr); + const double& sparse_thr, + const int precision); template void ModuleIO::output_SR>(Parallel_Orbitals& pv, const Grid_Driver& grid, hamilt::Hamilt>* p_ham, const std::string& SR_filename, const bool& binary, - const double& sparse_thr); + const double& sparse_thr, + const int precision); #include "source_lcao/module_hcontainer/hcontainer_funcs.h" #include "source_lcao/module_hcontainer/output_hcontainer.h" @@ -263,6 +272,11 @@ void ModuleIO::write_hcontainer_csr(const std::string& fname, { ofs.open(fname, std::ios::app); } + if (!ofs.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::write_hcontainer_csr", + "Cannot open HContainer CSR file: " + fname); + } ofs << " --- Ionic Step " << istep + 1 << " ---" << std::endl; ofs << " # print " << label << " matrix in real space " << label << "(R)" << std::endl; diff --git a/source/source_io/module_hs/write_HS_R.h b/source/source_io/module_hs/write_HS_R.h index 27c059f587..603fbd9ac0 100644 --- a/source/source_io/module_hs/write_HS_R.h +++ b/source/source_io/module_hs/write_HS_R.h @@ -24,7 +24,8 @@ void output_dHR(const int& istep, const LCAO_Orbitals& orb, const K_Vectors& kv, const bool& binary = false, - const double& sparse_threshold = 1e-10); + const double& sparse_threshold = 1e-10, + const int precision = 16); void output_dSR(const int& istep, const UnitCell& ucell, @@ -35,7 +36,8 @@ void output_dSR(const int& istep, const LCAO_Orbitals& orb, const K_Vectors& kv, const bool& binary = false, - const double& sparse_thr = 1e-10); + const double& sparse_thr = 1e-10, + const int precision = 16); void output_TR(const int istep, const UnitCell& ucell, @@ -46,7 +48,8 @@ void output_TR(const int istep, const LCAO_Orbitals& orb, const std::string& TR_filename = "trs1_nao.csr", const bool& binary = false, - const double& sparse_threshold = 1e-10); + const double& sparse_threshold = 1e-10, + const int precision = 16); template void output_SR(Parallel_Orbitals& pv, @@ -54,7 +57,8 @@ void output_SR(Parallel_Orbitals& pv, hamilt::Hamilt* p_ham, const std::string& SR_filename = "srs1_nao.csr", const bool& binary = false, - const double& sparse_threshold = 1e-10); + const double& sparse_threshold = 1e-10, + const int precision = 16); /// Generate filename for HR/SR CSR output. std::string hsr_gen_fname(const std::string& prefix, diff --git a/source/source_io/module_hs/write_HS_sparse.cpp b/source/source_io/module_hs/write_HS_sparse.cpp index 3ea1367ccf..8fffba237e 100644 --- a/source/source_io/module_hs/write_HS_sparse.cpp +++ b/source/source_io/module_hs/write_HS_sparse.cpp @@ -74,6 +74,11 @@ void open_sparse_file(std::ofstream& ofs, const ModuleIO::SparseWriteOptions& op mode |= std::ios::app; } ofs.open(options.filename.c_str(), mode); + if (!ofs.is_open()) + { + ModuleBase::WARNING_QUIT("ModuleIO::open_sparse_file", + "Cannot open sparse matrix file: " + options.filename); + } } void write_sparse_header(std::ofstream& ofs, @@ -120,6 +125,16 @@ void write_R_record(std::ofstream& ofs, << std::endl; } } + +void check_output_file_open(const std::ofstream& ofs, + const std::string& filename, + const std::string& context) +{ + if (!ofs.is_open()) + { + ModuleBase::WARNING_QUIT(context, "Cannot open sparse matrix file: " + filename); + } +} } // namespace void ModuleIO::save_dH_sparse(const int& istep, @@ -127,12 +142,14 @@ void ModuleIO::save_dH_sparse(const int& istep, LCAO_HS_Arrays& HS_Arrays, const double& sparse_thr, const bool& binary, - const std::string& fileflag) { + const std::string& fileflag, + const int precision) { ModuleBase::TITLE("ModuleIO", "save_dH_sparse"); ModuleBase::timer::start("ModuleIO", "save_dH_sparse"); SparseWriteOptions single_R_options; single_R_options.threshold = sparse_thr; single_R_options.binary = binary; + single_R_options.precision = precision; single_R_options.reduce = true; single_R_options.temp_dir = PARAM.globalv.global_out_dir; @@ -145,11 +162,11 @@ void ModuleIO::save_dH_sparse(const int& istep, auto& dHRz_sparse_ptr = HS_Arrays.dHRz_sparse; auto& dHRz_soc_sparse_ptr = HS_Arrays.dHRz_soc_sparse; - int total_R_num = all_R_coor_ptr.size(); + const int total_R_num = static_cast(all_R_coor_ptr.size()); int output_R_number = 0; - int* dHx_nonzero_num[2] = {nullptr, nullptr}; - int* dHy_nonzero_num[2] = {nullptr, nullptr}; - int* dHz_nonzero_num[2] = {nullptr, nullptr}; + std::vector dHx_nonzero_num[2]; + std::vector dHy_nonzero_num[2]; + std::vector dHz_nonzero_num[2]; int step = istep; int spin_loop = 1; @@ -157,81 +174,41 @@ void ModuleIO::save_dH_sparse(const int& istep, spin_loop = 2; } - for (int ispin = 0; ispin < spin_loop; ++ispin) { - dHx_nonzero_num[ispin] = new int[total_R_num]; - ModuleBase::GlobalFunc::ZEROS(dHx_nonzero_num[ispin], total_R_num); - dHy_nonzero_num[ispin] = new int[total_R_num]; - ModuleBase::GlobalFunc::ZEROS(dHy_nonzero_num[ispin], total_R_num); - dHz_nonzero_num[ispin] = new int[total_R_num]; - ModuleBase::GlobalFunc::ZEROS(dHz_nonzero_num[ispin], total_R_num); + if (PARAM.inp.nspin != 4) + { + for (int ispin = 0; ispin < spin_loop; ++ispin) + { + dHx_nonzero_num[ispin] = count_nonzeros_by_R(dHRx_sparse_ptr[ispin], all_R_coor_ptr, sparse_thr, true); + dHy_nonzero_num[ispin] = count_nonzeros_by_R(dHRy_sparse_ptr[ispin], all_R_coor_ptr, sparse_thr, true); + dHz_nonzero_num[ispin] = count_nonzeros_by_R(dHRz_sparse_ptr[ispin], all_R_coor_ptr, sparse_thr, true); + } + } + else + { + dHx_nonzero_num[0] = count_nonzeros_by_R(dHRx_soc_sparse_ptr, all_R_coor_ptr, sparse_thr, true); + dHy_nonzero_num[0] = count_nonzeros_by_R(dHRy_soc_sparse_ptr, all_R_coor_ptr, sparse_thr, true); + dHz_nonzero_num[0] = count_nonzeros_by_R(dHRz_soc_sparse_ptr, all_R_coor_ptr, sparse_thr, true); } - int count = 0; - for (auto& R_coor: all_R_coor_ptr) { - if (PARAM.inp.nspin != 4) { - for (int ispin = 0; ispin < spin_loop; ++ispin) { - auto iter1 = dHRx_sparse_ptr[ispin].find(R_coor); - if (iter1 != dHRx_sparse_ptr[ispin].end()) { - for (auto& row_loop: iter1->second) { - dHx_nonzero_num[ispin][count] += row_loop.second.size(); - } - } - - auto iter2 = dHRy_sparse_ptr[ispin].find(R_coor); - if (iter2 != dHRy_sparse_ptr[ispin].end()) { - for (auto& row_loop: iter2->second) { - dHy_nonzero_num[ispin][count] += row_loop.second.size(); - } - } - - auto iter3 = dHRz_sparse_ptr[ispin].find(R_coor); - if (iter3 != dHRz_sparse_ptr[ispin].end()) { - for (auto& row_loop: iter3->second) { - dHz_nonzero_num[ispin][count] += row_loop.second.size(); - } - } - } - } else { - auto iter = dHRx_soc_sparse_ptr.find(R_coor); - if (iter != dHRx_soc_sparse_ptr.end()) { - for (auto& row_loop: iter->second) { - dHx_nonzero_num[0][count] += row_loop.second.size(); - } + const auto has_output_R = [&](const int index) { + for (int ispin = 0; ispin < spin_loop; ++ispin) + { + if (dHx_nonzero_num[ispin][index] != 0 + || dHy_nonzero_num[ispin][index] != 0 + || dHz_nonzero_num[ispin][index] != 0) + { + return true; } } + return false; + }; - count++; - } - - for (int ispin = 0; ispin < spin_loop; ++ispin) { - Parallel_Reduce::reduce_all(dHx_nonzero_num[ispin], total_R_num); - Parallel_Reduce::reduce_all(dHy_nonzero_num[ispin], total_R_num); - Parallel_Reduce::reduce_all(dHz_nonzero_num[ispin], total_R_num); - } - - if (PARAM.inp.nspin == 2) - { - for (int index = 0; index < total_R_num; ++index) - { - if (dHx_nonzero_num[0][index] != 0 || dHx_nonzero_num[1][index] != 0 - || dHy_nonzero_num[0][index] != 0 - || dHy_nonzero_num[1][index] != 0 - || dHz_nonzero_num[0][index] != 0 - || dHz_nonzero_num[1][index] != 0) - { - output_R_number++; - } - } - } else - { - for (int index = 0; index < total_R_num; ++index) - { - if (dHx_nonzero_num[0][index] != 0 || dHy_nonzero_num[0][index] != 0 - || dHz_nonzero_num[0][index] != 0) - { - output_R_number++; - } - } + for (int index = 0; index < total_R_num; ++index) + { + if (has_output_R(index)) + { + output_R_number++; + } } std::stringstream sshx[2]; @@ -289,6 +266,9 @@ void ModuleIO::save_dH_sparse(const int& istep, g1y[ispin].open(sshy[ispin].str().c_str(),std::ios::binary); g1z[ispin].open(sshz[ispin].str().c_str(),std::ios::binary); } + check_output_file_open(g1x[ispin], sshx[ispin].str(), "ModuleIO::save_dH_sparse"); + check_output_file_open(g1y[ispin], sshy[ispin].str(), "ModuleIO::save_dH_sparse"); + check_output_file_open(g1z[ispin], sshz[ispin].str(), "ModuleIO::save_dH_sparse"); g1x[ispin].write(reinterpret_cast(&step), sizeof(int)); g1x[ispin].write(reinterpret_cast(&nlocal), @@ -328,6 +308,9 @@ void ModuleIO::save_dH_sparse(const int& istep, g1y[ispin].open(sshy[ispin].str().c_str()); g1z[ispin].open(sshz[ispin].str().c_str()); } + check_output_file_open(g1x[ispin], sshx[ispin].str(), "ModuleIO::save_dH_sparse"); + check_output_file_open(g1y[ispin], sshy[ispin].str(), "ModuleIO::save_dH_sparse"); + check_output_file_open(g1z[ispin], sshz[ispin].str(), "ModuleIO::save_dH_sparse"); g1x[ispin] << "STEP: " << step << std::endl; g1x[ispin] << "Matrix Dimension of dHx(R): " << PARAM.globalv.nlocal @@ -352,27 +335,16 @@ void ModuleIO::save_dH_sparse(const int& istep, output_R_coor_ptr.clear(); - count = 0; + int count = 0; for (auto& R_coor: all_R_coor_ptr) { int dRx = R_coor.x; int dRy = R_coor.y; int dRz = R_coor.z; - if (PARAM.inp.nspin == 2) { - if (dHx_nonzero_num[0][count] == 0 && dHx_nonzero_num[1][count] == 0 - && dHy_nonzero_num[0][count] == 0 - && dHy_nonzero_num[1][count] == 0 - && dHz_nonzero_num[0][count] == 0 - && dHz_nonzero_num[1][count] == 0) { - count++; - continue; - } - } else { - if (dHx_nonzero_num[0][count] == 0 && dHy_nonzero_num[0][count] == 0 - && dHz_nonzero_num[0][count] == 0) { - count++; - continue; - } + if (!has_output_R(count)) + { + count++; + continue; } output_R_coor_ptr.insert(R_coor); @@ -380,15 +352,17 @@ void ModuleIO::save_dH_sparse(const int& istep, if (GlobalV::DRANK == 0) { if (binary) { for (int ispin = 0; ispin < spin_loop; ++ispin) { + const int dHx_count = static_cast(dHx_nonzero_num[ispin][count]); + const int dHy_count = static_cast(dHy_nonzero_num[ispin][count]); + const int dHz_count = static_cast(dHz_nonzero_num[ispin][count]); g1x[ispin].write(reinterpret_cast(&dRx), sizeof(int)); g1x[ispin].write(reinterpret_cast(&dRy), sizeof(int)); g1x[ispin].write(reinterpret_cast(&dRz), sizeof(int)); - g1x[ispin].write( - reinterpret_cast(&dHx_nonzero_num[ispin][count]), - sizeof(int)); + g1x[ispin].write(reinterpret_cast(&dHx_count), + sizeof(int)); g1y[ispin].write(reinterpret_cast(&dRx), sizeof(int)); @@ -396,9 +370,8 @@ void ModuleIO::save_dH_sparse(const int& istep, sizeof(int)); g1y[ispin].write(reinterpret_cast(&dRz), sizeof(int)); - g1y[ispin].write( - reinterpret_cast(&dHy_nonzero_num[ispin][count]), - sizeof(int)); + g1y[ispin].write(reinterpret_cast(&dHy_count), + sizeof(int)); g1z[ispin].write(reinterpret_cast(&dRx), sizeof(int)); @@ -406,9 +379,8 @@ void ModuleIO::save_dH_sparse(const int& istep, sizeof(int)); g1z[ispin].write(reinterpret_cast(&dRz), sizeof(int)); - g1z[ispin].write( - reinterpret_cast(&dHz_nonzero_num[ispin][count]), - sizeof(int)); + g1z[ispin].write(reinterpret_cast(&dHz_count), + sizeof(int)); } } else { for (int ispin = 0; ispin < spin_loop; ++ispin) { @@ -479,15 +451,6 @@ void ModuleIO::save_dH_sparse(const int& istep, } } - for (int ispin = 0; ispin < spin_loop; ++ispin) { - delete[] dHx_nonzero_num[ispin]; - dHx_nonzero_num[ispin] = nullptr; - delete[] dHy_nonzero_num[ispin]; - dHy_nonzero_num[ispin] = nullptr; - delete[] dHz_nonzero_num[ispin]; - dHz_nonzero_num[ispin] = nullptr; - } - ModuleBase::timer::end("ModuleIO", "save_dH_sparse"); return; } diff --git a/source/source_io/module_hs/write_HS_sparse.h b/source/source_io/module_hs/write_HS_sparse.h index 8640972a84..f6271ebefb 100644 --- a/source/source_io/module_hs/write_HS_sparse.h +++ b/source/source_io/module_hs/write_HS_sparse.h @@ -25,6 +25,7 @@ struct SparseWriteOptions std::string label; double threshold = 0.0; bool binary = false; + int precision = 16; int istep = -1; bool reduce = true; std::string temp_dir; @@ -35,7 +36,8 @@ void save_dH_sparse(const int& istep, LCAO_HS_Arrays& HS_Arrays, const double& sparse_thr, const bool& binary, - const std::string& fileflag = "h"); + const std::string& fileflag = "h", + const int precision = 16); template void save_sparse(const SparseRMatrix& smat, diff --git a/source/source_io/module_hs/write_vxc_r.hpp b/source/source_io/module_hs/write_vxc_r.hpp index 6445378e37..a06ec6e806 100644 --- a/source/source_io/module_hs/write_vxc_r.hpp +++ b/source/source_io/module_hs/write_vxc_r.hpp @@ -12,14 +12,6 @@ namespace ModuleIO { -template -std::set> get_R_range(const hamilt::HContainer& hR) -{ - std::set> all_R_coor; - - return all_R_coor; -} - template std::map, std::map>> cal_HR_sparse(const hamilt::HContainer& hR, const double sparse_thr) diff --git a/source/source_io/module_parameter/read_input_item_output.cpp b/source/source_io/module_parameter/read_input_item_output.cpp index 295b9ff934..75a423a1b1 100644 --- a/source/source_io/module_parameter/read_input_item_output.cpp +++ b/source/source_io/module_parameter/read_input_item_output.cpp @@ -572,7 +572,7 @@ Also controled by out_freq_ion and out_app_flag. item.annotation = "output r(R) matrix"; item.category = "Output information"; item.type = R"(Boolean \[Integer\](optional))"; - item.description = "Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md." + item.description = "Whether to print the matrix representation of the position matrix into files named rxrs1_nao.csr, ryrs1_nao.csr, rzrs1_nao.csr in the directory OUT.${suffix}. The optional second parameter controls text output precision. If calculation is set to get_s, the position matrix can be obtained without scf iterations. For more information, please refer to position_matrix.md." "\n\n[NOTE] In the 3.10-LTS version, the file name is data-rR-sparse.csr."; item.default_value = "False 8"; item.unit = "Bohr"; @@ -610,7 +610,7 @@ Also controled by out_freq_ion and out_app_flag. item.annotation = "output T(R) matrix"; item.category = "Output information"; item.type = R"(Boolean \[Integer\](optional))"; - item.description = "Generate files containing the kinetic energy matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag." + item.description = "Generate files containing the kinetic energy matrix. The optional second parameter controls text output precision. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be trs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag." "\n\n[NOTE] In the 3.10-LTS version, the file name is data-TR-sparse_SPIN0.csr."; item.default_value = "False 8"; item.unit = "Ry"; @@ -637,8 +637,8 @@ Also controled by out_freq_ion and out_app_flag. Input_Item item("out_mat_dh"); item.annotation = "output Hamiltonian derivatives dH/dR matrices"; item.category = "Output information"; - item.type = "Integer"; - item.description = "Whether to print files containing the derivatives of the Hamiltonian matrix. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag." + item.type = R"(Boolean \[Integer\](optional))"; + item.description = "Whether to print files containing the derivatives of the Hamiltonian matrix. The optional second parameter controls text output precision. The format will be the same as the Hamiltonian matrix and overlap matrix as mentioned in out_mat_hs2. The name of the files will be dhrxs1_nao.csr, dhrys1_nao.csr, dhrzs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag." "\n\n[NOTE] In the 3.10-LTS version, the file name is data-dHRx-sparse_SPIN0.csr and so on."; item.default_value = "0 8"; item.unit = "Ry/Bohr"; @@ -672,7 +672,7 @@ Also controled by out_freq_ion and out_app_flag. item.annotation = "output of derivative of S(R) matrix"; item.category = "Output information"; item.type = R"(Boolean \[Integer\](optional))"; - item.description = "Whether to print files containing the derivatives of the overlap matrix. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s." + item.description = "Whether to print files containing the derivatives of the overlap matrix. The optional second parameter controls text output precision. The format will be the same as the overlap matrix as mentioned in out_mat_dh. The name of the files will be dsxrs1_nao.csr and so on. Also controled by out_freq_ion and out_app_flag. This feature can be used with calculation get_s." "\n\n[NOTE] In the 3.10-LTS version, the file name is data-dSRx-sparse_SPIN0.csr and so on."; item.default_value = "False 8"; item.unit = "Ry/Bohr"; diff --git a/source/source_io/test/CMakeLists.txt b/source/source_io/test/CMakeLists.txt index 5e200d99be..d1539268bd 100644 --- a/source/source_io/test/CMakeLists.txt +++ b/source/source_io/test/CMakeLists.txt @@ -292,6 +292,7 @@ AddTest( ../module_hs/write_HS_R.cpp ../module_hs/write_HS_sparse.cpp ../module_hs/single_R_io.cpp + ../module_hs/rr_sparse_writer.cpp ../module_dm/write_dmr.cpp ../module_output/ucell_io.cpp ../module_output/sparse_matrix.cpp diff --git a/source/source_io/test/single_R_io_test.cpp b/source/source_io/test/single_R_io_test.cpp index 8ce4531d47..594660b699 100644 --- a/source/source_io/test/single_R_io_test.cpp +++ b/source/source_io/test/single_R_io_test.cpp @@ -150,6 +150,36 @@ TEST(ModuleIOTest, OutputSingleRComplexKeepsHighPrecision) std::remove(filename.c_str()); } +TEST(ModuleIOTest, OutputSingleRUsesConfiguredPrecision) +{ + const std::string filename = "test_output_single_R_precision.dat"; + std::remove(filename.c_str()); + GlobalV::DRANK = 0; + std::ofstream ofs(filename); + + Parallel_Orbitals pv; + pv.set_serial(5, 5); + ModuleIO::SparseRBlock> XR = { + {0, {{1, std::complex(1.234567890123456, -2.5)}}} + }; + ModuleIO::SparseWriteOptions options; + options.threshold = 1e-12; + options.binary = false; + options.precision = 8; + options.reduce = false; + options.temp_dir = "./"; + + ModuleIO::output_single_R(ofs, XR, pv, options); + ofs.close(); + + std::ifstream ifs(filename); + const std::string output((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + EXPECT_THAT(output, testing::HasSubstr("(1.23456789e+00,-2.50000000e+00)")); + EXPECT_THAT(output, testing::Not(testing::HasSubstr("1.2345678901234560e+00"))); + + std::remove(filename.c_str()); +} + TEST(ModuleIOTest, OutputSingleRRejectsOutOfRangeColumn) { const char* filename = "/tmp/test_output_single_R_invalid.dat"; diff --git a/source/source_io/test/write_hs_r_compat_test.cpp b/source/source_io/test/write_hs_r_compat_test.cpp index f8d714a7d2..32e8b633e6 100644 --- a/source/source_io/test/write_hs_r_compat_test.cpp +++ b/source/source_io/test/write_hs_r_compat_test.cpp @@ -8,6 +8,8 @@ #include "source_base/global_variable.h" #include "source_cell/module_neighbor/sltk_grid_driver.h" #include "source_io/module_dm/write_dmr.h" +#include "source_io/module_hs/output_mat_sparse.h" +#include "source_io/module_hs/rr_sparse_writer.h" #include "source_io/module_hs/write_HS_R.h" #include "source_io/module_hs/write_HS_sparse.h" #include "source_lcao/module_hcontainer/atom_pair.h" @@ -184,6 +186,36 @@ void fill_matrix(hamilt::HContainer& matrix, Parallel_Orbitals& pv, doub matrix.insert_pair(pair); } +void init_sparse_output_globals(const int nspin = 1) +{ + GlobalV::DRANK = 0; + PARAM.inp.nspin = nspin; + PARAM.inp.calculation = "scf"; + PARAM.inp.out_app_flag = false; + PARAM.sys.global_out_dir = "./"; + PARAM.globalv.global_out_dir = "./"; + PARAM.sys.global_matrix_dir = "./"; + PARAM.globalv.global_matrix_dir = "./"; + PARAM.sys.nlocal = 2; + PARAM.globalv.nlocal = 2; +} + +void remove_derivative_files(const std::string& fileflag) +{ + const std::vector filenames = { + "d" + fileflag + "rxs1_nao.csr", + "d" + fileflag + "rys1_nao.csr", + "d" + fileflag + "rzs1_nao.csr", + "d" + fileflag + "rxs2_nao.csr", + "d" + fileflag + "rys2_nao.csr", + "d" + fileflag + "rzs2_nao.csr", + }; + for (const std::string& filename: filenames) + { + std::remove(filename.c_str()); + } +} + bool starts_with(const std::string& text, const std::string& prefix) { return text.find(prefix) == 0; @@ -479,6 +511,279 @@ TEST(WriteHsRCompatibility, LegacySparseBinaryCountsOnlyValuesAboveThreshold) std::remove(filename.c_str()); } +TEST(WriteHsRCompatibility, SaveDHSparseTextCountsOnlyValuesAboveThreshold) +{ + remove_derivative_files("h"); + init_sparse_output_globals(); + + Parallel_Orbitals pv; + init_serial_orbitals(pv); + LCAO_HS_Arrays arrays; + const Abfs::Vector3_Order r_vector(0, 0, 0); + arrays.all_R_coor.insert(r_vector); + arrays.dHRx_sparse[0][r_vector][0][0] = 1.0; + arrays.dHRx_sparse[0][r_vector][0][1] = 1e-12; + 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); + + const std::vector lines = read_lines("dhrxs1_nao.csr"); + ASSERT_GE(lines.size(), 7); + EXPECT_EQ(lines[0], "STEP: 5"); + EXPECT_EQ(lines[1], "Matrix Dimension of dHx(R): 2"); + EXPECT_EQ(lines[2], "Matrix number of dHx(R): 1"); + EXPECT_EQ(lines[3], "0 0 0 2"); + EXPECT_THAT(lines[4], testing::HasSubstr("1.00000000e+00")); + EXPECT_THAT(lines[4], testing::HasSubstr("-2.00000000e+00")); + + std::istringstream column_stream(lines[5]); + std::vector columns; + int column = 0; + while (column_stream >> column) + { + columns.push_back(column); + } + EXPECT_THAT(columns, testing::ElementsAre(0, 1)); + + std::istringstream indptr_stream(lines[6]); + std::vector indptr; + long long ptr = 0; + while (indptr_stream >> ptr) + { + indptr.push_back(ptr); + } + EXPECT_THAT(indptr, testing::ElementsAre(0, 1, 2)); + + const std::vector y_lines = read_lines("dhrys1_nao.csr"); + ASSERT_GE(y_lines.size(), 4); + EXPECT_EQ(y_lines[3], "0 0 0 0"); + + remove_derivative_files("h"); +} + +TEST(WriteHsRCompatibility, SaveDHSparseBinaryCountsOnlyValuesAboveThreshold) +{ + remove_derivative_files("h"); + init_sparse_output_globals(); + + Parallel_Orbitals pv; + init_serial_orbitals(pv); + LCAO_HS_Arrays arrays; + const Abfs::Vector3_Order r_vector(0, 0, 0); + arrays.all_R_coor.insert(r_vector); + arrays.dHRx_sparse[0][r_vector][0][0] = 1.0; + arrays.dHRx_sparse[0][r_vector][0][1] = 1e-12; + 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); + + std::ifstream ifs("dhrxs1_nao.csr", std::ios::binary); + ASSERT_TRUE(ifs.is_open()); + EXPECT_EQ(read_binary_value(ifs), 6); + EXPECT_EQ(read_binary_value(ifs), 2); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 2); + EXPECT_DOUBLE_EQ(read_binary_value(ifs), 1.0); + EXPECT_DOUBLE_EQ(read_binary_value(ifs), -2.0); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 2); + + remove_derivative_files("h"); +} + +TEST(WriteHsRCompatibility, SaveDSSparseSocWritesAllDirections) +{ + remove_derivative_files("s"); + init_sparse_output_globals(4); + + Parallel_Orbitals pv; + init_serial_orbitals(pv); + LCAO_HS_Arrays arrays; + const Abfs::Vector3_Order r_vector(0, 0, 0); + arrays.all_R_coor.insert(r_vector); + arrays.dHRx_soc_sparse[r_vector][0][0] = std::complex(1.0, 0.0); + 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); + + const std::string x_output = read_file("dsrxs1_nao.csr"); + const std::string y_output = read_file("dsrys1_nao.csr"); + const std::string z_output = read_file("dsrzs1_nao.csr"); + EXPECT_THAT(x_output, testing::HasSubstr("Matrix number of dHx(R): 1\n0 0 0 1\n")); + EXPECT_THAT(y_output, testing::HasSubstr("Matrix number of dHy(R): 1\n0 0 0 1\n")); + EXPECT_THAT(z_output, testing::HasSubstr("Matrix number of dHz(R): 1\n0 0 0 1\n")); + EXPECT_THAT(x_output, testing::HasSubstr("(1.00000000e+00,0.00000000e+00)")); + EXPECT_THAT(y_output, testing::HasSubstr("(2.00000000e+00,-1.00000000e+00)")); + EXPECT_THAT(z_output, testing::HasSubstr("(-3.00000000e+00,5.00000000e-01)")); + + remove_derivative_files("s"); +} + +TEST(WriteHsRCompatibility, MatSparseOutputOptionsKeepLegacyDefaults) +{ + ModuleIO::MatSparseOutputOptions options; + EXPECT_FALSE(options.out_mat_dh); + EXPECT_FALSE(options.out_mat_ds); + EXPECT_FALSE(options.out_mat_t); + EXPECT_FALSE(options.out_mat_r); + EXPECT_EQ(options.dh_precision, 16); + EXPECT_EQ(options.ds_precision, 16); + EXPECT_EQ(options.t_precision, 16); + EXPECT_EQ(options.r_precision, 16); + EXPECT_DOUBLE_EQ(options.sparse_threshold, 1e-10); + EXPECT_FALSE(options.binary); +} + +TEST(WriteHsRCompatibility, RRSparsePayloadDetectorSkipsEmptyBlocks) +{ + int empty_counts[3] = {0, 0, 0}; + int x_only_counts[3] = {1, 0, 0}; + int z_only_counts[3] = {0, 0, 2}; + + EXPECT_FALSE(ModuleIO::detail::rr_sparse_has_payload(empty_counts)); + EXPECT_TRUE(ModuleIO::detail::rr_sparse_has_payload(x_only_counts)); + EXPECT_TRUE(ModuleIO::detail::rr_sparse_has_payload(z_only_counts)); +} + +TEST(WriteHsRCompatibility, RRSparseTextFinalizerAllowsZeroBlocks) +{ + const std::string payload_filename = "rr_empty_payload.tmp"; + const std::string output_filename = "rr_empty.csr"; + std::remove(payload_filename.c_str()); + std::remove(output_filename.c_str()); + + std::ofstream payload(payload_filename.c_str()); + payload.close(); + + ModuleIO::detail::finalize_rr_sparse_file(output_filename, + payload_filename, + 9, + 2, + 0, + false, + false, + "WriteHsRCompatibility"); + + const std::vector lines = read_lines(output_filename); + ASSERT_EQ(lines.size(), 3); + EXPECT_EQ(lines[0], "STEP: 9"); + EXPECT_EQ(lines[1], "Matrix Dimension of r(R): 2"); + EXPECT_EQ(lines[2], "Matrix number of r(R): 0"); + + std::remove(payload_filename.c_str()); + std::remove(output_filename.c_str()); +} + +TEST(WriteHsRCompatibility, RRSparseTextFinalizerKeepsSingleDirectionPayload) +{ + const std::string payload_filename = "rr_single_direction_payload.tmp"; + const std::string output_filename = "rr_single_direction.csr"; + std::remove(payload_filename.c_str()); + std::remove(output_filename.c_str()); + + std::ofstream payload(payload_filename.c_str()); + payload << "1 0 -1\n"; + payload << "1\n"; + payload << " 4.00000000e+00\n"; + payload << " 0\n"; + payload << "0 1\n"; + payload << "0\n"; + payload << "0\n"; + payload.close(); + + ModuleIO::detail::finalize_rr_sparse_file(output_filename, + payload_filename, + 10, + 2, + 1, + false, + false, + "WriteHsRCompatibility"); + + const std::vector lines = read_lines(output_filename); + ASSERT_EQ(lines.size(), 10); + EXPECT_EQ(lines[0], "STEP: 10"); + EXPECT_EQ(lines[1], "Matrix Dimension of r(R): 2"); + EXPECT_EQ(lines[2], "Matrix number of r(R): 1"); + EXPECT_EQ(lines[3], "1 0 -1"); + EXPECT_EQ(lines[4], "1"); + EXPECT_EQ(lines[5], " 4.00000000e+00"); + EXPECT_EQ(lines[8], "0"); + EXPECT_EQ(lines[9], "0"); + + std::remove(payload_filename.c_str()); + std::remove(output_filename.c_str()); +} + +TEST(WriteHsRCompatibility, RRSparseBinaryFinalizerKeepsHeaderAndPayloadOrder) +{ + const std::string payload_filename = "rr_binary_payload.tmp"; + const std::string output_filename = "rr_binary.csr"; + std::remove(payload_filename.c_str()); + std::remove(output_filename.c_str()); + + std::ofstream payload(payload_filename.c_str(), std::ios::binary); + int dRx = 1; + int dRy = 2; + int dRz = 3; + int x_count = 1; + int y_count = 0; + int z_count = 0; + double value = 4.0; + int column = 1; + long long ptr0 = 0; + long long ptr1 = 1; + payload.write(reinterpret_cast(&dRx), sizeof(int)); + payload.write(reinterpret_cast(&dRy), sizeof(int)); + payload.write(reinterpret_cast(&dRz), sizeof(int)); + payload.write(reinterpret_cast(&x_count), sizeof(int)); + payload.write(reinterpret_cast(&value), sizeof(double)); + payload.write(reinterpret_cast(&column), sizeof(int)); + payload.write(reinterpret_cast(&ptr0), sizeof(long long)); + payload.write(reinterpret_cast(&ptr1), sizeof(long long)); + payload.write(reinterpret_cast(&y_count), sizeof(int)); + payload.write(reinterpret_cast(&z_count), sizeof(int)); + payload.close(); + + ModuleIO::detail::finalize_rr_sparse_file(output_filename, + payload_filename, + 11, + 2, + 1, + true, + false, + "WriteHsRCompatibility"); + + std::ifstream ifs(output_filename, std::ios::binary); + ASSERT_TRUE(ifs.is_open()); + EXPECT_EQ(read_binary_value(ifs), 11); + EXPECT_EQ(read_binary_value(ifs), 2); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 2); + EXPECT_EQ(read_binary_value(ifs), 3); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_DOUBLE_EQ(read_binary_value(ifs), 4.0); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 1); + EXPECT_EQ(read_binary_value(ifs), 0); + EXPECT_EQ(read_binary_value(ifs), 0); + ifs.close(); + + std::remove(payload_filename.c_str()); + std::remove(output_filename.c_str()); +} + TEST(WriteHsRCompatibility, HeaderStyleSamplesRemainDistinct) { EXPECT_TRUE(starts_with(" --- Ionic Step 1 ---", " --- Ionic Step")); From 2bff8fa576bcf2cc21c22787d19e0ba054075554 Mon Sep 17 00:00:00 2001 From: haochong zhang Date: Tue, 23 Jun 2026 07:11:43 +0000 Subject: [PATCH 3/3] test: fix module hs regression test builds --- source/source_io/test/CMakeLists.txt | 3 +- .../source_io/test/restart_exx_csr_test.cpp | 5 ++- source/source_io/test/single_R_io_test.cpp | 32 ++++++++++--------- source/source_io/test/tmp_mocks.cpp | 12 +++++++ .../source_io/test/write_hs_r_compat_test.cpp | 30 +++++++++++++---- 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/source/source_io/test/CMakeLists.txt b/source/source_io/test/CMakeLists.txt index d1539268bd..d3efa93548 100644 --- a/source/source_io/test/CMakeLists.txt +++ b/source/source_io/test/CMakeLists.txt @@ -306,9 +306,10 @@ endif() if(ENABLE_LIBRI) AddTest( TARGET MODULE_IO_restart_exx_csr_test - LIBS parameter base ${math_libs} device cell_info + LIBS parameter base ${math_libs} device SOURCES restart_exx_csr_test.cpp + tmp_mocks.cpp ) endif() diff --git a/source/source_io/test/restart_exx_csr_test.cpp b/source/source_io/test/restart_exx_csr_test.cpp index af023a7ef4..eee5fd96e5 100644 --- a/source/source_io/test/restart_exx_csr_test.cpp +++ b/source/source_io/test/restart_exx_csr_test.cpp @@ -15,9 +15,8 @@ void init_unitcell_for_ri(UnitCell& ucell) ucell.atoms[0].na = 1; ucell.atoms[0].nw = 2; ucell.atoms[0].stapos_wf = 0; - ucell.itia2iat(0, 0) = 0; - ucell.set_iat2itia(); - ucell.set_iat2iwt(1); + ucell.iat2it = new int[1]{0}; + ucell.iat2ia = new int[1]{0}; } } // namespace diff --git a/source/source_io/test/single_R_io_test.cpp b/source/source_io/test/single_R_io_test.cpp index 594660b699..fcadfaff91 100644 --- a/source/source_io/test/single_R_io_test.cpp +++ b/source/source_io/test/single_R_io_test.cpp @@ -180,26 +180,28 @@ TEST(ModuleIOTest, OutputSingleRUsesConfiguredPrecision) std::remove(filename.c_str()); } +void write_out_of_range_sparse_column(const char* filename) +{ + GlobalV::DRANK = 0; + std::ofstream ofs(filename); + Parallel_Orbitals pv; + pv.set_serial(5, 5); + ModuleIO::SparseRBlock XR; + XR[0][5] = 1.0; + ModuleIO::SparseWriteOptions options; + options.threshold = 1e-12; + options.binary = false; + options.reduce = false; + options.temp_dir = "/tmp/"; + ModuleIO::output_single_R(ofs, XR, pv, options); +} + TEST(ModuleIOTest, OutputSingleRRejectsOutOfRangeColumn) { const char* filename = "/tmp/test_output_single_R_invalid.dat"; std::remove(filename); EXPECT_EXIT( - { - GlobalV::DRANK = 0; - std::ofstream ofs(filename); - Parallel_Orbitals pv; - pv.set_serial(5, 5); - ModuleIO::SparseRBlock XR = { - {0, {{5, 1.0}}} - }; - ModuleIO::SparseWriteOptions options; - options.threshold = 1e-12; - options.binary = false; - options.reduce = false; - options.temp_dir = "/tmp/"; - ModuleIO::output_single_R(ofs, XR, pv, options); - }, + write_out_of_range_sparse_column(filename), ::testing::ExitedWithCode(1), "Sparse column index out of range"); std::remove(filename); diff --git a/source/source_io/test/tmp_mocks.cpp b/source/source_io/test/tmp_mocks.cpp index dc5834ad63..6c68572291 100644 --- a/source/source_io/test/tmp_mocks.cpp +++ b/source/source_io/test/tmp_mocks.cpp @@ -37,6 +37,18 @@ pseudo::~pseudo() { } +SepPot::SepPot() +{ +} +SepPot::~SepPot() +{ +} + +Sep_Cell::Sep_Cell() noexcept : ntype(0), omega(0.0), tpiba2(0.0) +{ +} +Sep_Cell::~Sep_Cell() noexcept = default; + // constructor of UnitCell UnitCell::UnitCell() { diff --git a/source/source_io/test/write_hs_r_compat_test.cpp b/source/source_io/test/write_hs_r_compat_test.cpp index 32e8b633e6..8c7c582124 100644 --- a/source/source_io/test/write_hs_r_compat_test.cpp +++ b/source/source_io/test/write_hs_r_compat_test.cpp @@ -24,6 +24,10 @@ #include #include +#ifdef __MPI +#include +#endif + namespace sparse_format { void cal_dH(const UnitCell&, @@ -189,15 +193,12 @@ void fill_matrix(hamilt::HContainer& matrix, Parallel_Orbitals& pv, doub void init_sparse_output_globals(const int nspin = 1) { GlobalV::DRANK = 0; - PARAM.inp.nspin = nspin; - PARAM.inp.calculation = "scf"; - PARAM.inp.out_app_flag = false; + PARAM.input.nspin = nspin; + PARAM.input.calculation = "scf"; + PARAM.input.out_app_flag = false; PARAM.sys.global_out_dir = "./"; - PARAM.globalv.global_out_dir = "./"; PARAM.sys.global_matrix_dir = "./"; - PARAM.globalv.global_matrix_dir = "./"; PARAM.sys.nlocal = 2; - PARAM.globalv.nlocal = 2; } void remove_derivative_files(const std::string& fileflag) @@ -790,3 +791,20 @@ TEST(WriteHsRCompatibility, HeaderStyleSamplesRemainDistinct) EXPECT_TRUE(starts_with("STEP: 0", "STEP:")); EXPECT_TRUE(starts_with("IONIC_STEP: 1", "IONIC_STEP:")); } + +int main(int argc, char** argv) +{ +#ifdef __MPI + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &GlobalV::NPROC); + MPI_Comm_rank(MPI_COMM_WORLD, &GlobalV::MY_RANK); +#endif + + ::testing::InitGoogleTest(&argc, argv); + const int result = RUN_ALL_TESTS(); + +#ifdef __MPI + MPI_Finalize(); +#endif + return result; +}