diff --git a/docs/advanced/interface/LibRPA.md b/docs/advanced/interface/LibRPA.md new file mode 100644 index 00000000000..1838dc23054 --- /dev/null +++ b/docs/advanced/interface/LibRPA.md @@ -0,0 +1,37 @@ +# LibRPA reader-v1 SOC symmetry export + +For an LCAO RPA export consumed by a reader-v1 LibRPA build, set: + +```text +basis_type lcao +rpa 1 +out_librpa_reader_version 1 +``` + +SOC symmetry export additionally requires `nspin 4`, `lspinorb 1`, and +`symmetry 1`. Magnetic systems must define the intended magnetic moments in +`STRU`. + +## `stru_out.txt` symmetry block + +After the existing lattice, atom, and k-point records, ABACUS writes the +spatial operation table when symmetry is enabled: + +```text +N row +<9 integer rotation entries and 3 fractional translations, repeated N times> +``` + +The same 12-field spatial rows are used for ordinary space groups and magnetic +groups. A magnetic group's antiunitary spatial operations are written after its +unitary operations. For `nspin=4`, ABACUS appends: + +```text +spin_symmetry 2 + +``` + +`grey_group` is `1` for a nonmagnetic SOC calculation and `0` for a magnetic +group. The `2` indicates that LibRPA reconstructs the spin rotation from the +spatial operation; ABACUS does not export the old `symrot_*` sidecar files as +part of this reader-v1 interface. diff --git a/docs/advanced/interface/index.rst b/docs/advanced/interface/index.rst index 1033502a281..1fac861aae4 100644 --- a/docs/advanced/interface/index.rst +++ b/docs/advanced/interface/index.rst @@ -20,3 +20,4 @@ Interfaces to Other Softwares candela TB2J migration-guide-csr-format + LibRPA diff --git a/source/source_lcao/module_ri/librpa_stru_symmetry.h b/source/source_lcao/module_ri/librpa_stru_symmetry.h new file mode 100644 index 00000000000..b685197abea --- /dev/null +++ b/source/source_lcao/module_ri/librpa_stru_symmetry.h @@ -0,0 +1,79 @@ +#ifndef LIBRPA_STRU_SYMMETRY_H +#define LIBRPA_STRU_SYMMETRY_H + +#include "source_base/matrix3.h" +#include "source_base/vector3.h" +#include "source_cell/module_symmetry/symmetry.h" + +#include +#include +#include +#include +#include + +namespace RpaLriDetail +{ +inline int checked_near_int(const double value, const std::string& context) +{ + const double rounded = std::round(value); + if (std::abs(value - rounded) > 1e-8) + { + throw std::runtime_error(context + " is not close to an integer."); + } + return static_cast(rounded); +} + +// LibRPA derives the SOC spin rotation from each spatial operation. ABACUS +// therefore writes one spatial table for both ordinary and magnetic groups, +// followed by the antiunitary flags required to reconstruct that action. +inline void write_librpa_symmetry_block(std::ostream& output, const ModuleSymmetry::Symmetry& symmetry, const int nspin) +{ + if (symmetry.nrotk <= 0) + { + return; + } + + const int n_anti = symmetry.magnetic_nspin4 ? symmetry.nrotk_anti : 0; + const auto write_operation + = [&output](const ModuleBase::Matrix3& rotation, const ModuleBase::Vector3& translation) { + output << std::setw(4) << checked_near_int(rotation.e11, "symmetry rotation e11") << std::setw(4) + << checked_near_int(rotation.e12, "symmetry rotation e12") << std::setw(4) + << checked_near_int(rotation.e13, "symmetry rotation e13") << std::setw(4) + << checked_near_int(rotation.e21, "symmetry rotation e21") << std::setw(4) + << checked_near_int(rotation.e22, "symmetry rotation e22") << std::setw(4) + << checked_near_int(rotation.e23, "symmetry rotation e23") << std::setw(4) + << checked_near_int(rotation.e31, "symmetry rotation e31") << std::setw(4) + << checked_near_int(rotation.e32, "symmetry rotation e32") << std::setw(4) + << checked_near_int(rotation.e33, "symmetry rotation e33") << std::setw(24) << std::scientific + << std::setprecision(15) << translation.x << std::setw(24) << std::scientific + << std::setprecision(15) << translation.y << std::setw(24) << std::scientific + << std::setprecision(15) << translation.z << std::endl; + }; + + output << (symmetry.nrotk + n_anti) << " row" << std::endl; + for (int isym = 0; isym < symmetry.nrotk; ++isym) + { + write_operation(symmetry.gmatrix[isym], symmetry.gtrans[isym]); + } + for (int isym = 0; isym < n_anti; ++isym) + { + write_operation(symmetry.gmatrix_anti[isym], symmetry.gtrans_anti[isym]); + } + + if (nspin == 4) + { + // source=2 means LibRPA reconstructs U_s from det(Q) Q. + output << "spin_symmetry " << (symmetry.magnetic_nspin4 ? 0 : 1) << " 2" << std::endl; + for (int isym = 0; isym < symmetry.nrotk; ++isym) + { + output << 0 << std::endl; + } + for (int isym = 0; isym < n_anti; ++isym) + { + output << 1 << std::endl; + } + } +} +} // namespace RpaLriDetail + +#endif diff --git a/source/source_lcao/module_ri/rpa_lri.hpp b/source/source_lcao/module_ri/rpa_lri.hpp index ae17d37863d..76df0312415 100644 --- a/source/source_lcao/module_ri/rpa_lri.hpp +++ b/source/source_lcao/module_ri/rpa_lri.hpp @@ -24,6 +24,7 @@ #include "rpa_lri.h" #include "exx_lri.h" +#include "librpa_stru_symmetry.h" #include "source_basis/module_ao/elem_basis_idx_orb.h" #include "source_base/global_function.h" #include "source_estate/elecstate_lcao.h" @@ -2720,6 +2721,10 @@ void RPA_LRI::out_struc(const UnitCell& ucell) ofs << (ik + 1) << std::endl; } } + if (ModuleSymmetry::Symmetry::symm_flag == 1 && ucell.symm.nrotk > 0) + { + RpaLriDetail::write_librpa_symmetry_block(ofs, ucell.symm, this->runtime.input.nspin); + } ofs.close(); return; } diff --git a/source/source_lcao/module_ri/test/CMakeLists.txt b/source/source_lcao/module_ri/test/CMakeLists.txt index ff75006e5b6..47f98cd8282 100644 --- a/source/source_lcao/module_ri/test/CMakeLists.txt +++ b/source/source_lcao/module_ri/test/CMakeLists.txt @@ -16,4 +16,9 @@ AddTest( LIBS parameter SOURCES abfs_vec3_order_test.cpp ) +AddTest( + TARGET MODULE_RI_librpa_stru_symmetry_test + LIBS base symmetry device + SOURCES librpa_stru_symmetry_test.cpp +) install(DIRECTORY support DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/source/source_lcao/module_ri/test/librpa_stru_symmetry_test.cpp b/source/source_lcao/module_ri/test/librpa_stru_symmetry_test.cpp new file mode 100644 index 00000000000..02b8d3ffa3e --- /dev/null +++ b/source/source_lcao/module_ri/test/librpa_stru_symmetry_test.cpp @@ -0,0 +1,107 @@ +#include "source_lcao/module_ri/librpa_stru_symmetry.h" + +#include +#include +#include +#include +#include +#include + +namespace +{ +void require(const bool condition, const char* message) +{ + if (!condition) + { + std::cerr << "FAILED: " << message << '\n'; + std::exit(1); + } +} + +std::vector split_lines(const std::string& text) +{ + std::vector lines; + std::istringstream input(text); + std::string line; + while (std::getline(input, line)) + { + lines.push_back(line); + } + return lines; +} + +void require_spatial_row(const std::string& line) +{ + std::istringstream input(line); + std::vector fields; + std::string field; + while (input >> field) + { + fields.push_back(field); + } + require(fields.size() == 12, "a symmetry row must contain 9 integer and 3 translation fields"); + for (int i = 0; i < 9; ++i) + { + std::size_t consumed = 0; + (void)std::stoi(fields[static_cast(i)], &consumed); + require(consumed == fields[static_cast(i)].size(), "rotation fields must be integers"); + } + for (int i = 9; i < 12; ++i) + { + std::size_t consumed = 0; + const double value = std::stod(fields[static_cast(i)], &consumed); + require(consumed == fields[static_cast(i)].size() && std::isfinite(value), + "translation fields must be finite floating-point values"); + } +} + +void test_magnetic_block() +{ + ModuleSymmetry::Symmetry symmetry; + symmetry.nrotk = 2; + symmetry.nrotk_anti = 1; + symmetry.magnetic_nspin4 = true; + symmetry.gmatrix[0] = ModuleBase::Matrix3(); + symmetry.gmatrix[1] = ModuleBase::Matrix3(0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0); + symmetry.gtrans[1] = ModuleBase::Vector3(0.5, 0.0, 0.0); + symmetry.gmatrix_anti[0] = ModuleBase::Matrix3(0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0); + symmetry.gtrans_anti[0] = ModuleBase::Vector3(0.125, 0.25, 0.375); + + std::ostringstream output; + RpaLriDetail::write_librpa_symmetry_block(output, symmetry, 4); + const auto lines = split_lines(output.str()); + require(lines.size() == 8, "magnetic SOC block must contain 3 spatial and 3 spin rows"); + require(lines[0] == "3 row", "unitary and antiunitary operations share one spatial block"); + require_spatial_row(lines[1]); + require_spatial_row(lines[2]); + require_spatial_row(lines[3]); + require(lines[3].find("1.250000000000000e-01") != std::string::npos, + "antiunitary spatial operation must follow unitary operations"); + require(lines[4] == "spin_symmetry 0 2", "LibRPA must reconstruct the magnetic spin action"); + require(lines[5] == "0" && lines[6] == "0" && lines[7] == "1", "only the final operation is antiunitary"); +} + +void test_nonmagnetic_soc_block() +{ + ModuleSymmetry::Symmetry symmetry; + symmetry.nrotk = 1; + symmetry.magnetic_nspin4 = false; + symmetry.gmatrix[0] = ModuleBase::Matrix3(); + + std::ostringstream output; + RpaLriDetail::write_librpa_symmetry_block(output, symmetry, 4); + const auto lines = split_lines(output.str()); + require(lines.size() == 4, "nonmagnetic SOC block must contain one spatial and one spin row"); + require(lines[0] == "1 row", "nonmagnetic block must retain its spatial operation"); + require(lines[2] == "spin_symmetry 1 2", "grey-group SOC metadata must be preserved"); + require(lines[3] == "0", "the nonmagnetic spatial operation must be unitary"); +} +} // namespace + +int main() +{ + test_magnetic_block(); + test_nonmagnetic_soc_block(); + std::cout << "LibRPA stru_out symmetry tests passed\n"; + return 0; +} diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/INPUT b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/INPUT new file mode 100644 index 00000000000..a3a129f04d8 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/INPUT @@ -0,0 +1,30 @@ +INPUT_PARAMETERS +suffix autotest +pseudo_dir ../../PP_ORB +orbital_dir ../../PP_ORB +calculation scf +ntype 1 +nbands 4 +gamma_only 0 +ecutwfc 20 +lspinorb 1 +nspin 4 +smearing_method gaussian +smearing_sigma 1e-4 +basis_type lcao +ks_solver genelpa +dft_functional pbe +rpa 1 +rpa_out_vel 1 +out_mat_xc 1 +out_wfc_lcao 1 +out_librpa_reader_version 1 +symmetry 1 +exx_separate_loop 1 +exx_pca_threshold 1e-3 +shrink_abfs_pca_thr 1e-1 +shrink_lu_inv_thr 1e-3 +exx_singularity_correction massidda +exx_ccp_rmesh_times 1 +rpa_ccp_rmesh_times 1 +exx_real_number 1 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/KPT b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/KPT new file mode 100644 index 00000000000..a427751e525 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/KPT @@ -0,0 +1,4 @@ +K_POINTS +0 +Gamma +1 1 2 0 0 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/README b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/README new file mode 100644 index 00000000000..13680cab939 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/README @@ -0,0 +1,4 @@ +Check reader-v1 RPA producer output, SOC GW-preprocessor inputs, and serialized +spatial and spin symmetry tables for a compact full-relativistic two-atom H +calculation. This is a serialization contract, not a symmetry-on/off +energy-equivalence comparison. diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/STRU b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/STRU new file mode 100644 index 00000000000..1871d8dded6 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/STRU @@ -0,0 +1,22 @@ +ATOMIC_SPECIES +H 1.008 H_ONCV_PBE_FR-1.0.upf + +NUMERICAL_ORBITAL +H_gga_6au_60Ry_1s.orb + +LATTICE_CONSTANT +1.8897261254578281 + +LATTICE_VECTORS +0.000000 1.500000 1.500000 +1.500000 0.000000 1.500000 +1.500000 1.500000 0.000000 + +ATOMIC_POSITIONS +Direct + +H +0.0 +2 +0.000000 0.000000 0.000000 0 0 0 +0.500000 0.500000 0.500000 0 0 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/librpa_producer_manifest.json b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/librpa_producer_manifest.json new file mode 100644 index 00000000000..6da3436bb13 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/librpa_producer_manifest.json @@ -0,0 +1,20 @@ +{ + "output_dir": "OUT.librpa", + "reference_dir": "producer_reference", + "required": [ + {"pattern": "stru_out.txt", "kind": "stru", "symmetry_rows": 1, "spin_symmetry_source": 2, "spin_symmetry_grey_group": 1, "reference": true, "abs_tol": 1e-7}, + {"pattern": "band_out.txt", "kind": "band", "reference": true, "abs_tol": 1e-7}, + {"pattern": "basis_*", "kind": "text", "reference": true, "abs_tol": 1e-7}, + {"pattern": "bz_sampling_out", "kind": "text", "reference": true, "abs_tol": 1e-7}, + {"pattern": "v1_Cs_shrinked_data_*.txt", "kind": "lri_coeff_v1", "reference": true, "abs_tol": 1e-7}, + {"pattern": "v1_Cs_data_*.txt", "kind": "lri_coeff_v1", "reference": true, "abs_tol": 1e-7}, + {"pattern": "v1_shrink_sinvS_*.txt", "kind": "shrink_sinvs_v1", "reference": true, "abs_tol": 1e-7}, + {"pattern": "v1_coulomb_cut_iq_*.dat", "kind": "coulomb_v1", "reference": true, "abs_tol": 1e-7}, + {"pattern": "v1_coulomb_full_iq_*.dat", "kind": "coulomb_v1", "reference": true, "abs_tol": 1e-7}, + {"pattern": "KS_eigenvector_*.dat", "kind": "gauge"}, + {"pattern": "velocity_matrix", "kind": "gauge"}, + {"base_dir": ".", "pattern": "OUT.autotest/vxc_out.dat", "kind": "text", "reference": true, "abs_tol": 1e-7}, + {"base_dir": ".", "pattern": "OUT.autotest/KPT.info", "kind": "text", "reference": true, "abs_tol": 1e-7}, + {"base_dir": ".", "pattern": "OUT.autotest/wfk*s4_nao.txt", "kind": "wfc_nao", "expected_count": 2} + ] +} diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/OUT.autotest/KPT.info b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/OUT.autotest/KPT.info new file mode 100644 index 00000000000..b2d4842ba88 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/OUT.autotest/KPT.info @@ -0,0 +1,10 @@ + nkstot now = 2 + K-POINTS DIRECT COORDINATES + KPOINTS DIRECT_X DIRECT_Y DIRECT_Z WEIGHT + 1 0.00000000 0.00000000 0.00000000 0.5000 + 2 0.00000000 0.00000000 0.50000000 0.5000 + nkstot = 2 ibzkpt +K-POINTS REDUCTION ACCORDING TO SYMMETRY + KPT DIRECT_X DIRECT_Y DIRECT_Z IBZ DIRECT_X DIRECT_Y DIRECT_Z + 1 0.00000000 0.00000000 0.00000000 1 0.00000000 0.00000000 0.00000000 + 2 0.00000000 0.00000000 0.50000000 2 0.00000000 0.00000000 0.50000000 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/OUT.autotest/vxc_out.dat b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/OUT.autotest/vxc_out.dat new file mode 100644 index 00000000000..ffcc8e562a0 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/OUT.autotest/vxc_out.dat @@ -0,0 +1,11 @@ +2 +1 +4 +-4.0274539288505579e-01 -1.0959264372970836e+01 +-4.0274539288505579e-01 -1.0959264372970836e+01 +-5.2769536070469791e-01 -1.4359327427498375e+01 +-5.2769536070469791e-01 -1.4359327427498375e+01 +-4.4986613169200201e-01 -1.2241485456459218e+01 +-4.4986613169200168e-01 -1.2241485456459207e+01 +-4.4986613138922499e-01 -1.2241485448220232e+01 +-4.4986613138922515e-01 -1.2241485448220237e+01 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/band_out.txt b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/band_out.txt new file mode 100644 index 00000000000..9058920c99a --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/band_out.txt @@ -0,0 +1,15 @@ +2 +1 +4 +4 +0.023189820575926 + 1 1 + 1 1.000000000000000 -0.443892166842433 -12.078925533247524 + 2 1.000000000000000 -0.443892166842433 -12.078925533247524 + 3 0.000000000000000 0.783096439472231 21.309147320668909 + 4 0.000000000000000 0.783096439472231 21.309147320668909 + 2 1 + 1 0.500000003527986 0.023189820575614 0.631027390851974 + 2 0.500000003527986 0.023189820575614 0.631027390851974 + 3 0.499999996427854 0.023189820576243 0.631027390869097 + 4 0.499999996427854 0.023189820576243 0.631027390869097 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_aux_out b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_aux_out new file mode 100644 index 00000000000..cbfe2adfdcc --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_aux_out @@ -0,0 +1,4 @@ + 1 2 abacus + 1 1 + 1 1 + 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_aux_shrink_out b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_aux_shrink_out new file mode 100644 index 00000000000..cbfe2adfdcc --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_aux_shrink_out @@ -0,0 +1,4 @@ + 1 2 abacus + 1 1 + 1 1 + 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_out b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_out new file mode 100644 index 00000000000..d144ade7bb6 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_out @@ -0,0 +1,6 @@ + 1 2 2 fallback + 1 1 1 + 1 1 + 0 + 1 1 + 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_out_shrink b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_out_shrink new file mode 100644 index 00000000000..d144ade7bb6 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_out_shrink @@ -0,0 +1,6 @@ + 1 2 2 fallback + 1 1 1 + 1 1 + 0 + 1 1 + 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_wfc_out b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_wfc_out new file mode 100644 index 00000000000..cbfe2adfdcc --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/basis_wfc_out @@ -0,0 +1,4 @@ + 1 2 abacus + 1 1 + 1 1 + 0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/bz_sampling_out b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/bz_sampling_out new file mode 100644 index 00000000000..d01f0c6b8c6 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/bz_sampling_out @@ -0,0 +1,4 @@ +1 1 2 +2 2 + 1 5.000000000000000e-01 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 1 1 + 2 5.000000000000000e-01 0.000000000000000e+00 0.000000000000000e+00 5.000000000000012e-01 5.541530791626714e-01 5.541530791626714e-01 -5.541530791626714e-01 2 2 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/stru_out.txt b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/stru_out.txt new file mode 100644 index 00000000000..2834c392566 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/stru_out.txt @@ -0,0 +1,107 @@ + 0.000000000000000e+00 2.834589188186742e+00 2.834589188186742e+00 + 2.834589188186742e+00 0.000000000000000e+00 2.834589188186742e+00 + 2.834589188186742e+00 2.834589188186742e+00 0.000000000000000e+00 + -1.108306158325340e+00 1.108306158325340e+00 1.108306158325340e+00 + 1.108306158325340e+00 -1.108306158325340e+00 1.108306158325340e+00 + 1.108306158325340e+00 1.108306158325340e+00 -1.108306158325340e+00 +2 + 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 1 + 2.834589188186742e+00 2.834589188186742e+00 2.834589188186742e+00 1 +48 row + 1 0 0 0 1 0 0 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 0 0 -1 0 0 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 0 1 -1 0 0 -1 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 0 -1 1 0 0 1 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 1 0 -1 0 0 -1 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 -1 0 1 0 0 1 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 -1 1 0 0 1 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 1 -1 0 0 -1 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 0 0 0 -1 0 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 0 0 0 1 0 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 1 -1 0 1 0 -1 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 -1 1 0 -1 0 1 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 -1 1 0 -1 0 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 1 -1 0 1 0 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 1 -1 1 0 -1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 -1 1 -1 0 1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 -1 0 0 -1 1 0 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 1 0 0 1 -1 0 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 0 0 1 -1 -1 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 0 0 -1 1 1 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 1 0 0 1 -1 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 -1 0 0 -1 1 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 -1 0 -1 0 -1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 1 0 1 0 1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 -1 0 0 -1 0 1 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 1 0 0 1 0 -1 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 1 1 0 0 0 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 -1 -1 0 0 0 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 0 -1 0 1 -1 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 0 1 0 -1 1 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 -1 0 1 0 -1 1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 1 0 -1 0 1 -1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 1 0 -1 1 0 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 -1 0 1 -1 0 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 -1 -1 1 0 0 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 1 1 -1 0 0 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 -1 0 1 -1 1 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 0 1 0 -1 1 -1 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 1 0 -1 0 1 -1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 -1 0 1 0 -1 1 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 0 0 0 1 1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 0 0 0 -1 -1 0 0 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 0 0 1 -1 0 1 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 0 0 -1 1 0 -1 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 -1 0 -1 0 0 0 0 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 0 1 0 1 0 0 0 0 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + -1 1 0 0 1 0 0 1 -1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 + 1 -1 0 0 -1 0 0 -1 1 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 +spin_symmetry 1 2 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_Cs_data_0.txt b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_Cs_data_0.txt new file mode 100644 index 00000000000..0ae852db19d Binary files /dev/null and b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_Cs_data_0.txt differ diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_Cs_shrinked_data_0.txt b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_Cs_shrinked_data_0.txt new file mode 100644 index 00000000000..0ae852db19d Binary files /dev/null and b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_Cs_shrinked_data_0.txt differ diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_coulomb_cut_iq_1_rank0.dat b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_coulomb_cut_iq_1_rank0.dat new file mode 100644 index 00000000000..9be55b5de80 Binary files /dev/null and b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_coulomb_cut_iq_1_rank0.dat differ diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_coulomb_full_iq_1_rank0.dat b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_coulomb_full_iq_1_rank0.dat new file mode 100644 index 00000000000..d9b32b8516b Binary files /dev/null and b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_coulomb_full_iq_1_rank0.dat differ diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_shrink_sinvS_0.txt b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_shrink_sinvS_0.txt new file mode 100644 index 00000000000..7a1726f27f2 Binary files /dev/null and b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/producer_reference/v1_shrink_sinvS_0.txt differ diff --git a/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/result.ref b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/result.ref new file mode 100644 index 00000000000..c491cbb6811 --- /dev/null +++ b/tests/08_EXX/63_LIBRPA_SOC_SYMMETRY/result.ref @@ -0,0 +1,7 @@ +etotref -34.21184903678268 +etotperatomref -17.1059245184 +Etot_without_rpa -1.228068413351746 +pointgroupref O_h +spacegroupref O_h +nksibzref 2 +totaltimeref 9.40 diff --git a/tests/08_EXX/CASES_LIBRPA_PRODUCER.txt b/tests/08_EXX/CASES_LIBRPA_PRODUCER.txt index 62735a2d0de..7e0081e9c11 100644 --- a/tests/08_EXX/CASES_LIBRPA_PRODUCER.txt +++ b/tests/08_EXX/CASES_LIBRPA_PRODUCER.txt @@ -1,2 +1,3 @@ 60_LIBRPA_RPA_READER_V1 +63_LIBRPA_SOC_SYMMETRY 64_LIBRPA_NSPIN2 diff --git a/tests/integrate/tools/check_librpa_producer.py b/tests/integrate/tools/check_librpa_producer.py index e828c8f3116..2c59dd144dc 100644 --- a/tests/integrate/tools/check_librpa_producer.py +++ b/tests/integrate/tools/check_librpa_producer.py @@ -85,7 +85,10 @@ def _compare_text(actual, reference, tolerance): ) -def _check_stru(path, minimum_symmetry_rows): +def _check_stru(path, + minimum_symmetry_rows, + expected_spin_symmetry_source, + expected_spin_symmetry_grey_group): lines = path.read_text().splitlines() if len(lines) < 8: raise ProducerContractError("{} is too short for stru_out".format(path)) @@ -134,6 +137,47 @@ def _check_stru(path, minimum_symmetry_rows): raise ProducerContractError("{} has a non-integer symmetry rotation".format(path)) for token in tokens[9:]: _number(token) + if expected_spin_symmetry_source is not None: + if row_match is None: + raise ProducerContractError("{} has no spatial symmetry block for spin metadata".format(path)) + spin_index = row_index + 1 + row_match + if spin_index >= len(lines): + raise ProducerContractError("{} has no spin_symmetry block".format(path)) + match = re.match(r"^spin_symmetry\s+([01])\s+([12])$", lines[spin_index]) + if match is None: + raise ProducerContractError("{} has an invalid spin_symmetry header".format(path)) + source = int(match.group(2)) + grey_group = int(match.group(1)) + if source != int(expected_spin_symmetry_source): + raise ProducerContractError( + "{} spin_symmetry source {} does not match expected {}".format( + path, source, expected_spin_symmetry_source + ) + ) + if (expected_spin_symmetry_grey_group is not None + and grey_group != int(expected_spin_symmetry_grey_group)): + raise ProducerContractError( + "{} spin_symmetry grey group {} does not match expected {}".format( + path, grey_group, expected_spin_symmetry_grey_group + ) + ) + spin_rows = lines[spin_index + 1 :] + if len(spin_rows) != row_match: + raise ProducerContractError( + "{} has {} spin symmetry rows for {} spatial operations".format( + path, len(spin_rows), row_match + ) + ) + for line in spin_rows: + tokens = line.split() + if source == 2 and len(tokens) != 1: + raise ProducerContractError("{} source-2 spin row has unexpected data".format(path)) + if source == 1 and len(tokens) != 9: + raise ProducerContractError("{} source-1 spin row is incomplete".format(path)) + if not tokens or tokens[0] not in ("0", "1"): + raise ProducerContractError("{} has an invalid antiunitary flag".format(path)) + for token in tokens[1:]: + _number(token) def _check_wfc_nao(path): """Validate the text LCAO wavefunction format consumed by GW preprocessing.""" lines = [line.strip() for line in path.read_text().splitlines() if line.strip()] @@ -379,7 +423,10 @@ def _check_file(path, entry): if kind == "gauge" or kind == "presence": return if kind == "stru": - _check_stru(path, entry.get("symmetry_rows")) + _check_stru(path, + entry.get("symmetry_rows"), + entry.get("spin_symmetry_source"), + entry.get("spin_symmetry_grey_group")) elif kind == "wfc_nao": _check_wfc_nao(path) elif kind == "band":