From 52e895902dbd23b123f2ba83c224344e51df79eb Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 17:51:42 +0800 Subject: [PATCH 01/13] Normalize CRLF line endings to LF --- docs/advanced/interface/pyatb.md | 218 ++-- .../source_base/test/tool_threading_test.cpp | 324 ++--- source/source_base/test/ylm_test.cpp | 796 ++++++------ .../module_ao/element_basis_index-ORB.cpp | 86 +- .../module_ao/element_basis_index-ORB.h | 42 +- .../source_estate/module_pot/pot_xc_fdm.cpp | 118 +- source/source_hamilt/test/CMakeLists.txt | 20 +- .../module_genelpa/elpa_generic.hpp | 888 ++++++------- source/source_lcao/module_ri/Inverse_Matrix.h | 72 +- source/source_lcao/module_ri/LRI_CV_Tools.h | 552 ++++---- source/source_lcao/module_ri/LRI_CV_Tools.hpp | 1124 ++++++++--------- .../source_lcao/module_ri/Matrix_Orbs22.hpp | 624 ++++----- source/source_lcao/module_ri/Mix_DMk_2D.cpp | 176 +-- source/source_lcao/module_ri/Mix_DMk_2D.h | 134 +- .../source_pw/module_stodft/sto_stress_pw.h | 134 +- .../pytorch_dpsi/IO/cal_weight.py | 140 +- .../pytorch_dpsi/IO/read_istate.py | 82 +- .../examples/Absorpation-N2/ABACUS-INPUT | 64 +- .../ground-state-projection-Si/On1.dat | 202 +-- 19 files changed, 2898 insertions(+), 2898 deletions(-) diff --git a/docs/advanced/interface/pyatb.md b/docs/advanced/interface/pyatb.md index 7c1ed0b9f2f..1ca689bd2f4 100644 --- a/docs/advanced/interface/pyatb.md +++ b/docs/advanced/interface/pyatb.md @@ -1,110 +1,110 @@ -# PYATB - -## Introduction - -[PYATB](https://github.com/pyatb/pyatb) (Python ab initio tight binding simulation package) is an open-source software package designed for computing electronic structures and related properties based on the ab initio tight binding Hamiltonian. The Hamiltonian can be directly obtained after conducting self-consistent calculations with ABACUS using numerical atomic orbital (NAO) bases. The package comprises three modules - Bands, Geometric, and Optical, each providing a comprehensive set of tools for analyzing different aspects of a material's electronic structure. - -## Installation - -```bash -git clone https://github.com/pyatb/pyatb.git -cd pyatb -python setup.py install --record log -``` - -To customize the `setup.py` file, you must make changes to the **CXX** and **LAPACK_DIR** variables in line with your environment. **CXX** denotes the C++ compiler you intend to use, for instance, icpc (note that it should not be the mpi version). Furthermore, **LAPACK_DIR** is used to specify the Intel MKL path. - -After completing the installation process, you can access the `pyatb` executable and corresponding module, which can be imported using the `import pyatb` command. - -## How to use - -We take Bi$_2$Se$_3$ as an example to illustrate how to use ABACUS to generate the tight binding Hamiltonian required for PYATB, and then perform calculations related to PYATB functions. - -1. Perform ABACUS self consistent calculation: - -``` -INPUT_PARAMETERS - -# System variables -suffix Bi2Se3 -ntype 2 -calculation scf -esolver_type ksdft -symmetry 1 -init_chg atomic - -# Plane wave related variables -ecutwfc 100 - -# Electronic structure -basis_type lcao -ks_solver genelpa -nspin 4 -smearing_method gauss -smearing_sigma 0.02 -mixing_type broyden -mixing_beta 0.7 -scf_nmax 200 -scf_thr 1e-8 -lspinorb 1 -noncolin 0 - -# Variables related to output information -out_chg 1 -out_mat_hs2 1 -out_mat_r 1 -``` - -After the key parameters `out_mat_hs2` and `out_mat_r` are turned on, ABACUS will generate files containing the Hamiltonian matrix $H(R)$, overlap matrix $S(R)$, and dipole matrix $r(R)$ after completing the self-consistent calculation. These parameters can be found in the ABACUS `INPUT` file. - -2. Copy the HR, SR, and rR files output by ABACUS's self-consistent calculation, which are located in the `OUT*` directory and named `data-HR-sparse_SPIN0.csr`, `data-SR-sparse_SPIN0.csr`, and `data-rR-sparse.csr`, respectively. Copy these files to the working directory and write the `Input` file for PYATB: - -``` -INPUT_PARAMETERS -{ - nspin 4 - package ABACUS - fermi_energy 9.557219691497478 - fermi_energy_unit eV - HR_route data-HR-sparse_SPIN0.csr - SR_route data-SR-sparse_SPIN0.csr - rR_route data-rR-sparse.csr - HR_unit Ry - rR_unit Bohr - max_kpoint_num 8000 -} - -LATTICE -{ - lattice_constant 1.8897162 - lattice_constant_unit Bohr - lattice_vector - -2.069 -3.583614 0.000000 - 2.069 -3.583614 0.000000 - 0.000 2.389075 9.546667 -} - -BAND_STRUCTURE -{ - wf_collect 0 - kpoint_mode line - kpoint_num 5 - high_symmetry_kpoint - 0.00000 0.00000 0.0000 100 # G - 0.00000 0.00000 0.5000 100 # Z - 0.50000 0.50000 0.0000 100 # F - 0.00000 0.00000 0.0000 100 # G - 0.50000 0.00000 0.0000 1 # L -} -``` - -For specific input file writing, please refer to PYATB's quick start. - -3. Perform PYATB calculation: - -``` -export OMP_NUM_THREADS=2 -mpirun -np 6 pyatb -``` - +# PYATB + +## Introduction + +[PYATB](https://github.com/pyatb/pyatb) (Python ab initio tight binding simulation package) is an open-source software package designed for computing electronic structures and related properties based on the ab initio tight binding Hamiltonian. The Hamiltonian can be directly obtained after conducting self-consistent calculations with ABACUS using numerical atomic orbital (NAO) bases. The package comprises three modules - Bands, Geometric, and Optical, each providing a comprehensive set of tools for analyzing different aspects of a material's electronic structure. + +## Installation + +```bash +git clone https://github.com/pyatb/pyatb.git +cd pyatb +python setup.py install --record log +``` + +To customize the `setup.py` file, you must make changes to the **CXX** and **LAPACK_DIR** variables in line with your environment. **CXX** denotes the C++ compiler you intend to use, for instance, icpc (note that it should not be the mpi version). Furthermore, **LAPACK_DIR** is used to specify the Intel MKL path. + +After completing the installation process, you can access the `pyatb` executable and corresponding module, which can be imported using the `import pyatb` command. + +## How to use + +We take Bi$_2$Se$_3$ as an example to illustrate how to use ABACUS to generate the tight binding Hamiltonian required for PYATB, and then perform calculations related to PYATB functions. + +1. Perform ABACUS self consistent calculation: + +``` +INPUT_PARAMETERS + +# System variables +suffix Bi2Se3 +ntype 2 +calculation scf +esolver_type ksdft +symmetry 1 +init_chg atomic + +# Plane wave related variables +ecutwfc 100 + +# Electronic structure +basis_type lcao +ks_solver genelpa +nspin 4 +smearing_method gauss +smearing_sigma 0.02 +mixing_type broyden +mixing_beta 0.7 +scf_nmax 200 +scf_thr 1e-8 +lspinorb 1 +noncolin 0 + +# Variables related to output information +out_chg 1 +out_mat_hs2 1 +out_mat_r 1 +``` + +After the key parameters `out_mat_hs2` and `out_mat_r` are turned on, ABACUS will generate files containing the Hamiltonian matrix $H(R)$, overlap matrix $S(R)$, and dipole matrix $r(R)$ after completing the self-consistent calculation. These parameters can be found in the ABACUS `INPUT` file. + +2. Copy the HR, SR, and rR files output by ABACUS's self-consistent calculation, which are located in the `OUT*` directory and named `data-HR-sparse_SPIN0.csr`, `data-SR-sparse_SPIN0.csr`, and `data-rR-sparse.csr`, respectively. Copy these files to the working directory and write the `Input` file for PYATB: + +``` +INPUT_PARAMETERS +{ + nspin 4 + package ABACUS + fermi_energy 9.557219691497478 + fermi_energy_unit eV + HR_route data-HR-sparse_SPIN0.csr + SR_route data-SR-sparse_SPIN0.csr + rR_route data-rR-sparse.csr + HR_unit Ry + rR_unit Bohr + max_kpoint_num 8000 +} + +LATTICE +{ + lattice_constant 1.8897162 + lattice_constant_unit Bohr + lattice_vector + -2.069 -3.583614 0.000000 + 2.069 -3.583614 0.000000 + 0.000 2.389075 9.546667 +} + +BAND_STRUCTURE +{ + wf_collect 0 + kpoint_mode line + kpoint_num 5 + high_symmetry_kpoint + 0.00000 0.00000 0.0000 100 # G + 0.00000 0.00000 0.5000 100 # Z + 0.50000 0.50000 0.0000 100 # F + 0.00000 0.00000 0.0000 100 # G + 0.50000 0.00000 0.0000 1 # L +} +``` + +For specific input file writing, please refer to PYATB's quick start. + +3. Perform PYATB calculation: + +``` +export OMP_NUM_THREADS=2 +mpirun -np 6 pyatb +``` + After the calculation is completed, the band structure data and figures of Bi$_2$Se$_3$ can be found in the `Out/Band_Structure` folder. \ No newline at end of file diff --git a/source/source_base/test/tool_threading_test.cpp b/source/source_base/test/tool_threading_test.cpp index d816aacded8..55ce874b824 100644 --- a/source/source_base/test/tool_threading_test.cpp +++ b/source/source_base/test/tool_threading_test.cpp @@ -1,162 +1,162 @@ -#include "../tool_threading.h" -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include -/************************************************ -* unit test of threading tool -***********************************************/ - -/** -* - Tested functions of class threading tool: -* - TASK_DIST_1D: -* - (template)Distributing 1d tasks by worker id (int and long long) -* - BLOCK_TASK_DIST_1D: -* - (template)Distributing 1d tasks by block_size and worker id (int and long long) -* - OMP_PARALLE: -* - Run functions in parallel mode -* - TRY_OMP_PARALLEL: -* - Run functions in parallel mode(Add the judgment statement to determine whether program is in parallel) -**/ - -// The meaning of the parameters used in the following tests -// nw: nworker -// iw: iworker -// nt: ntask -// st: start -// le: len -// bs: block_size - -//Test function used in the following tests -void test_fun(int a,int b) - { - std::cout< +/************************************************ +* unit test of threading tool +***********************************************/ + +/** +* - Tested functions of class threading tool: +* - TASK_DIST_1D: +* - (template)Distributing 1d tasks by worker id (int and long long) +* - BLOCK_TASK_DIST_1D: +* - (template)Distributing 1d tasks by block_size and worker id (int and long long) +* - OMP_PARALLE: +* - Run functions in parallel mode +* - TRY_OMP_PARALLEL: +* - Run functions in parallel mode(Add the judgment statement to determine whether program is in parallel) +**/ + +// The meaning of the parameters used in the following tests +// nw: nworker +// iw: iworker +// nt: ntask +// st: start +// le: len +// bs: block_size + +//Test function used in the following tests +void test_fun(int a,int b) + { + std::cout< -/************************************************ - * unit test of class ylm - ***********************************************/ - -/** - * - Tested Functions: - * - ZEROS - * - set all elements of a double float array to zero - * - hes_rl_sph_harm - * - test Hessian symmetry for l=5, l=6 - * - test finite difference validation for l=5, l=6 - * - test all Hessian components (H_xx, H_xy, H_xz, H_yy, H_yz, H_zz) for l=2 - * - test m=0 values across different l (l=0,1,2,3,4) - * - test special points (on coordinate axes) for l=4 - * - verify l>6 is not implemented - * */ - -class ylmTest : public testing::Test -{ -}; - -TEST_F(ylmTest,Zeros) -{ - double aaaa[100]; - ModuleBase::Ylm::ZEROS(aaaa,100); - for(int i = 0; i < 100; i++) - { - EXPECT_EQ(aaaa[i],0.0); - } -} - -// Test Hessian symmetry for l=5 -TEST_F(ylmTest, HessianSymmetryL5) -{ - const int l = 5; - const double x = 1.5, y = 2.0, z = 1.0; - std::vector> hrly; - - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Check that Hessian is symmetric for all m values - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - // hrly format: [H_xx, H_xy, H_xz, H_yy, H_yz, H_zz] - // Symmetry is built into the storage format - // Just verify the array is properly sized - EXPECT_EQ(hrly[idx].size(), 6); - } -} - -// Test Hessian symmetry for l=6 -TEST_F(ylmTest, HessianSymmetryL6) -{ - const int l = 6; - const double x = 1.5, y = 2.0, z = 1.0; - std::vector> hrly; - - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Check that Hessian is symmetric for all m values - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - EXPECT_EQ(hrly[idx].size(), 6); - } -} - -// Test Hessian finite difference for l=5 using central difference -TEST_F(ylmTest, HessianFiniteDifferenceL5) -{ - const int l = 5; - const double x = 1.5, y = 2.0, z = 1.0; - const double h = 1e-5; - const double tol = 1e-3; // Relaxed tolerance for numerical differentiation - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Allocate gradient arrays for central difference - const int nylm = (l+1)*(l+1); - std::vector rly_xp(nylm), rly_xm(nylm); - std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); - - // Compute gradient at (x+h, y, z) and (x-h, y, z) - ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); - - // Test H_xx for m=0 (index 25) using central difference - int idx = 25; - double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); - double H_xx_analytic = hrly[idx][0]; - - EXPECT_NEAR(H_xx_fd, H_xx_analytic, tol); -} - -// Test Hessian finite difference for l=6 using central difference -TEST_F(ylmTest, HessianFiniteDifferenceL6) -{ - const int l = 6; - const double x = 1.5, y = 2.0, z = 1.0; - const double h = 1e-5; - const double tol = 1e-3; // Relaxed tolerance for numerical differentiation - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Allocate gradient arrays for central difference - const int nylm = (l+1)*(l+1); - std::vector rly_xp(nylm), rly_xm(nylm); - std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); - - // Compute gradient at (x+h, y, z) and (x-h, y, z) - ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); - - // Test H_xx for m=0 (index 36) using central difference - int idx = 36; - double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); - double H_xx_analytic = hrly[idx][0]; - - EXPECT_NEAR(H_xx_fd, H_xx_analytic, tol); -} - -// Test that l>6 triggers error -TEST_F(ylmTest, HessianL7NotImplemented) -{ - const int l = 7; - const double x = 1.0, y = 0.0, z = 0.0; - std::vector> hrly; - - // This should call WARNING_QUIT and exit - // We can't easily test this in gtest without death tests - // EXPECT_DEATH(ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly), "l>6 not implemented"); -} - -// Test all Hessian components for l=2 -TEST_F(ylmTest, HessianAllComponentsL2) -{ - const int l = 2; - const double x = 0.5, y = 1.0, z = 1.5; - const double h = 1e-5; - const double tol = 1e-3; - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Test all 6 Hessian components for m=0 (index 4) - int idx = 4; - - // Allocate gradient arrays - const int nylm = (l+1)*(l+1); - std::vector rly_xp(nylm), rly_xm(nylm); - std::vector rly_yp(nylm), rly_ym(nylm); - std::vector rly_zp(nylm), rly_zm(nylm); - - std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); - std::vector grly_yp(nylm * 3), grly_ym(nylm * 3); - std::vector grly_zp(nylm * 3), grly_zm(nylm * 3); - - // Compute gradients at perturbed points - ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x, y+h, z, rly_yp.data(), grly_yp.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x, y-h, z, rly_ym.data(), grly_ym.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x, y, z+h, rly_zp.data(), grly_zp.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x, y, z-h, rly_zm.data(), grly_zm.data()); - - // Test H_xx (index 0) - double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); - EXPECT_NEAR(H_xx_fd, hrly[idx][0], tol); - - // Test H_xy (index 1) - double H_xy_fd = (grly_xp[idx*3 + 1] - grly_xm[idx*3 + 1]) / (2.0 * h); - EXPECT_NEAR(H_xy_fd, hrly[idx][1], tol); - - // Test H_xz (index 2) - double H_xz_fd = (grly_xp[idx*3 + 2] - grly_xm[idx*3 + 2]) / (2.0 * h); - EXPECT_NEAR(H_xz_fd, hrly[idx][2], tol); - - // Test H_yy (index 3) - double H_yy_fd = (grly_yp[idx*3 + 1] - grly_ym[idx*3 + 1]) / (2.0 * h); - EXPECT_NEAR(H_yy_fd, hrly[idx][3], tol); - - // Test H_yz (index 4) - double H_yz_fd = (grly_yp[idx*3 + 2] - grly_ym[idx*3 + 2]) / (2.0 * h); - EXPECT_NEAR(H_yz_fd, hrly[idx][4], tol); - - // Test H_zz (index 5) - double H_zz_fd = (grly_zp[idx*3 + 2] - grly_zm[idx*3 + 2]) / (2.0 * h); - EXPECT_NEAR(H_zz_fd, hrly[idx][5], tol); -} - -// Test Hessian for m=0 values across different l -TEST_F(ylmTest, HessianM0DifferentL) -{ - const double x = 1.0, y = 0.5, z = 2.0; - const double h = 1e-5; - const double tol = 1e-3; - - // Test m=0 for l=0,1,2,3,4 - std::vector l_values = {0, 1, 2, 3, 4}; - - for (int l : l_values) { - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Allocate gradient arrays - const int nylm = (l+1)*(l+1); - std::vector rly_xp(nylm), rly_xm(nylm); - std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); - - ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); - ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); - - // Test H_xx for m=0 (index l*l) - int idx = l * l; - double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); - EXPECT_NEAR(H_xx_fd, hrly[idx][0], tol) << "Failed for l=" << l << " m=0"; - } -} - -// Test Hessian at special points (on axes) -TEST_F(ylmTest, HessianSpecialPointsL4) -{ - const int l = 4; - const double h = 1e-5; - const double tol = 1e-3; - - // Test on z-axis - { - const double x = 0.0, y = 0.0, z = 1.0; - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Verify array is properly sized - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - EXPECT_EQ(hrly[idx].size(), 6); - } - } - - // Test on x-axis - { - const double x = 1.0, y = 0.0, z = 0.0; - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - EXPECT_EQ(hrly[idx].size(), 6); - } - } - - // Test on y-axis - { - const double x = 0.0, y = 1.0, z = 0.0; - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - EXPECT_EQ(hrly[idx].size(), 6); - } - } -} - -// Test Hessian trace property (Laplacian = 0 for harmonic functions) -TEST_F(ylmTest, HessianTraceL3) -{ - const int l = 3; - const double x = 1.2, y = 0.8, z = 1.5; - const double tol = 1e-10; - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // For spherical harmonics Y_lm(r), the Laplacian should satisfy: - // ∇²(r^l * Y_lm) = l(l+1) * r^(l-2) * Y_lm - // For real spherical harmonics, we need to check the trace - // Note: This is a property check, not a strict zero test - - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - // Trace = H_xx + H_yy + H_zz - double trace = hrly[idx][0] + hrly[idx][3] + hrly[idx][5]; - // The trace should be finite and well-defined - EXPECT_FALSE(std::isnan(trace)); - EXPECT_FALSE(std::isinf(trace)); - } -} - -// Test Hessian consistency across different coordinate systems -TEST_F(ylmTest, HessianRotationalInvariance) -{ - const int l = 2; - const double r = 2.0; - const double tol = 1e-3; - - // Test at two points with same radius but different angles - const double x1 = r, y1 = 0.0, z1 = 0.0; - const double x2 = 0.0, y2 = r, z2 = 0.0; - - std::vector> hrly1, hrly2; - ModuleBase::Ylm::hes_rl_sph_harm(l, x1, y1, z1, hrly1); - ModuleBase::Ylm::hes_rl_sph_harm(l, x2, y2, z2, hrly2); - - // For m=0 (index 4), the Hessian should have certain symmetries - int idx = 4; - - // Both should be properly sized - EXPECT_EQ(hrly1[idx].size(), 6); - EXPECT_EQ(hrly2[idx].size(), 6); - - // Values should be finite - for (int i = 0; i < 6; i++) { - EXPECT_FALSE(std::isnan(hrly1[idx][i])); - EXPECT_FALSE(std::isnan(hrly2[idx][i])); - EXPECT_FALSE(std::isinf(hrly1[idx][i])); - EXPECT_FALSE(std::isinf(hrly2[idx][i])); - } -} - -// Test Hessian for l=0 (constant function) -TEST_F(ylmTest, HessianL0Constant) -{ - const int l = 0; - const double x = 1.0, y = 2.0, z = 3.0; - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // For l=0, Y_00 is constant, so all second derivatives should be zero - int idx = 0; - const double tol = 1e-10; - - EXPECT_NEAR(hrly[idx][0], 0.0, tol); // H_xx - EXPECT_NEAR(hrly[idx][1], 0.0, tol); // H_xy - EXPECT_NEAR(hrly[idx][2], 0.0, tol); // H_xz - EXPECT_NEAR(hrly[idx][3], 0.0, tol); // H_yy - EXPECT_NEAR(hrly[idx][4], 0.0, tol); // H_yz - EXPECT_NEAR(hrly[idx][5], 0.0, tol); // H_zz -} - -// Test Hessian for l=1 (linear functions) -TEST_F(ylmTest, HessianL1Linear) -{ - const int l = 1; - const double x = 1.0, y = 2.0, z = 3.0; - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // For l=1, Y_1m are linear functions, so all second derivatives should be zero - const double tol = 1e-10; - - for (int idx = 1; idx <= 3; idx++) { - EXPECT_NEAR(hrly[idx][0], 0.0, tol); // H_xx - EXPECT_NEAR(hrly[idx][1], 0.0, tol); // H_xy - EXPECT_NEAR(hrly[idx][2], 0.0, tol); // H_xz - EXPECT_NEAR(hrly[idx][3], 0.0, tol); // H_yy - EXPECT_NEAR(hrly[idx][4], 0.0, tol); // H_yz - EXPECT_NEAR(hrly[idx][5], 0.0, tol); // H_zz - } -} - -// Test Hessian numerical stability for small coordinates -TEST_F(ylmTest, HessianNumericalStability) -{ - const int l = 3; - const double x = 1e-3, y = 2e-3, z = 3e-3; - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Check that all values are finite (no NaN or Inf) - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - for (int i = 0; i < 6; i++) { - EXPECT_FALSE(std::isnan(hrly[idx][i])) - << "NaN detected at idx=" << idx << " component=" << i; - EXPECT_FALSE(std::isinf(hrly[idx][i])) - << "Inf detected at idx=" << idx << " component=" << i; - } - } -} - -// Test Hessian for large coordinates -TEST_F(ylmTest, HessianLargeCoordinates) -{ - const int l = 4; - const double x = 100.0, y = 200.0, z = 300.0; - - std::vector> hrly; - ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); - - // Check that all values are finite - for (int idx = l*l; idx < (l+1)*(l+1); idx++) { - for (int i = 0; i < 6; i++) { - EXPECT_FALSE(std::isnan(hrly[idx][i])); - EXPECT_FALSE(std::isinf(hrly[idx][i])); - } - } -} +#include "../ylm.h" +#include "gtest/gtest.h" +#include +/************************************************ + * unit test of class ylm + ***********************************************/ + +/** + * - Tested Functions: + * - ZEROS + * - set all elements of a double float array to zero + * - hes_rl_sph_harm + * - test Hessian symmetry for l=5, l=6 + * - test finite difference validation for l=5, l=6 + * - test all Hessian components (H_xx, H_xy, H_xz, H_yy, H_yz, H_zz) for l=2 + * - test m=0 values across different l (l=0,1,2,3,4) + * - test special points (on coordinate axes) for l=4 + * - verify l>6 is not implemented + * */ + +class ylmTest : public testing::Test +{ +}; + +TEST_F(ylmTest,Zeros) +{ + double aaaa[100]; + ModuleBase::Ylm::ZEROS(aaaa,100); + for(int i = 0; i < 100; i++) + { + EXPECT_EQ(aaaa[i],0.0); + } +} + +// Test Hessian symmetry for l=5 +TEST_F(ylmTest, HessianSymmetryL5) +{ + const int l = 5; + const double x = 1.5, y = 2.0, z = 1.0; + std::vector> hrly; + + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Check that Hessian is symmetric for all m values + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + // hrly format: [H_xx, H_xy, H_xz, H_yy, H_yz, H_zz] + // Symmetry is built into the storage format + // Just verify the array is properly sized + EXPECT_EQ(hrly[idx].size(), 6); + } +} + +// Test Hessian symmetry for l=6 +TEST_F(ylmTest, HessianSymmetryL6) +{ + const int l = 6; + const double x = 1.5, y = 2.0, z = 1.0; + std::vector> hrly; + + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Check that Hessian is symmetric for all m values + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + EXPECT_EQ(hrly[idx].size(), 6); + } +} + +// Test Hessian finite difference for l=5 using central difference +TEST_F(ylmTest, HessianFiniteDifferenceL5) +{ + const int l = 5; + const double x = 1.5, y = 2.0, z = 1.0; + const double h = 1e-5; + const double tol = 1e-3; // Relaxed tolerance for numerical differentiation + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Allocate gradient arrays for central difference + const int nylm = (l+1)*(l+1); + std::vector rly_xp(nylm), rly_xm(nylm); + std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); + + // Compute gradient at (x+h, y, z) and (x-h, y, z) + ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); + + // Test H_xx for m=0 (index 25) using central difference + int idx = 25; + double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); + double H_xx_analytic = hrly[idx][0]; + + EXPECT_NEAR(H_xx_fd, H_xx_analytic, tol); +} + +// Test Hessian finite difference for l=6 using central difference +TEST_F(ylmTest, HessianFiniteDifferenceL6) +{ + const int l = 6; + const double x = 1.5, y = 2.0, z = 1.0; + const double h = 1e-5; + const double tol = 1e-3; // Relaxed tolerance for numerical differentiation + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Allocate gradient arrays for central difference + const int nylm = (l+1)*(l+1); + std::vector rly_xp(nylm), rly_xm(nylm); + std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); + + // Compute gradient at (x+h, y, z) and (x-h, y, z) + ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); + + // Test H_xx for m=0 (index 36) using central difference + int idx = 36; + double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); + double H_xx_analytic = hrly[idx][0]; + + EXPECT_NEAR(H_xx_fd, H_xx_analytic, tol); +} + +// Test that l>6 triggers error +TEST_F(ylmTest, HessianL7NotImplemented) +{ + const int l = 7; + const double x = 1.0, y = 0.0, z = 0.0; + std::vector> hrly; + + // This should call WARNING_QUIT and exit + // We can't easily test this in gtest without death tests + // EXPECT_DEATH(ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly), "l>6 not implemented"); +} + +// Test all Hessian components for l=2 +TEST_F(ylmTest, HessianAllComponentsL2) +{ + const int l = 2; + const double x = 0.5, y = 1.0, z = 1.5; + const double h = 1e-5; + const double tol = 1e-3; + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Test all 6 Hessian components for m=0 (index 4) + int idx = 4; + + // Allocate gradient arrays + const int nylm = (l+1)*(l+1); + std::vector rly_xp(nylm), rly_xm(nylm); + std::vector rly_yp(nylm), rly_ym(nylm); + std::vector rly_zp(nylm), rly_zm(nylm); + + std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); + std::vector grly_yp(nylm * 3), grly_ym(nylm * 3); + std::vector grly_zp(nylm * 3), grly_zm(nylm * 3); + + // Compute gradients at perturbed points + ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x, y+h, z, rly_yp.data(), grly_yp.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x, y-h, z, rly_ym.data(), grly_ym.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x, y, z+h, rly_zp.data(), grly_zp.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x, y, z-h, rly_zm.data(), grly_zm.data()); + + // Test H_xx (index 0) + double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); + EXPECT_NEAR(H_xx_fd, hrly[idx][0], tol); + + // Test H_xy (index 1) + double H_xy_fd = (grly_xp[idx*3 + 1] - grly_xm[idx*3 + 1]) / (2.0 * h); + EXPECT_NEAR(H_xy_fd, hrly[idx][1], tol); + + // Test H_xz (index 2) + double H_xz_fd = (grly_xp[idx*3 + 2] - grly_xm[idx*3 + 2]) / (2.0 * h); + EXPECT_NEAR(H_xz_fd, hrly[idx][2], tol); + + // Test H_yy (index 3) + double H_yy_fd = (grly_yp[idx*3 + 1] - grly_ym[idx*3 + 1]) / (2.0 * h); + EXPECT_NEAR(H_yy_fd, hrly[idx][3], tol); + + // Test H_yz (index 4) + double H_yz_fd = (grly_yp[idx*3 + 2] - grly_ym[idx*3 + 2]) / (2.0 * h); + EXPECT_NEAR(H_yz_fd, hrly[idx][4], tol); + + // Test H_zz (index 5) + double H_zz_fd = (grly_zp[idx*3 + 2] - grly_zm[idx*3 + 2]) / (2.0 * h); + EXPECT_NEAR(H_zz_fd, hrly[idx][5], tol); +} + +// Test Hessian for m=0 values across different l +TEST_F(ylmTest, HessianM0DifferentL) +{ + const double x = 1.0, y = 0.5, z = 2.0; + const double h = 1e-5; + const double tol = 1e-3; + + // Test m=0 for l=0,1,2,3,4 + std::vector l_values = {0, 1, 2, 3, 4}; + + for (int l : l_values) { + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Allocate gradient arrays + const int nylm = (l+1)*(l+1); + std::vector rly_xp(nylm), rly_xm(nylm); + std::vector grly_xp(nylm * 3), grly_xm(nylm * 3); + + ModuleBase::Ylm::grad_rl_sph_harm(l, x+h, y, z, rly_xp.data(), grly_xp.data()); + ModuleBase::Ylm::grad_rl_sph_harm(l, x-h, y, z, rly_xm.data(), grly_xm.data()); + + // Test H_xx for m=0 (index l*l) + int idx = l * l; + double H_xx_fd = (grly_xp[idx*3] - grly_xm[idx*3]) / (2.0 * h); + EXPECT_NEAR(H_xx_fd, hrly[idx][0], tol) << "Failed for l=" << l << " m=0"; + } +} + +// Test Hessian at special points (on axes) +TEST_F(ylmTest, HessianSpecialPointsL4) +{ + const int l = 4; + const double h = 1e-5; + const double tol = 1e-3; + + // Test on z-axis + { + const double x = 0.0, y = 0.0, z = 1.0; + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Verify array is properly sized + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + EXPECT_EQ(hrly[idx].size(), 6); + } + } + + // Test on x-axis + { + const double x = 1.0, y = 0.0, z = 0.0; + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + EXPECT_EQ(hrly[idx].size(), 6); + } + } + + // Test on y-axis + { + const double x = 0.0, y = 1.0, z = 0.0; + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + EXPECT_EQ(hrly[idx].size(), 6); + } + } +} + +// Test Hessian trace property (Laplacian = 0 for harmonic functions) +TEST_F(ylmTest, HessianTraceL3) +{ + const int l = 3; + const double x = 1.2, y = 0.8, z = 1.5; + const double tol = 1e-10; + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // For spherical harmonics Y_lm(r), the Laplacian should satisfy: + // ∇²(r^l * Y_lm) = l(l+1) * r^(l-2) * Y_lm + // For real spherical harmonics, we need to check the trace + // Note: This is a property check, not a strict zero test + + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + // Trace = H_xx + H_yy + H_zz + double trace = hrly[idx][0] + hrly[idx][3] + hrly[idx][5]; + // The trace should be finite and well-defined + EXPECT_FALSE(std::isnan(trace)); + EXPECT_FALSE(std::isinf(trace)); + } +} + +// Test Hessian consistency across different coordinate systems +TEST_F(ylmTest, HessianRotationalInvariance) +{ + const int l = 2; + const double r = 2.0; + const double tol = 1e-3; + + // Test at two points with same radius but different angles + const double x1 = r, y1 = 0.0, z1 = 0.0; + const double x2 = 0.0, y2 = r, z2 = 0.0; + + std::vector> hrly1, hrly2; + ModuleBase::Ylm::hes_rl_sph_harm(l, x1, y1, z1, hrly1); + ModuleBase::Ylm::hes_rl_sph_harm(l, x2, y2, z2, hrly2); + + // For m=0 (index 4), the Hessian should have certain symmetries + int idx = 4; + + // Both should be properly sized + EXPECT_EQ(hrly1[idx].size(), 6); + EXPECT_EQ(hrly2[idx].size(), 6); + + // Values should be finite + for (int i = 0; i < 6; i++) { + EXPECT_FALSE(std::isnan(hrly1[idx][i])); + EXPECT_FALSE(std::isnan(hrly2[idx][i])); + EXPECT_FALSE(std::isinf(hrly1[idx][i])); + EXPECT_FALSE(std::isinf(hrly2[idx][i])); + } +} + +// Test Hessian for l=0 (constant function) +TEST_F(ylmTest, HessianL0Constant) +{ + const int l = 0; + const double x = 1.0, y = 2.0, z = 3.0; + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // For l=0, Y_00 is constant, so all second derivatives should be zero + int idx = 0; + const double tol = 1e-10; + + EXPECT_NEAR(hrly[idx][0], 0.0, tol); // H_xx + EXPECT_NEAR(hrly[idx][1], 0.0, tol); // H_xy + EXPECT_NEAR(hrly[idx][2], 0.0, tol); // H_xz + EXPECT_NEAR(hrly[idx][3], 0.0, tol); // H_yy + EXPECT_NEAR(hrly[idx][4], 0.0, tol); // H_yz + EXPECT_NEAR(hrly[idx][5], 0.0, tol); // H_zz +} + +// Test Hessian for l=1 (linear functions) +TEST_F(ylmTest, HessianL1Linear) +{ + const int l = 1; + const double x = 1.0, y = 2.0, z = 3.0; + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // For l=1, Y_1m are linear functions, so all second derivatives should be zero + const double tol = 1e-10; + + for (int idx = 1; idx <= 3; idx++) { + EXPECT_NEAR(hrly[idx][0], 0.0, tol); // H_xx + EXPECT_NEAR(hrly[idx][1], 0.0, tol); // H_xy + EXPECT_NEAR(hrly[idx][2], 0.0, tol); // H_xz + EXPECT_NEAR(hrly[idx][3], 0.0, tol); // H_yy + EXPECT_NEAR(hrly[idx][4], 0.0, tol); // H_yz + EXPECT_NEAR(hrly[idx][5], 0.0, tol); // H_zz + } +} + +// Test Hessian numerical stability for small coordinates +TEST_F(ylmTest, HessianNumericalStability) +{ + const int l = 3; + const double x = 1e-3, y = 2e-3, z = 3e-3; + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Check that all values are finite (no NaN or Inf) + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + for (int i = 0; i < 6; i++) { + EXPECT_FALSE(std::isnan(hrly[idx][i])) + << "NaN detected at idx=" << idx << " component=" << i; + EXPECT_FALSE(std::isinf(hrly[idx][i])) + << "Inf detected at idx=" << idx << " component=" << i; + } + } +} + +// Test Hessian for large coordinates +TEST_F(ylmTest, HessianLargeCoordinates) +{ + const int l = 4; + const double x = 100.0, y = 200.0, z = 300.0; + + std::vector> hrly; + ModuleBase::Ylm::hes_rl_sph_harm(l, x, y, z, hrly); + + // Check that all values are finite + for (int idx = l*l; idx < (l+1)*(l+1); idx++) { + for (int i = 0; i < 6; i++) { + EXPECT_FALSE(std::isnan(hrly[idx][i])); + EXPECT_FALSE(std::isinf(hrly[idx][i])); + } + } +} diff --git a/source/source_basis/module_ao/element_basis_index-ORB.cpp b/source/source_basis/module_ao/element_basis_index-ORB.cpp index c9441b44978..d5ca9947a4f 100644 --- a/source/source_basis/module_ao/element_basis_index-ORB.cpp +++ b/source/source_basis/module_ao/element_basis_index-ORB.cpp @@ -1,44 +1,44 @@ -#include "element_basis_index-ORB.h" - -#include "ORB_read.h" -#include "ORB_atomic_lm.h" - -namespace ModuleBase -{ - -ModuleBase::Element_Basis_Index::Range -Element_Basis_Index::construct_range( const LCAO_Orbitals &orb ) -{ - ModuleBase::Element_Basis_Index::Range range; - range.resize( orb.get_ntype() ); - for( std::size_t T=0; T!=range.size(); ++T ) - { - range[T].resize( orb.Phi[T].getLmax()+1 ); - for( std::size_t L=0; L!=range[T].size(); ++L ) - { - range[T][L].N = orb.Phi[T].getNchi(L); - range[T][L].M = 2*L+1; - } - } - return range; -} - - -ModuleBase::Element_Basis_Index::Range -Element_Basis_Index::construct_range( const std::vector>> &orb ) -{ - ModuleBase::Element_Basis_Index::Range range; - range.resize( orb.size() ); - for( std::size_t T=0; T!=range.size(); ++T ) - { - range[T].resize( orb[T].size() ); - for( std::size_t L=0; L!=range[T].size(); ++L ) - { - range[T][L].N = orb[T][L].size(); - range[T][L].M = 2*L+1; - } - } - return range; -} - +#include "element_basis_index-ORB.h" + +#include "ORB_read.h" +#include "ORB_atomic_lm.h" + +namespace ModuleBase +{ + +ModuleBase::Element_Basis_Index::Range +Element_Basis_Index::construct_range( const LCAO_Orbitals &orb ) +{ + ModuleBase::Element_Basis_Index::Range range; + range.resize( orb.get_ntype() ); + for( std::size_t T=0; T!=range.size(); ++T ) + { + range[T].resize( orb.Phi[T].getLmax()+1 ); + for( std::size_t L=0; L!=range[T].size(); ++L ) + { + range[T][L].N = orb.Phi[T].getNchi(L); + range[T][L].M = 2*L+1; + } + } + return range; +} + + +ModuleBase::Element_Basis_Index::Range +Element_Basis_Index::construct_range( const std::vector>> &orb ) +{ + ModuleBase::Element_Basis_Index::Range range; + range.resize( orb.size() ); + for( std::size_t T=0; T!=range.size(); ++T ) + { + range[T].resize( orb[T].size() ); + for( std::size_t L=0; L!=range[T].size(); ++L ) + { + range[T][L].N = orb[T][L].size(); + range[T][L].M = 2*L+1; + } + } + return range; +} + } \ No newline at end of file diff --git a/source/source_basis/module_ao/element_basis_index-ORB.h b/source/source_basis/module_ao/element_basis_index-ORB.h index ec2415e6a0d..a7c75752836 100644 --- a/source/source_basis/module_ao/element_basis_index-ORB.h +++ b/source/source_basis/module_ao/element_basis_index-ORB.h @@ -1,22 +1,22 @@ -#ifndef ELEMENT_BASIS_INDEX_ORB_H -#define ELEMENT_BASIS_INDEX_ORB_H - -#include "../../source_base/element_basis_index.h" -#include - - class Numerical_Orbital_Lm; - class LCAO_Orbitals; - -namespace ModuleBase -{ - -namespace Element_Basis_Index -{ - extern Range construct_range( const LCAO_Orbitals &orb ); - - extern Range construct_range( const std::vector>> &orb ); // orb[T][L][N] -} - -} - +#ifndef ELEMENT_BASIS_INDEX_ORB_H +#define ELEMENT_BASIS_INDEX_ORB_H + +#include "../../source_base/element_basis_index.h" +#include + + class Numerical_Orbital_Lm; + class LCAO_Orbitals; + +namespace ModuleBase +{ + +namespace Element_Basis_Index +{ + extern Range construct_range( const LCAO_Orbitals &orb ); + + extern Range construct_range( const std::vector>> &orb ); // orb[T][L][N] +} + +} + #endif \ No newline at end of file diff --git a/source/source_estate/module_pot/pot_xc_fdm.cpp b/source/source_estate/module_pot/pot_xc_fdm.cpp index d0a49cc1012..c30c8091e4b 100644 --- a/source/source_estate/module_pot/pot_xc_fdm.cpp +++ b/source/source_estate/module_pot/pot_xc_fdm.cpp @@ -1,59 +1,59 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2025-10-01 -//======================= - -#include "pot_xc_fdm.h" -#include "source_hamilt/module_xc/xc_functional.h" - -namespace elecstate -{ - -PotXC_FDM::PotXC_FDM( - const ModulePW::PW_Basis* rho_basis_in, - const Charge*const chg_0_in, - const UnitCell*const ucell) - : chg_0(chg_0_in) -{ - this->rho_basis_ = rho_basis_in; - this->dynamic_mode = true; - this->fixed_mode = false; - - const std::tuple etxc_vtxc_v_0 - = XC_Functional::v_xc(this->chg_0->nrxx, this->chg_0, ucell); - this->v_xc_0 = std::get<2>(etxc_vtxc_v_0); -} - -void PotXC_FDM::cal_v_eff( - const Charge*const chg_1, - const UnitCell*const ucell, - ModuleBase::matrix& v_eff) -{ - ModuleBase::TITLE("PotXC_FDM", "cal_veff"); - ModuleBase::timer::start("PotXC_FDM", "cal_veff"); - - assert(this->chg_0->nrxx == chg_1->nrxx); - assert(this->chg_0->nspin == chg_1->nspin); - - Charge chg_01; - chg_01.set_rhopw(chg_1->rhopw); - chg_01.allocate(chg_1->nspin, chg_01.kin_density()); - - for(int ir=0; irrho[is][ir] + chg_1->rho[is][ir]; } - chg_01.rho_core[ir] = chg_0->rho_core[ir] + chg_1->rho_core[ir]; - } - - const std::tuple etxc_vtxc_v_01 - = XC_Functional::v_xc(chg_01.nrxx, &chg_01, ucell); - const ModuleBase::matrix &v_xc_01 = std::get<2>(etxc_vtxc_v_01); - - v_eff += v_xc_01 - this->v_xc_0; - - ModuleBase::timer::end("PotXC_FDM", "cal_veff"); -} - -} // namespace elecstate - +//======================= +// AUTHOR : Peize Lin +// DATE : 2025-10-01 +//======================= + +#include "pot_xc_fdm.h" +#include "source_hamilt/module_xc/xc_functional.h" + +namespace elecstate +{ + +PotXC_FDM::PotXC_FDM( + const ModulePW::PW_Basis* rho_basis_in, + const Charge*const chg_0_in, + const UnitCell*const ucell) + : chg_0(chg_0_in) +{ + this->rho_basis_ = rho_basis_in; + this->dynamic_mode = true; + this->fixed_mode = false; + + const std::tuple etxc_vtxc_v_0 + = XC_Functional::v_xc(this->chg_0->nrxx, this->chg_0, ucell); + this->v_xc_0 = std::get<2>(etxc_vtxc_v_0); +} + +void PotXC_FDM::cal_v_eff( + const Charge*const chg_1, + const UnitCell*const ucell, + ModuleBase::matrix& v_eff) +{ + ModuleBase::TITLE("PotXC_FDM", "cal_veff"); + ModuleBase::timer::start("PotXC_FDM", "cal_veff"); + + assert(this->chg_0->nrxx == chg_1->nrxx); + assert(this->chg_0->nspin == chg_1->nspin); + + Charge chg_01; + chg_01.set_rhopw(chg_1->rhopw); + chg_01.allocate(chg_1->nspin, chg_01.kin_density()); + + for(int ir=0; irrho[is][ir] + chg_1->rho[is][ir]; } + chg_01.rho_core[ir] = chg_0->rho_core[ir] + chg_1->rho_core[ir]; + } + + const std::tuple etxc_vtxc_v_01 + = XC_Functional::v_xc(chg_01.nrxx, &chg_01, ucell); + const ModuleBase::matrix &v_xc_01 = std::get<2>(etxc_vtxc_v_01); + + v_eff += v_xc_01 - this->v_xc_0; + + ModuleBase::timer::end("PotXC_FDM", "cal_veff"); +} + +} // namespace elecstate + diff --git a/source/source_hamilt/test/CMakeLists.txt b/source/source_hamilt/test/CMakeLists.txt index 8994824db09..09672aab4b4 100644 --- a/source/source_hamilt/test/CMakeLists.txt +++ b/source/source_hamilt/test/CMakeLists.txt @@ -1,10 +1,10 @@ -AddTest( - TARGET MODULE_HAMILT_ewald_dnrm2 - SOURCES dnrm2_test.cpp ../module_ewald/dnrm2.cpp -) - -AddTest( - TARGET MODULE_HAMILT_ewald_rgen - LIBS parameter ${math_libs} base device - SOURCES rgen_test.cpp ../module_ewald/H_Ewald_pw.cpp ../module_ewald/dnrm2.cpp -) +AddTest( + TARGET MODULE_HAMILT_ewald_dnrm2 + SOURCES dnrm2_test.cpp ../module_ewald/dnrm2.cpp +) + +AddTest( + TARGET MODULE_HAMILT_ewald_rgen + LIBS parameter ${math_libs} base device + SOURCES rgen_test.cpp ../module_ewald/H_Ewald_pw.cpp ../module_ewald/dnrm2.cpp +) diff --git a/source/source_hsolver/module_genelpa/elpa_generic.hpp b/source/source_hsolver/module_genelpa/elpa_generic.hpp index c20a52eb4d3..0f84e9cc060 100644 --- a/source/source_hsolver/module_genelpa/elpa_generic.hpp +++ b/source/source_hsolver/module_genelpa/elpa_generic.hpp @@ -1,444 +1,444 @@ -#pragma once -#include "elpa_new.h" -#include -/*! \brief generic C method for elpa_set - * - * \details - * \param handle handle of the ELPA object for which a key/value pair should be set - * \param name the name of the key - * \param value integer/double value to be set for the key - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -inline void elpa_set(elpa_t handle, const char *name, int value, int *error) -{ - elpa_set_integer(handle, name, value, error); -} -inline void elpa_set(elpa_t handle, const char *name, double value, int *error) -{ - elpa_set_double(handle, name, value, error); -} - -/*! \brief generic C method for elpa_get - * - * \details - * \param handle handle of the ELPA object for which a key/value pair should be queried - * \param name the name of the key - * \param value integer/double value to be queried - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -inline void elpa_get(elpa_t handle, const char *name, int *value, int *error) -{ - elpa_get_integer(handle, name, value, error); -} -inline void elpa_get(elpa_t handle, const char *name, double *value, int *error) -{ - elpa_get_double(handle, name, value, error); -} - -/*! \brief generic C method for elpa_eigenvectors - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a - * \param ev on return: float/double pointer to eigenvalues - * \param q on return: float/double float complex/double complex pointer to eigenvectors - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions -inline void elpa_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) -{ - elpa_eigenvectors_d(handle, a, ev, q, error); -} - -inline void elpa_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) -{ - elpa_eigenvectors_f(handle, a, ev, q, error); -} - -inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, double *ev, std::complex *q, int *error) -{ - elpa_eigenvectors_dc(handle, reinterpret_cast(a), ev, reinterpret_cast(q), error); -} - -inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, float *ev, std::complex *q, int *error) -{ - elpa_eigenvectors_fc(handle, reinterpret_cast(a), ev, reinterpret_cast(q), error); -} -#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 -inline void elpa_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) -{ - elpa_eigenvectors_all_host_arrays_d(handle, a, ev, q, error); -} - -inline void elpa_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) -{ - elpa_eigenvectors_all_host_arrays_f(handle, a, ev, q, error); -} - -inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, double *ev, std::complex *q, int *error) -{ - elpa_eigenvectors_all_host_arrays_dc(handle, reinterpret_cast(a), - ev, reinterpret_cast(q), error); -} - -inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, float *ev, std::complex *q, int *error) -{ - elpa_eigenvectors_all_host_arrays_fc(handle, reinterpret_cast(a), - ev, reinterpret_cast(q), error); -} -#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 -inline void elpa_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) -{ - elpa_eigenvectors_a_h_a_d(handle, a, ev, q, error); -} - -inline void elpa_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) -{ - elpa_eigenvectors_a_h_a_f(handle, a, ev, q, error); -} - -inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, double *ev, std::complex *q, int *error) -{ - elpa_eigenvectors_a_h_a_dc(handle, reinterpret_cast(a), - ev, reinterpret_cast(q), error); -} - -inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, float *ev, std::complex *q, int *error) -{ - elpa_eigenvectors_a_h_a_fc(handle, reinterpret_cast(a), - ev, reinterpret_cast(q), error); -} -#endif - -/*! \brief generic C method for elpa_skew_eigenvectors - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a - * \param ev on return: float/double pointer to eigenvalues - * \param q on return: float/double float complex/double complex pointer to eigenvectors - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions -inline void elpa_skew_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) -{ - elpa_eigenvectors_d(handle, a, ev, q, error); -} - -inline void elpa_skew_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) -{ - elpa_eigenvectors_f(handle, a, ev, q, error); -} -#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 -inline void elpa_skew_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) -{ - elpa_eigenvectors_all_host_arrays_d(handle, a, ev, q, error); -} - -inline void elpa_skew_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) -{ - elpa_eigenvectors_all_host_arrays_f(handle, a, ev, q, error); -} -#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 -inline void elpa_skew_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) -{ - elpa_skew_eigenvectors_a_h_a_d(handle, a, ev, q, error); -} - -inline void elpa_skew_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) -{ - elpa_skew_eigenvectors_a_h_a_f(handle, a, ev, q, error); -} -#endif - - - -/*! \brief generic C method for elpa_generalized_eigenvectors - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a - * \param b float/double float complex/double complex pointer to matrix b - * \param ev on return: float/double pointer to eigenvalues - * \param q on return: float/double float complex/double complex pointer to eigenvectors - * \param is_already_decomposed set to 1, if b already decomposed by previous call to elpa_generalized - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -inline void elpa_generalized_eigenvectors(elpa_t handle, double *a, double *b, double *ev, double *q, int is_already_decomposed, int *error) -{ - elpa_generalized_eigenvectors_d(handle, a, b, ev, q, is_already_decomposed, error); -} - -inline void elpa_generalized_eigenvectors(elpa_t handle, float *a, float *b, float *ev, float *q, int is_already_decomposed, int *error) -{ - elpa_generalized_eigenvectors_f(handle, a, b, ev, q, is_already_decomposed, error); -} - -inline void elpa_generalized_eigenvectors(elpa_t handle, std::complex *a, std::complex *b, double *ev, std::complex *q, int is_already_decomposed, int *error) -{ - elpa_generalized_eigenvectors_dc(handle, reinterpret_cast(a), reinterpret_cast(b), - ev, reinterpret_cast(q), is_already_decomposed, error); -} - -inline void elpa_generalized_eigenvectors(elpa_t handle, std::complex *a, std::complex *b, float *ev, std::complex *q, int is_already_decomposed, int *error) -{ - elpa_generalized_eigenvectors_fc(handle, reinterpret_cast(a), reinterpret_cast(b), - ev, reinterpret_cast(q), is_already_decomposed, error); -} - -/*! \brief generic C method for elpa_eigenvalues - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a - * \param ev on return: float/double pointer to eigenvalues - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions -inline void elpa_eigenvalues(elpa_t handle, double *a, double *ev, int *error) -{ - elpa_eigenvalues_d(handle, a, ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, float *a, float *ev, int *error) -{ - elpa_eigenvalues_f(handle, a, ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, std::complex *a, double *ev, int *error) -{ - elpa_eigenvalues_dc(handle, reinterpret_cast(a), ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, std::complex *a, float *ev, int *error) -{ - elpa_eigenvalues_fc (handle, reinterpret_cast(a), ev, error); -} -#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 -inline void elpa_eigenvalues(elpa_t handle, double *a, double *ev, int *error) -{ - elpa_eigenvalues_all_host_arrays_d(handle, a, ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, float *a, float *ev, int *error) -{ - elpa_eigenvalues_all_host_arrays_f(handle, a, ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, std::complex *a, double *ev, int *error) -{ - elpa_eigenvalues_all_host_arrays_dc(handle, reinterpret_cast(a), ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, std::complex *a, float *ev, int *error) -{ - elpa_eigenvalues_all_host_arrays_fc(handle, reinterpret_cast(a), ev, error); -} -#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 -inline void elpa_eigenvalues(elpa_t handle, double *a, double *ev, int *error) -{ - elpa_eigenvalues_a_h_a_d(handle, a, ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, float *a, float *ev, int *error) -{ - elpa_eigenvalues_a_h_a_f(handle, a, ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, std::complex *a, double *ev, int *error) -{ - elpa_eigenvalues_a_h_a_dc(handle, reinterpret_cast(a), ev, error); -} -inline void elpa_eigenvalues(elpa_t handle, std::complex *a, float *ev, int *error) -{ - elpa_eigenvalues_a_h_a_fc(handle, reinterpret_cast(a), ev, error); -} -#endif - -/*! \brief generic C method for elpa_skew_eigenvalues - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a - * \param ev on return: float/double pointer to eigenvalues - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions -inline void elpa_skew_eigenvalues(elpa_t handle, double *a, double *ev, int *error) -{ - elpa_eigenvalues_d(handle, a, ev, error); -} -inline void elpa_skew_eigenvalues(elpa_t handle, float *a, float *ev, int *error) -{ - elpa_eigenvalues_f(handle, a, ev, error); -} -#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 -inline void elpa_skew_eigenvalues(elpa_t handle, double *a, double *ev, int *error) -{ - elpa_eigenvalues_all_host_arrays_d(handle, a, ev, error); -} -inline void elpa_skew_eigenvalues(elpa_t handle, float *a, float *ev, int *error) -{ - elpa_eigenvalues_all_host_arrays_f(handle, a, ev, error); -} -#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 -inline void elpa_skew_eigenvalues(elpa_t handle, double *a, double *ev, int *error) -{ - elpa_eigenvalues_a_h_a_d(handle, a, ev, error); -} -inline void elpa_skew_eigenvalues(elpa_t handle, float *a, float *ev, int *error) -{ - elpa_eigenvalues_a_h_a_f(handle, a, ev, error); -} -#endif - -/*! \brief generic C method for elpa_cholesky - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a, for which - * the cholesky factorizaion will be computed - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ - -#if ELPA_API_VERSION < 20220501 // ELPA version before 2022.05.001 -inline void elpa_cholesky(elpa_t handle, double *a, int *error) -{ - elpa_cholesky_d(handle, a, error); -} -inline void elpa_cholesky(elpa_t handle, float *a, int *error) -{ - elpa_cholesky_f(handle, a, error); -} -inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) -{ - elpa_cholesky_dc(handle, reinterpret_cast(a), error); -} -inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) -{ - elpa_cholesky_fc(handle, reinterpret_cast(a), error); -} -#else -inline void elpa_cholesky(elpa_t handle, double *a, int *error) -{ - elpa_cholesky_a_h_a_d(handle, a, error); -} -inline void elpa_cholesky(elpa_t handle, float *a, int *error) -{ - elpa_cholesky_a_h_a_f(handle, a, error); -} -inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) -{ - elpa_cholesky_a_h_a_dc(handle, reinterpret_cast(a), error); -} -inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) -{ - elpa_cholesky_a_h_a_fc(handle, reinterpret_cast(a), error); -} -#endif - -/*! \brief generic C method for elpa_hermitian_multiply - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param uplo_a descriptor for matrix a - * \param uplo_c descriptor for matrix c - * \param ncb int - * \param a float/double float complex/double complex pointer to matrix a - * \param b float/double float complex/double complex pointer to matrix b - * \param nrows_b number of rows for matrix b - * \param ncols_b number of cols for matrix b - * \param c float/double float complex/double complex pointer to matrix c - * \param nrows_c number of rows for matrix c - * \param ncols_c number of cols for matrix c - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -#if ELPA_API_VERSION < 20220501 // ELPA version before 2022.05.001 -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_d(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); -} -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_df(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); -} -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_dc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), - reinterpret_cast(b), nrows_b, ncols_b, - reinterpret_cast(c), nrows_c, ncols_c, error); -} -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_fc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), - reinterpret_cast(b), nrows_b, ncols_b, - reinterpret_cast(c), nrows_c, ncols_c, error); -} -#else -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_a_h_a_d(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); -} -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_a_h_a_f(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); -} -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_a_h_a_dc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), - reinterpret_cast(b), nrows_b, ncols_b, - reinterpret_cast(c), nrows_c, ncols_c, error); -} -inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) -{ - elpa_hermitian_multiply_a_h_a_fc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), - reinterpret_cast(b), nrows_b, ncols_b, - reinterpret_cast(c), nrows_c, ncols_c, error); -} -#endif - -/*! \brief generic C method for elpa_invert_triangular - * - * \details - * \param handle handle of the ELPA object, which defines the problem - * \param a float/double float complex/double complex pointer to matrix a, which - * should be inverted - * \param error on return the error code, which can be queried with elpa_strerr() - * \result void - */ -#if ELPA_API_VERSION < 20220501 // ELPA version before 2022.05.001 -inline void elpa_invert_triangular(elpa_t handle, double *a, int *error) -{ - elpa_invert_trm_d(handle, a, error); -} -inline void elpa_invert_triangular(elpa_t handle, float *a, int *error) -{ - elpa_invert_trm_f(handle, a, error); -} -inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) -{ - elpa_invert_trm_dc(handle, reinterpret_cast(a), error); -} -inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) -{ - elpa_invert_trm_fc(handle, reinterpret_cast(a), error); -} -#else -inline void elpa_invert_triangular(elpa_t handle, double *a, int *error) -{ - elpa_invert_trm_a_h_a_d(handle, a, error); -} -inline void elpa_invert_triangular(elpa_t handle, float *a, int *error) -{ - elpa_invert_trm_a_h_a_f(handle, a, error); -} -inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) -{ - elpa_invert_trm_a_h_a_dc(handle, reinterpret_cast(a), error); -} -inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) -{ - elpa_invert_trm_a_h_a_fc(handle, reinterpret_cast(a), error); -} -#endif +#pragma once +#include "elpa_new.h" +#include +/*! \brief generic C method for elpa_set + * + * \details + * \param handle handle of the ELPA object for which a key/value pair should be set + * \param name the name of the key + * \param value integer/double value to be set for the key + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +inline void elpa_set(elpa_t handle, const char *name, int value, int *error) +{ + elpa_set_integer(handle, name, value, error); +} +inline void elpa_set(elpa_t handle, const char *name, double value, int *error) +{ + elpa_set_double(handle, name, value, error); +} + +/*! \brief generic C method for elpa_get + * + * \details + * \param handle handle of the ELPA object for which a key/value pair should be queried + * \param name the name of the key + * \param value integer/double value to be queried + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +inline void elpa_get(elpa_t handle, const char *name, int *value, int *error) +{ + elpa_get_integer(handle, name, value, error); +} +inline void elpa_get(elpa_t handle, const char *name, double *value, int *error) +{ + elpa_get_double(handle, name, value, error); +} + +/*! \brief generic C method for elpa_eigenvectors + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a + * \param ev on return: float/double pointer to eigenvalues + * \param q on return: float/double float complex/double complex pointer to eigenvectors + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions +inline void elpa_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) +{ + elpa_eigenvectors_d(handle, a, ev, q, error); +} + +inline void elpa_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) +{ + elpa_eigenvectors_f(handle, a, ev, q, error); +} + +inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, double *ev, std::complex *q, int *error) +{ + elpa_eigenvectors_dc(handle, reinterpret_cast(a), ev, reinterpret_cast(q), error); +} + +inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, float *ev, std::complex *q, int *error) +{ + elpa_eigenvectors_fc(handle, reinterpret_cast(a), ev, reinterpret_cast(q), error); +} +#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 +inline void elpa_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) +{ + elpa_eigenvectors_all_host_arrays_d(handle, a, ev, q, error); +} + +inline void elpa_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) +{ + elpa_eigenvectors_all_host_arrays_f(handle, a, ev, q, error); +} + +inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, double *ev, std::complex *q, int *error) +{ + elpa_eigenvectors_all_host_arrays_dc(handle, reinterpret_cast(a), + ev, reinterpret_cast(q), error); +} + +inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, float *ev, std::complex *q, int *error) +{ + elpa_eigenvectors_all_host_arrays_fc(handle, reinterpret_cast(a), + ev, reinterpret_cast(q), error); +} +#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 +inline void elpa_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) +{ + elpa_eigenvectors_a_h_a_d(handle, a, ev, q, error); +} + +inline void elpa_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) +{ + elpa_eigenvectors_a_h_a_f(handle, a, ev, q, error); +} + +inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, double *ev, std::complex *q, int *error) +{ + elpa_eigenvectors_a_h_a_dc(handle, reinterpret_cast(a), + ev, reinterpret_cast(q), error); +} + +inline void elpa_eigenvectors(const elpa_t handle, std::complex *a, float *ev, std::complex *q, int *error) +{ + elpa_eigenvectors_a_h_a_fc(handle, reinterpret_cast(a), + ev, reinterpret_cast(q), error); +} +#endif + +/*! \brief generic C method for elpa_skew_eigenvectors + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a + * \param ev on return: float/double pointer to eigenvalues + * \param q on return: float/double float complex/double complex pointer to eigenvectors + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions +inline void elpa_skew_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) +{ + elpa_eigenvectors_d(handle, a, ev, q, error); +} + +inline void elpa_skew_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) +{ + elpa_eigenvectors_f(handle, a, ev, q, error); +} +#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 +inline void elpa_skew_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) +{ + elpa_eigenvectors_all_host_arrays_d(handle, a, ev, q, error); +} + +inline void elpa_skew_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) +{ + elpa_eigenvectors_all_host_arrays_f(handle, a, ev, q, error); +} +#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 +inline void elpa_skew_eigenvectors(const elpa_t handle, double *a, double *ev, double *q, int *error) +{ + elpa_skew_eigenvectors_a_h_a_d(handle, a, ev, q, error); +} + +inline void elpa_skew_eigenvectors(const elpa_t handle, float *a, float *ev, float *q, int *error) +{ + elpa_skew_eigenvectors_a_h_a_f(handle, a, ev, q, error); +} +#endif + + + +/*! \brief generic C method for elpa_generalized_eigenvectors + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a + * \param b float/double float complex/double complex pointer to matrix b + * \param ev on return: float/double pointer to eigenvalues + * \param q on return: float/double float complex/double complex pointer to eigenvectors + * \param is_already_decomposed set to 1, if b already decomposed by previous call to elpa_generalized + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +inline void elpa_generalized_eigenvectors(elpa_t handle, double *a, double *b, double *ev, double *q, int is_already_decomposed, int *error) +{ + elpa_generalized_eigenvectors_d(handle, a, b, ev, q, is_already_decomposed, error); +} + +inline void elpa_generalized_eigenvectors(elpa_t handle, float *a, float *b, float *ev, float *q, int is_already_decomposed, int *error) +{ + elpa_generalized_eigenvectors_f(handle, a, b, ev, q, is_already_decomposed, error); +} + +inline void elpa_generalized_eigenvectors(elpa_t handle, std::complex *a, std::complex *b, double *ev, std::complex *q, int is_already_decomposed, int *error) +{ + elpa_generalized_eigenvectors_dc(handle, reinterpret_cast(a), reinterpret_cast(b), + ev, reinterpret_cast(q), is_already_decomposed, error); +} + +inline void elpa_generalized_eigenvectors(elpa_t handle, std::complex *a, std::complex *b, float *ev, std::complex *q, int is_already_decomposed, int *error) +{ + elpa_generalized_eigenvectors_fc(handle, reinterpret_cast(a), reinterpret_cast(b), + ev, reinterpret_cast(q), is_already_decomposed, error); +} + +/*! \brief generic C method for elpa_eigenvalues + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a + * \param ev on return: float/double pointer to eigenvalues + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions +inline void elpa_eigenvalues(elpa_t handle, double *a, double *ev, int *error) +{ + elpa_eigenvalues_d(handle, a, ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, float *a, float *ev, int *error) +{ + elpa_eigenvalues_f(handle, a, ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, std::complex *a, double *ev, int *error) +{ + elpa_eigenvalues_dc(handle, reinterpret_cast(a), ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, std::complex *a, float *ev, int *error) +{ + elpa_eigenvalues_fc (handle, reinterpret_cast(a), ev, error); +} +#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 +inline void elpa_eigenvalues(elpa_t handle, double *a, double *ev, int *error) +{ + elpa_eigenvalues_all_host_arrays_d(handle, a, ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, float *a, float *ev, int *error) +{ + elpa_eigenvalues_all_host_arrays_f(handle, a, ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, std::complex *a, double *ev, int *error) +{ + elpa_eigenvalues_all_host_arrays_dc(handle, reinterpret_cast(a), ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, std::complex *a, float *ev, int *error) +{ + elpa_eigenvalues_all_host_arrays_fc(handle, reinterpret_cast(a), ev, error); +} +#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 +inline void elpa_eigenvalues(elpa_t handle, double *a, double *ev, int *error) +{ + elpa_eigenvalues_a_h_a_d(handle, a, ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, float *a, float *ev, int *error) +{ + elpa_eigenvalues_a_h_a_f(handle, a, ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, std::complex *a, double *ev, int *error) +{ + elpa_eigenvalues_a_h_a_dc(handle, reinterpret_cast(a), ev, error); +} +inline void elpa_eigenvalues(elpa_t handle, std::complex *a, float *ev, int *error) +{ + elpa_eigenvalues_a_h_a_fc(handle, reinterpret_cast(a), ev, error); +} +#endif + +/*! \brief generic C method for elpa_skew_eigenvalues + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a + * \param ev on return: float/double pointer to eigenvalues + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +#if ELPA_API_VERSION <= 20210502 // ELPA 2021.05.002 and earlier versions +inline void elpa_skew_eigenvalues(elpa_t handle, double *a, double *ev, int *error) +{ + elpa_eigenvalues_d(handle, a, ev, error); +} +inline void elpa_skew_eigenvalues(elpa_t handle, float *a, float *ev, int *error) +{ + elpa_eigenvalues_f(handle, a, ev, error); +} +#elif ELPA_API_VERSION < 20220501 // ELPA version between 2021.11.001 and 2022.05.001 +inline void elpa_skew_eigenvalues(elpa_t handle, double *a, double *ev, int *error) +{ + elpa_eigenvalues_all_host_arrays_d(handle, a, ev, error); +} +inline void elpa_skew_eigenvalues(elpa_t handle, float *a, float *ev, int *error) +{ + elpa_eigenvalues_all_host_arrays_f(handle, a, ev, error); +} +#else // ELPA version 2022.05.001, ELPA has its own c++ interface from version 2022.11.001 +inline void elpa_skew_eigenvalues(elpa_t handle, double *a, double *ev, int *error) +{ + elpa_eigenvalues_a_h_a_d(handle, a, ev, error); +} +inline void elpa_skew_eigenvalues(elpa_t handle, float *a, float *ev, int *error) +{ + elpa_eigenvalues_a_h_a_f(handle, a, ev, error); +} +#endif + +/*! \brief generic C method for elpa_cholesky + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a, for which + * the cholesky factorizaion will be computed + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ + +#if ELPA_API_VERSION < 20220501 // ELPA version before 2022.05.001 +inline void elpa_cholesky(elpa_t handle, double *a, int *error) +{ + elpa_cholesky_d(handle, a, error); +} +inline void elpa_cholesky(elpa_t handle, float *a, int *error) +{ + elpa_cholesky_f(handle, a, error); +} +inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) +{ + elpa_cholesky_dc(handle, reinterpret_cast(a), error); +} +inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) +{ + elpa_cholesky_fc(handle, reinterpret_cast(a), error); +} +#else +inline void elpa_cholesky(elpa_t handle, double *a, int *error) +{ + elpa_cholesky_a_h_a_d(handle, a, error); +} +inline void elpa_cholesky(elpa_t handle, float *a, int *error) +{ + elpa_cholesky_a_h_a_f(handle, a, error); +} +inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) +{ + elpa_cholesky_a_h_a_dc(handle, reinterpret_cast(a), error); +} +inline void elpa_cholesky(elpa_t handle, std::complex *a, int *error) +{ + elpa_cholesky_a_h_a_fc(handle, reinterpret_cast(a), error); +} +#endif + +/*! \brief generic C method for elpa_hermitian_multiply + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param uplo_a descriptor for matrix a + * \param uplo_c descriptor for matrix c + * \param ncb int + * \param a float/double float complex/double complex pointer to matrix a + * \param b float/double float complex/double complex pointer to matrix b + * \param nrows_b number of rows for matrix b + * \param ncols_b number of cols for matrix b + * \param c float/double float complex/double complex pointer to matrix c + * \param nrows_c number of rows for matrix c + * \param ncols_c number of cols for matrix c + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +#if ELPA_API_VERSION < 20220501 // ELPA version before 2022.05.001 +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_d(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); +} +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_df(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); +} +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_dc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), + reinterpret_cast(b), nrows_b, ncols_b, + reinterpret_cast(c), nrows_c, ncols_c, error); +} +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_fc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), + reinterpret_cast(b), nrows_b, ncols_b, + reinterpret_cast(c), nrows_c, ncols_c, error); +} +#else +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_a_h_a_d(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); +} +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_a_h_a_f(handle, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error); +} +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_a_h_a_dc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), + reinterpret_cast(b), nrows_b, ncols_b, + reinterpret_cast(c), nrows_c, ncols_c, error); +} +inline void elpa_hermitian_multiply(elpa_t handle, char uplo_a, char uplo_c, int ncb, std::complex *a, std::complex *b, int nrows_b, int ncols_b, std::complex *c, int nrows_c, int ncols_c, int *error) +{ + elpa_hermitian_multiply_a_h_a_fc(handle, uplo_a, uplo_c, ncb, reinterpret_cast(a), + reinterpret_cast(b), nrows_b, ncols_b, + reinterpret_cast(c), nrows_c, ncols_c, error); +} +#endif + +/*! \brief generic C method for elpa_invert_triangular + * + * \details + * \param handle handle of the ELPA object, which defines the problem + * \param a float/double float complex/double complex pointer to matrix a, which + * should be inverted + * \param error on return the error code, which can be queried with elpa_strerr() + * \result void + */ +#if ELPA_API_VERSION < 20220501 // ELPA version before 2022.05.001 +inline void elpa_invert_triangular(elpa_t handle, double *a, int *error) +{ + elpa_invert_trm_d(handle, a, error); +} +inline void elpa_invert_triangular(elpa_t handle, float *a, int *error) +{ + elpa_invert_trm_f(handle, a, error); +} +inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) +{ + elpa_invert_trm_dc(handle, reinterpret_cast(a), error); +} +inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) +{ + elpa_invert_trm_fc(handle, reinterpret_cast(a), error); +} +#else +inline void elpa_invert_triangular(elpa_t handle, double *a, int *error) +{ + elpa_invert_trm_a_h_a_d(handle, a, error); +} +inline void elpa_invert_triangular(elpa_t handle, float *a, int *error) +{ + elpa_invert_trm_a_h_a_f(handle, a, error); +} +inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) +{ + elpa_invert_trm_a_h_a_dc(handle, reinterpret_cast(a), error); +} +inline void elpa_invert_triangular(elpa_t handle, std::complex *a, int *error) +{ + elpa_invert_trm_a_h_a_fc(handle, reinterpret_cast(a), error); +} +#endif diff --git a/source/source_lcao/module_ri/Inverse_Matrix.h b/source/source_lcao/module_ri/Inverse_Matrix.h index 141a09b39e7..0cc106f24f6 100644 --- a/source/source_lcao/module_ri/Inverse_Matrix.h +++ b/source/source_lcao/module_ri/Inverse_Matrix.h @@ -1,37 +1,37 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#pragma once - -#include "ABFs_Construct-PCA.h" - -#include -#include - -template -class Inverse_Matrix -{ - public: - enum class Method - { - potrf, - syev - }; - void cal_inverse(const Method& method, const double& threshold_condition_number = 0.); - - void input(const RI::Tensor& m); - void input(const std::vector>>& ms); - RI::Tensor output() const; - std::vector>> output(const std::vector& n0, - const std::vector& n1) const; - - private: - void using_potrf(); - void using_syev(const double& threshold_condition_number); - void copy_down_triangle(); - RI::Tensor A; -}; - +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#pragma once + +#include "ABFs_Construct-PCA.h" + +#include +#include + +template +class Inverse_Matrix +{ + public: + enum class Method + { + potrf, + syev + }; + void cal_inverse(const Method& method, const double& threshold_condition_number = 0.); + + void input(const RI::Tensor& m); + void input(const std::vector>>& ms); + RI::Tensor output() const; + std::vector>> output(const std::vector& n0, + const std::vector& n1) const; + + private: + void using_potrf(); + void using_syev(const double& threshold_condition_number); + void copy_down_triangle(); + RI::Tensor A; +}; + #include "Inverse_Matrix.hpp" \ No newline at end of file diff --git a/source/source_lcao/module_ri/LRI_CV_Tools.h b/source/source_lcao/module_ri/LRI_CV_Tools.h index b3f60706cdf..55f01db3ecd 100644 --- a/source/source_lcao/module_ri/LRI_CV_Tools.h +++ b/source/source_lcao/module_ri/LRI_CV_Tools.h @@ -1,276 +1,276 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-10-24 -//======================= - -#ifndef LRI_CV_TOOLS_H -#define LRI_CV_TOOLS_H - -#include "Inverse_Matrix.h" -#include "abfs-vector3_order.h" -#include "source_lcao/module_ri/abfs.h" - -#include -#include -#include -#include -#include -#include - -namespace LRI_CV_Tools -{ -template -extern RI::Tensor cal_I(const RI::Tensor& m, - const typename Inverse_Matrix::Method method - = Inverse_Matrix::Method::potrf, - const double& threshold_condition_number = 0.); -template -extern std::vector>> cal_I(const std::vector>>& ms, - const typename Inverse_Matrix::Method method - = Inverse_Matrix::Method::potrf, - const double& threshold_condition_number = 0.); - -template -inline RI::Tensor transform_Rm(const RI::Tensor& V); -template -inline std::array, 3> transform_Rm(const std::array, 3>& dV); - -// template inline bool exist(const T &V); - -// template -// extern Treturn mul1(const T1 &t1, const T2 &t2); -// template -// extern Treturn mul2(const T1 &mat, const T2 &vec); - -template -inline bool exist(const RI::Tensor& V); -template -inline bool exist(const std::array& dV); - -template -extern RI::Tensor mul1(const RI::Tensor& t1, const RI::Tensor& t2); -template -extern std::array mul1(const std::array& t1, const T& t2); - -template -extern std::vector> mul2(const std::vector>>& mat, - const std::vector>& vec); -template -extern std::array mul2(const T1& t1, const std::array& t2); -template -extern RI::Tensor mul2(const T& t1, const RI::Tensor& t2); -template -extern std::map> mul2(const T& t1, const std::map>& t2); - -// template -// std::array operator-(const std::array &v1, const std::array -// &v2); template std::vector operator-(const std::vector &v1, -// const std::vector &v2); -template -extern std::vector> minus(const std::vector>& v1, - const std::vector>& v2); -template -extern std::array>, N> minus( - std::array>, N>& v1, - std::array>, N>& v2); -template -inline std::map>> minus( - std::map>>& v1, - std::map>>& v2); -template -extern std::map> minus(std::map>& v1, - std::map>& v2); - -template -extern std::vector> add(const std::vector>& v1, - const std::vector>& v2); -template -extern std::array>, N> add( - std::array>, N>& v1, - std::array>, N>& v2); -template -inline std::map>> add( - std::map>>& v1, - std::map>>& v2); -template -extern std::map> add(std::map>& v1, - std::map>& v2); - -template -extern std::array negative(const std::array& v_in); - -// template T transpose12(const T &c_in); -template -RI::Tensor transpose12(const RI::Tensor& c_in); -template -std::array transpose12(const std::array& c_in); - -template -extern std::array, N> change_order(std::vector>&& ds_in); -template -std::vector> change_order(std::array, N>&& ds_in); -template -extern std::array>, N> change_order(std::vector>>&& ds_in); -template -extern std::array>, N> change_order( - std::map>>&& ds_in); -template -extern std::map>> change_order( - std::array>, N>&& ds_in); - -template -extern std::array cal_latvec_range(const double& rcut_times, - const UnitCell& ucell, - const std::vector& orb_cutoff); - -template -extern std::map, RI::Tensor>>> get_CVws( - const UnitCell& ucell, - const std::map>, RI::Tensor>>& CVs); -template -extern std::map, std::array, 3>>>> get_dCVws( - const UnitCell& ucell, - const std::map>, std::array, 3>>>& dCVs); -template -extern std::array, RI::Tensor>>, 3>, 3> cal_dMRs( - const UnitCell& ucell, - const std::array, RI::Tensor>>, 3>& dMs); - -using TC = std::array; -using TAC = std::pair; -template -using TLRI = std::map>>; -template -TLRI read_Cs_ao(const std::string& file_path, const double& threshold = 1e-10); -template -void write_Cs_ao(const TLRI& Vs, const std::string& file_path); -template -TLRI read_Vs_abf(const std::string& file_path, const double& threshold = 1e-10); -template -void write_Vs_abf(const TLRI& Vs, const std::string& file_path); - -template -struct is_std_array : std::false_type -{ -}; -template -struct is_std_array> : std::true_type -{ -}; -template -struct is_tensor : std::false_type -{ -}; -template -struct is_tensor> : std::true_type -{ -}; - -template -struct TinType; - -template -struct TinType> -{ - using type = T; -}; - -template -struct TinType, N>> -{ - using type = T; -}; - -template ::value>> -inline void init_elem(Tdata& data, const size_t ndim0, const size_t ndim1) -{ - data = Tdata({ndim0, ndim1}); -}; -template -extern void init_elem(std::array, N>& data, const size_t ndim0, const size_t ndim1); - -template ::value && !is_tensor::value>> -inline void add_elem(Tdata& data, const Tdata& val, const Tdata& frac) -{ - data += frac * val; -}; -template -extern void add_elem(std::array& data, const T& val, const T& frac); -template ::value>> -inline void add_elem(const Tdata& data, - const int lmp, - const int lmq, - const typename TinType::type& val, - const typename TinType::type& frac) -{ - data(lmp, lmq) += frac * val; -}; -template -extern void add_elem(std::array, N>& data, - const int lmp, - const int lmq, - const std::array& val, - const T& frac); -template ::value>> -inline void add_elem(Tdata& data, - const int lmp0, - const int lmq0, - const Tdata& val, - const int lmp1, - const int lmq1, - const typename TinType::type& frac) -{ - data(lmp0, lmq0) += frac * val(lmp1, lmq1); -}; -template -extern void add_elem(std::array, N>& data, - const int lmp0, - const int lmq0, - const std::array, N>& val, - const int lmp1, - const int lmq1, - const T& frac); - -template -inline RI::Tensor convert(RI::Tensor&& data); -template -extern std::array, N> convert(std::array, N>&& data); - -// template -// typename std::enable_if::value, T>::type -// inline check_zero(T value) { -// return (std::abs(value) < 1e-8) ? static_cast(0) : value; -// } - -// template -// typename std::enable_if::value, T>::type -// inline check_zero(const T& value) { -// using RealType = typename T::value_type; -// RealType real_part = std::real(value); -// RealType imag_part = std::imag(value); - -// real_part = (std::abs(real_part) < 1e-8) ? 0 : real_part; -// imag_part = (std::abs(imag_part) < 1e-8) ? 0 : imag_part; - -// return std::complex(real_part, imag_part); -// } - -// template -// extern RI::Tensor check_zero(RI::Tensor&& data); -// template -// extern std::array, N> check_zero(std::array, N>&& data); - -template -struct plus -{ - T operator()(const T& lhs, const T& rhs) const - { - using namespace RI::Array_Operator; - return lhs + rhs; - } -}; -} // namespace LRI_CV_Tools - -#include "LRI_CV_Tools.hpp" -#include "write_ri_cv.hpp" -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-10-24 +//======================= + +#ifndef LRI_CV_TOOLS_H +#define LRI_CV_TOOLS_H + +#include "Inverse_Matrix.h" +#include "abfs-vector3_order.h" +#include "source_lcao/module_ri/abfs.h" + +#include +#include +#include +#include +#include +#include + +namespace LRI_CV_Tools +{ +template +extern RI::Tensor cal_I(const RI::Tensor& m, + const typename Inverse_Matrix::Method method + = Inverse_Matrix::Method::potrf, + const double& threshold_condition_number = 0.); +template +extern std::vector>> cal_I(const std::vector>>& ms, + const typename Inverse_Matrix::Method method + = Inverse_Matrix::Method::potrf, + const double& threshold_condition_number = 0.); + +template +inline RI::Tensor transform_Rm(const RI::Tensor& V); +template +inline std::array, 3> transform_Rm(const std::array, 3>& dV); + +// template inline bool exist(const T &V); + +// template +// extern Treturn mul1(const T1 &t1, const T2 &t2); +// template +// extern Treturn mul2(const T1 &mat, const T2 &vec); + +template +inline bool exist(const RI::Tensor& V); +template +inline bool exist(const std::array& dV); + +template +extern RI::Tensor mul1(const RI::Tensor& t1, const RI::Tensor& t2); +template +extern std::array mul1(const std::array& t1, const T& t2); + +template +extern std::vector> mul2(const std::vector>>& mat, + const std::vector>& vec); +template +extern std::array mul2(const T1& t1, const std::array& t2); +template +extern RI::Tensor mul2(const T& t1, const RI::Tensor& t2); +template +extern std::map> mul2(const T& t1, const std::map>& t2); + +// template +// std::array operator-(const std::array &v1, const std::array +// &v2); template std::vector operator-(const std::vector &v1, +// const std::vector &v2); +template +extern std::vector> minus(const std::vector>& v1, + const std::vector>& v2); +template +extern std::array>, N> minus( + std::array>, N>& v1, + std::array>, N>& v2); +template +inline std::map>> minus( + std::map>>& v1, + std::map>>& v2); +template +extern std::map> minus(std::map>& v1, + std::map>& v2); + +template +extern std::vector> add(const std::vector>& v1, + const std::vector>& v2); +template +extern std::array>, N> add( + std::array>, N>& v1, + std::array>, N>& v2); +template +inline std::map>> add( + std::map>>& v1, + std::map>>& v2); +template +extern std::map> add(std::map>& v1, + std::map>& v2); + +template +extern std::array negative(const std::array& v_in); + +// template T transpose12(const T &c_in); +template +RI::Tensor transpose12(const RI::Tensor& c_in); +template +std::array transpose12(const std::array& c_in); + +template +extern std::array, N> change_order(std::vector>&& ds_in); +template +std::vector> change_order(std::array, N>&& ds_in); +template +extern std::array>, N> change_order(std::vector>>&& ds_in); +template +extern std::array>, N> change_order( + std::map>>&& ds_in); +template +extern std::map>> change_order( + std::array>, N>&& ds_in); + +template +extern std::array cal_latvec_range(const double& rcut_times, + const UnitCell& ucell, + const std::vector& orb_cutoff); + +template +extern std::map, RI::Tensor>>> get_CVws( + const UnitCell& ucell, + const std::map>, RI::Tensor>>& CVs); +template +extern std::map, std::array, 3>>>> get_dCVws( + const UnitCell& ucell, + const std::map>, std::array, 3>>>& dCVs); +template +extern std::array, RI::Tensor>>, 3>, 3> cal_dMRs( + const UnitCell& ucell, + const std::array, RI::Tensor>>, 3>& dMs); + +using TC = std::array; +using TAC = std::pair; +template +using TLRI = std::map>>; +template +TLRI read_Cs_ao(const std::string& file_path, const double& threshold = 1e-10); +template +void write_Cs_ao(const TLRI& Vs, const std::string& file_path); +template +TLRI read_Vs_abf(const std::string& file_path, const double& threshold = 1e-10); +template +void write_Vs_abf(const TLRI& Vs, const std::string& file_path); + +template +struct is_std_array : std::false_type +{ +}; +template +struct is_std_array> : std::true_type +{ +}; +template +struct is_tensor : std::false_type +{ +}; +template +struct is_tensor> : std::true_type +{ +}; + +template +struct TinType; + +template +struct TinType> +{ + using type = T; +}; + +template +struct TinType, N>> +{ + using type = T; +}; + +template ::value>> +inline void init_elem(Tdata& data, const size_t ndim0, const size_t ndim1) +{ + data = Tdata({ndim0, ndim1}); +}; +template +extern void init_elem(std::array, N>& data, const size_t ndim0, const size_t ndim1); + +template ::value && !is_tensor::value>> +inline void add_elem(Tdata& data, const Tdata& val, const Tdata& frac) +{ + data += frac * val; +}; +template +extern void add_elem(std::array& data, const T& val, const T& frac); +template ::value>> +inline void add_elem(const Tdata& data, + const int lmp, + const int lmq, + const typename TinType::type& val, + const typename TinType::type& frac) +{ + data(lmp, lmq) += frac * val; +}; +template +extern void add_elem(std::array, N>& data, + const int lmp, + const int lmq, + const std::array& val, + const T& frac); +template ::value>> +inline void add_elem(Tdata& data, + const int lmp0, + const int lmq0, + const Tdata& val, + const int lmp1, + const int lmq1, + const typename TinType::type& frac) +{ + data(lmp0, lmq0) += frac * val(lmp1, lmq1); +}; +template +extern void add_elem(std::array, N>& data, + const int lmp0, + const int lmq0, + const std::array, N>& val, + const int lmp1, + const int lmq1, + const T& frac); + +template +inline RI::Tensor convert(RI::Tensor&& data); +template +extern std::array, N> convert(std::array, N>&& data); + +// template +// typename std::enable_if::value, T>::type +// inline check_zero(T value) { +// return (std::abs(value) < 1e-8) ? static_cast(0) : value; +// } + +// template +// typename std::enable_if::value, T>::type +// inline check_zero(const T& value) { +// using RealType = typename T::value_type; +// RealType real_part = std::real(value); +// RealType imag_part = std::imag(value); + +// real_part = (std::abs(real_part) < 1e-8) ? 0 : real_part; +// imag_part = (std::abs(imag_part) < 1e-8) ? 0 : imag_part; + +// return std::complex(real_part, imag_part); +// } + +// template +// extern RI::Tensor check_zero(RI::Tensor&& data); +// template +// extern std::array, N> check_zero(std::array, N>&& data); + +template +struct plus +{ + T operator()(const T& lhs, const T& rhs) const + { + using namespace RI::Array_Operator; + return lhs + rhs; + } +}; +} // namespace LRI_CV_Tools + +#include "LRI_CV_Tools.hpp" +#include "write_ri_cv.hpp" +#endif diff --git a/source/source_lcao/module_ri/LRI_CV_Tools.hpp b/source/source_lcao/module_ri/LRI_CV_Tools.hpp index 110db1bf806..bbf393a6ec2 100644 --- a/source/source_lcao/module_ri/LRI_CV_Tools.hpp +++ b/source/source_lcao/module_ri/LRI_CV_Tools.hpp @@ -1,562 +1,562 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-10-24 -//======================= - -#ifndef LRI_CV_TOOLS_HPP -#define LRI_CV_TOOLS_HPP - -#include "../../source_base/mathzone.h" -#include "Inverse_Matrix.h" -#include "LRI_CV_Tools.h" -#include "RI_Util.h" - -#include -#include - -template -RI::Tensor LRI_CV_Tools::cal_I(const RI::Tensor& m, - const typename Inverse_Matrix::Method method, - const double& threshold_condition_number) -{ - Inverse_Matrix I; - I.input(m); - I.cal_inverse(method, threshold_condition_number); - return I.output(); -} - -template -std::vector>> LRI_CV_Tools::cal_I(const std::vector>>& ms, - const typename Inverse_Matrix::Method method, - const double& threshold_condition_number) -{ - Inverse_Matrix I; - I.input(ms); - I.cal_inverse(method, threshold_condition_number); - return I.output({ms[0][0].shape[0], ms[1][0].shape[0]}, {ms[0][0].shape[1], ms[0][1].shape[1]}); -} - -template -RI::Tensor LRI_CV_Tools::transform_Rm(const RI::Tensor& V) { - return V.transpose(); -} - -template -std::array, 3> - LRI_CV_Tools::transform_Rm(const std::array, 3>& dV) { - return std::array, 3>{-dV[0].transpose(), - -dV[1].transpose(), - -dV[2].transpose()}; -} - -template -bool LRI_CV_Tools::exist(const RI::Tensor& V) { - return !V.empty(); -} - -template -bool LRI_CV_Tools::exist(const std::array& dV) { - for (size_t i = 0; i < 3; ++i) - if (!dV[i].empty()) - return true; - return false; -} - -template -RI::Tensor LRI_CV_Tools::mul1(const RI::Tensor& t1, - const RI::Tensor& t2) { - const size_t sa0 = t1.shape[0], sa1 = t2.shape[0], sl0 = t2.shape[1], - sl1 = t2.shape[2]; - return (t1 * t2.reshape({sa1, sl0 * sl1})).reshape({sa0, sl0, sl1}); -} -template -std::array LRI_CV_Tools::mul1(const std::array& t1, const T& t2) { - return std::array{mul1(t1[0], t2), mul1(t1[1], t2), mul1(t1[2], t2)}; -} -/* -template -std::array LRI_CV_Tools::mul1( - const T &t1, - const std::array &t2) -{ - return std::array{ - mul1(t1,t2[0]), mul1(t1,t2[1]), mul1(t1,t2[2]) }; -} -*/ - -template -std::vector> - LRI_CV_Tools::mul2(const std::vector>>& mat, - const std::vector>& vec) { - const size_t sa0 = vec[0].shape[0], sa1 = vec[1].shape[0], - sl0 = vec[0].shape[1], sl1 = vec[0].shape[2]; - const RI::Tensor vec0 = vec[0].reshape({sa0, sl0 * sl1}), - vec1 = vec[1].reshape({sa1, sl0 * sl1}); - return std::vector>{ - (mat[0][0] * vec0 + mat[0][1] * vec1).reshape({sa0, sl0, sl1}), - (mat[1][0] * vec0 + mat[1][1] * vec1).reshape({sa1, sl0, sl1})}; -} -/* -template -std::array LRI_CV_Tools::mul2( - const std::array &t1, - const T2 &t2) -{ - return std::array{ - mul2(t1[0],t2), mul2(t1[1],t2), mul2(t1[2],t2) }; -} -*/ -template -std::array LRI_CV_Tools::mul2(const T1& t1, - const std::array& t2) { - return std::array{mul2(t1, t2[0]), mul2(t1, t2[1]), mul2(t1, t2[2])}; -} - -template -RI::Tensor LRI_CV_Tools::mul2(const T& t1, const RI::Tensor& t2) { - return t1 * t2; -} - -template -std::map> - LRI_CV_Tools::mul2(const T& t1, - const std::map>& t2) { - std::map> res; - for (const auto& outerPair: t2) { - const TkeyA keyA = outerPair.first; - const std::map& innerMap = outerPair.second; - std::map newInnerMap; - - for (const auto& innerPair: innerMap) { - const TkeyB keyB = innerPair.first; - const Tvalue value = innerPair.second; - newInnerMap[keyB] = mul2(t1, value); - } - - res[keyA] = newInnerMap; - } - - return res; -} - -/* -template -std::array LRI_CV_Tools::operator-(const std::array &v1, const -std::array &v2) -{ - std::array v; - for(std::size_t i=0; i -std::vector LRI_CV_Tools::operator-(const std::vector &v1, const -std::vector &v2) -{ - assert(v1.size()==v2.size()); - std::vector v(v1.size()); - for(std::size_t i=0; i -std::vector> - LRI_CV_Tools::minus(const std::vector>& v1, - const std::vector>& v2) { - assert(v1.size() == v2.size()); - std::vector> v(v1.size()); - for (std::size_t i = 0; i < v.size(); ++i) - for (std::size_t j = 0; j < N; ++j) - v[i][j] = v1[i][j] - v2[i][j]; - return v; -} - -template -std::map>> LRI_CV_Tools::minus( - std::map>>& v1, - std::map>>& v2) { - std::array>, N> v1_order - = change_order(std::move(v1)); - std::array>, N> v2_order - = change_order(std::move(v2)); - auto dv = minus(v1_order, v2_order); - return change_order(std::move(dv)); -} - -template -std::array>, N> LRI_CV_Tools::minus( - std::array>, N>& v1, - std::array>, N>& v2) { - std::array>, N> dv; - for (size_t i = 0; i != N; ++i) - dv[i] = minus(v1[i], v2[i]); - return dv; -} - -template -std::map> - LRI_CV_Tools::minus(std::map>& v1, - std::map>& v2) { - assert(v1.size() == v2.size()); - using namespace RI::Map_Operator; - using namespace RI::Array_Operator; - - std::map> dv; - auto it1 = v1.begin(); - auto it2 = v2.begin(); - while (it1 != v1.end() && it2 != v2.end()) { - assert(it1->first == it2->first); - const TkeyA& keyA = it1->first; - const std::map& map1 = it1->second; - const std::map& map2 = it2->second; - dv[keyA] = map1 - map2; - ++it1; - ++it2; - } - return dv; -} - -template -std::vector> - LRI_CV_Tools::add(const std::vector>& v1, - const std::vector>& v2) { - assert(v1.size() == v2.size()); - std::vector> v(v1.size()); - for (std::size_t i = 0; i < v.size(); ++i) - for (std::size_t j = 0; j < N; ++j) - v[i][j] = v1[i][j] + v2[i][j]; - return v; -} - -template -std::map>> LRI_CV_Tools::add( - std::map>>& v1, - std::map>>& v2) { - std::array>, N> v1_order - = change_order(std::move(v1)); - std::array>, N> v2_order - = change_order(std::move(v2)); - auto dv = add(v1_order, v2_order); - return change_order(std::move(dv)); -} - -template -std::array>, N> LRI_CV_Tools::add( - std::array>, N>& v1, - std::array>, N>& v2) { - std::array>, N> dv; - for (size_t i = 0; i != N; ++i) - dv[i] = add(v1[i], v2[i]); - return dv; -} - -template -std::map> - LRI_CV_Tools::add(std::map>& v1, - std::map>& v2) { - assert(v1.size() == v2.size()); - using namespace RI::Map_Operator; - using namespace RI::Array_Operator; - - std::map> dv; - auto it1 = v1.begin(); - auto it2 = v2.begin(); - while (it1 != v1.end() && it2 != v2.end()) { - assert(it1->first == it2->first); - const TkeyA& keyA = it1->first; - const std::map& map1 = it1->second; - const std::map& map2 = it2->second; - dv[keyA] = map1 + map2; - ++it1; - ++it2; - } - return dv; -} - -template -std::array LRI_CV_Tools::negative(const std::array& v_in) { - std::array v_out; - for (std::size_t i = 0; i < N; ++i) - v_out[i] = -v_in[i]; - return v_out; -} - -template -RI::Tensor LRI_CV_Tools::transpose12(const RI::Tensor& c_in) { - RI::Tensor c_out({c_in.shape[0], c_in.shape[2], c_in.shape[1]}); - for (size_t i0 = 0; i0 < c_in.shape[0]; ++i0) - for (size_t i1 = 0; i1 < c_in.shape[1]; ++i1) - for (size_t i2 = 0; i2 < c_in.shape[2]; ++i2) - c_out(i0, i2, i1) = c_in(i0, i1, i2); - return c_out; -} - -template -std::array LRI_CV_Tools::transpose12(const std::array& c_in) { - std::array c_out; - for (size_t i = 0; i < N; ++i) - c_out[i] = transpose12(c_in[i]); - return c_out; -} - -template -std::array, N> - LRI_CV_Tools::change_order(std::vector>&& ds_in) { - std::array, N> ds; - for (int ix = 0; ix < N; ++ix) { - ds[ix].resize(ds_in.size()); - for (int iv = 0; iv < ds_in.size(); ++iv) - ds[ix][iv] = std::move(ds_in[iv][ix]); - } - return ds; -} - -template -std::vector> - LRI_CV_Tools::change_order(std::array, N>&& ds_in) { - std::vector> ds(ds_in[0].size()); - for (int ix = 0; ix < N; ++ix) { - assert(ds.size() == ds_in[ix].size()); - for (int iv = 0; iv < ds.size(); ++iv) - ds[iv][ix] = std::move(ds_in[ix][iv]); - } - return ds; -} - -template -std::array>, N> LRI_CV_Tools::change_order( - std::vector>>&& ds_in) { - std::array>, N> ds; - for (int ix = 0; ix < N; ++ix) { - ds[ix].resize(ds_in.size()); - for (int i0 = 0; i0 < ds_in.size(); ++i0) { - ds[ix][i0].resize(ds_in[i0].size()); - for (int i1 = 0; i1 < ds_in[i0].size(); ++i1) - ds[ix][i0][i1] = std::move(ds_in[i0][i1][ix]); - } - } - return ds; -} - -template -std::array>, N> - LRI_CV_Tools::change_order( - std::map>>&& ds_in) { - std::array>, N> ds; - for (auto& ds_A: ds_in) - for (auto& ds_B: ds_A.second) - for (int ix = 0; ix < N; ++ix) - ds[ix][ds_A.first][ds_B.first] = std::move(ds_B.second[ix]); - return ds; -} - -template -std::map>> - LRI_CV_Tools::change_order( - std::array>, N>&& ds_in) { - std::map>> ds; - for (int ix = 0; ix < N; ++ix) - for (auto& ds_A: ds_in[ix]) - for (auto& ds_B: ds_A.second) - ds[ds_A.first][ds_B.first][ix] = std::move(ds_B.second); - return ds; -} - -template -std::array LRI_CV_Tools::cal_latvec_range(const double& rcut_times, - const UnitCell &ucell, - const std::vector& orb_cutoff) { - double Rcut_max = 0; - for(int T=0; T proj = ModuleBase::Mathzone::latvec_projection( - std::array,3>{ucell.a1, ucell.a2, ucell.a3}); - const ModuleBase::Vector3 latvec_times = Rcut_max * rcut_times / (proj * ucell.lat0); - const ModuleBase::Vector3 latvec_times_ceil = {static_cast(std::ceil(latvec_times.x)), - static_cast(std::ceil(latvec_times.y)), - static_cast(std::ceil(latvec_times.z))}; - const ModuleBase::Vector3 period = 2 * latvec_times_ceil + ModuleBase::Vector3{1,1,1}; - return std::array{period.x, period.y, period.z}; -} - -template -std::map,RI::Tensor>>> -LRI_CV_Tools::get_CVws( - const UnitCell &ucell, - const std::map>,RI::Tensor>> &CVs) -{ - std::map,RI::Tensor>>> CVws; - for(const auto &CVs_A : CVs) - { - const TA iat0 = CVs_A.first; - const int it0 = ucell.iat2it[iat0]; - const int ia0 = ucell.iat2ia[iat0]; - const ModuleBase::Vector3 tau0 = ucell.atoms[it0].tau[ia0]; - for(const auto &CVs_B : CVs_A.second) - { - const TA iat1 = CVs_B.first.first; - const int it1 = ucell.iat2it[iat1]; - const int ia1 = ucell.iat2ia[iat1]; - const std::array &cell1 = CVs_B.first.second; - const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; - const Abfs::Vector3_Order R_delta = -tau0+tau1+(RI_Util::array3_to_Vector3(cell1)*ucell.latvec); - CVws[it0][it1][R_delta] = CVs_B.second; - } - } - return CVws; -} - -template -std::map, std::array, 3>>>> LRI_CV_Tools:: - get_dCVws(const UnitCell& ucell, - const std::map>, std::array, 3>>>& dCVs) -{ - std::map, std::array, 3>>>> dCVws; - for (const auto& dCVs_A: dCVs) - { - const TA iat0 = dCVs_A.first; - const int it0 = ucell.iat2it[iat0]; - const int ia0 = ucell.iat2ia[iat0]; - const ModuleBase::Vector3 tau0 = ucell.atoms[it0].tau[ia0]; - for (const auto& dCVs_B: dCVs_A.second) - { - const TA iat1 = dCVs_B.first.first; - const int it1 = ucell.iat2it[iat1]; - const int ia1 = ucell.iat2ia[iat1]; - const std::array& cell1 = dCVs_B.first.second; - const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; - const Abfs::Vector3_Order R_delta - = -tau0 + tau1 + (RI_Util::array3_to_Vector3(cell1) * ucell.latvec); - dCVws[it0][it1][R_delta] = dCVs_B.second; - } - } - return dCVws; -} - -template -void LRI_CV_Tools::init_elem(std::array, N>& data, - const size_t ndim0, - const size_t ndim1) { - for (size_t i = 0; i < N; ++i) { - data[i] = RI::Tensor({ndim0, ndim1}); - } -} - -template -void LRI_CV_Tools::add_elem(std::array& data, - const T& val, - const T& frac) { - for (size_t i = 0; i < N; ++i) - data[i] += frac * val; -} - -template -void LRI_CV_Tools::add_elem(std::array, N>& data, - const int lmp, - const int lmq, - const std::array& val, - const T& frac) { - for (size_t i = 0; i < N; ++i) { - data[i](lmp, lmq) += frac * val[i]; - } -} - -template -void LRI_CV_Tools::add_elem(std::array, N>& data, - const int lmp0, - const int lmq0, - const std::array, N>& val, - const int lmp1, - const int lmq1, - const T& frac) { - for (size_t i = 0; i < N; ++i) { - data[i](lmp0, lmq0) += frac * val[i](lmp1, lmq1); - } -} - -template -RI::Tensor LRI_CV_Tools::convert(RI::Tensor&& data) { - return RI::Global_Func::convert(data); -} - -template -std::array, N> - LRI_CV_Tools::convert(std::array, N>&& data) { - std::array, N> out; - for (size_t i = 0; i != N; ++i) - out[i] = RI::Global_Func::convert(data[i]); - return out; -} - -// template -// RI::Tensor LRI_CV_Tools::check_zero(RI::Tensor&& data) { -// RI::Tensor result(data.shape); - -// const std::size_t rows = data.shape[0]; -// const std::size_t cols = data.shape[1]; - -// for (std::size_t i = 0; i < rows; ++i) { -// for (std::size_t j = 0; j < cols; ++j) { -// result(i, j) = LRI_CV_Tools::check_zero(data(i, j)); -// } -// } - -// return result; -// } - -// template -// std::array, N> -// LRI_CV_Tools::check_zero(std::array, N>&& data) { -// std::array, N> result; - -// for (size_t i = 0; i != N; ++i) -// result[i] = LRI_CV_Tools::check_zero(std::move(data[i])); - -// return result; -// } - - -// dMRs[ipos0][ipos1] = \nabla_{ipos0} M R_{ipos1} -template -std::array,RI::Tensor>>,3>,3> -LRI_CV_Tools::cal_dMRs( - const UnitCell &ucell, - const std::array,RI::Tensor>>,3> &dMs) -{ - auto get_R_delta = [&](const TA &iat0, const std::pair &A1) -> std::array - { - const TA iat1 = A1.first; - const TC &cell1 = A1.second; - const int it0 = ucell.iat2it[iat0]; - const int ia0 = ucell.iat2ia[iat0]; - const int it1 = ucell.iat2it[iat1]; - const int ia1 = ucell.iat2ia[iat1]; - const ModuleBase::Vector3 tau0 = ucell.atoms[it0].tau[ia0]; - const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; - const Abfs::Vector3_Order R_delta = -tau0+tau1+(RI_Util::array3_to_Vector3(cell1)*ucell.latvec); - return std::array{R_delta.x, R_delta.y, R_delta.z}; - }; - constexpr int Npos = 3; - std::array,RI::Tensor>>,Npos>,Npos> dMRs; - for(int ipos0=0; ipos0 A1 = dMs_B.first; - const RI::Tensor &dM = dMs_B.second; - const std::array R_delta = get_R_delta(iat0, A1); - dMRs[ipos0][ipos1][iat0][A1] = dM * R_delta[ipos1]; - } - } - } - } - return dMRs; -} - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-10-24 +//======================= + +#ifndef LRI_CV_TOOLS_HPP +#define LRI_CV_TOOLS_HPP + +#include "../../source_base/mathzone.h" +#include "Inverse_Matrix.h" +#include "LRI_CV_Tools.h" +#include "RI_Util.h" + +#include +#include + +template +RI::Tensor LRI_CV_Tools::cal_I(const RI::Tensor& m, + const typename Inverse_Matrix::Method method, + const double& threshold_condition_number) +{ + Inverse_Matrix I; + I.input(m); + I.cal_inverse(method, threshold_condition_number); + return I.output(); +} + +template +std::vector>> LRI_CV_Tools::cal_I(const std::vector>>& ms, + const typename Inverse_Matrix::Method method, + const double& threshold_condition_number) +{ + Inverse_Matrix I; + I.input(ms); + I.cal_inverse(method, threshold_condition_number); + return I.output({ms[0][0].shape[0], ms[1][0].shape[0]}, {ms[0][0].shape[1], ms[0][1].shape[1]}); +} + +template +RI::Tensor LRI_CV_Tools::transform_Rm(const RI::Tensor& V) { + return V.transpose(); +} + +template +std::array, 3> + LRI_CV_Tools::transform_Rm(const std::array, 3>& dV) { + return std::array, 3>{-dV[0].transpose(), + -dV[1].transpose(), + -dV[2].transpose()}; +} + +template +bool LRI_CV_Tools::exist(const RI::Tensor& V) { + return !V.empty(); +} + +template +bool LRI_CV_Tools::exist(const std::array& dV) { + for (size_t i = 0; i < 3; ++i) + if (!dV[i].empty()) + return true; + return false; +} + +template +RI::Tensor LRI_CV_Tools::mul1(const RI::Tensor& t1, + const RI::Tensor& t2) { + const size_t sa0 = t1.shape[0], sa1 = t2.shape[0], sl0 = t2.shape[1], + sl1 = t2.shape[2]; + return (t1 * t2.reshape({sa1, sl0 * sl1})).reshape({sa0, sl0, sl1}); +} +template +std::array LRI_CV_Tools::mul1(const std::array& t1, const T& t2) { + return std::array{mul1(t1[0], t2), mul1(t1[1], t2), mul1(t1[2], t2)}; +} +/* +template +std::array LRI_CV_Tools::mul1( + const T &t1, + const std::array &t2) +{ + return std::array{ + mul1(t1,t2[0]), mul1(t1,t2[1]), mul1(t1,t2[2]) }; +} +*/ + +template +std::vector> + LRI_CV_Tools::mul2(const std::vector>>& mat, + const std::vector>& vec) { + const size_t sa0 = vec[0].shape[0], sa1 = vec[1].shape[0], + sl0 = vec[0].shape[1], sl1 = vec[0].shape[2]; + const RI::Tensor vec0 = vec[0].reshape({sa0, sl0 * sl1}), + vec1 = vec[1].reshape({sa1, sl0 * sl1}); + return std::vector>{ + (mat[0][0] * vec0 + mat[0][1] * vec1).reshape({sa0, sl0, sl1}), + (mat[1][0] * vec0 + mat[1][1] * vec1).reshape({sa1, sl0, sl1})}; +} +/* +template +std::array LRI_CV_Tools::mul2( + const std::array &t1, + const T2 &t2) +{ + return std::array{ + mul2(t1[0],t2), mul2(t1[1],t2), mul2(t1[2],t2) }; +} +*/ +template +std::array LRI_CV_Tools::mul2(const T1& t1, + const std::array& t2) { + return std::array{mul2(t1, t2[0]), mul2(t1, t2[1]), mul2(t1, t2[2])}; +} + +template +RI::Tensor LRI_CV_Tools::mul2(const T& t1, const RI::Tensor& t2) { + return t1 * t2; +} + +template +std::map> + LRI_CV_Tools::mul2(const T& t1, + const std::map>& t2) { + std::map> res; + for (const auto& outerPair: t2) { + const TkeyA keyA = outerPair.first; + const std::map& innerMap = outerPair.second; + std::map newInnerMap; + + for (const auto& innerPair: innerMap) { + const TkeyB keyB = innerPair.first; + const Tvalue value = innerPair.second; + newInnerMap[keyB] = mul2(t1, value); + } + + res[keyA] = newInnerMap; + } + + return res; +} + +/* +template +std::array LRI_CV_Tools::operator-(const std::array &v1, const +std::array &v2) +{ + std::array v; + for(std::size_t i=0; i +std::vector LRI_CV_Tools::operator-(const std::vector &v1, const +std::vector &v2) +{ + assert(v1.size()==v2.size()); + std::vector v(v1.size()); + for(std::size_t i=0; i +std::vector> + LRI_CV_Tools::minus(const std::vector>& v1, + const std::vector>& v2) { + assert(v1.size() == v2.size()); + std::vector> v(v1.size()); + for (std::size_t i = 0; i < v.size(); ++i) + for (std::size_t j = 0; j < N; ++j) + v[i][j] = v1[i][j] - v2[i][j]; + return v; +} + +template +std::map>> LRI_CV_Tools::minus( + std::map>>& v1, + std::map>>& v2) { + std::array>, N> v1_order + = change_order(std::move(v1)); + std::array>, N> v2_order + = change_order(std::move(v2)); + auto dv = minus(v1_order, v2_order); + return change_order(std::move(dv)); +} + +template +std::array>, N> LRI_CV_Tools::minus( + std::array>, N>& v1, + std::array>, N>& v2) { + std::array>, N> dv; + for (size_t i = 0; i != N; ++i) + dv[i] = minus(v1[i], v2[i]); + return dv; +} + +template +std::map> + LRI_CV_Tools::minus(std::map>& v1, + std::map>& v2) { + assert(v1.size() == v2.size()); + using namespace RI::Map_Operator; + using namespace RI::Array_Operator; + + std::map> dv; + auto it1 = v1.begin(); + auto it2 = v2.begin(); + while (it1 != v1.end() && it2 != v2.end()) { + assert(it1->first == it2->first); + const TkeyA& keyA = it1->first; + const std::map& map1 = it1->second; + const std::map& map2 = it2->second; + dv[keyA] = map1 - map2; + ++it1; + ++it2; + } + return dv; +} + +template +std::vector> + LRI_CV_Tools::add(const std::vector>& v1, + const std::vector>& v2) { + assert(v1.size() == v2.size()); + std::vector> v(v1.size()); + for (std::size_t i = 0; i < v.size(); ++i) + for (std::size_t j = 0; j < N; ++j) + v[i][j] = v1[i][j] + v2[i][j]; + return v; +} + +template +std::map>> LRI_CV_Tools::add( + std::map>>& v1, + std::map>>& v2) { + std::array>, N> v1_order + = change_order(std::move(v1)); + std::array>, N> v2_order + = change_order(std::move(v2)); + auto dv = add(v1_order, v2_order); + return change_order(std::move(dv)); +} + +template +std::array>, N> LRI_CV_Tools::add( + std::array>, N>& v1, + std::array>, N>& v2) { + std::array>, N> dv; + for (size_t i = 0; i != N; ++i) + dv[i] = add(v1[i], v2[i]); + return dv; +} + +template +std::map> + LRI_CV_Tools::add(std::map>& v1, + std::map>& v2) { + assert(v1.size() == v2.size()); + using namespace RI::Map_Operator; + using namespace RI::Array_Operator; + + std::map> dv; + auto it1 = v1.begin(); + auto it2 = v2.begin(); + while (it1 != v1.end() && it2 != v2.end()) { + assert(it1->first == it2->first); + const TkeyA& keyA = it1->first; + const std::map& map1 = it1->second; + const std::map& map2 = it2->second; + dv[keyA] = map1 + map2; + ++it1; + ++it2; + } + return dv; +} + +template +std::array LRI_CV_Tools::negative(const std::array& v_in) { + std::array v_out; + for (std::size_t i = 0; i < N; ++i) + v_out[i] = -v_in[i]; + return v_out; +} + +template +RI::Tensor LRI_CV_Tools::transpose12(const RI::Tensor& c_in) { + RI::Tensor c_out({c_in.shape[0], c_in.shape[2], c_in.shape[1]}); + for (size_t i0 = 0; i0 < c_in.shape[0]; ++i0) + for (size_t i1 = 0; i1 < c_in.shape[1]; ++i1) + for (size_t i2 = 0; i2 < c_in.shape[2]; ++i2) + c_out(i0, i2, i1) = c_in(i0, i1, i2); + return c_out; +} + +template +std::array LRI_CV_Tools::transpose12(const std::array& c_in) { + std::array c_out; + for (size_t i = 0; i < N; ++i) + c_out[i] = transpose12(c_in[i]); + return c_out; +} + +template +std::array, N> + LRI_CV_Tools::change_order(std::vector>&& ds_in) { + std::array, N> ds; + for (int ix = 0; ix < N; ++ix) { + ds[ix].resize(ds_in.size()); + for (int iv = 0; iv < ds_in.size(); ++iv) + ds[ix][iv] = std::move(ds_in[iv][ix]); + } + return ds; +} + +template +std::vector> + LRI_CV_Tools::change_order(std::array, N>&& ds_in) { + std::vector> ds(ds_in[0].size()); + for (int ix = 0; ix < N; ++ix) { + assert(ds.size() == ds_in[ix].size()); + for (int iv = 0; iv < ds.size(); ++iv) + ds[iv][ix] = std::move(ds_in[ix][iv]); + } + return ds; +} + +template +std::array>, N> LRI_CV_Tools::change_order( + std::vector>>&& ds_in) { + std::array>, N> ds; + for (int ix = 0; ix < N; ++ix) { + ds[ix].resize(ds_in.size()); + for (int i0 = 0; i0 < ds_in.size(); ++i0) { + ds[ix][i0].resize(ds_in[i0].size()); + for (int i1 = 0; i1 < ds_in[i0].size(); ++i1) + ds[ix][i0][i1] = std::move(ds_in[i0][i1][ix]); + } + } + return ds; +} + +template +std::array>, N> + LRI_CV_Tools::change_order( + std::map>>&& ds_in) { + std::array>, N> ds; + for (auto& ds_A: ds_in) + for (auto& ds_B: ds_A.second) + for (int ix = 0; ix < N; ++ix) + ds[ix][ds_A.first][ds_B.first] = std::move(ds_B.second[ix]); + return ds; +} + +template +std::map>> + LRI_CV_Tools::change_order( + std::array>, N>&& ds_in) { + std::map>> ds; + for (int ix = 0; ix < N; ++ix) + for (auto& ds_A: ds_in[ix]) + for (auto& ds_B: ds_A.second) + ds[ds_A.first][ds_B.first][ix] = std::move(ds_B.second); + return ds; +} + +template +std::array LRI_CV_Tools::cal_latvec_range(const double& rcut_times, + const UnitCell &ucell, + const std::vector& orb_cutoff) { + double Rcut_max = 0; + for(int T=0; T proj = ModuleBase::Mathzone::latvec_projection( + std::array,3>{ucell.a1, ucell.a2, ucell.a3}); + const ModuleBase::Vector3 latvec_times = Rcut_max * rcut_times / (proj * ucell.lat0); + const ModuleBase::Vector3 latvec_times_ceil = {static_cast(std::ceil(latvec_times.x)), + static_cast(std::ceil(latvec_times.y)), + static_cast(std::ceil(latvec_times.z))}; + const ModuleBase::Vector3 period = 2 * latvec_times_ceil + ModuleBase::Vector3{1,1,1}; + return std::array{period.x, period.y, period.z}; +} + +template +std::map,RI::Tensor>>> +LRI_CV_Tools::get_CVws( + const UnitCell &ucell, + const std::map>,RI::Tensor>> &CVs) +{ + std::map,RI::Tensor>>> CVws; + for(const auto &CVs_A : CVs) + { + const TA iat0 = CVs_A.first; + const int it0 = ucell.iat2it[iat0]; + const int ia0 = ucell.iat2ia[iat0]; + const ModuleBase::Vector3 tau0 = ucell.atoms[it0].tau[ia0]; + for(const auto &CVs_B : CVs_A.second) + { + const TA iat1 = CVs_B.first.first; + const int it1 = ucell.iat2it[iat1]; + const int ia1 = ucell.iat2ia[iat1]; + const std::array &cell1 = CVs_B.first.second; + const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; + const Abfs::Vector3_Order R_delta = -tau0+tau1+(RI_Util::array3_to_Vector3(cell1)*ucell.latvec); + CVws[it0][it1][R_delta] = CVs_B.second; + } + } + return CVws; +} + +template +std::map, std::array, 3>>>> LRI_CV_Tools:: + get_dCVws(const UnitCell& ucell, + const std::map>, std::array, 3>>>& dCVs) +{ + std::map, std::array, 3>>>> dCVws; + for (const auto& dCVs_A: dCVs) + { + const TA iat0 = dCVs_A.first; + const int it0 = ucell.iat2it[iat0]; + const int ia0 = ucell.iat2ia[iat0]; + const ModuleBase::Vector3 tau0 = ucell.atoms[it0].tau[ia0]; + for (const auto& dCVs_B: dCVs_A.second) + { + const TA iat1 = dCVs_B.first.first; + const int it1 = ucell.iat2it[iat1]; + const int ia1 = ucell.iat2ia[iat1]; + const std::array& cell1 = dCVs_B.first.second; + const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; + const Abfs::Vector3_Order R_delta + = -tau0 + tau1 + (RI_Util::array3_to_Vector3(cell1) * ucell.latvec); + dCVws[it0][it1][R_delta] = dCVs_B.second; + } + } + return dCVws; +} + +template +void LRI_CV_Tools::init_elem(std::array, N>& data, + const size_t ndim0, + const size_t ndim1) { + for (size_t i = 0; i < N; ++i) { + data[i] = RI::Tensor({ndim0, ndim1}); + } +} + +template +void LRI_CV_Tools::add_elem(std::array& data, + const T& val, + const T& frac) { + for (size_t i = 0; i < N; ++i) + data[i] += frac * val; +} + +template +void LRI_CV_Tools::add_elem(std::array, N>& data, + const int lmp, + const int lmq, + const std::array& val, + const T& frac) { + for (size_t i = 0; i < N; ++i) { + data[i](lmp, lmq) += frac * val[i]; + } +} + +template +void LRI_CV_Tools::add_elem(std::array, N>& data, + const int lmp0, + const int lmq0, + const std::array, N>& val, + const int lmp1, + const int lmq1, + const T& frac) { + for (size_t i = 0; i < N; ++i) { + data[i](lmp0, lmq0) += frac * val[i](lmp1, lmq1); + } +} + +template +RI::Tensor LRI_CV_Tools::convert(RI::Tensor&& data) { + return RI::Global_Func::convert(data); +} + +template +std::array, N> + LRI_CV_Tools::convert(std::array, N>&& data) { + std::array, N> out; + for (size_t i = 0; i != N; ++i) + out[i] = RI::Global_Func::convert(data[i]); + return out; +} + +// template +// RI::Tensor LRI_CV_Tools::check_zero(RI::Tensor&& data) { +// RI::Tensor result(data.shape); + +// const std::size_t rows = data.shape[0]; +// const std::size_t cols = data.shape[1]; + +// for (std::size_t i = 0; i < rows; ++i) { +// for (std::size_t j = 0; j < cols; ++j) { +// result(i, j) = LRI_CV_Tools::check_zero(data(i, j)); +// } +// } + +// return result; +// } + +// template +// std::array, N> +// LRI_CV_Tools::check_zero(std::array, N>&& data) { +// std::array, N> result; + +// for (size_t i = 0; i != N; ++i) +// result[i] = LRI_CV_Tools::check_zero(std::move(data[i])); + +// return result; +// } + + +// dMRs[ipos0][ipos1] = \nabla_{ipos0} M R_{ipos1} +template +std::array,RI::Tensor>>,3>,3> +LRI_CV_Tools::cal_dMRs( + const UnitCell &ucell, + const std::array,RI::Tensor>>,3> &dMs) +{ + auto get_R_delta = [&](const TA &iat0, const std::pair &A1) -> std::array + { + const TA iat1 = A1.first; + const TC &cell1 = A1.second; + const int it0 = ucell.iat2it[iat0]; + const int ia0 = ucell.iat2ia[iat0]; + const int it1 = ucell.iat2it[iat1]; + const int ia1 = ucell.iat2ia[iat1]; + const ModuleBase::Vector3 tau0 = ucell.atoms[it0].tau[ia0]; + const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; + const Abfs::Vector3_Order R_delta = -tau0+tau1+(RI_Util::array3_to_Vector3(cell1)*ucell.latvec); + return std::array{R_delta.x, R_delta.y, R_delta.z}; + }; + constexpr int Npos = 3; + std::array,RI::Tensor>>,Npos>,Npos> dMRs; + for(int ipos0=0; ipos0 A1 = dMs_B.first; + const RI::Tensor &dM = dMs_B.second; + const std::array R_delta = get_R_delta(iat0, A1); + dMRs[ipos0][ipos1][iat0][A1] = dM * R_delta[ipos1]; + } + } + } + } + return dMRs; +} + +#endif diff --git a/source/source_lcao/module_ri/Matrix_Orbs22.hpp b/source/source_lcao/module_ri/Matrix_Orbs22.hpp index c7a6c155840..2e63ac77398 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs22.hpp +++ b/source/source_lcao/module_ri/Matrix_Orbs22.hpp @@ -1,312 +1,312 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2023-02-23 -//======================= - -#ifndef MATRIX_ORB22_HPP -#define MATRIX_ORB22_HPP - -#include "Matrix_Orbs22.h" -#include "RI_Util.h" - -template -RI::Tensor Matrix_Orbs22::cal_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3 &tauA, - const ModuleBase::Vector3 &tauB, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B2, - const Matrix_Order &matrix_order) const -{ - const double lat0 = *this->lat0; - RI::Tensor m; - const size_t sizeA1 = index_A1[TA].count_size; - const size_t sizeA2 = index_A2[TA].count_size; - const size_t sizeB1 = index_B1[TB].count_size; - const size_t sizeB2 = index_B2[TB].count_size; - switch(matrix_order) - { - case Matrix_Order::A1A2B1B2: m = RI::Tensor({sizeA1, sizeA2, sizeB1, sizeB2}); break; - case Matrix_Order::A1A2B2B1: m = RI::Tensor({sizeA1, sizeA2, sizeB2, sizeB1}); break; - case Matrix_Order::A1B1A2B2: m = RI::Tensor({sizeA1, sizeB1, sizeA2, sizeB2}); break; - case Matrix_Order::A1B1B2A2: m = RI::Tensor({sizeA1, sizeB1, sizeB2, sizeA2}); break; - case Matrix_Order::A1B2A2B1: m = RI::Tensor({sizeA1, sizeB2, sizeA2, sizeB1}); break; - case Matrix_Order::A1B2B1A2: m = RI::Tensor({sizeA1, sizeB2, sizeB1, sizeA2}); break; - case Matrix_Order::A2A1B1B2: m = RI::Tensor({sizeA2, sizeA1, sizeB1, sizeB2}); break; - case Matrix_Order::A2A1B2B1: m = RI::Tensor({sizeA2, sizeA1, sizeB2, sizeB1}); break; - case Matrix_Order::A2B1A1B2: m = RI::Tensor({sizeA2, sizeB1, sizeA1, sizeB2}); break; - case Matrix_Order::A2B1B2A1: m = RI::Tensor({sizeA2, sizeB1, sizeB2, sizeA1}); break; - case Matrix_Order::A2B2A1B1: m = RI::Tensor({sizeA2, sizeB2, sizeA1, sizeB1}); break; - case Matrix_Order::A2B2B1A1: m = RI::Tensor({sizeA2, sizeB2, sizeB1, sizeA1}); break; - case Matrix_Order::B1A1A2B2: m = RI::Tensor({sizeB1, sizeA1, sizeA2, sizeB2}); break; - case Matrix_Order::B1A1B2A2: m = RI::Tensor({sizeB1, sizeA1, sizeB2, sizeA2}); break; - case Matrix_Order::B1A2A1B2: m = RI::Tensor({sizeB1, sizeA2, sizeA1, sizeB2}); break; - case Matrix_Order::B1A2B2A1: m = RI::Tensor({sizeB1, sizeA2, sizeB2, sizeA1}); break; - case Matrix_Order::B1B2A1A2: m = RI::Tensor({sizeB1, sizeB2, sizeA1, sizeA2}); break; - case Matrix_Order::B1B2A2A1: m = RI::Tensor({sizeB1, sizeB2, sizeA2, sizeA1}); break; - case Matrix_Order::B2A1A2B1: m = RI::Tensor({sizeB2, sizeA1, sizeA2, sizeB1}); break; - case Matrix_Order::B2A1B1A2: m = RI::Tensor({sizeB2, sizeA1, sizeB1, sizeA2}); break; - case Matrix_Order::B2A2A1B1: m = RI::Tensor({sizeB2, sizeA2, sizeA1, sizeB1}); break; - case Matrix_Order::B2A2B1A1: m = RI::Tensor({sizeB2, sizeA2, sizeB1, sizeA1}); break; - case Matrix_Order::B2B1A1A2: m = RI::Tensor({sizeB2, sizeB1, sizeA1, sizeA2}); break; - case Matrix_Order::B2B1A2A1: m = RI::Tensor({sizeB2, sizeB1, sizeA2, sizeA1}); break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - - for( const auto &co3 : center2_orb22_s.at(TA).at(TB) ) - { - const int LA1 = co3.first; - for( const auto &co4 : co3.second ) - { - const size_t NA1 = co4.first; - for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) - { - for( const auto &co5 : co4.second ) - { - const int LA2 = co5.first; - for( const auto &co6 : co5.second ) - { - const size_t NA2 = co6.first; - for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) - { - for( const auto &co7 : co6.second ) - { - const int LB1 = co7.first; - for( const auto &co8 : co7.second ) - { - const size_t NB1 = co8.first; - for( size_t MB1=0; MB1!=2*LB1+1; ++MB1 ) - { - for( const auto &co9 : co8.second ) - { - const int LB2 = co9.first; - for( const auto &co10 : co9.second ) - { - const size_t NB2 = co10.first; - for( size_t MB2=0; MB2!=2*LB2+1; ++MB2 ) - { - const Tdata overlap = co10.second.cal_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB1, MB2 ); - const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; - const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; - const size_t iB1 = index_B1[TB][LB1][NB1][MB1]; - const size_t iB2 = index_B2[TB][LB2][NB2][MB2]; - switch(matrix_order) - { - case Matrix_Order::A1A2B1B2: m(iA1,iA2,iB1,iB2) = overlap; break; - case Matrix_Order::A1A2B2B1: m(iA1,iA2,iB2,iB1) = overlap; break; - case Matrix_Order::A1B1A2B2: m(iA1,iB1,iA2,iB2) = overlap; break; - case Matrix_Order::A1B1B2A2: m(iA1,iB1,iB2,iA2) = overlap; break; - case Matrix_Order::A1B2A2B1: m(iA1,iB2,iA2,iB1) = overlap; break; - case Matrix_Order::A1B2B1A2: m(iA1,iB2,iB1,iA2) = overlap; break; - case Matrix_Order::A2A1B1B2: m(iA2,iA1,iB1,iB2) = overlap; break; - case Matrix_Order::A2A1B2B1: m(iA2,iA1,iB2,iB1) = overlap; break; - case Matrix_Order::A2B1A1B2: m(iA2,iB1,iA1,iB2) = overlap; break; - case Matrix_Order::A2B1B2A1: m(iA2,iB1,iB2,iA1) = overlap; break; - case Matrix_Order::A2B2A1B1: m(iA2,iB2,iA1,iB1) = overlap; break; - case Matrix_Order::A2B2B1A1: m(iA2,iB2,iB1,iA1) = overlap; break; - case Matrix_Order::B1A1A2B2: m(iB1,iA1,iA2,iB2) = overlap; break; - case Matrix_Order::B1A1B2A2: m(iB1,iA1,iB2,iA2) = overlap; break; - case Matrix_Order::B1A2A1B2: m(iB1,iA2,iA1,iB2) = overlap; break; - case Matrix_Order::B1A2B2A1: m(iB1,iA2,iB2,iA1) = overlap; break; - case Matrix_Order::B1B2A1A2: m(iB1,iB2,iA1,iA2) = overlap; break; - case Matrix_Order::B1B2A2A1: m(iB1,iB2,iA2,iA1) = overlap; break; - case Matrix_Order::B2A1A2B1: m(iB2,iA1,iA2,iB1) = overlap; break; - case Matrix_Order::B2A1B1A2: m(iB2,iA1,iB1,iA2) = overlap; break; - case Matrix_Order::B2A2A1B1: m(iB2,iA2,iA1,iB1) = overlap; break; - case Matrix_Order::B2A2B1A1: m(iB2,iA2,iB1,iA1) = overlap; break; - case Matrix_Order::B2B1A1A2: m(iB2,iB1,iA1,iA2) = overlap; break; - case Matrix_Order::B2B1A2A1: m(iB2,iB1,iA2,iA1) = overlap; break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - } - } - } - } - } - } - } - } - } - } - } - } - return m; -} - -template -std::array,3> Matrix_Orbs22::cal_grad_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3 &tauA, - const ModuleBase::Vector3 &tauB, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B2, - const Matrix_Order &matrix_order) const -{ - std::array,3> m; - const size_t sizeA1 = index_A1[TA].count_size; - const size_t sizeA2 = index_A2[TA].count_size; - const size_t sizeB1 = index_B1[TB].count_size; - const size_t sizeB2 = index_B2[TB].count_size; - for(int i=0; i({sizeA1, sizeA2, sizeB1, sizeB2}); break; - case Matrix_Order::A1A2B2B1: m[i] = RI::Tensor({sizeA1, sizeA2, sizeB2, sizeB1}); break; - case Matrix_Order::A1B1A2B2: m[i] = RI::Tensor({sizeA1, sizeB1, sizeA2, sizeB2}); break; - case Matrix_Order::A1B1B2A2: m[i] = RI::Tensor({sizeA1, sizeB1, sizeB2, sizeA2}); break; - case Matrix_Order::A1B2A2B1: m[i] = RI::Tensor({sizeA1, sizeB2, sizeA2, sizeB1}); break; - case Matrix_Order::A1B2B1A2: m[i] = RI::Tensor({sizeA1, sizeB2, sizeB1, sizeA2}); break; - case Matrix_Order::A2A1B1B2: m[i] = RI::Tensor({sizeA2, sizeA1, sizeB1, sizeB2}); break; - case Matrix_Order::A2A1B2B1: m[i] = RI::Tensor({sizeA2, sizeA1, sizeB2, sizeB1}); break; - case Matrix_Order::A2B1A1B2: m[i] = RI::Tensor({sizeA2, sizeB1, sizeA1, sizeB2}); break; - case Matrix_Order::A2B1B2A1: m[i] = RI::Tensor({sizeA2, sizeB1, sizeB2, sizeA1}); break; - case Matrix_Order::A2B2A1B1: m[i] = RI::Tensor({sizeA2, sizeB2, sizeA1, sizeB1}); break; - case Matrix_Order::A2B2B1A1: m[i] = RI::Tensor({sizeA2, sizeB2, sizeB1, sizeA1}); break; - case Matrix_Order::B1A1A2B2: m[i] = RI::Tensor({sizeB1, sizeA1, sizeA2, sizeB2}); break; - case Matrix_Order::B1A1B2A2: m[i] = RI::Tensor({sizeB1, sizeA1, sizeB2, sizeA2}); break; - case Matrix_Order::B1A2A1B2: m[i] = RI::Tensor({sizeB1, sizeA2, sizeA1, sizeB2}); break; - case Matrix_Order::B1A2B2A1: m[i] = RI::Tensor({sizeB1, sizeA2, sizeB2, sizeA1}); break; - case Matrix_Order::B1B2A1A2: m[i] = RI::Tensor({sizeB1, sizeB2, sizeA1, sizeA2}); break; - case Matrix_Order::B1B2A2A1: m[i] = RI::Tensor({sizeB1, sizeB2, sizeA2, sizeA1}); break; - case Matrix_Order::B2A1A2B1: m[i] = RI::Tensor({sizeB2, sizeA1, sizeA2, sizeB1}); break; - case Matrix_Order::B2A1B1A2: m[i] = RI::Tensor({sizeB2, sizeA1, sizeB1, sizeA2}); break; - case Matrix_Order::B2A2A1B1: m[i] = RI::Tensor({sizeB2, sizeA2, sizeA1, sizeB1}); break; - case Matrix_Order::B2A2B1A1: m[i] = RI::Tensor({sizeB2, sizeA2, sizeB1, sizeA1}); break; - case Matrix_Order::B2B1A1A2: m[i] = RI::Tensor({sizeB2, sizeB1, sizeA1, sizeA2}); break; - case Matrix_Order::B2B1A2A1: m[i] = RI::Tensor({sizeB2, sizeB1, sizeA2, sizeA1}); break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - } - const double lat0 = *this->lat0; - for( const auto &co3 : center2_orb22_s.at(TA).at(TB) ) - { - const int LA1 = co3.first; - for( const auto &co4 : co3.second ) - { - const size_t NA1 = co4.first; - for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) - { - for( const auto &co5 : co4.second ) - { - const int LA2 = co5.first; - for( const auto &co6 : co5.second ) - { - const size_t NA2 = co6.first; - for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) - { - for( const auto &co7 : co6.second ) - { - const int LB1 = co7.first; - for( const auto &co8 : co7.second ) - { - const size_t NB1 = co8.first; - for( size_t MB1=0; MB1!=2*LB1+1; ++MB1 ) - { - for( const auto &co9 : co8.second ) - { - const int LB2 = co9.first; - for( const auto &co10 : co9.second ) - { - const size_t NB2 = co10.first; - for( size_t MB2=0; MB2!=2*LB2+1; ++MB2 ) - { - const std::array grad_overlap = RI_Util::Vector3_to_array3(co10.second.cal_grad_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB1, MB2 )); - const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; - const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; - const size_t iB1 = index_B1[TB][LB1][NB1][MB1]; - const size_t iB2 = index_B2[TB][LB2][NB2][MB2]; - for(size_t i=0; i -std::map < size_t, std::map>>>> Matrix_Orbs22::cal_overlap_matrix_all( - const UnitCell &ucell, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B2 ) const -{ - std::map>>>> matrixes; - - for( const auto &co1 : center2_orb22_s ) - { - const size_t TA = co1.first; - for( size_t IA=0; IA!=ucell.atoms[TA].na; ++IA ) - { - const ModuleBase::Vector3 &tauA( ucell.atoms[TA].tau[IA] ); - - for( const auto &co2 : co1.second ) - { - const size_t TB = co2.first; - for( size_t IB=0; IB!=ucell.atoms[TB].na; ++IB ) - { - const ModuleBase::Vector3 &tauB( ucell.atoms[TB].tau[IB] ); - - matrixes[TA][IA][TB][IB] = cal_overlap_matrix( - TA, - TB, - ucell.atoms[TA].tau[IA], - ucell.atoms[TB].tau[IB], - index_A1, - index_A2, - index_B1, - index_B2, - Matrix_Order::A1B1A2B2); - } - } - } - } - return matrixes; -} -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2023-02-23 +//======================= + +#ifndef MATRIX_ORB22_HPP +#define MATRIX_ORB22_HPP + +#include "Matrix_Orbs22.h" +#include "RI_Util.h" + +template +RI::Tensor Matrix_Orbs22::cal_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3 &tauA, + const ModuleBase::Vector3 &tauB, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B2, + const Matrix_Order &matrix_order) const +{ + const double lat0 = *this->lat0; + RI::Tensor m; + const size_t sizeA1 = index_A1[TA].count_size; + const size_t sizeA2 = index_A2[TA].count_size; + const size_t sizeB1 = index_B1[TB].count_size; + const size_t sizeB2 = index_B2[TB].count_size; + switch(matrix_order) + { + case Matrix_Order::A1A2B1B2: m = RI::Tensor({sizeA1, sizeA2, sizeB1, sizeB2}); break; + case Matrix_Order::A1A2B2B1: m = RI::Tensor({sizeA1, sizeA2, sizeB2, sizeB1}); break; + case Matrix_Order::A1B1A2B2: m = RI::Tensor({sizeA1, sizeB1, sizeA2, sizeB2}); break; + case Matrix_Order::A1B1B2A2: m = RI::Tensor({sizeA1, sizeB1, sizeB2, sizeA2}); break; + case Matrix_Order::A1B2A2B1: m = RI::Tensor({sizeA1, sizeB2, sizeA2, sizeB1}); break; + case Matrix_Order::A1B2B1A2: m = RI::Tensor({sizeA1, sizeB2, sizeB1, sizeA2}); break; + case Matrix_Order::A2A1B1B2: m = RI::Tensor({sizeA2, sizeA1, sizeB1, sizeB2}); break; + case Matrix_Order::A2A1B2B1: m = RI::Tensor({sizeA2, sizeA1, sizeB2, sizeB1}); break; + case Matrix_Order::A2B1A1B2: m = RI::Tensor({sizeA2, sizeB1, sizeA1, sizeB2}); break; + case Matrix_Order::A2B1B2A1: m = RI::Tensor({sizeA2, sizeB1, sizeB2, sizeA1}); break; + case Matrix_Order::A2B2A1B1: m = RI::Tensor({sizeA2, sizeB2, sizeA1, sizeB1}); break; + case Matrix_Order::A2B2B1A1: m = RI::Tensor({sizeA2, sizeB2, sizeB1, sizeA1}); break; + case Matrix_Order::B1A1A2B2: m = RI::Tensor({sizeB1, sizeA1, sizeA2, sizeB2}); break; + case Matrix_Order::B1A1B2A2: m = RI::Tensor({sizeB1, sizeA1, sizeB2, sizeA2}); break; + case Matrix_Order::B1A2A1B2: m = RI::Tensor({sizeB1, sizeA2, sizeA1, sizeB2}); break; + case Matrix_Order::B1A2B2A1: m = RI::Tensor({sizeB1, sizeA2, sizeB2, sizeA1}); break; + case Matrix_Order::B1B2A1A2: m = RI::Tensor({sizeB1, sizeB2, sizeA1, sizeA2}); break; + case Matrix_Order::B1B2A2A1: m = RI::Tensor({sizeB1, sizeB2, sizeA2, sizeA1}); break; + case Matrix_Order::B2A1A2B1: m = RI::Tensor({sizeB2, sizeA1, sizeA2, sizeB1}); break; + case Matrix_Order::B2A1B1A2: m = RI::Tensor({sizeB2, sizeA1, sizeB1, sizeA2}); break; + case Matrix_Order::B2A2A1B1: m = RI::Tensor({sizeB2, sizeA2, sizeA1, sizeB1}); break; + case Matrix_Order::B2A2B1A1: m = RI::Tensor({sizeB2, sizeA2, sizeB1, sizeA1}); break; + case Matrix_Order::B2B1A1A2: m = RI::Tensor({sizeB2, sizeB1, sizeA1, sizeA2}); break; + case Matrix_Order::B2B1A2A1: m = RI::Tensor({sizeB2, sizeB1, sizeA2, sizeA1}); break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + + for( const auto &co3 : center2_orb22_s.at(TA).at(TB) ) + { + const int LA1 = co3.first; + for( const auto &co4 : co3.second ) + { + const size_t NA1 = co4.first; + for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) + { + for( const auto &co5 : co4.second ) + { + const int LA2 = co5.first; + for( const auto &co6 : co5.second ) + { + const size_t NA2 = co6.first; + for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) + { + for( const auto &co7 : co6.second ) + { + const int LB1 = co7.first; + for( const auto &co8 : co7.second ) + { + const size_t NB1 = co8.first; + for( size_t MB1=0; MB1!=2*LB1+1; ++MB1 ) + { + for( const auto &co9 : co8.second ) + { + const int LB2 = co9.first; + for( const auto &co10 : co9.second ) + { + const size_t NB2 = co10.first; + for( size_t MB2=0; MB2!=2*LB2+1; ++MB2 ) + { + const Tdata overlap = co10.second.cal_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB1, MB2 ); + const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; + const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; + const size_t iB1 = index_B1[TB][LB1][NB1][MB1]; + const size_t iB2 = index_B2[TB][LB2][NB2][MB2]; + switch(matrix_order) + { + case Matrix_Order::A1A2B1B2: m(iA1,iA2,iB1,iB2) = overlap; break; + case Matrix_Order::A1A2B2B1: m(iA1,iA2,iB2,iB1) = overlap; break; + case Matrix_Order::A1B1A2B2: m(iA1,iB1,iA2,iB2) = overlap; break; + case Matrix_Order::A1B1B2A2: m(iA1,iB1,iB2,iA2) = overlap; break; + case Matrix_Order::A1B2A2B1: m(iA1,iB2,iA2,iB1) = overlap; break; + case Matrix_Order::A1B2B1A2: m(iA1,iB2,iB1,iA2) = overlap; break; + case Matrix_Order::A2A1B1B2: m(iA2,iA1,iB1,iB2) = overlap; break; + case Matrix_Order::A2A1B2B1: m(iA2,iA1,iB2,iB1) = overlap; break; + case Matrix_Order::A2B1A1B2: m(iA2,iB1,iA1,iB2) = overlap; break; + case Matrix_Order::A2B1B2A1: m(iA2,iB1,iB2,iA1) = overlap; break; + case Matrix_Order::A2B2A1B1: m(iA2,iB2,iA1,iB1) = overlap; break; + case Matrix_Order::A2B2B1A1: m(iA2,iB2,iB1,iA1) = overlap; break; + case Matrix_Order::B1A1A2B2: m(iB1,iA1,iA2,iB2) = overlap; break; + case Matrix_Order::B1A1B2A2: m(iB1,iA1,iB2,iA2) = overlap; break; + case Matrix_Order::B1A2A1B2: m(iB1,iA2,iA1,iB2) = overlap; break; + case Matrix_Order::B1A2B2A1: m(iB1,iA2,iB2,iA1) = overlap; break; + case Matrix_Order::B1B2A1A2: m(iB1,iB2,iA1,iA2) = overlap; break; + case Matrix_Order::B1B2A2A1: m(iB1,iB2,iA2,iA1) = overlap; break; + case Matrix_Order::B2A1A2B1: m(iB2,iA1,iA2,iB1) = overlap; break; + case Matrix_Order::B2A1B1A2: m(iB2,iA1,iB1,iA2) = overlap; break; + case Matrix_Order::B2A2A1B1: m(iB2,iA2,iA1,iB1) = overlap; break; + case Matrix_Order::B2A2B1A1: m(iB2,iA2,iB1,iA1) = overlap; break; + case Matrix_Order::B2B1A1A2: m(iB2,iB1,iA1,iA2) = overlap; break; + case Matrix_Order::B2B1A2A1: m(iB2,iB1,iA2,iA1) = overlap; break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + } + } + } + } + } + } + } + } + } + } + } + } + return m; +} + +template +std::array,3> Matrix_Orbs22::cal_grad_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3 &tauA, + const ModuleBase::Vector3 &tauB, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B2, + const Matrix_Order &matrix_order) const +{ + std::array,3> m; + const size_t sizeA1 = index_A1[TA].count_size; + const size_t sizeA2 = index_A2[TA].count_size; + const size_t sizeB1 = index_B1[TB].count_size; + const size_t sizeB2 = index_B2[TB].count_size; + for(int i=0; i({sizeA1, sizeA2, sizeB1, sizeB2}); break; + case Matrix_Order::A1A2B2B1: m[i] = RI::Tensor({sizeA1, sizeA2, sizeB2, sizeB1}); break; + case Matrix_Order::A1B1A2B2: m[i] = RI::Tensor({sizeA1, sizeB1, sizeA2, sizeB2}); break; + case Matrix_Order::A1B1B2A2: m[i] = RI::Tensor({sizeA1, sizeB1, sizeB2, sizeA2}); break; + case Matrix_Order::A1B2A2B1: m[i] = RI::Tensor({sizeA1, sizeB2, sizeA2, sizeB1}); break; + case Matrix_Order::A1B2B1A2: m[i] = RI::Tensor({sizeA1, sizeB2, sizeB1, sizeA2}); break; + case Matrix_Order::A2A1B1B2: m[i] = RI::Tensor({sizeA2, sizeA1, sizeB1, sizeB2}); break; + case Matrix_Order::A2A1B2B1: m[i] = RI::Tensor({sizeA2, sizeA1, sizeB2, sizeB1}); break; + case Matrix_Order::A2B1A1B2: m[i] = RI::Tensor({sizeA2, sizeB1, sizeA1, sizeB2}); break; + case Matrix_Order::A2B1B2A1: m[i] = RI::Tensor({sizeA2, sizeB1, sizeB2, sizeA1}); break; + case Matrix_Order::A2B2A1B1: m[i] = RI::Tensor({sizeA2, sizeB2, sizeA1, sizeB1}); break; + case Matrix_Order::A2B2B1A1: m[i] = RI::Tensor({sizeA2, sizeB2, sizeB1, sizeA1}); break; + case Matrix_Order::B1A1A2B2: m[i] = RI::Tensor({sizeB1, sizeA1, sizeA2, sizeB2}); break; + case Matrix_Order::B1A1B2A2: m[i] = RI::Tensor({sizeB1, sizeA1, sizeB2, sizeA2}); break; + case Matrix_Order::B1A2A1B2: m[i] = RI::Tensor({sizeB1, sizeA2, sizeA1, sizeB2}); break; + case Matrix_Order::B1A2B2A1: m[i] = RI::Tensor({sizeB1, sizeA2, sizeB2, sizeA1}); break; + case Matrix_Order::B1B2A1A2: m[i] = RI::Tensor({sizeB1, sizeB2, sizeA1, sizeA2}); break; + case Matrix_Order::B1B2A2A1: m[i] = RI::Tensor({sizeB1, sizeB2, sizeA2, sizeA1}); break; + case Matrix_Order::B2A1A2B1: m[i] = RI::Tensor({sizeB2, sizeA1, sizeA2, sizeB1}); break; + case Matrix_Order::B2A1B1A2: m[i] = RI::Tensor({sizeB2, sizeA1, sizeB1, sizeA2}); break; + case Matrix_Order::B2A2A1B1: m[i] = RI::Tensor({sizeB2, sizeA2, sizeA1, sizeB1}); break; + case Matrix_Order::B2A2B1A1: m[i] = RI::Tensor({sizeB2, sizeA2, sizeB1, sizeA1}); break; + case Matrix_Order::B2B1A1A2: m[i] = RI::Tensor({sizeB2, sizeB1, sizeA1, sizeA2}); break; + case Matrix_Order::B2B1A2A1: m[i] = RI::Tensor({sizeB2, sizeB1, sizeA2, sizeA1}); break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + } + const double lat0 = *this->lat0; + for( const auto &co3 : center2_orb22_s.at(TA).at(TB) ) + { + const int LA1 = co3.first; + for( const auto &co4 : co3.second ) + { + const size_t NA1 = co4.first; + for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) + { + for( const auto &co5 : co4.second ) + { + const int LA2 = co5.first; + for( const auto &co6 : co5.second ) + { + const size_t NA2 = co6.first; + for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) + { + for( const auto &co7 : co6.second ) + { + const int LB1 = co7.first; + for( const auto &co8 : co7.second ) + { + const size_t NB1 = co8.first; + for( size_t MB1=0; MB1!=2*LB1+1; ++MB1 ) + { + for( const auto &co9 : co8.second ) + { + const int LB2 = co9.first; + for( const auto &co10 : co9.second ) + { + const size_t NB2 = co10.first; + for( size_t MB2=0; MB2!=2*LB2+1; ++MB2 ) + { + const std::array grad_overlap = RI_Util::Vector3_to_array3(co10.second.cal_grad_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB1, MB2 )); + const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; + const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; + const size_t iB1 = index_B1[TB][LB1][NB1][MB1]; + const size_t iB2 = index_B2[TB][LB2][NB2][MB2]; + for(size_t i=0; i +std::map < size_t, std::map>>>> Matrix_Orbs22::cal_overlap_matrix_all( + const UnitCell &ucell, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B2 ) const +{ + std::map>>>> matrixes; + + for( const auto &co1 : center2_orb22_s ) + { + const size_t TA = co1.first; + for( size_t IA=0; IA!=ucell.atoms[TA].na; ++IA ) + { + const ModuleBase::Vector3 &tauA( ucell.atoms[TA].tau[IA] ); + + for( const auto &co2 : co1.second ) + { + const size_t TB = co2.first; + for( size_t IB=0; IB!=ucell.atoms[TB].na; ++IB ) + { + const ModuleBase::Vector3 &tauB( ucell.atoms[TB].tau[IB] ); + + matrixes[TA][IA][TB][IB] = cal_overlap_matrix( + TA, + TB, + ucell.atoms[TA].tau[IA], + ucell.atoms[TB].tau[IB], + index_A1, + index_A2, + index_B1, + index_B2, + Matrix_Order::A1B1A2B2); + } + } + } + } + return matrixes; +} +#endif diff --git a/source/source_lcao/module_ri/Mix_DMk_2D.cpp b/source/source_lcao/module_ri/Mix_DMk_2D.cpp index 15b3e8f7dd7..b52ea4c9bf2 100644 --- a/source/source_lcao/module_ri/Mix_DMk_2D.cpp +++ b/source/source_lcao/module_ri/Mix_DMk_2D.cpp @@ -1,88 +1,88 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2023-05-09 -//======================= - -#include "Mix_DMk_2D.h" -#include "source_base/module_mixing/plain_mixing.h" -#include "source_base/tool_title.h" - -#include - -template -Mix_DMk_2D::~Mix_DMk_2D() -{ - if(this->flag_del_mixing) - delete this->mixing; -} - -template -void Mix_DMk_2D::set_nks(const int nks) -{ - this->mix_DMk.clear(); - this->mix_DMk.resize(nks); -} - -template -void Mix_DMk_2D::set_mixing(Base_Mixing::Mixing* mixing_in) -{ - if(this->flag_del_mixing) - delete this->mixing; - this->mixing = mixing_in; - this->flag_del_mixing = false; -} - -template -void Mix_DMk_2D::set_mixing_plain(const double& mixing_beta) -{ - if(this->flag_del_mixing) - delete this->mixing; - this->mixing = new Base_Mixing::Plain_Mixing(mixing_beta); - this->flag_del_mixing = true; -} - -template -void Mix_DMk_2D::mix(const std::vector>& dm, const bool flag_restart) -{ - ModuleBase::TITLE("Mix_DMk_2D", "mix"); - if (flag_restart) - { this->restart_all(dm); } - else - { this->mix_all(dm); } -} - -template -std::vector*> Mix_DMk_2D::get_DMk_out() const -{ - std::vector*> DMk_out(this->mix_DMk.size()); - for (int ik = 0; ik < this->mix_DMk.size(); ++ik) - { DMk_out[ik] = &this->mix_DMk[ik].data_out; } - return DMk_out; -} - -template -void Mix_DMk_2D::restart_all(const std::vector>& data_in) -{ - assert(this->mix_DMk.size() == data_in.size()); - assert(this->mixing != nullptr); - for (int ik = 0; ik < data_in.size(); ++ik) - { - this->mix_DMk[ik].data_out = data_in[ik]; - this->mixing->init_mixing_data(this->mix_DMk[ik].mixing_data, data_in[ik].size(), sizeof(Tdata)); - } -} - -template -void Mix_DMk_2D::mix_all(const std::vector>& data_in) -{ - assert(this->mix_DMk.size() == data_in.size()); - assert(this->mixing != nullptr); - for (int ik = 0; ik < data_in.size(); ++ik) - { - this->mixing->push_data(this->mix_DMk[ik].mixing_data, this->mix_DMk[ik].data_out.data(), data_in[ik].data(), nullptr, false); - this->mixing->mix_data(this->mix_DMk[ik].mixing_data, this->mix_DMk[ik].data_out.data()); - } -} - -template class Mix_DMk_2D; -template class Mix_DMk_2D>; +//======================= +// AUTHOR : Peize Lin +// DATE : 2023-05-09 +//======================= + +#include "Mix_DMk_2D.h" +#include "source_base/module_mixing/plain_mixing.h" +#include "source_base/tool_title.h" + +#include + +template +Mix_DMk_2D::~Mix_DMk_2D() +{ + if(this->flag_del_mixing) + delete this->mixing; +} + +template +void Mix_DMk_2D::set_nks(const int nks) +{ + this->mix_DMk.clear(); + this->mix_DMk.resize(nks); +} + +template +void Mix_DMk_2D::set_mixing(Base_Mixing::Mixing* mixing_in) +{ + if(this->flag_del_mixing) + delete this->mixing; + this->mixing = mixing_in; + this->flag_del_mixing = false; +} + +template +void Mix_DMk_2D::set_mixing_plain(const double& mixing_beta) +{ + if(this->flag_del_mixing) + delete this->mixing; + this->mixing = new Base_Mixing::Plain_Mixing(mixing_beta); + this->flag_del_mixing = true; +} + +template +void Mix_DMk_2D::mix(const std::vector>& dm, const bool flag_restart) +{ + ModuleBase::TITLE("Mix_DMk_2D", "mix"); + if (flag_restart) + { this->restart_all(dm); } + else + { this->mix_all(dm); } +} + +template +std::vector*> Mix_DMk_2D::get_DMk_out() const +{ + std::vector*> DMk_out(this->mix_DMk.size()); + for (int ik = 0; ik < this->mix_DMk.size(); ++ik) + { DMk_out[ik] = &this->mix_DMk[ik].data_out; } + return DMk_out; +} + +template +void Mix_DMk_2D::restart_all(const std::vector>& data_in) +{ + assert(this->mix_DMk.size() == data_in.size()); + assert(this->mixing != nullptr); + for (int ik = 0; ik < data_in.size(); ++ik) + { + this->mix_DMk[ik].data_out = data_in[ik]; + this->mixing->init_mixing_data(this->mix_DMk[ik].mixing_data, data_in[ik].size(), sizeof(Tdata)); + } +} + +template +void Mix_DMk_2D::mix_all(const std::vector>& data_in) +{ + assert(this->mix_DMk.size() == data_in.size()); + assert(this->mixing != nullptr); + for (int ik = 0; ik < data_in.size(); ++ik) + { + this->mixing->push_data(this->mix_DMk[ik].mixing_data, this->mix_DMk[ik].data_out.data(), data_in[ik].data(), nullptr, false); + this->mixing->mix_data(this->mix_DMk[ik].mixing_data, this->mix_DMk[ik].data_out.data()); + } +} + +template class Mix_DMk_2D; +template class Mix_DMk_2D>; diff --git a/source/source_lcao/module_ri/Mix_DMk_2D.h b/source/source_lcao/module_ri/Mix_DMk_2D.h index a37348415e2..042935ccb74 100644 --- a/source/source_lcao/module_ri/Mix_DMk_2D.h +++ b/source/source_lcao/module_ri/Mix_DMk_2D.h @@ -1,67 +1,67 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2023-05-09 -//======================= - -#ifndef MIX_DMK_2D_H -#define MIX_DMK_2D_H - -#include "source_base/module_mixing/mixing.h" - -#include -#include - -template -class Mix_DMk_2D -{ -public: - ~Mix_DMk_2D(); - - /** - * @brief Sets the number of k-points. - * @param nks Number of k-points. - */ - void set_nks(const int nks); - - /** - * @brief Sets the mixing mode. - * @param Mixing Mixing pointer. - */ - void set_mixing(Base_Mixing::Mixing* mixing_in); - - /** - * @brief Sets Base_Mixing::Plain_Mixing. - * @param mixing_beta mixing beta for plain mixing. - */ - void set_mixing_plain(const double& mixing_beta); - - /** - * @brief Mixes the density matrix. - * @param dm Density matrix. - * @param flag_restart Flag indicating whether restart mixing. - */ - void mix(const std::vector>& dm, const bool flag_restart); - - /** - * @brief Returns the density matrix. - * @return Density matrices for each k-points. - */ - std::vector*> get_DMk_out() const; - -private: - struct DMk_Mix_Data - { - std::vector data_out; - Base_Mixing::Mixing_Data mixing_data; - }; - - void restart_all(const std::vector>& data_in); - - void mix_all(const std::vector>& data_in); - - std::vector mix_DMk; - Base_Mixing::Mixing* mixing = nullptr; - bool flag_del_mixing = false; -}; - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2023-05-09 +//======================= + +#ifndef MIX_DMK_2D_H +#define MIX_DMK_2D_H + +#include "source_base/module_mixing/mixing.h" + +#include +#include + +template +class Mix_DMk_2D +{ +public: + ~Mix_DMk_2D(); + + /** + * @brief Sets the number of k-points. + * @param nks Number of k-points. + */ + void set_nks(const int nks); + + /** + * @brief Sets the mixing mode. + * @param Mixing Mixing pointer. + */ + void set_mixing(Base_Mixing::Mixing* mixing_in); + + /** + * @brief Sets Base_Mixing::Plain_Mixing. + * @param mixing_beta mixing beta for plain mixing. + */ + void set_mixing_plain(const double& mixing_beta); + + /** + * @brief Mixes the density matrix. + * @param dm Density matrix. + * @param flag_restart Flag indicating whether restart mixing. + */ + void mix(const std::vector>& dm, const bool flag_restart); + + /** + * @brief Returns the density matrix. + * @return Density matrices for each k-points. + */ + std::vector*> get_DMk_out() const; + +private: + struct DMk_Mix_Data + { + std::vector data_out; + Base_Mixing::Mixing_Data mixing_data; + }; + + void restart_all(const std::vector>& data_in); + + void mix_all(const std::vector>& data_in); + + std::vector mix_DMk; + Base_Mixing::Mixing* mixing = nullptr; + bool flag_del_mixing = false; +}; + +#endif diff --git a/source/source_pw/module_stodft/sto_stress_pw.h b/source/source_pw/module_stodft/sto_stress_pw.h index 21edb937978..c357cb1fb6f 100644 --- a/source/source_pw/module_stodft/sto_stress_pw.h +++ b/source/source_pw/module_stodft/sto_stress_pw.h @@ -1,67 +1,67 @@ -#ifndef STO_STRESS_PW_H -#define STO_STRESS_PW_H - -#include "source_basis/module_pw/pw_basis_k.h" -#include "source_estate/elecstate.h" -#include "source_pw/module_pwdft/vl_pw.h" -#include "source_pw/module_pwdft/stress_func.h" -#include "sto_wf.h" - -// qianrui create 2021-6-4 - -template -class Sto_Stress_PW : public Stress_Func -{ - public: - Sto_Stress_PW(){}; - ~Sto_Stress_PW(){}; - - // calculate the stress in PW basis - void cal_stress(ModuleBase::matrix& sigmatot, - const elecstate::ElecState& elec, - ModulePW::PW_Basis* rho_basis, - ModuleSymmetry::Symmetry* p_symm, - Structure_Factor* p_sf, - K_Vectors* p_kv, - ModulePW::PW_Basis_K* wfc_basis, - const psi::Psi, Device>& psi_in, - const Stochastic_WF, Device>& stowf, - const Charge* const chr, - const pseudopot_cell_vl* locpp, - const pseudopot_cell_vnl* nlpp, - UnitCell& ucell_in); - - private: - void sto_stress_kin(ModuleBase::matrix& sigma, - const ModuleBase::matrix& wg, - ModuleSymmetry::Symmetry* p_symm, - K_Vectors* p_kv, - ModulePW::PW_Basis_K* wfc_basis, - const psi::Psi, Device>& psi_in, - const Stochastic_WF, Device>& stowf); - - void sto_stress_nl(ModuleBase::matrix& sigma, - const ModuleBase::matrix& wg, - Structure_Factor* p_sf, - ModuleSymmetry::Symmetry* p_symm, - K_Vectors* p_kv, - ModulePW::PW_Basis_K* wfc_basis, - const pseudopot_cell_vnl& nlpp, - const UnitCell& ucell, - const psi::Psi, Device>& psi, - const Stochastic_WF, Device>& stowf); - - private: -#ifdef __DSP - using resmem_var_op = base_device::memory::resize_memory_op_mt; - using setmem_var_op = base_device::memory::set_memory_op_mt; - using delmem_var_op = base_device::memory::delete_memory_op_mt; - -#else - using resmem_var_op = base_device::memory::resize_memory_op; - using setmem_var_op = base_device::memory::set_memory_op; - using delmem_var_op = base_device::memory::delete_memory_op; -#endif - using syncmem_var_d2h_op = base_device::memory::synchronize_memory_op; -}; -#endif +#ifndef STO_STRESS_PW_H +#define STO_STRESS_PW_H + +#include "source_basis/module_pw/pw_basis_k.h" +#include "source_estate/elecstate.h" +#include "source_pw/module_pwdft/vl_pw.h" +#include "source_pw/module_pwdft/stress_func.h" +#include "sto_wf.h" + +// qianrui create 2021-6-4 + +template +class Sto_Stress_PW : public Stress_Func +{ + public: + Sto_Stress_PW(){}; + ~Sto_Stress_PW(){}; + + // calculate the stress in PW basis + void cal_stress(ModuleBase::matrix& sigmatot, + const elecstate::ElecState& elec, + ModulePW::PW_Basis* rho_basis, + ModuleSymmetry::Symmetry* p_symm, + Structure_Factor* p_sf, + K_Vectors* p_kv, + ModulePW::PW_Basis_K* wfc_basis, + const psi::Psi, Device>& psi_in, + const Stochastic_WF, Device>& stowf, + const Charge* const chr, + const pseudopot_cell_vl* locpp, + const pseudopot_cell_vnl* nlpp, + UnitCell& ucell_in); + + private: + void sto_stress_kin(ModuleBase::matrix& sigma, + const ModuleBase::matrix& wg, + ModuleSymmetry::Symmetry* p_symm, + K_Vectors* p_kv, + ModulePW::PW_Basis_K* wfc_basis, + const psi::Psi, Device>& psi_in, + const Stochastic_WF, Device>& stowf); + + void sto_stress_nl(ModuleBase::matrix& sigma, + const ModuleBase::matrix& wg, + Structure_Factor* p_sf, + ModuleSymmetry::Symmetry* p_symm, + K_Vectors* p_kv, + ModulePW::PW_Basis_K* wfc_basis, + const pseudopot_cell_vnl& nlpp, + const UnitCell& ucell, + const psi::Psi, Device>& psi, + const Stochastic_WF, Device>& stowf); + + private: +#ifdef __DSP + using resmem_var_op = base_device::memory::resize_memory_op_mt; + using setmem_var_op = base_device::memory::set_memory_op_mt; + using delmem_var_op = base_device::memory::delete_memory_op_mt; + +#else + using resmem_var_op = base_device::memory::resize_memory_op; + using setmem_var_op = base_device::memory::set_memory_op; + using delmem_var_op = base_device::memory::delete_memory_op; +#endif + using syncmem_var_d2h_op = base_device::memory::synchronize_memory_op; +}; +#endif diff --git a/tools/01_NAO_generation/pytorch_dpsi/IO/cal_weight.py b/tools/01_NAO_generation/pytorch_dpsi/IO/cal_weight.py index 7580d6717d8..d6e50339cc9 100644 --- a/tools/01_NAO_generation/pytorch_dpsi/IO/cal_weight.py +++ b/tools/01_NAO_generation/pytorch_dpsi/IO/cal_weight.py @@ -1,70 +1,70 @@ -import IO.read_istate -import torch -import re -import functools -import operator - -def cal_weight(info_weight, flag_same_band, stru_file_list=None): - """ weight[ist][ib] """ - - if "bands_file" in info_weight.keys(): - if "bands_range" in info_weight.keys(): - raise IOError('"bands_file" and "bands_range" only once') - - weight = [] # weight[ist][ib] - for weight_stru, file_name in zip(info_weight["stru"], info_weight["bands_file"]): - occ = IO.read_istate.read_istate(file_name) - weight += [occ_k * weight_stru for occ_k in occ] - - elif "bands_range" in info_weight.keys(): - k_weight = read_k_weight(stru_file_list) # k_weight[ist][ik] - nbands = read_nbands(stru_file_list) # nbands[ist] - - st_weight = [] # st_weight[ist][ib] - for weight_stru, bands_range, nbands_ist in zip(info_weight["stru"], info_weight["bands_range"], nbands): - st_weight_tmp = torch.zeros((nbands_ist,)) - st_weight_tmp[:bands_range] = weight_stru - st_weight.append( st_weight_tmp ) - - weight = [] # weight[ist][ib] - for ist,_ in enumerate(k_weight): - for ik,_ in enumerate(k_weight[ist]): - weight.append(st_weight[ist] * k_weight[ist][ik]) - - else: - raise IOError('"bands_file" and "bands_range" must once') - - - if not flag_same_band: - for ist,_ in enumerate(weight): - weight[ist] = torch.tensordot(weight[ist], weight[ist], dims=0) - - - normalization = functools.reduce(operator.add, map(torch.sum, weight), 0) - weight = list(map(lambda x:x/normalization, weight)) - - return weight - - -def read_k_weight(stru_file_list): - """ weight[ist][ik] """ - weight = [] # weight[ist][ik] - for file_name in stru_file_list: - weight_k = [] # weight_k[ik] - with open(file_name,"r") as file: - data = re.compile(r"(.+)", re.S).search(file.read()).group(1).split("\n") - for line in data: - line = line.strip() - if line: - weight_k.append(float(line.split()[-1])) - weight.append(weight_k) - return weight - - -def read_nbands(stru_file_list): - """ nbands[ib] """ - nbands = [] - for file_name in stru_file_list: - with open(file_name,"r") as file: - nbands.append(int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1))) - return nbands +import IO.read_istate +import torch +import re +import functools +import operator + +def cal_weight(info_weight, flag_same_band, stru_file_list=None): + """ weight[ist][ib] """ + + if "bands_file" in info_weight.keys(): + if "bands_range" in info_weight.keys(): + raise IOError('"bands_file" and "bands_range" only once') + + weight = [] # weight[ist][ib] + for weight_stru, file_name in zip(info_weight["stru"], info_weight["bands_file"]): + occ = IO.read_istate.read_istate(file_name) + weight += [occ_k * weight_stru for occ_k in occ] + + elif "bands_range" in info_weight.keys(): + k_weight = read_k_weight(stru_file_list) # k_weight[ist][ik] + nbands = read_nbands(stru_file_list) # nbands[ist] + + st_weight = [] # st_weight[ist][ib] + for weight_stru, bands_range, nbands_ist in zip(info_weight["stru"], info_weight["bands_range"], nbands): + st_weight_tmp = torch.zeros((nbands_ist,)) + st_weight_tmp[:bands_range] = weight_stru + st_weight.append( st_weight_tmp ) + + weight = [] # weight[ist][ib] + for ist,_ in enumerate(k_weight): + for ik,_ in enumerate(k_weight[ist]): + weight.append(st_weight[ist] * k_weight[ist][ik]) + + else: + raise IOError('"bands_file" and "bands_range" must once') + + + if not flag_same_band: + for ist,_ in enumerate(weight): + weight[ist] = torch.tensordot(weight[ist], weight[ist], dims=0) + + + normalization = functools.reduce(operator.add, map(torch.sum, weight), 0) + weight = list(map(lambda x:x/normalization, weight)) + + return weight + + +def read_k_weight(stru_file_list): + """ weight[ist][ik] """ + weight = [] # weight[ist][ik] + for file_name in stru_file_list: + weight_k = [] # weight_k[ik] + with open(file_name,"r") as file: + data = re.compile(r"(.+)", re.S).search(file.read()).group(1).split("\n") + for line in data: + line = line.strip() + if line: + weight_k.append(float(line.split()[-1])) + weight.append(weight_k) + return weight + + +def read_nbands(stru_file_list): + """ nbands[ib] """ + nbands = [] + for file_name in stru_file_list: + with open(file_name,"r") as file: + nbands.append(int(re.compile(r"(\d+)\s+nbands").search(file.read()).group(1))) + return nbands diff --git a/tools/01_NAO_generation/pytorch_dpsi/IO/read_istate.py b/tools/01_NAO_generation/pytorch_dpsi/IO/read_istate.py index e1e7277e47a..f938a66d401 100644 --- a/tools/01_NAO_generation/pytorch_dpsi/IO/read_istate.py +++ b/tools/01_NAO_generation/pytorch_dpsi/IO/read_istate.py @@ -1,42 +1,42 @@ -import re -import torch -import itertools - -# occ[ik][ib] -def read_istate(file_name): - nspin0 = get_nspin0(file_name) - if nspin0==1: occ = [[]] - elif nspin0==2: occ = [[],[]] - with open(file_name,"r") as file: - content = file.read().split("BAND") - for content_k in content[1:]: - content_k = content_k.split("\n") - k = get_k(content_k[0]) - for ispin in range(nspin0): - occ[ispin].append([]) - for line in content_k[1:]: - line = line.strip() - if line: - line = line.split() - if nspin0==1: - occ[0][-1].append(float(line[2])) - elif nspin0==2: - occ[0][-1].append(float(line[2])) - occ[1][-1].append(float(line[4])) - for ispin in range(nspin0): - occ[ispin][-1] = torch.Tensor(occ[ispin][-1]) - occ = list(itertools.chain(*occ)) - return occ - -def get_k(line): - k = re.compile(r"Kpoint\s*=\s*(\d+)").search(line).group(1) - return int(k) - -def get_nspin0(file_name): - with open(file_name,"r") as file: - file.readline() - line = file.readline() - lens = len(line.split()) - if lens == 3: return 1 - elif lens == 5: return 2 +import re +import torch +import itertools + +# occ[ik][ib] +def read_istate(file_name): + nspin0 = get_nspin0(file_name) + if nspin0==1: occ = [[]] + elif nspin0==2: occ = [[],[]] + with open(file_name,"r") as file: + content = file.read().split("BAND") + for content_k in content[1:]: + content_k = content_k.split("\n") + k = get_k(content_k[0]) + for ispin in range(nspin0): + occ[ispin].append([]) + for line in content_k[1:]: + line = line.strip() + if line: + line = line.split() + if nspin0==1: + occ[0][-1].append(float(line[2])) + elif nspin0==2: + occ[0][-1].append(float(line[2])) + occ[1][-1].append(float(line[4])) + for ispin in range(nspin0): + occ[ispin][-1] = torch.Tensor(occ[ispin][-1]) + occ = list(itertools.chain(*occ)) + return occ + +def get_k(line): + k = re.compile(r"Kpoint\s*=\s*(\d+)").search(line).group(1) + return int(k) + +def get_nspin0(file_name): + with open(file_name,"r") as file: + file.readline() + line = file.readline() + lens = len(line.split()) + if lens == 3: return 1 + elif lens == 5: return 2 else: raise \ No newline at end of file diff --git a/tools/02_postprocessing/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT b/tools/02_postprocessing/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT index 1044cdf06ef..f1a54e1b7af 100644 --- a/tools/02_postprocessing/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT +++ b/tools/02_postprocessing/rt-tddft-tools/examples/Absorpation-N2/ABACUS-INPUT @@ -1,32 +1,32 @@ -INPUT_PARAMETERS -suffix tddft -basis_type lcao - -ecutwfc 60 -scf_nmax 100 -scf_thr 1e-6 - -calculation md -esolver_type tddft -md_type nve -md_nstep 10000 -md_dt 0.0024 -md_tfirst 0 - -td_vext 1 -td_vext_dire 3 3 -td_stype 0 -td_ttype 0 0 -td_tstart 1 -td_tend 2000 -td_lcut1 0.01 -td_lcut2 0.99 -td_gauss_freq 3.66 1.22 -td_gauss_phase 0.0 0.0 -td_gauss_sigma 0.2 0.2 -td_gauss_t0 800 800 -td_gauss_amp 0.6 0.6 - -out_chg 1 -out_efield 1 -out_dipole 1 +INPUT_PARAMETERS +suffix tddft +basis_type lcao + +ecutwfc 60 +scf_nmax 100 +scf_thr 1e-6 + +calculation md +esolver_type tddft +md_type nve +md_nstep 10000 +md_dt 0.0024 +md_tfirst 0 + +td_vext 1 +td_vext_dire 3 3 +td_stype 0 +td_ttype 0 0 +td_tstart 1 +td_tend 2000 +td_lcut1 0.01 +td_lcut2 0.99 +td_gauss_freq 3.66 1.22 +td_gauss_phase 0.0 0.0 +td_gauss_sigma 0.2 0.2 +td_gauss_t0 800 800 +td_gauss_amp 0.6 0.6 + +out_chg 1 +out_efield 1 +out_dipole 1 diff --git a/tools/02_postprocessing/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat b/tools/02_postprocessing/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat index d745542ce92..4aed610292e 100644 --- a/tools/02_postprocessing/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat +++ b/tools/02_postprocessing/rt-tddft-tools/examples/ground-state-projection-Si/On1.dat @@ -1,101 +1,101 @@ -7.812499853032692752e-03 7.812500279798491667e-03 7.812350082550026734e-03 7.812350082567939488e-03 6.686717854768583909e-18 1.273966279961955695e-20 1.281536489683403687e-20 2.436224928051321290e-17 1.455721960673305505e-20 -7.812499853032699691e-03 7.812500279798476055e-03 7.812350082258740641e-03 7.812350082365753998e-03 1.490247763194331891e-17 1.077391542540353658e-17 9.648851966739274479e-18 2.698813529540607934e-17 3.969790221977746295e-20 -7.812499853032702293e-03 7.812500279798481259e-03 7.812350082258744978e-03 7.812350082365754865e-03 1.338629013537693114e-17 1.040157544868407331e-17 8.023705175726225935e-18 2.818645043139415115e-17 2.152965149171645697e-19 -7.812499853032704028e-03 7.812500279798481259e-03 7.812350082258739774e-03 7.812350082365751396e-03 1.050061327306201373e-17 1.018748243646475980e-17 1.255526088916916614e-17 2.884255147975228781e-17 9.256801281552135578e-19 -7.812499853032684079e-03 7.812500279798443095e-03 7.812350082258605333e-03 7.812350082365557974e-03 1.110234188146072923e-16 5.476475696791553340e-17 9.458349117056311261e-17 7.886970031758802209e-17 3.443302604107927034e-17 -7.812499853032585199e-03 7.812500279797884514e-03 7.812350082257480365e-03 7.812350082363527480e-03 1.221025990081458542e-15 5.277097822561900040e-16 8.042486056611601589e-16 6.609800012573974879e-16 3.388298157432289595e-16 -7.812499853032228714e-03 7.812500279794808850e-03 7.812350082251317759e-03 7.812350082352021927e-03 7.688773607708341558e-15 3.222952618985768202e-15 4.719067260205915655e-15 4.031146146161859528e-15 1.884039370417977416e-15 -7.812499853031174869e-03 7.812500279782960688e-03 7.812350082226447029e-03 7.812350082305783740e-03 3.459153926335484060e-14 1.423009475135000606e-14 2.065106717651520955e-14 1.758670007424376872e-14 7.474971242608616118e-15 -7.812499853028622224e-03 7.812500279747522022e-03 7.812350082146477144e-03 7.812350082159213484e-03 1.228145204190944378e-13 4.981559865801570222e-14 7.232334033967236660e-14 6.002620078048621925e-14 2.330673017550618989e-14 -7.812499853023407645e-03 7.812500279660945443e-03 7.812350081934199032e-03 7.812350081777151914e-03 3.610941462883710220e-13 1.446487842594735793e-13 2.106461858849508682e-13 1.682485411779086762e-13 5.969979759489234567e-14 -7.812499853014897092e-03 7.812500279486930127e-03 7.812350081463906824e-03 7.812350080947388573e-03 8.986578228190934686e-13 3.554742578353971945e-13 5.197792228478134614e-13 3.957470702999447474e-13 1.276867248607976924e-13 -7.812499853005088098e-03 7.812500279205564918e-03 7.812350080604125828e-03 7.812350079464436790e-03 1.902129002541687645e-12 7.419716841836609477e-13 1.090168097358521198e-12 7.836573236885160296e-13 2.269353059419004219e-13 -7.812499853000657614e-03 7.812500278866488929e-03 7.812350079367172580e-03 7.812350077389442968e-03 3.385603051914610680e-12 1.299293649069382529e-12 1.919379016255142377e-12 1.289038721443987301e-12 3.261388284048605778e-13 -7.812499853009330364e-03 7.812500278626734532e-03 7.812350078155607877e-03 7.812350075432913411e-03 4.901700794298826520e-12 1.845807442333131019e-12 2.742383323432933970e-12 1.711872500631155452e-12 3.618101175167228489e-13 -7.812499853018082911e-03 7.812500278590924635e-03 7.812350077802290675e-03 7.812350074866239967e-03 5.396993520182899994e-12 2.001504125631436744e-12 2.981955563864776735e-12 1.839553005394764809e-12 3.385082846655620411e-13 -7.812499852932987786e-03 7.812500278033927478e-03 7.812350078412555986e-03 7.812350075183738599e-03 4.315407145162125193e-12 1.703056079344719690e-12 2.468677803485621447e-12 2.361762504659291149e-12 6.950218203357612152e-13 -7.812499852466974273e-03 7.812500273374220830e-03 7.812350074989517223e-03 7.812350066099102777e-03 6.283159864873798714e-12 3.169681657633534525e-12 4.281083262384277953e-12 7.474396685349264012e-12 3.134461378552293558e-12 -7.812499851005201730e-03 7.812500254476032260e-03 7.812350047197313789e-03 7.812350009764495659e-03 3.267183280083109047e-11 1.552890608038603436e-11 2.153012832021432507e-11 2.999039571018929183e-11 1.192963004046087639e-11 -7.812499847572922963e-03 7.812500200162266970e-03 7.812349942262116105e-03 7.812349812582107186e-03 1.418939026414260175e-10 6.257923727216895362e-11 8.890829388137152469e-11 9.827167982682776205e-11 3.508698292183345656e-11 -7.812499841149679949e-03 7.812500076640842978e-03 7.812349656646455642e-03 7.812349297842300852e-03 4.531185304792351007e-10 1.911716241251917738e-10 2.754704942626815632e-10 2.605143014572550335e-10 8.366148061447493069e-11 -7.812499831578885272e-03 7.812499846019973354e-03 7.812349034944595511e-03 7.812348211501761626e-03 1.153088037609147093e-09 4.718569550809047194e-10 6.864440626384909332e-10 5.765652531795112974e-10 1.666204089618884149e-10 -7.812499820987390577e-03 7.812499492320172136e-03 7.812347918113238948e-03 7.812346312754753913e-03 2.447702082586668115e-09 9.771504459394998477e-10 1.432182592776262639e-09 1.085202190312603517e-09 2.797335493584696527e-10 -7.812499814740346896e-03 7.812499062254251760e-03 7.812346269952624885e-03 7.812343587535403380e-03 4.418222801594663738e-09 1.724018381710924485e-09 2.543369039502271716e-09 1.745678194287174871e-09 3.925477856832722905e-10 -7.812499819669653858e-03 7.812498690802675665e-03 7.812344360995931644e-03 7.812340529108604235e-03 6.791658385448597663e-09 2.589635535318124385e-09 3.843587174577796148e-09 2.388121726329547615e-09 4.486778634736386646e-10 -7.812499836541287289e-03 7.812498540333734538e-03 7.812342867626963228e-03 7.812338223696329957e-03 8.770998199078791133e-09 3.264672608722082367e-09 4.871569121144878528e-09 2.769177408961638509e-09 4.069975426300912668e-10 -7.812499844218311236e-03 7.812498550624985029e-03 7.812342564980947340e-03 7.812337706375470196e-03 9.284480356680769592e-09 3.391579366265826169e-09 5.070184887145676427e-09 2.882656183351129511e-09 3.547336710690416432e-10 -7.812499781849658459e-03 7.812497938502010325e-03 7.812343184217111422e-03 7.812337931984741912e-03 8.187553284667456409e-09 3.083966817157662608e-09 4.539467182508874874e-09 3.660704609143170800e-09 6.855413362771258625e-10 -7.812499539571283146e-03 7.812494543140142793e-03 7.812341152959785887e-03 7.812332057382916951e-03 8.841744470361763275e-09 3.960847677671831129e-09 5.566699818414017084e-09 7.988727728025107941e-09 2.269703900840955374e-09 -7.812498977478036198e-03 7.812484406984244664e-03 7.812326615005588636e-03 7.812302905420510403e-03 2.180228070163895656e-08 1.051910237351932575e-08 1.469509777326951620e-08 2.154800783639236158e-08 6.441336062768101019e-09 -7.812497994380795431e-03 7.812462264526452878e-03 7.812281302555792832e-03 7.812220353796601319e-03 6.797441971956459514e-08 3.112683845546636387e-08 4.428691811001559565e-08 5.250018216563952165e-08 1.458559667171380079e-08 -7.812496642031469159e-03 7.812423582450244049e-03 7.812180052545585236e-03 7.812045025095691250e-03 1.780202938069342282e-07 7.735204086169203320e-08 1.116600602934448646e-07 1.089078623714063587e-07 2.722494382585283444e-08 -7.812495230981619278e-03 7.812368096507126165e-03 7.811998844602665269e-03 7.811742231074614295e-03 3.842368801176499279e-07 1.602847291236858473e-07 2.337376488854461481e-07 1.935971465318801878e-07 4.285591415854843683e-08 -7.812494328139583770e-03 7.812303379348786367e-03 7.811729874197701103e-03 7.811305756875472177e-03 7.032546837354541918e-07 2.835793382204843004e-07 4.166897389954705580e-07 2.982177140607078031e-07 5.728193039849254671e-08 -7.812494550142056599e-03 7.812245427258719503e-03 7.811398810282921268e-03 7.810782527030078054e-03 1.113727748184818239e-06 4.354043797212895802e-07 6.437087438942030785e-07 4.008686263785850362e-07 6.449845579325761372e-08 -7.812496138080336598e-03 7.812212893856464342e-03 7.811072727768756351e-03 7.810279691796943348e-03 1.541461156476913746e-06 5.846309847418375274e-07 8.688045986117029490e-07 4.729147334166597758e-07 5.986995545985544601e-08 -7.812498445556872832e-03 7.812213704232950744e-03 7.810843583203532815e-03 7.809932136645577130e-03 1.870616030668633253e-06 6.884156571567480939e-07 1.027329365299366220e-06 4.981846542090092702e-07 4.512119076652669270e-08 -7.812499643314411817e-03 7.812227465998996048e-03 7.810777050788949953e-03 7.809818584425421741e-03 1.996915864576686549e-06 7.162014155120878158e-07 1.070908963295831547e-06 5.007358000999807850e-07 3.290430957355282637e-08 -7.812497004583882597e-03 7.812192420099366673e-03 7.810833005781974391e-03 7.809841229764222931e-03 1.921887432159646985e-06 6.874135529587402941e-07 1.023172530687733249e-06 5.684268623121463193e-07 4.737660114594148372e-08 -7.812487977686922644e-03 7.812008194689230509e-03 7.810787695955377988e-03 7.809619485122610769e-03 1.857942469276308112e-06 7.085479518432960039e-07 1.035821288261976948e-06 8.540461262419201573e-07 1.176737671272773021e-07 -7.812471748767348123e-03 7.811562352071302860e-03 7.810207234515143850e-03 7.808473164261869534e-03 2.285569265615626913e-06 9.854058759137348325e-07 1.409932401056303498e-06 1.539858543220769961e-06 2.640648030851998174e-07 -7.812450529143469789e-03 7.810779042843053223e-03 7.808519956579640028e-03 7.805560882451594018e-03 3.896605580814575925e-06 1.787075451064486949e-06 2.548005225924580296e-06 2.765201026029978535e-06 4.813926593788763635e-07 -7.812429661862023596e-03 7.809674641149721812e-03 7.805202887404326904e-03 7.800181116207064586e-03 7.390363320579293810e-06 3.354519377221000757e-06 4.824207063860702588e-06 4.537698916556045439e-06 7.287005859073173523e-07 -7.812416165084923141e-03 7.808393536111879127e-03 7.800038510484820671e-03 7.792149825718211638e-03 1.316122584248707086e-05 5.776773434575371999e-06 8.402178779544433807e-06 6.667369014382867723e-06 9.343828152441929552e-07 -7.812415835781623234e-03 7.807194132714686402e-03 7.793337863448148058e-03 7.782082517240840498e-03 2.099925837947448981e-05 8.887746642244384300e-06 1.307323485563547160e-05 8.770203536976671789e-06 1.021168349833567159e-06 -7.812430158111208570e-03 7.806368467992530306e-03 7.786000020659196962e-03 7.771393248244110735e-03 2.996771098010651084e-05 1.224706928486793432e-05 1.820790009944723024e-05 1.037469218978934016e-05 9.437824387095230784e-07 -7.812454690656026220e-03 7.806110337177065567e-03 7.779316215103107730e-03 7.761914895057454335e-03 3.858110769296473004e-05 1.524525220567434296e-05 2.288872843530340110e-05 1.112352046586807781e-05 7.209921399975341084e-07 -7.812480201788416824e-03 7.806386805941349476e-03 7.774529785912486640e-03 7.755223553030285953e-03 4.528347453745602184e-05 1.731960264508936400e-05 2.622053730063316743e-05 1.100113352190226156e-05 4.399041900332164704e-07 -7.812496176044654919e-03 7.806891664948079936e-03 7.772291495159932770e-03 7.751926368829008263e-03 4.907275643454239819e-05 1.820754084061740197e-05 2.772288834078687984e-05 1.046061247568982606e-05 2.225225911981681611e-07 -7.812495292061822673e-03 7.807139215375609106e-03 7.772241751786874986e-03 7.751242393952807209e-03 5.001574978626547913e-05 1.812741955189118513e-05 2.764027203504243102e-05 1.032613486388670125e-05 1.665620513368287718e-07 -7.812476894523122731e-03 7.806683943209593787e-03 7.772945300038862533e-03 7.751111453457110168e-03 4.940863028517055046e-05 1.778892355151607562e-05 2.700354558676601411e-05 1.144278173216673945e-05 2.931356705096467600e-07 -7.812447633371830819e-03 7.805360622923213781e-03 7.772280325110742481e-03 7.748841300394401430e-03 4.946498788292683508e-05 1.819664607815776332e-05 2.735932394244346047e-05 1.421182877230432772e-05 5.348146728831700359e-07 -7.812418676200951796e-03 7.803399072295380545e-03 7.768182598560221565e-03 7.742056677893807692e-03 5.260502689341779259e-05 2.029938517503130136e-05 3.022889388385826916e-05 1.827918656212739249e-05 7.737969837445373764e-07 -7.812400713050573174e-03 7.801328899352429937e-03 7.759458933900293363e-03 7.729571012333778281e-03 6.059554765283085880e-05 2.461554399679295580e-05 3.650070756930909251e-05 2.260937471593158608e-05 9.062974796379607276e-07 -7.812399402924678250e-03 7.799725111593778897e-03 7.746317787884777345e-03 7.711834931169255294e-03 7.387281172230948569e-05 3.099207090489362784e-05 4.602122468061838116e-05 2.595267368927323958e-05 8.916091203328781368e-07 -7.812413332542555815e-03 7.798951317677097449e-03 7.730372562608386205e-03 7.690803617564479985e-03 9.132598392869010779e-05 3.860912329843406692e-05 5.757879489393928250e-05 2.744243129201358010e-05 7.582080085956336064e-07 -7.812435655750508100e-03 7.799045564899258556e-03 7.714106581128725958e-03 7.669307408003667517e-03 1.106354824953435383e-04 4.624173039586804786e-05 6.930319478072197116e-05 2.696493794476126531e-05 5.706638856372884918e-07 -7.812458049977899846e-03 7.799779002849843365e-03 7.700032119112999729e-03 7.650185626982551265e-03 1.290317728818038228e-04 5.267491242189746055e-05 7.931021912472004868e-05 2.510498190276937440e-05 3.874743003157170213e-07 -7.812474472833470102e-03 7.800806553791946735e-03 7.689895100482323394e-03 7.635495440478613609e-03 1.441671433054891155e-04 5.710082886942940348e-05 8.631673803264112315e-05 2.275885910941017286e-05 2.386244849668603841e-07 -7.812482976849034755e-03 7.801806678970187037e-03 7.684226346611384290e-03 7.626043122362352773e-03 1.547629942338338998e-04 5.933866733362661114e-05 8.998326647379967301e-05 2.069121747385026391e-05 1.297730912415325758e-07 -7.812485232220344605e-03 7.802559641047198541e-03 7.682363107231317788e-03 7.621351204389437833e-03 1.608167121281512204e-04 5.980453704693076267e-05 9.088196765691194143e-05 1.927999912557097661e-05 5.844008953976879205e-08 -7.812484687099224487e-03 7.802969819103481100e-03 7.682863284657014818e-03 7.620020195549746453e-03 1.633555907751381572e-04 5.927321903152686335e-05 9.015594799946130046e-05 1.851857110723650212e-05 2.355680679308437475e-08 -7.812484528579055273e-03 7.803053725096873068e-03 7.684099485053701856e-03 7.620313644105695082e-03 1.639054050789472161e-04 5.855667006084784424e-05 8.904796951092744850e-05 1.818147643885591132e-05 2.259562066722161082e-08 -7.812486347732097020e-03 7.802906138662985686e-03 7.684792010505495964e-03 7.620734657771241656e-03 1.639180799370792388e-04 5.823836154829621197e-05 8.849453651262909287e-05 1.801056113072297418e-05 4.482718225915012074e-08 -7.812489966877368686e-03 7.802652857458577430e-03 7.684311301855815610e-03 7.620397450278489949e-03 1.643642387066439835e-04 5.854960502899452695e-05 8.891359154098924097e-05 1.782919431049579911e-05 7.161912630444491773e-08 -7.812494127122805894e-03 7.802404580937485380e-03 7.682698807419341414e-03 7.619109876382451629e-03 1.655862811202974880e-04 5.939615713527549305e-05 9.021286715380141135e-05 1.757035112025118347e-05 8.559997302272443172e-08 -7.812497470211249989e-03 7.802228932425433333e-03 7.680464665858448801e-03 7.617210995022639063e-03 1.673906019698739671e-04 6.048444806446939652e-05 9.196185539774789648e-05 1.725117344749978250e-05 8.071052106673271989e-08 -7.812499262283496664e-03 7.802147068445501599e-03 7.678284905384741635e-03 7.615288498122666817e-03 1.692825327983098758e-04 6.147641588181483141e-05 9.362872093630432619e-05 1.693047970507380231e-05 6.424811185473353517e-08 -7.812499556017950091e-03 7.802145493693739449e-03 7.676725520415324244e-03 7.613906859695971675e-03 1.707300961208414974e-04 6.211532079841483437e-05 9.478777861569192588e-05 1.666872075534763098e-05 4.957518521111539337e-08 -7.812498898940323407e-03 7.802189426919653448e-03 7.676076529785660213e-03 7.613428103579155878e-03 1.713654284443885114e-04 6.229347725606795285e-05 9.523952736898054429e-05 1.649883460424523220e-05 4.584613527028352739e-08 -7.812497920560946760e-03 7.802232495060661827e-03 7.676319544958354509e-03 7.613946242661542678e-03 1.710785375910244487e-04 6.205778441104415428e-05 9.502791401655731585e-05 1.641215865889956077e-05 5.255976528493730751e-08 -7.812497066894792501e-03 7.802227167898124344e-03 7.677201581430874618e-03 7.615314113993682313e-03 1.700042512425950004e-04 6.156635540337338387e-05 9.437552276658168148e-05 1.636184653588275881e-05 6.184665501771761686e-08 -7.812496511241781051e-03 7.802139573436450704e-03 7.678360934842314196e-03 7.617224476854871258e-03 1.684368934514004535e-04 6.102002790153284524e-05 9.357839679933613655e-05 1.628189975863044079e-05 6.526686105702234742e-08 -7.812496219646037840e-03 7.801963573583982695e-03 7.679448409179731941e-03 7.619307392520942475e-03 1.667211245983212084e-04 6.059647760585791217e-05 9.290647870527361698e-05 1.611438596915572326e-05 5.944474959016087870e-08 -7.812496067262236082e-03 7.801724521784449314e-03 7.680207555690407410e-03 7.621215867234738643e-03 1.651611118942663268e-04 6.040796446319642645e-05 9.254061247558314075e-05 1.583289243326745281e-05 4.721294373152034348e-08 -7.812495939725520519e-03 7.801468805562560005e-03 7.680500815485480186e-03 7.622682332336906674e-03 1.639704408479166744e-04 6.049154736383084284e-05 9.255705934859457618e-05 1.545276710389118145e-05 3.486730501181152877e-08 -7.812495810392372161e-03 7.801245471614342251e-03 7.680293265591961113e-03 7.623542163437857511e-03 1.632627294083275303e-04 6.082500272239638590e-05 9.294827781949960212e-05 1.502481172788627132e-05 2.836530457701504368e-08 -7.812495774057383324e-03 7.801090398214164875e-03 7.679617741755038161e-03 7.623730980268567277e-03 1.630687270832232910e-04 6.135328767953494530e-05 9.365818359531991294e-05 1.461705702769232774e-05 3.062975683152378586e-08 -7.812496004572946559e-03 7.801019097885079565e-03 7.678544236128501121e-03 7.623267186730509938e-03 1.633636498553494383e-04 6.201144366886053398e-05 9.461157972898225999e-05 1.429342797726595519e-05 4.043850989161355651e-08 -7.812496631779798119e-03 7.801027496962795009e-03 7.677165776783217294e-03 7.622229199252808160e-03 1.640937838916600819e-04 6.273706605913448688e-05 9.572723457634188516e-05 1.409693806672889080e-05 5.277965583598395105e-08 -7.812497593986529945e-03 7.801096856079874943e-03 7.675599630972139084e-03 7.620731771399200105e-03 1.651974699868906436e-04 6.347246017827182240e-05 9.691547544110199126e-05 1.404137420550190033e-05 6.090756096056601143e-08 -7.812498566204971115e-03 7.801199754440974084e-03 7.673992897753495815e-03 7.618903661828040075e-03 1.666176502970805691e-04 6.416043472906765414e-05 9.806960623076769253e-05 1.411294308233202020e-05 5.993589060455973356e-08 -7.812499053771074925e-03 7.801305349386283491e-03 7.672518875246725489e-03 7.616869257773883906e-03 1.683046089823451085e-04 6.473936921646154048e-05 9.906343259329801248e-05 1.428210110113845229e-05 5.027682857905558417e-08 -7.812498632159666813e-03 7.801382900472925326e-03 7.671356652224933619e-03 7.614739595271466377e-03 1.702096434999436484e-04 6.514310541558802512e-05 9.976321818125709177e-05 1.452125443129783517e-05 3.829448713707502261e-08 -7.812497201837249015e-03 7.801403862531090978e-03 7.670657640407920266e-03 7.612615855838451850e-03 1.722743768132731137e-04 6.530927069172183942e-05 1.000534417096700466e-04 1.481781435146641011e-05 3.294263590754535029e-08 -7.812495078364333281e-03 7.801344666489945685e-03 7.670510553714322832e-03 7.610600036568103931e-03 1.744227893749939232e-04 6.519571551979745270e-05 9.986799788108100028e-05 1.517179567317124298e-05 4.016604303805187084e-08 -7.812492900103195845e-03 7.801192644470767747e-03 7.670919899304099940e-03 7.608803560422339532e-03 1.765599991482183864e-04 6.479804001506211746e-05 9.921318396850725772e-05 1.557572355818140049e-05 5.876129580872593247e-08 -7.812491399909044648e-03 7.800954310441960901e-03 7.671806713972414808e-03 7.607344211055998458e-03 1.785775612115598305e-04 6.415814227891146265e-05 9.817148076228197353e-05 1.599052210317778022e-05 8.069995376715356099e-08 -7.812491115931742038e-03 7.800660131530765505e-03 7.673033286305866278e-03 7.606329970254107307e-03 1.803626974654734159e-04 6.335517272175504935e-05 9.688053494765318523e-05 1.633939801180696436e-05 9.591747241806178274e-08 -7.812492133591250783e-03 7.800359190254140332e-03 7.674441600347642854e-03 7.605837575408820259e-03 1.818080321303487473e-04 6.248181849103899717e-05 9.549537823929271684e-05 1.653082719052810295e-05 9.833364655358530313e-08 -7.812494031046210430e-03 7.800102179172256622e-03 7.675896495846616999e-03 7.605897118576439818e-03 1.828226666389231193e-04 6.161441159967244615e-05 9.414446198404529656e-05 1.650237702724804381e-05 8.885369315965530215e-08 -7.812496052543584438e-03 7.799921303838168625e-03 7.677317282524499797e-03 7.606490090774489093e-03 1.833430573543588750e-04 6.079269373977964908e-05 9.289859503958730949e-05 1.625765820792788300e-05 7.334301113257308106e-08 -7.812497439077231015e-03 7.799819160821133690e-03 7.678687734277541560e-03 7.607558169686876905e-03 1.833426694457979708e-04 6.001769729579950902e-05 9.176364274852043203e-05 1.587269546633251967e-05 5.755832196158116801e-08 -7.812497729013648771e-03 7.799773549843452315e-03 7.680039522150496067e-03 7.609017003352169274e-03 1.828346147238102306e-04 5.926707271268964972e-05 9.069961910013031267e-05 1.546620639546001242e-05 4.367983950618309385e-08 -7.812496926672149108e-03 7.799752994451267067e-03 7.681416702438653189e-03 7.610766790791871801e-03 1.818667647155675722e-04 5.851800025715518221e-05 8.965562716129177984e-05 1.515316230951711319e-05 3.122579787001255668e-08 -7.812495468274187685e-03 7.799731951055652486e-03 7.682835526327059031e-03 7.612698745924777015e-03 1.805102346395485047e-04 5.776728284319049658e-05 8.860630501187015645e-05 1.500776599250491295e-05 2.081738234097757612e-08 -7.812494016638638072e-03 7.799697603207485230e-03 7.684256601122156811e-03 7.614700518728856164e-03 1.788464912402624996e-04 5.704162388654450915e-05 8.757577061659674008e-05 1.505214344464923625e-05 1.619689641452411641e-08 -7.812493190330011515e-03 7.799648584005202875e-03 7.685580722774925863e-03 7.616663927961365814e-03 1.769587121590053330e-04 5.639621921786125067e-05 8.664108488644773742e-05 1.526756760774609803e-05 2.164868747164934285e-08 -7.812493299653834079e-03 7.799590748379032698e-03 7.686670407032592141e-03 7.618494928507740273e-03 1.749302970073336380e-04 5.590279367022501475e-05 8.591411849626973997e-05 1.561254289370475563e-05 3.696860078954675002e-08 -7.812494265631523410e-03 7.799534011930964357e-03 7.687386700992878373e-03 7.620121303322026016e-03 1.728492941645273838e-04 5.563158007306383187e-05 8.550992286051971704e-05 1.603327927725472439e-05 5.520836506281878338e-08 -7.812495719581083985e-03 7.799488670675083432e-03 7.687630571093129368e-03 7.621494785823084046e-03 1.708138484432252554e-04 5.563085091837701400e-05 8.551007496670540967e-05 1.646635384646213534e-05 6.626114818767479494e-08 -7.812497205244232044e-03 7.799460270436679374e-03 7.687372984260292669e-03 7.622586576308315945e-03 1.689329458115936781e-04 5.591130652985255368e-05 8.593512815630114645e-05 1.684156091513745103e-05 6.387890909022737881e-08 +7.812499853032692752e-03 7.812500279798491667e-03 7.812350082550026734e-03 7.812350082567939488e-03 6.686717854768583909e-18 1.273966279961955695e-20 1.281536489683403687e-20 2.436224928051321290e-17 1.455721960673305505e-20 +7.812499853032699691e-03 7.812500279798476055e-03 7.812350082258740641e-03 7.812350082365753998e-03 1.490247763194331891e-17 1.077391542540353658e-17 9.648851966739274479e-18 2.698813529540607934e-17 3.969790221977746295e-20 +7.812499853032702293e-03 7.812500279798481259e-03 7.812350082258744978e-03 7.812350082365754865e-03 1.338629013537693114e-17 1.040157544868407331e-17 8.023705175726225935e-18 2.818645043139415115e-17 2.152965149171645697e-19 +7.812499853032704028e-03 7.812500279798481259e-03 7.812350082258739774e-03 7.812350082365751396e-03 1.050061327306201373e-17 1.018748243646475980e-17 1.255526088916916614e-17 2.884255147975228781e-17 9.256801281552135578e-19 +7.812499853032684079e-03 7.812500279798443095e-03 7.812350082258605333e-03 7.812350082365557974e-03 1.110234188146072923e-16 5.476475696791553340e-17 9.458349117056311261e-17 7.886970031758802209e-17 3.443302604107927034e-17 +7.812499853032585199e-03 7.812500279797884514e-03 7.812350082257480365e-03 7.812350082363527480e-03 1.221025990081458542e-15 5.277097822561900040e-16 8.042486056611601589e-16 6.609800012573974879e-16 3.388298157432289595e-16 +7.812499853032228714e-03 7.812500279794808850e-03 7.812350082251317759e-03 7.812350082352021927e-03 7.688773607708341558e-15 3.222952618985768202e-15 4.719067260205915655e-15 4.031146146161859528e-15 1.884039370417977416e-15 +7.812499853031174869e-03 7.812500279782960688e-03 7.812350082226447029e-03 7.812350082305783740e-03 3.459153926335484060e-14 1.423009475135000606e-14 2.065106717651520955e-14 1.758670007424376872e-14 7.474971242608616118e-15 +7.812499853028622224e-03 7.812500279747522022e-03 7.812350082146477144e-03 7.812350082159213484e-03 1.228145204190944378e-13 4.981559865801570222e-14 7.232334033967236660e-14 6.002620078048621925e-14 2.330673017550618989e-14 +7.812499853023407645e-03 7.812500279660945443e-03 7.812350081934199032e-03 7.812350081777151914e-03 3.610941462883710220e-13 1.446487842594735793e-13 2.106461858849508682e-13 1.682485411779086762e-13 5.969979759489234567e-14 +7.812499853014897092e-03 7.812500279486930127e-03 7.812350081463906824e-03 7.812350080947388573e-03 8.986578228190934686e-13 3.554742578353971945e-13 5.197792228478134614e-13 3.957470702999447474e-13 1.276867248607976924e-13 +7.812499853005088098e-03 7.812500279205564918e-03 7.812350080604125828e-03 7.812350079464436790e-03 1.902129002541687645e-12 7.419716841836609477e-13 1.090168097358521198e-12 7.836573236885160296e-13 2.269353059419004219e-13 +7.812499853000657614e-03 7.812500278866488929e-03 7.812350079367172580e-03 7.812350077389442968e-03 3.385603051914610680e-12 1.299293649069382529e-12 1.919379016255142377e-12 1.289038721443987301e-12 3.261388284048605778e-13 +7.812499853009330364e-03 7.812500278626734532e-03 7.812350078155607877e-03 7.812350075432913411e-03 4.901700794298826520e-12 1.845807442333131019e-12 2.742383323432933970e-12 1.711872500631155452e-12 3.618101175167228489e-13 +7.812499853018082911e-03 7.812500278590924635e-03 7.812350077802290675e-03 7.812350074866239967e-03 5.396993520182899994e-12 2.001504125631436744e-12 2.981955563864776735e-12 1.839553005394764809e-12 3.385082846655620411e-13 +7.812499852932987786e-03 7.812500278033927478e-03 7.812350078412555986e-03 7.812350075183738599e-03 4.315407145162125193e-12 1.703056079344719690e-12 2.468677803485621447e-12 2.361762504659291149e-12 6.950218203357612152e-13 +7.812499852466974273e-03 7.812500273374220830e-03 7.812350074989517223e-03 7.812350066099102777e-03 6.283159864873798714e-12 3.169681657633534525e-12 4.281083262384277953e-12 7.474396685349264012e-12 3.134461378552293558e-12 +7.812499851005201730e-03 7.812500254476032260e-03 7.812350047197313789e-03 7.812350009764495659e-03 3.267183280083109047e-11 1.552890608038603436e-11 2.153012832021432507e-11 2.999039571018929183e-11 1.192963004046087639e-11 +7.812499847572922963e-03 7.812500200162266970e-03 7.812349942262116105e-03 7.812349812582107186e-03 1.418939026414260175e-10 6.257923727216895362e-11 8.890829388137152469e-11 9.827167982682776205e-11 3.508698292183345656e-11 +7.812499841149679949e-03 7.812500076640842978e-03 7.812349656646455642e-03 7.812349297842300852e-03 4.531185304792351007e-10 1.911716241251917738e-10 2.754704942626815632e-10 2.605143014572550335e-10 8.366148061447493069e-11 +7.812499831578885272e-03 7.812499846019973354e-03 7.812349034944595511e-03 7.812348211501761626e-03 1.153088037609147093e-09 4.718569550809047194e-10 6.864440626384909332e-10 5.765652531795112974e-10 1.666204089618884149e-10 +7.812499820987390577e-03 7.812499492320172136e-03 7.812347918113238948e-03 7.812346312754753913e-03 2.447702082586668115e-09 9.771504459394998477e-10 1.432182592776262639e-09 1.085202190312603517e-09 2.797335493584696527e-10 +7.812499814740346896e-03 7.812499062254251760e-03 7.812346269952624885e-03 7.812343587535403380e-03 4.418222801594663738e-09 1.724018381710924485e-09 2.543369039502271716e-09 1.745678194287174871e-09 3.925477856832722905e-10 +7.812499819669653858e-03 7.812498690802675665e-03 7.812344360995931644e-03 7.812340529108604235e-03 6.791658385448597663e-09 2.589635535318124385e-09 3.843587174577796148e-09 2.388121726329547615e-09 4.486778634736386646e-10 +7.812499836541287289e-03 7.812498540333734538e-03 7.812342867626963228e-03 7.812338223696329957e-03 8.770998199078791133e-09 3.264672608722082367e-09 4.871569121144878528e-09 2.769177408961638509e-09 4.069975426300912668e-10 +7.812499844218311236e-03 7.812498550624985029e-03 7.812342564980947340e-03 7.812337706375470196e-03 9.284480356680769592e-09 3.391579366265826169e-09 5.070184887145676427e-09 2.882656183351129511e-09 3.547336710690416432e-10 +7.812499781849658459e-03 7.812497938502010325e-03 7.812343184217111422e-03 7.812337931984741912e-03 8.187553284667456409e-09 3.083966817157662608e-09 4.539467182508874874e-09 3.660704609143170800e-09 6.855413362771258625e-10 +7.812499539571283146e-03 7.812494543140142793e-03 7.812341152959785887e-03 7.812332057382916951e-03 8.841744470361763275e-09 3.960847677671831129e-09 5.566699818414017084e-09 7.988727728025107941e-09 2.269703900840955374e-09 +7.812498977478036198e-03 7.812484406984244664e-03 7.812326615005588636e-03 7.812302905420510403e-03 2.180228070163895656e-08 1.051910237351932575e-08 1.469509777326951620e-08 2.154800783639236158e-08 6.441336062768101019e-09 +7.812497994380795431e-03 7.812462264526452878e-03 7.812281302555792832e-03 7.812220353796601319e-03 6.797441971956459514e-08 3.112683845546636387e-08 4.428691811001559565e-08 5.250018216563952165e-08 1.458559667171380079e-08 +7.812496642031469159e-03 7.812423582450244049e-03 7.812180052545585236e-03 7.812045025095691250e-03 1.780202938069342282e-07 7.735204086169203320e-08 1.116600602934448646e-07 1.089078623714063587e-07 2.722494382585283444e-08 +7.812495230981619278e-03 7.812368096507126165e-03 7.811998844602665269e-03 7.811742231074614295e-03 3.842368801176499279e-07 1.602847291236858473e-07 2.337376488854461481e-07 1.935971465318801878e-07 4.285591415854843683e-08 +7.812494328139583770e-03 7.812303379348786367e-03 7.811729874197701103e-03 7.811305756875472177e-03 7.032546837354541918e-07 2.835793382204843004e-07 4.166897389954705580e-07 2.982177140607078031e-07 5.728193039849254671e-08 +7.812494550142056599e-03 7.812245427258719503e-03 7.811398810282921268e-03 7.810782527030078054e-03 1.113727748184818239e-06 4.354043797212895802e-07 6.437087438942030785e-07 4.008686263785850362e-07 6.449845579325761372e-08 +7.812496138080336598e-03 7.812212893856464342e-03 7.811072727768756351e-03 7.810279691796943348e-03 1.541461156476913746e-06 5.846309847418375274e-07 8.688045986117029490e-07 4.729147334166597758e-07 5.986995545985544601e-08 +7.812498445556872832e-03 7.812213704232950744e-03 7.810843583203532815e-03 7.809932136645577130e-03 1.870616030668633253e-06 6.884156571567480939e-07 1.027329365299366220e-06 4.981846542090092702e-07 4.512119076652669270e-08 +7.812499643314411817e-03 7.812227465998996048e-03 7.810777050788949953e-03 7.809818584425421741e-03 1.996915864576686549e-06 7.162014155120878158e-07 1.070908963295831547e-06 5.007358000999807850e-07 3.290430957355282637e-08 +7.812497004583882597e-03 7.812192420099366673e-03 7.810833005781974391e-03 7.809841229764222931e-03 1.921887432159646985e-06 6.874135529587402941e-07 1.023172530687733249e-06 5.684268623121463193e-07 4.737660114594148372e-08 +7.812487977686922644e-03 7.812008194689230509e-03 7.810787695955377988e-03 7.809619485122610769e-03 1.857942469276308112e-06 7.085479518432960039e-07 1.035821288261976948e-06 8.540461262419201573e-07 1.176737671272773021e-07 +7.812471748767348123e-03 7.811562352071302860e-03 7.810207234515143850e-03 7.808473164261869534e-03 2.285569265615626913e-06 9.854058759137348325e-07 1.409932401056303498e-06 1.539858543220769961e-06 2.640648030851998174e-07 +7.812450529143469789e-03 7.810779042843053223e-03 7.808519956579640028e-03 7.805560882451594018e-03 3.896605580814575925e-06 1.787075451064486949e-06 2.548005225924580296e-06 2.765201026029978535e-06 4.813926593788763635e-07 +7.812429661862023596e-03 7.809674641149721812e-03 7.805202887404326904e-03 7.800181116207064586e-03 7.390363320579293810e-06 3.354519377221000757e-06 4.824207063860702588e-06 4.537698916556045439e-06 7.287005859073173523e-07 +7.812416165084923141e-03 7.808393536111879127e-03 7.800038510484820671e-03 7.792149825718211638e-03 1.316122584248707086e-05 5.776773434575371999e-06 8.402178779544433807e-06 6.667369014382867723e-06 9.343828152441929552e-07 +7.812415835781623234e-03 7.807194132714686402e-03 7.793337863448148058e-03 7.782082517240840498e-03 2.099925837947448981e-05 8.887746642244384300e-06 1.307323485563547160e-05 8.770203536976671789e-06 1.021168349833567159e-06 +7.812430158111208570e-03 7.806368467992530306e-03 7.786000020659196962e-03 7.771393248244110735e-03 2.996771098010651084e-05 1.224706928486793432e-05 1.820790009944723024e-05 1.037469218978934016e-05 9.437824387095230784e-07 +7.812454690656026220e-03 7.806110337177065567e-03 7.779316215103107730e-03 7.761914895057454335e-03 3.858110769296473004e-05 1.524525220567434296e-05 2.288872843530340110e-05 1.112352046586807781e-05 7.209921399975341084e-07 +7.812480201788416824e-03 7.806386805941349476e-03 7.774529785912486640e-03 7.755223553030285953e-03 4.528347453745602184e-05 1.731960264508936400e-05 2.622053730063316743e-05 1.100113352190226156e-05 4.399041900332164704e-07 +7.812496176044654919e-03 7.806891664948079936e-03 7.772291495159932770e-03 7.751926368829008263e-03 4.907275643454239819e-05 1.820754084061740197e-05 2.772288834078687984e-05 1.046061247568982606e-05 2.225225911981681611e-07 +7.812495292061822673e-03 7.807139215375609106e-03 7.772241751786874986e-03 7.751242393952807209e-03 5.001574978626547913e-05 1.812741955189118513e-05 2.764027203504243102e-05 1.032613486388670125e-05 1.665620513368287718e-07 +7.812476894523122731e-03 7.806683943209593787e-03 7.772945300038862533e-03 7.751111453457110168e-03 4.940863028517055046e-05 1.778892355151607562e-05 2.700354558676601411e-05 1.144278173216673945e-05 2.931356705096467600e-07 +7.812447633371830819e-03 7.805360622923213781e-03 7.772280325110742481e-03 7.748841300394401430e-03 4.946498788292683508e-05 1.819664607815776332e-05 2.735932394244346047e-05 1.421182877230432772e-05 5.348146728831700359e-07 +7.812418676200951796e-03 7.803399072295380545e-03 7.768182598560221565e-03 7.742056677893807692e-03 5.260502689341779259e-05 2.029938517503130136e-05 3.022889388385826916e-05 1.827918656212739249e-05 7.737969837445373764e-07 +7.812400713050573174e-03 7.801328899352429937e-03 7.759458933900293363e-03 7.729571012333778281e-03 6.059554765283085880e-05 2.461554399679295580e-05 3.650070756930909251e-05 2.260937471593158608e-05 9.062974796379607276e-07 +7.812399402924678250e-03 7.799725111593778897e-03 7.746317787884777345e-03 7.711834931169255294e-03 7.387281172230948569e-05 3.099207090489362784e-05 4.602122468061838116e-05 2.595267368927323958e-05 8.916091203328781368e-07 +7.812413332542555815e-03 7.798951317677097449e-03 7.730372562608386205e-03 7.690803617564479985e-03 9.132598392869010779e-05 3.860912329843406692e-05 5.757879489393928250e-05 2.744243129201358010e-05 7.582080085956336064e-07 +7.812435655750508100e-03 7.799045564899258556e-03 7.714106581128725958e-03 7.669307408003667517e-03 1.106354824953435383e-04 4.624173039586804786e-05 6.930319478072197116e-05 2.696493794476126531e-05 5.706638856372884918e-07 +7.812458049977899846e-03 7.799779002849843365e-03 7.700032119112999729e-03 7.650185626982551265e-03 1.290317728818038228e-04 5.267491242189746055e-05 7.931021912472004868e-05 2.510498190276937440e-05 3.874743003157170213e-07 +7.812474472833470102e-03 7.800806553791946735e-03 7.689895100482323394e-03 7.635495440478613609e-03 1.441671433054891155e-04 5.710082886942940348e-05 8.631673803264112315e-05 2.275885910941017286e-05 2.386244849668603841e-07 +7.812482976849034755e-03 7.801806678970187037e-03 7.684226346611384290e-03 7.626043122362352773e-03 1.547629942338338998e-04 5.933866733362661114e-05 8.998326647379967301e-05 2.069121747385026391e-05 1.297730912415325758e-07 +7.812485232220344605e-03 7.802559641047198541e-03 7.682363107231317788e-03 7.621351204389437833e-03 1.608167121281512204e-04 5.980453704693076267e-05 9.088196765691194143e-05 1.927999912557097661e-05 5.844008953976879205e-08 +7.812484687099224487e-03 7.802969819103481100e-03 7.682863284657014818e-03 7.620020195549746453e-03 1.633555907751381572e-04 5.927321903152686335e-05 9.015594799946130046e-05 1.851857110723650212e-05 2.355680679308437475e-08 +7.812484528579055273e-03 7.803053725096873068e-03 7.684099485053701856e-03 7.620313644105695082e-03 1.639054050789472161e-04 5.855667006084784424e-05 8.904796951092744850e-05 1.818147643885591132e-05 2.259562066722161082e-08 +7.812486347732097020e-03 7.802906138662985686e-03 7.684792010505495964e-03 7.620734657771241656e-03 1.639180799370792388e-04 5.823836154829621197e-05 8.849453651262909287e-05 1.801056113072297418e-05 4.482718225915012074e-08 +7.812489966877368686e-03 7.802652857458577430e-03 7.684311301855815610e-03 7.620397450278489949e-03 1.643642387066439835e-04 5.854960502899452695e-05 8.891359154098924097e-05 1.782919431049579911e-05 7.161912630444491773e-08 +7.812494127122805894e-03 7.802404580937485380e-03 7.682698807419341414e-03 7.619109876382451629e-03 1.655862811202974880e-04 5.939615713527549305e-05 9.021286715380141135e-05 1.757035112025118347e-05 8.559997302272443172e-08 +7.812497470211249989e-03 7.802228932425433333e-03 7.680464665858448801e-03 7.617210995022639063e-03 1.673906019698739671e-04 6.048444806446939652e-05 9.196185539774789648e-05 1.725117344749978250e-05 8.071052106673271989e-08 +7.812499262283496664e-03 7.802147068445501599e-03 7.678284905384741635e-03 7.615288498122666817e-03 1.692825327983098758e-04 6.147641588181483141e-05 9.362872093630432619e-05 1.693047970507380231e-05 6.424811185473353517e-08 +7.812499556017950091e-03 7.802145493693739449e-03 7.676725520415324244e-03 7.613906859695971675e-03 1.707300961208414974e-04 6.211532079841483437e-05 9.478777861569192588e-05 1.666872075534763098e-05 4.957518521111539337e-08 +7.812498898940323407e-03 7.802189426919653448e-03 7.676076529785660213e-03 7.613428103579155878e-03 1.713654284443885114e-04 6.229347725606795285e-05 9.523952736898054429e-05 1.649883460424523220e-05 4.584613527028352739e-08 +7.812497920560946760e-03 7.802232495060661827e-03 7.676319544958354509e-03 7.613946242661542678e-03 1.710785375910244487e-04 6.205778441104415428e-05 9.502791401655731585e-05 1.641215865889956077e-05 5.255976528493730751e-08 +7.812497066894792501e-03 7.802227167898124344e-03 7.677201581430874618e-03 7.615314113993682313e-03 1.700042512425950004e-04 6.156635540337338387e-05 9.437552276658168148e-05 1.636184653588275881e-05 6.184665501771761686e-08 +7.812496511241781051e-03 7.802139573436450704e-03 7.678360934842314196e-03 7.617224476854871258e-03 1.684368934514004535e-04 6.102002790153284524e-05 9.357839679933613655e-05 1.628189975863044079e-05 6.526686105702234742e-08 +7.812496219646037840e-03 7.801963573583982695e-03 7.679448409179731941e-03 7.619307392520942475e-03 1.667211245983212084e-04 6.059647760585791217e-05 9.290647870527361698e-05 1.611438596915572326e-05 5.944474959016087870e-08 +7.812496067262236082e-03 7.801724521784449314e-03 7.680207555690407410e-03 7.621215867234738643e-03 1.651611118942663268e-04 6.040796446319642645e-05 9.254061247558314075e-05 1.583289243326745281e-05 4.721294373152034348e-08 +7.812495939725520519e-03 7.801468805562560005e-03 7.680500815485480186e-03 7.622682332336906674e-03 1.639704408479166744e-04 6.049154736383084284e-05 9.255705934859457618e-05 1.545276710389118145e-05 3.486730501181152877e-08 +7.812495810392372161e-03 7.801245471614342251e-03 7.680293265591961113e-03 7.623542163437857511e-03 1.632627294083275303e-04 6.082500272239638590e-05 9.294827781949960212e-05 1.502481172788627132e-05 2.836530457701504368e-08 +7.812495774057383324e-03 7.801090398214164875e-03 7.679617741755038161e-03 7.623730980268567277e-03 1.630687270832232910e-04 6.135328767953494530e-05 9.365818359531991294e-05 1.461705702769232774e-05 3.062975683152378586e-08 +7.812496004572946559e-03 7.801019097885079565e-03 7.678544236128501121e-03 7.623267186730509938e-03 1.633636498553494383e-04 6.201144366886053398e-05 9.461157972898225999e-05 1.429342797726595519e-05 4.043850989161355651e-08 +7.812496631779798119e-03 7.801027496962795009e-03 7.677165776783217294e-03 7.622229199252808160e-03 1.640937838916600819e-04 6.273706605913448688e-05 9.572723457634188516e-05 1.409693806672889080e-05 5.277965583598395105e-08 +7.812497593986529945e-03 7.801096856079874943e-03 7.675599630972139084e-03 7.620731771399200105e-03 1.651974699868906436e-04 6.347246017827182240e-05 9.691547544110199126e-05 1.404137420550190033e-05 6.090756096056601143e-08 +7.812498566204971115e-03 7.801199754440974084e-03 7.673992897753495815e-03 7.618903661828040075e-03 1.666176502970805691e-04 6.416043472906765414e-05 9.806960623076769253e-05 1.411294308233202020e-05 5.993589060455973356e-08 +7.812499053771074925e-03 7.801305349386283491e-03 7.672518875246725489e-03 7.616869257773883906e-03 1.683046089823451085e-04 6.473936921646154048e-05 9.906343259329801248e-05 1.428210110113845229e-05 5.027682857905558417e-08 +7.812498632159666813e-03 7.801382900472925326e-03 7.671356652224933619e-03 7.614739595271466377e-03 1.702096434999436484e-04 6.514310541558802512e-05 9.976321818125709177e-05 1.452125443129783517e-05 3.829448713707502261e-08 +7.812497201837249015e-03 7.801403862531090978e-03 7.670657640407920266e-03 7.612615855838451850e-03 1.722743768132731137e-04 6.530927069172183942e-05 1.000534417096700466e-04 1.481781435146641011e-05 3.294263590754535029e-08 +7.812495078364333281e-03 7.801344666489945685e-03 7.670510553714322832e-03 7.610600036568103931e-03 1.744227893749939232e-04 6.519571551979745270e-05 9.986799788108100028e-05 1.517179567317124298e-05 4.016604303805187084e-08 +7.812492900103195845e-03 7.801192644470767747e-03 7.670919899304099940e-03 7.608803560422339532e-03 1.765599991482183864e-04 6.479804001506211746e-05 9.921318396850725772e-05 1.557572355818140049e-05 5.876129580872593247e-08 +7.812491399909044648e-03 7.800954310441960901e-03 7.671806713972414808e-03 7.607344211055998458e-03 1.785775612115598305e-04 6.415814227891146265e-05 9.817148076228197353e-05 1.599052210317778022e-05 8.069995376715356099e-08 +7.812491115931742038e-03 7.800660131530765505e-03 7.673033286305866278e-03 7.606329970254107307e-03 1.803626974654734159e-04 6.335517272175504935e-05 9.688053494765318523e-05 1.633939801180696436e-05 9.591747241806178274e-08 +7.812492133591250783e-03 7.800359190254140332e-03 7.674441600347642854e-03 7.605837575408820259e-03 1.818080321303487473e-04 6.248181849103899717e-05 9.549537823929271684e-05 1.653082719052810295e-05 9.833364655358530313e-08 +7.812494031046210430e-03 7.800102179172256622e-03 7.675896495846616999e-03 7.605897118576439818e-03 1.828226666389231193e-04 6.161441159967244615e-05 9.414446198404529656e-05 1.650237702724804381e-05 8.885369315965530215e-08 +7.812496052543584438e-03 7.799921303838168625e-03 7.677317282524499797e-03 7.606490090774489093e-03 1.833430573543588750e-04 6.079269373977964908e-05 9.289859503958730949e-05 1.625765820792788300e-05 7.334301113257308106e-08 +7.812497439077231015e-03 7.799819160821133690e-03 7.678687734277541560e-03 7.607558169686876905e-03 1.833426694457979708e-04 6.001769729579950902e-05 9.176364274852043203e-05 1.587269546633251967e-05 5.755832196158116801e-08 +7.812497729013648771e-03 7.799773549843452315e-03 7.680039522150496067e-03 7.609017003352169274e-03 1.828346147238102306e-04 5.926707271268964972e-05 9.069961910013031267e-05 1.546620639546001242e-05 4.367983950618309385e-08 +7.812496926672149108e-03 7.799752994451267067e-03 7.681416702438653189e-03 7.610766790791871801e-03 1.818667647155675722e-04 5.851800025715518221e-05 8.965562716129177984e-05 1.515316230951711319e-05 3.122579787001255668e-08 +7.812495468274187685e-03 7.799731951055652486e-03 7.682835526327059031e-03 7.612698745924777015e-03 1.805102346395485047e-04 5.776728284319049658e-05 8.860630501187015645e-05 1.500776599250491295e-05 2.081738234097757612e-08 +7.812494016638638072e-03 7.799697603207485230e-03 7.684256601122156811e-03 7.614700518728856164e-03 1.788464912402624996e-04 5.704162388654450915e-05 8.757577061659674008e-05 1.505214344464923625e-05 1.619689641452411641e-08 +7.812493190330011515e-03 7.799648584005202875e-03 7.685580722774925863e-03 7.616663927961365814e-03 1.769587121590053330e-04 5.639621921786125067e-05 8.664108488644773742e-05 1.526756760774609803e-05 2.164868747164934285e-08 +7.812493299653834079e-03 7.799590748379032698e-03 7.686670407032592141e-03 7.618494928507740273e-03 1.749302970073336380e-04 5.590279367022501475e-05 8.591411849626973997e-05 1.561254289370475563e-05 3.696860078954675002e-08 +7.812494265631523410e-03 7.799534011930964357e-03 7.687386700992878373e-03 7.620121303322026016e-03 1.728492941645273838e-04 5.563158007306383187e-05 8.550992286051971704e-05 1.603327927725472439e-05 5.520836506281878338e-08 +7.812495719581083985e-03 7.799488670675083432e-03 7.687630571093129368e-03 7.621494785823084046e-03 1.708138484432252554e-04 5.563085091837701400e-05 8.551007496670540967e-05 1.646635384646213534e-05 6.626114818767479494e-08 +7.812497205244232044e-03 7.799460270436679374e-03 7.687372984260292669e-03 7.622586576308315945e-03 1.689329458115936781e-04 5.591130652985255368e-05 8.593512815630114645e-05 1.684156091513745103e-05 6.387890909022737881e-08 From 2685560654446436bdb1274f2143682473b21188 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 18:04:32 +0800 Subject: [PATCH 02/13] Normalize whitespace in legacy text files --- examples/22_rt-tddft/01_H2_length_gauge/STRU | 46 +- .../22_rt-tddft/02_H2_velocity_gauge/STRU | 46 +- source/source_base/test/tool_title_test.cpp | 116 +-- source/source_estate/module_pot/pot_cosikr.h | 70 +- source/source_hamilt/test/dnrm2_test.cpp | 86 +- .../source_io/module_chgpot/write_libxc_r.h | 108 +- source/source_lcao/module_ri/Exx_LRI.h | 270 ++--- source/source_lcao/module_ri/LRI_CV.h | 284 +++--- source/source_lcao/module_ri/LRI_CV.hpp | 932 +++++++++--------- .../source_lcao/module_ri/Matrix_Orbs11.cpp | 294 +++--- source/source_lcao/module_ri/Matrix_Orbs11.h | 166 ++-- .../source_lcao/module_ri/Matrix_Orbs11.hpp | 320 +++--- .../source_lcao/module_ri/Matrix_Orbs21.cpp | 398 ++++---- source/source_lcao/module_ri/Matrix_Orbs21.h | 184 ++-- .../source_lcao/module_ri/Matrix_Orbs21.hpp | 440 ++++----- .../source_lcao/module_ri/Matrix_Orbs22.cpp | 346 +++---- source/source_lcao/module_ri/Matrix_Orbs22.h | 236 ++--- source/source_lcao/module_ri/RI_2D_Comm.h | 278 +++--- source/source_lcao/module_ri/RI_Util.h | 164 +-- source/source_lcao/module_ri/RI_Util.hpp | 344 +++---- .../module_ri/test_code/Inverse_Matrix-test.h | 274 ++--- tests/01_PW/074_PW_SY_LiRH/INPUT | 81 +- tests/05_rtTDDFT/17_NO_vel_TDDFT/INPUT | 93 +- tests/05_rtTDDFT/18_NO_hyb_TDDFT/INPUT | 87 +- tests/08_EXX/14_NO_TDDFT_PBE0/INPUT | 100 +- .../15_rtTDDFT_GPU/17_NO_vel_TDDFT_GPU/INPUT | 95 +- .../15_rtTDDFT_GPU/18_NO_hyb_TDDFT_GPU/INPUT | 89 +- .../SIAB/src_parallel/parallel_global.cpp | 128 +-- tools/01_NAO_generation/pytorch/inverse.py | 110 +-- .../pytorch/opt_orbital.py_real | 170 ++-- .../pytorch/torch_complex.py | 164 +-- .../pytorch/unittest_inverse.py | 56 +- .../pytorch_dpsi/IO/change_info.py | 196 ++-- .../pytorch_dpsi/torch_complex_bak.py | 166 ++-- .../pytorch_gradient_source/inverse.py | 110 +-- .../opt_orbital.py_real | 170 ++-- .../pytorch_gradient_source/torch_complex.py | 164 +-- .../unittest_inverse.py | 56 +- 38 files changed, 3736 insertions(+), 3701 deletions(-) diff --git a/examples/22_rt-tddft/01_H2_length_gauge/STRU b/examples/22_rt-tddft/01_H2_length_gauge/STRU index 5086c31bdf7..d178dcd38f8 100644 --- a/examples/22_rt-tddft/01_H2_length_gauge/STRU +++ b/examples/22_rt-tddft/01_H2_length_gauge/STRU @@ -1,23 +1,23 @@ -ATOMIC_SPECIES -H 1.008 H_ONCV_PBE-1.0.upf - -NUMERICAL_ORBITAL -1_H_gga_100Ry_7au_2s1p.orb - -LATTICE_CONSTANT -1.8897261258369282 - -LATTICE_VECTORS -10.000100000 0.0000000000 0.0000000000 -0.0000000000 10.006500000 0.0000000000 -0.0000000000 0.0000000000 10.740000000 - -ATOMIC_POSITIONS -Direct - -H -0.0000000000 -2 -0.4999950000 0.4996750000 0.5344510000 m 0 0 0 -0.5000050000 0.5003250000 0.4655490000 m 0 0 0 - +ATOMIC_SPECIES +H 1.008 H_ONCV_PBE-1.0.upf + +NUMERICAL_ORBITAL +1_H_gga_100Ry_7au_2s1p.orb + +LATTICE_CONSTANT +1.8897261258369282 + +LATTICE_VECTORS +10.000100000 0.0000000000 0.0000000000 +0.0000000000 10.006500000 0.0000000000 +0.0000000000 0.0000000000 10.740000000 + +ATOMIC_POSITIONS +Direct + +H +0.0000000000 +2 +0.4999950000 0.4996750000 0.5344510000 m 0 0 0 +0.5000050000 0.5003250000 0.4655490000 m 0 0 0 + diff --git a/examples/22_rt-tddft/02_H2_velocity_gauge/STRU b/examples/22_rt-tddft/02_H2_velocity_gauge/STRU index 5086c31bdf7..d178dcd38f8 100644 --- a/examples/22_rt-tddft/02_H2_velocity_gauge/STRU +++ b/examples/22_rt-tddft/02_H2_velocity_gauge/STRU @@ -1,23 +1,23 @@ -ATOMIC_SPECIES -H 1.008 H_ONCV_PBE-1.0.upf - -NUMERICAL_ORBITAL -1_H_gga_100Ry_7au_2s1p.orb - -LATTICE_CONSTANT -1.8897261258369282 - -LATTICE_VECTORS -10.000100000 0.0000000000 0.0000000000 -0.0000000000 10.006500000 0.0000000000 -0.0000000000 0.0000000000 10.740000000 - -ATOMIC_POSITIONS -Direct - -H -0.0000000000 -2 -0.4999950000 0.4996750000 0.5344510000 m 0 0 0 -0.5000050000 0.5003250000 0.4655490000 m 0 0 0 - +ATOMIC_SPECIES +H 1.008 H_ONCV_PBE-1.0.upf + +NUMERICAL_ORBITAL +1_H_gga_100Ry_7au_2s1p.orb + +LATTICE_CONSTANT +1.8897261258369282 + +LATTICE_VECTORS +10.000100000 0.0000000000 0.0000000000 +0.0000000000 10.006500000 0.0000000000 +0.0000000000 0.0000000000 10.740000000 + +ATOMIC_POSITIONS +Direct + +H +0.0000000000 +2 +0.4999950000 0.4996750000 0.5344510000 m 0 0 0 +0.5000050000 0.5003250000 0.4655490000 m 0 0 0 + diff --git a/source/source_base/test/tool_title_test.cpp b/source/source_base/test/tool_title_test.cpp index 0fbe7096170..fd8f1d66095 100644 --- a/source/source_base/test/tool_title_test.cpp +++ b/source/source_base/test/tool_title_test.cpp @@ -1,58 +1,58 @@ -#include "../tool_title.h" -#include "../global_variable.h" -#include "gtest/gtest.h" -#include "gmock/gmock.h" - -/************************************************ - * unit test of functions in tool_title.h - ***********************************************/ - -/** - * - Tested Function - * - ModuleBase::TITLE - * - Output title for each function. - */ - -class ToolTitleTest : public testing::Test -{ - protected: - std::ifstream ifs; - const std::string claname="ComplexMatrix"; - const std::string funname="scaled_sum()"; - const std::string cfname="ComplexMatrix::scaled_sum()"; - void SetUp() - { - - } - void TearDown() - { - remove("TITLEtest2.log"); - remove("TITLEtest3.log"); - } -}; - -TEST_F(ToolTitleTest, TITLE2) -{ - GlobalV::ofs_running.open("TITLEtest2.log"); - std::string output2; - ModuleBase::TITLE(claname,funname,false); - GlobalV::ofs_running.close(); - ifs.open("TITLEtest2.log"); - getline(ifs,output2); - EXPECT_THAT(output2,testing::HasSubstr(" ==> ComplexMatrix::scaled_sum()")); - ifs.close(); -} - -TEST_F(ToolTitleTest, TITLE3) -{ - std::ofstream oofs; - std::string output3a; - std::string output3b; - oofs.open("TITLEtest3.log"); - ModuleBase::TITLE(oofs,claname,funname,false); - oofs.close(); - ifs.open("TITLEtest3.log"); - getline(ifs,output3a); - EXPECT_THAT(output3a,testing::HasSubstr(" ==> ComplexMatrix::scaled_sum()")); - ifs.close(); -} +#include "../tool_title.h" +#include "../global_variable.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +/************************************************ + * unit test of functions in tool_title.h + ***********************************************/ + +/** + * - Tested Function + * - ModuleBase::TITLE + * - Output title for each function. + */ + +class ToolTitleTest : public testing::Test +{ + protected: + std::ifstream ifs; + const std::string claname="ComplexMatrix"; + const std::string funname="scaled_sum()"; + const std::string cfname="ComplexMatrix::scaled_sum()"; + void SetUp() + { + + } + void TearDown() + { + remove("TITLEtest2.log"); + remove("TITLEtest3.log"); + } +}; + +TEST_F(ToolTitleTest, TITLE2) +{ + GlobalV::ofs_running.open("TITLEtest2.log"); + std::string output2; + ModuleBase::TITLE(claname,funname,false); + GlobalV::ofs_running.close(); + ifs.open("TITLEtest2.log"); + getline(ifs,output2); + EXPECT_THAT(output2,testing::HasSubstr(" ==> ComplexMatrix::scaled_sum()")); + ifs.close(); +} + +TEST_F(ToolTitleTest, TITLE3) +{ + std::ofstream oofs; + std::string output3a; + std::string output3b; + oofs.open("TITLEtest3.log"); + ModuleBase::TITLE(oofs,claname,funname,false); + oofs.close(); + ifs.open("TITLEtest3.log"); + getline(ifs,output3a); + EXPECT_THAT(output3a,testing::HasSubstr(" ==> ComplexMatrix::scaled_sum()")); + ifs.close(); +} diff --git a/source/source_estate/module_pot/pot_cosikr.h b/source/source_estate/module_pot/pot_cosikr.h index d6953a5dfe6..7e144e548ea 100644 --- a/source/source_estate/module_pot/pot_cosikr.h +++ b/source/source_estate/module_pot/pot_cosikr.h @@ -1,36 +1,36 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2025-10-05 -//======================= - -#ifndef POT_COSIKR_H -#define POT_COSIKR_H - -#include "pot_base.h" -#include "source_base/vector3.h" - - -namespace elecstate -{ - -// ampitude * cos( 2pi*( k * r + phase ) ) -class Pot_Cosikr : public PotBase -{ - public: - Pot_Cosikr( - const ModulePW::PW_Basis* rho_basis_in, - const ModuleBase::Vector3 &kvec_d_in, - const std::vector &phase_in, - const std::vector &litude_in); - - void cal_v_eff(const Charge*const chg, const UnitCell*const ucell, ModuleBase::matrix &v_eff) override; - - private: - const ModuleBase::Vector3 kvec_d; - const std::vector phase; - const std::vector amplitude; -}; - -} - +//======================= +// AUTHOR : Peize Lin +// DATE : 2025-10-05 +//======================= + +#ifndef POT_COSIKR_H +#define POT_COSIKR_H + +#include "pot_base.h" +#include "source_base/vector3.h" + + +namespace elecstate +{ + +// ampitude * cos( 2pi*( k * r + phase ) ) +class Pot_Cosikr : public PotBase +{ + public: + Pot_Cosikr( + const ModulePW::PW_Basis* rho_basis_in, + const ModuleBase::Vector3 &kvec_d_in, + const std::vector &phase_in, + const std::vector &litude_in); + + void cal_v_eff(const Charge*const chg, const UnitCell*const ucell, ModuleBase::matrix &v_eff) override; + + private: + const ModuleBase::Vector3 kvec_d; + const std::vector phase; + const std::vector amplitude; +}; + +} + #endif \ No newline at end of file diff --git a/source/source_hamilt/test/dnrm2_test.cpp b/source/source_hamilt/test/dnrm2_test.cpp index bc6a6e31c92..8c868c125e9 100644 --- a/source/source_hamilt/test/dnrm2_test.cpp +++ b/source/source_hamilt/test/dnrm2_test.cpp @@ -1,43 +1,43 @@ -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include "../module_ewald/dnrm2.h" - -/************************************************ - * unit test of dnrm2.cpp - ***********************************************/ - -/** - * - Tested Functions: - * - dnrm2(const int n, const double *x, const int incx): - * - compute the Euclidean length (12 norm) of std::vector x, - * with scaling of input to avoid destructive underflow and overflow - */ - -class EwaldTest : public ::testing::Test -{ - -}; - -TEST_F(EwaldTest,Dnrm2Test) -{ - std::string output; - double x[3]={1.5,2.5,3.5} ; - int incx1=1; - int n1=-1; - int n2=0; - int n3=3; - // case 1 - testing :: internal :: CaptureStderr(); - EXPECT_EQ(dnrm2(n1,x,incx1), 0); - output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output,testing::HasSubstr("error in dnrm2, n < 0 or incx <= 0,")); - testing :: internal :: CaptureStderr(); - EXPECT_EQ(dnrm2(n3,x,0), 0); - output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output,testing::HasSubstr("error in dnrm2, n < 0 or incx <= 0,")); - // case 2 - EXPECT_EQ(dnrm2(n2,x,incx1), 0); - // case 3 - EXPECT_EQ(dnrm2(n3,x,incx1), sqrt(1.5*1.5+2.5*2.5+3.5*3.5)); -} - +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../module_ewald/dnrm2.h" + +/************************************************ + * unit test of dnrm2.cpp + ***********************************************/ + +/** + * - Tested Functions: + * - dnrm2(const int n, const double *x, const int incx): + * - compute the Euclidean length (12 norm) of std::vector x, + * with scaling of input to avoid destructive underflow and overflow + */ + +class EwaldTest : public ::testing::Test +{ + +}; + +TEST_F(EwaldTest,Dnrm2Test) +{ + std::string output; + double x[3]={1.5,2.5,3.5} ; + int incx1=1; + int n1=-1; + int n2=0; + int n3=3; + // case 1 + testing :: internal :: CaptureStderr(); + EXPECT_EQ(dnrm2(n1,x,incx1), 0); + output = testing::internal::GetCapturedStderr(); + EXPECT_THAT(output,testing::HasSubstr("error in dnrm2, n < 0 or incx <= 0,")); + testing :: internal :: CaptureStderr(); + EXPECT_EQ(dnrm2(n3,x,0), 0); + output = testing::internal::GetCapturedStderr(); + EXPECT_THAT(output,testing::HasSubstr("error in dnrm2, n < 0 or incx <= 0,")); + // case 2 + EXPECT_EQ(dnrm2(n2,x,incx1), 0); + // case 3 + EXPECT_EQ(dnrm2(n3,x,incx1), sqrt(1.5*1.5+2.5*2.5+3.5*3.5)); +} + diff --git a/source/source_io/module_chgpot/write_libxc_r.h b/source/source_io/module_chgpot/write_libxc_r.h index d5464998eaa..db9b3b62ffb 100644 --- a/source/source_io/module_chgpot/write_libxc_r.h +++ b/source/source_io/module_chgpot/write_libxc_r.h @@ -1,54 +1,54 @@ -//====================== -// AUTHOR : Peize Lin -// DATE : 2024-09-12 -//====================== - -#ifndef WRITE_LIBXC_R_H -#define WRITE_LIBXC_R_H - -#ifdef USE_LIBXC - -#include -#include - -class Charge; -namespace ModulePW{ class PW_Basis_Big; } -namespace ModulePW{ class PW_Basis; } - -namespace ModuleIO -{ - extern void write_libxc_r( - const int order, - const std::vector &func_id, - const int &nrxx, // number of real-space grid - const double &omega, // volume of cell - const double tpiba, - const Charge &chr, - const ModulePW::PW_Basis_Big &pw_big, - const ModulePW::PW_Basis &pw_rhod); - - #ifdef __MPI - extern void write_cube_core( - std::ofstream &ofs_cube, - const int bz, - const int nbz, - const int nplane, - const int startz_current, - const double*const data, - const int nxy, - const int nz, - const int nld, - const int n_data_newline); - #else - extern void write_cube_core( - std::ofstream &ofs_cube, - const double*const data, - const int nxy, - const int nz, - const int n_data_newline); - #endif -} - -#endif // USE_LIBXC - -#endif // WRITE_LIBXC_R_H +//====================== +// AUTHOR : Peize Lin +// DATE : 2024-09-12 +//====================== + +#ifndef WRITE_LIBXC_R_H +#define WRITE_LIBXC_R_H + +#ifdef USE_LIBXC + +#include +#include + +class Charge; +namespace ModulePW{ class PW_Basis_Big; } +namespace ModulePW{ class PW_Basis; } + +namespace ModuleIO +{ + extern void write_libxc_r( + const int order, + const std::vector &func_id, + const int &nrxx, // number of real-space grid + const double &omega, // volume of cell + const double tpiba, + const Charge &chr, + const ModulePW::PW_Basis_Big &pw_big, + const ModulePW::PW_Basis &pw_rhod); + + #ifdef __MPI + extern void write_cube_core( + std::ofstream &ofs_cube, + const int bz, + const int nbz, + const int nplane, + const int startz_current, + const double*const data, + const int nxy, + const int nz, + const int nld, + const int n_data_newline); + #else + extern void write_cube_core( + std::ofstream &ofs_cube, + const double*const data, + const int nxy, + const int nz, + const int n_data_newline); + #endif +} + +#endif // USE_LIBXC + +#endif // WRITE_LIBXC_R_H diff --git a/source/source_lcao/module_ri/Exx_LRI.h b/source/source_lcao/module_ri/Exx_LRI.h index b25958ad65f..5b145de9fb3 100644 --- a/source/source_lcao/module_ri/Exx_LRI.h +++ b/source/source_lcao/module_ri/Exx_LRI.h @@ -1,142 +1,142 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef EXX_LRI_H -#define EXX_LRI_H - -#include "LRI_CV.h" -#include "ewald_Vq.h" -#include "source_hamilt/module_xc/exx_info.h" -#include "source_basis/module_ao/ORB_atomic_lm.h" -#include "source_base/matrix.h" -#include - -#include -#include -#include -#include -#include - -#include "module_exx_symmetry/symmetry_rotation.h" - - class Parallel_Orbitals; - - template - class RPA_LRI; - - template - class Exx_LRI_Interface; - - namespace LR - { - template - class ESolver_LR; - - template - class OperatorLREXX; - } - -template -class Exx_Obj -{ - // match with Conv_Coulomb_Pot_K::Coulomb_Method - public: - LRI_CV cv; - Ewald_Vq evq; - std::vector>> abfs_ccp; -}; - -template -class Exx_LRI -{ -private: - using TA = int; - using Tcell = int; - static constexpr std::size_t Ndim = 3; - using TC = std::array; - using TAC = std::pair; - using TatomR = std::array; // tmp - -public: - Exx_LRI(const Exx_Info_RI& info_in) :info(info_in) {} - Exx_LRI operator=(const Exx_LRI&) = delete; - Exx_LRI operator=(Exx_LRI&&); - - void init( - const MPI_Comm &mpi_comm_in, - const UnitCell &ucell, - const K_Vectors &kv_in, - const LCAO_Orbitals& orb, - const std::vector>>& abfs_in = {}); +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef EXX_LRI_H +#define EXX_LRI_H + +#include "LRI_CV.h" +#include "ewald_Vq.h" +#include "source_hamilt/module_xc/exx_info.h" +#include "source_basis/module_ao/ORB_atomic_lm.h" +#include "source_base/matrix.h" +#include + +#include +#include +#include +#include +#include + +#include "module_exx_symmetry/symmetry_rotation.h" + + class Parallel_Orbitals; + + template + class RPA_LRI; + + template + class Exx_LRI_Interface; + + namespace LR + { + template + class ESolver_LR; + + template + class OperatorLREXX; + } + +template +class Exx_Obj +{ + // match with Conv_Coulomb_Pot_K::Coulomb_Method + public: + LRI_CV cv; + Ewald_Vq evq; + std::vector>> abfs_ccp; +}; + +template +class Exx_LRI +{ +private: + using TA = int; + using Tcell = int; + static constexpr std::size_t Ndim = 3; + using TC = std::array; + using TAC = std::pair; + using TatomR = std::array; // tmp + +public: + Exx_LRI(const Exx_Info_RI& info_in) :info(info_in) {} + Exx_LRI operator=(const Exx_LRI&) = delete; + Exx_LRI operator=(Exx_LRI&&); + + void init( + const MPI_Comm &mpi_comm_in, + const UnitCell &ucell, + const K_Vectors &kv_in, + const LCAO_Orbitals& orb, + const std::vector>>& abfs_in = {}); void init_spencer(const MPI_Comm& mpi_comm_in, const UnitCell& ucell, const K_Vectors& kv_in, const LCAO_Orbitals& orb, const std::vector>>& abfs_in = {}); - void cal_exx_ions(const UnitCell& ucell, const bool write_cv = false); - void cal_cut_coulomb_cs( - std::map>>& Vs_cut_IJR, - std::map>>& Cs, - const UnitCell& ucell, - const bool write_cv = false); - void cal_ewald_coulomb( - std::map>>& Vs_full_IJR, - std::map>>& Cs, - const UnitCell& ucell, - const bool write_cv = false); - void cal_exx_elec( - const std::vector>>>& Ds, - const UnitCell& ucell, - const Parallel_Orbitals& pv, - const ModuleSymmetry::Symmetry_rotation* p_symrot = nullptr); - void cal_exx_force(const int& nat); - void cal_exx_stress(const double& omega, const double& lat0); - - void reset_Cs(const std::map>>& Cs_in) { this->exx_lri.set_Cs(Cs_in, this->info.C_threshold); } - void reset_Vs(const std::map>>& Vs_in) { this->exx_lri.set_Vs(Vs_in, this->info.V_threshold); } - //std::vector> get_abfs_nchis() const; - - std::vector< std::map>>> Hexxs; - double Eexx; - ModuleBase::matrix force_exx; - ModuleBase::matrix stress_exx; - - -private: + void cal_exx_ions(const UnitCell& ucell, const bool write_cv = false); + void cal_cut_coulomb_cs( + std::map>>& Vs_cut_IJR, + std::map>>& Cs, + const UnitCell& ucell, + const bool write_cv = false); + void cal_ewald_coulomb( + std::map>>& Vs_full_IJR, + std::map>>& Cs, + const UnitCell& ucell, + const bool write_cv = false); + void cal_exx_elec( + const std::vector>>>& Ds, + const UnitCell& ucell, + const Parallel_Orbitals& pv, + const ModuleSymmetry::Symmetry_rotation* p_symrot = nullptr); + void cal_exx_force(const int& nat); + void cal_exx_stress(const double& omega, const double& lat0); + + void reset_Cs(const std::map>>& Cs_in) { this->exx_lri.set_Cs(Cs_in, this->info.C_threshold); } + void reset_Vs(const std::map>>& Vs_in) { this->exx_lri.set_Vs(Vs_in, this->info.V_threshold); } + //std::vector> get_abfs_nchis() const; + + std::vector< std::map>>> Hexxs; + double Eexx; + ModuleBase::matrix force_exx; + ModuleBase::matrix stress_exx; + + +private: // WARNING: reference to Exx_Info_RI, which holds references into Exx_Info_Global. // Must not outlive GlobalC::exx_info. See exx_info.h for details. - const Exx_Info_RI &info; - MPI_Comm mpi_comm; - const K_Vectors *p_kv = nullptr; - std::shared_ptr MGT; - std::vector orb_cutoff_; - - std::vector>> lcaos; - std::vector>> abfs; - //std::vector>> abfs_ccp; - std::map> exx_objs; - //LRI_CV cv; - RI::Exx exx_lri; - std::map>>>> coulomb_settings; - - void post_process_Hexx( std::map>> &Hexxs_io ) const; - double post_process_Eexx(const double& Eexx_in) const; - - friend class RPA_LRI; - friend class RPA_LRI, Tdata>; - friend class Exx_LRI_Interface; - friend class Exx_LRI_Interface, Tdata>; - friend class LR::ESolver_LR; - friend class LR::ESolver_LR, double>; - friend class LR::OperatorLREXX; - friend class LR::OperatorLREXX>; -}; - -#include "Exx_LRI.hpp" - -#endif + const Exx_Info_RI &info; + MPI_Comm mpi_comm; + const K_Vectors *p_kv = nullptr; + std::shared_ptr MGT; + std::vector orb_cutoff_; + + std::vector>> lcaos; + std::vector>> abfs; + //std::vector>> abfs_ccp; + std::map> exx_objs; + //LRI_CV cv; + RI::Exx exx_lri; + std::map>>>> coulomb_settings; + + void post_process_Hexx( std::map>> &Hexxs_io ) const; + double post_process_Eexx(const double& Eexx_in) const; + + friend class RPA_LRI; + friend class RPA_LRI, Tdata>; + friend class Exx_LRI_Interface; + friend class Exx_LRI_Interface, Tdata>; + friend class LR::ESolver_LR; + friend class LR::ESolver_LR, double>; + friend class LR::OperatorLREXX; + friend class LR::OperatorLREXX>; +}; + +#include "Exx_LRI.hpp" + +#endif diff --git a/source/source_lcao/module_ri/LRI_CV.h b/source/source_lcao/module_ri/LRI_CV.h index fc17e4d2707..c23f1e5c614 100644 --- a/source/source_lcao/module_ri/LRI_CV.h +++ b/source/source_lcao/module_ri/LRI_CV.h @@ -1,142 +1,142 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef LRI_CV_H -#define LRI_CV_H - -#include "Matrix_Orbs11.h" -#include "Matrix_Orbs21.h" -#include "source_basis/module_ao/ORB_atomic_lm.h" -#include "abfs-vector3_order.h" -#include "source_base/element_basis_index.h" - -#include -#include - -#include -#include -#include -#include - -template -class LRI_CV -{ -private: - using TA = int; - using TC = std::array; - using TAC = std::pair; - using Tdata_real = RI::Global_Func::To_Real_t; - -public: - LRI_CV(); - ~LRI_CV(); - - void set_orbitals( - const UnitCell &ucell, - const LCAO_Orbitals& orb, - const std::vector>> &lcaos_in, - const std::vector>> &abfs_in, - const std::vector>> &abfs_ccp_in, - const double &kmesh_times, - std::shared_ptr MGT, - const bool& init_C); - inline std::map>> - cal_Vs( - const UnitCell &ucell, - const std::vector &list_A0, - const std::vector &list_A1, - const std::map &flags); // "writable_Vws" - inline std::map, 3>>> - cal_dVs( - const UnitCell &ucell, - const std::vector &list_A0, - const std::vector &list_A1, - const std::map &flags); // "writable_dVws" - std::pair>>, - std::map, 3>>>> - cal_Cs_dCs( - const UnitCell &ucell, - const std::vector &list_A0, - const std::vector &list_A1, - const std::map &flags); // "cal_dC", "writable_Cws", "writable_dCws", "writable_Vws", "writable_dVws" - - size_t get_index_abfs_size(const size_t &iat){return this->index_abfs[iat].count_size; } - -private: - std::vector>> lcaos; - std::vector>> abfs; - std::vector>> abfs_ccp; - ModuleBase::Element_Basis_Index::IndexLNM index_lcaos; - ModuleBase::Element_Basis_Index::IndexLNM index_abfs; - std::vector lcaos_rcut; - std::vector abfs_ccp_rcut; - -public: - std::map,RI::Tensor>>> Vws; - std::map,RI::Tensor>>> Cws; - std::map,std::array,3>>>> dVws; - std::map,std::array,3>>>> dCws; -private: - pthread_rwlock_t rwlock_Vw; - pthread_rwlock_t rwlock_Cw; - pthread_rwlock_t rwlock_dVw; - pthread_rwlock_t rwlock_dCw; - - Matrix_Orbs11 m_abfs_abfs; - Matrix_Orbs21 m_abfslcaos_lcaos; - - template - using T_func_DPcal_data = std::function &R, - const std::map &flags)>; - using T_func_cal_Rcut = std::function; - template - std::map> - cal_datas( - const UnitCell &ucell, - const std::vector& list_A0, - const std::vector& list_A1, - const std::map& flags, - const T_func_cal_Rcut& func_cal_Rcut, - const T_func_DPcal_data& func_DPcal_data); - - inline double cal_V_Rcut(const int it0, const int it1); - inline double cal_C_Rcut(const int it0, const int it1); - - inline RI::Tensor - DPcal_V( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const std::map &flags); // "writable_Vws" - inline std::array,3> - DPcal_dV( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const std::map &flags); // "writable_dVws" - std::pair, std::array,3>> - DPcal_C_dC( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const std::map &flags); // "cal_dC", "writable_Cws", "writable_dCws", "writable_Vws", "writable_dVws" - - template - To11 DPcal_o11( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const bool &flag_writable_o11ws, - pthread_rwlock_t &rwlock_o11, - std::map,To11>>> &o11ws, - const Tfunc &func_cal_o11); -}; - -#include "LRI_CV.hpp" - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef LRI_CV_H +#define LRI_CV_H + +#include "Matrix_Orbs11.h" +#include "Matrix_Orbs21.h" +#include "source_basis/module_ao/ORB_atomic_lm.h" +#include "abfs-vector3_order.h" +#include "source_base/element_basis_index.h" + +#include +#include + +#include +#include +#include +#include + +template +class LRI_CV +{ +private: + using TA = int; + using TC = std::array; + using TAC = std::pair; + using Tdata_real = RI::Global_Func::To_Real_t; + +public: + LRI_CV(); + ~LRI_CV(); + + void set_orbitals( + const UnitCell &ucell, + const LCAO_Orbitals& orb, + const std::vector>> &lcaos_in, + const std::vector>> &abfs_in, + const std::vector>> &abfs_ccp_in, + const double &kmesh_times, + std::shared_ptr MGT, + const bool& init_C); + inline std::map>> + cal_Vs( + const UnitCell &ucell, + const std::vector &list_A0, + const std::vector &list_A1, + const std::map &flags); // "writable_Vws" + inline std::map, 3>>> + cal_dVs( + const UnitCell &ucell, + const std::vector &list_A0, + const std::vector &list_A1, + const std::map &flags); // "writable_dVws" + std::pair>>, + std::map, 3>>>> + cal_Cs_dCs( + const UnitCell &ucell, + const std::vector &list_A0, + const std::vector &list_A1, + const std::map &flags); // "cal_dC", "writable_Cws", "writable_dCws", "writable_Vws", "writable_dVws" + + size_t get_index_abfs_size(const size_t &iat){return this->index_abfs[iat].count_size; } + +private: + std::vector>> lcaos; + std::vector>> abfs; + std::vector>> abfs_ccp; + ModuleBase::Element_Basis_Index::IndexLNM index_lcaos; + ModuleBase::Element_Basis_Index::IndexLNM index_abfs; + std::vector lcaos_rcut; + std::vector abfs_ccp_rcut; + +public: + std::map,RI::Tensor>>> Vws; + std::map,RI::Tensor>>> Cws; + std::map,std::array,3>>>> dVws; + std::map,std::array,3>>>> dCws; +private: + pthread_rwlock_t rwlock_Vw; + pthread_rwlock_t rwlock_Cw; + pthread_rwlock_t rwlock_dVw; + pthread_rwlock_t rwlock_dCw; + + Matrix_Orbs11 m_abfs_abfs; + Matrix_Orbs21 m_abfslcaos_lcaos; + + template + using T_func_DPcal_data = std::function &R, + const std::map &flags)>; + using T_func_cal_Rcut = std::function; + template + std::map> + cal_datas( + const UnitCell &ucell, + const std::vector& list_A0, + const std::vector& list_A1, + const std::map& flags, + const T_func_cal_Rcut& func_cal_Rcut, + const T_func_DPcal_data& func_DPcal_data); + + inline double cal_V_Rcut(const int it0, const int it1); + inline double cal_C_Rcut(const int it0, const int it1); + + inline RI::Tensor + DPcal_V( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const std::map &flags); // "writable_Vws" + inline std::array,3> + DPcal_dV( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const std::map &flags); // "writable_dVws" + std::pair, std::array,3>> + DPcal_C_dC( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const std::map &flags); // "cal_dC", "writable_Cws", "writable_dCws", "writable_Vws", "writable_dVws" + + template + To11 DPcal_o11( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const bool &flag_writable_o11ws, + pthread_rwlock_t &rwlock_o11, + std::map,To11>>> &o11ws, + const Tfunc &func_cal_o11); +}; + +#include "LRI_CV.hpp" + +#endif diff --git a/source/source_lcao/module_ri/LRI_CV.hpp b/source/source_lcao/module_ri/LRI_CV.hpp index 883b6c9cbcd..d429904f14a 100644 --- a/source/source_lcao/module_ri/LRI_CV.hpp +++ b/source/source_lcao/module_ri/LRI_CV.hpp @@ -1,466 +1,466 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef LRI_CV_HPP -#define LRI_CV_HPP - -#include "LRI_CV.h" -#include "LRI_CV_Tools.h" -#include "exx_abfs-construct_orbs.h" -#include "RI_Util.h" -#include "../../source_basis/module_ao/element_basis_index-ORB.h" -#include "../../source_base/tool_title.h" -#include "../../source_base/timer.h" -#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info -#include -#include - -template -LRI_CV::LRI_CV() -{ - pthread_rwlock_init(&rwlock_Vw,NULL); - pthread_rwlock_init(&rwlock_Cw,NULL); - pthread_rwlock_init(&rwlock_dVw,NULL); - pthread_rwlock_init(&rwlock_dCw,NULL); -} - -template -LRI_CV::~LRI_CV() -{ - pthread_rwlock_destroy(&rwlock_Vw); - pthread_rwlock_destroy(&rwlock_Cw); - pthread_rwlock_destroy(&rwlock_dVw); - pthread_rwlock_destroy(&rwlock_dCw); -} - - -template -void LRI_CV::set_orbitals( - const UnitCell &ucell, - const LCAO_Orbitals& orb, - const std::vector>> &lcaos_in, - const std::vector>> &abfs_in, - const std::vector>> &abfs_ccp_in, - const double &kmesh_times, - std::shared_ptr MGT, - const bool& init_C) -{ - ModuleBase::TITLE("LRI_CV", "set_orbitals"); - ModuleBase::timer::start("LRI_CV", "set_orbitals"); - - this->lcaos = lcaos_in; - this->abfs = abfs_in; - this->abfs_ccp = abfs_ccp_in; - - this->lcaos_rcut = Exx_Abfs::Construct_Orbs::get_Rcut(this->lcaos); - this->abfs_ccp_rcut = Exx_Abfs::Construct_Orbs::get_Rcut(this->abfs_ccp); - - const ModuleBase::Element_Basis_Index::Range - range_lcaos = ModuleBase::Element_Basis_Index::construct_range( lcaos ); - this->index_lcaos = ModuleBase::Element_Basis_Index::construct_index( range_lcaos ); - - const ModuleBase::Element_Basis_Index::Range - range_abfs = ModuleBase::Element_Basis_Index::construct_range( abfs ); - this->index_abfs = ModuleBase::Element_Basis_Index::construct_index( range_abfs ); - - this->m_abfs_abfs.MGT = this->m_abfslcaos_lcaos.MGT = MGT; - this->m_abfs_abfs.init( - this->abfs_ccp, this->abfs, - ucell, orb, kmesh_times); - if (init_C) - this->m_abfslcaos_lcaos.init( - this->abfs_ccp, this->lcaos, this->lcaos, - ucell, orb, kmesh_times); - - this->m_abfs_abfs.init_radial_table(); - if (init_C) { - this->m_abfslcaos_lcaos.init_radial_table(); - } - - ModuleBase::timer::end("LRI_CV", "set_orbitals"); -} - -template -double LRI_CV::cal_V_Rcut(const int it0, const int it1) { - return this->abfs_ccp_rcut[it0] + this->lcaos_rcut[it1]; -} - -template -double LRI_CV::cal_C_Rcut(const int it0, const int it1) { - return std::min(this->abfs_ccp_rcut[it0], this->lcaos_rcut[it0]) - + this->lcaos_rcut[it1]; -} - -template template -auto LRI_CV::cal_datas( - const UnitCell &ucell, - const std::vector& list_A0, - const std::vector& list_A1, - const std::map& flags, - const T_func_cal_Rcut& func_cal_Rcut, - const T_func_DPcal_data& func_DPcal_data) --> std::map> -{ - ModuleBase::TITLE("LRI_CV","cal_datas"); - ModuleBase::timer::start("LRI_CV", "cal_datas"); - - std::map> Datas; - #pragma omp parallel - for(size_t i0=0; i0 tau0 = ucell.atoms[it0].tau[ia0]; - const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; - const double Rcut - = std::min(func_cal_Rcut(it0, it1), func_cal_Rcut(it1, it0)); - const Abfs::Vector3_Order R_delta = -tau0+tau1+(RI_Util::array3_to_Vector3(cell1)*ucell.latvec); - if( R_delta.norm()*ucell.lat0 < Rcut ) - { - const Tresult Data = func_DPcal_data(it0, it1, R_delta, flags); - // if(Data.norm(std::numeric_limits::max()) > threshold) - // { - #pragma omp critical(LRI_CV_cal_datas) - Datas[list_A0[i0]][list_A1[i1]] = Data; - // } - } - } - } - ModuleBase::timer::end("LRI_CV", "cal_datas"); - return Datas; -} - - -template -auto LRI_CV::cal_Vs( - const UnitCell &ucell, - const std::vector &list_A0, - const std::vector &list_A1, - const std::map &flags) // + "writable_Vws" --> std::map>> -{ - ModuleBase::TITLE("LRI_CV","cal_Vs"); - const T_func_DPcal_data> - func_DPcal_V = std::bind( - &LRI_CV::DPcal_V, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); - const T_func_cal_Rcut func_cal_Rcut = std::bind(&LRI_CV::cal_V_Rcut, - this, - std::placeholders::_1, - std::placeholders::_2); - - return this->cal_datas(ucell,list_A0, list_A1, flags, func_cal_Rcut, func_DPcal_V); -} - -template -auto LRI_CV::cal_dVs( - const UnitCell &ucell, - const std::vector &list_A0, - const std::vector &list_A1, - const std::map &flags) // + "writable_dVws" --> std::map, 3>>> -{ - ModuleBase::TITLE("LRI_CV","cal_dVs"); - const T_func_DPcal_data,3>> - func_DPcal_dV = std::bind( - &LRI_CV::DPcal_dV, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); - - const T_func_cal_Rcut func_cal_Rcut = std::bind(&LRI_CV::cal_V_Rcut, - this, - std::placeholders::_1, - std::placeholders::_2); - - return this->cal_datas(ucell,list_A0, list_A1, flags, func_cal_Rcut, func_DPcal_dV); -} - -template -auto LRI_CV::cal_Cs_dCs( - const UnitCell &ucell, - const std::vector &list_A0, - const std::vector &list_A1, - const std::map &flags) // "cal_dC" + "writable_Cws", "writable_dCws", "writable_Vws", "writable_dVws" --> std::pair< - std::map>>, - std::map, 3>>>> -{ - ModuleBase::TITLE("LRI_CV","cal_Cs_dCs"); - const T_func_DPcal_data, std::array,3>>> - func_DPcal_C_dC = std::bind( - &LRI_CV::DPcal_C_dC, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); - const T_func_cal_Rcut func_cal_Rcut = std::bind(&LRI_CV::cal_C_Rcut, - this, - std::placeholders::_1, - std::placeholders::_2); - - std::map, std::array,3>>>> - Cs_dCs_tmp = this->cal_datas(ucell,list_A0, list_A1, flags, func_cal_Rcut, func_DPcal_C_dC); - - std::map>> Cs; - std::map, 3>>> dCs; - for (auto& Cs_dCs_A: Cs_dCs_tmp) - for (auto& Cs_dCs_B: Cs_dCs_A.second) { - Cs[Cs_dCs_A.first][Cs_dCs_B.first] - = std::move(std::get<0>(Cs_dCs_B.second)); - if (flags.at("cal_dC")) - dCs[Cs_dCs_A.first][Cs_dCs_B.first] - = std::move(std::get<1>(Cs_dCs_B.second)); - } - return std::make_pair(Cs, dCs); -} - - -template template -To11 LRI_CV::DPcal_o11( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const bool &flag_writable_o11ws, - pthread_rwlock_t &rwlock_o11, - std::map,To11>>> &o11ws, - const Tfunc &func_cal_o11) -{ - const Abfs::Vector3_Order Rm = -R; - pthread_rwlock_rdlock(&rwlock_o11); - const To11 o11_read = RI::Global_Func::find(o11ws, it0, it1, R); - pthread_rwlock_unlock(&rwlock_o11); - - if(LRI_CV_Tools::exist(o11_read)) - { - return o11_read; - } - else - { - pthread_rwlock_rdlock(&rwlock_o11); - const To11 o11_transform_read = RI::Global_Func::find(o11ws, it1, it0, Rm); - pthread_rwlock_unlock(&rwlock_o11); - - if(LRI_CV_Tools::exist(o11_transform_read)) - { - const To11 o11 = LRI_CV_Tools::transform_Rm(o11_transform_read); - if(flag_writable_o11ws) // such write may be deleted for memory saving with transform_Rm() every time - { - pthread_rwlock_wrlock(&rwlock_o11); - o11ws[it0][it1][R] = o11; - pthread_rwlock_unlock(&rwlock_o11); - } - return o11; - } - else - { - const To11 o11 = func_cal_o11( - it0, it1, ModuleBase::Vector3{0,0,0}, R, - this->index_abfs, this->index_abfs, - Matrix_Orbs11::Matrix_Order::AB); - if(flag_writable_o11ws) - { - pthread_rwlock_wrlock(&rwlock_o11); - o11ws[it0][it1][R] = o11; - pthread_rwlock_unlock(&rwlock_o11); - } - return o11; - } // end else (!exist(o11_transform_read)) - } // end else (!exist(o11_read)) -} - -template -RI::Tensor -LRI_CV::DPcal_V( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const std::map &flags) // "writable_Vws" -{ - const auto cal_overlap_matrix = std::bind( - &Matrix_Orbs11::cal_overlap_matrix, - &this->m_abfs_abfs, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7); - return this->DPcal_o11(it0, it1, R, flags.at("writable_Vws"), this->rwlock_Vw, this->Vws, cal_overlap_matrix); -} - -template -std::array, 3> -LRI_CV::DPcal_dV( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const std::map &flags) // "writable_dVws" -{ - if(ModuleBase::Vector3(0,0,0)==R) - { - assert(it0==it1); - const size_t size = this->index_abfs[it0].count_size; - const std::array, 3> dV = { RI::Tensor({size,size}), RI::Tensor({size,size}), RI::Tensor({size,size}) }; - if(flags.at("writable_dVws")) - { - pthread_rwlock_wrlock(&this->rwlock_dVw); - this->dVws[it0][it1][R] = dV; - pthread_rwlock_unlock(&this->rwlock_dVw); - } - return dV; - } - - const auto cal_grad_overlap_matrix = std::bind( - &Matrix_Orbs11::cal_grad_overlap_matrix, - &this->m_abfs_abfs, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7); - return this->DPcal_o11(it0, it1, R, flags.at("writable_dVws"), this->rwlock_dVw, this->dVws, cal_grad_overlap_matrix); -} - - -template -std::pair, std::array,3>> -LRI_CV::DPcal_C_dC( - const int it0, - const int it1, - const Abfs::Vector3_Order &R, - const std::map &flags) // "cal_dC", "writable_Cws", "writable_dCws" + "writable_Vws", "writable_dVws" -{ - using namespace LRI_CV_Tools; - - const Abfs::Vector3_Order Rm = -R; - pthread_rwlock_rdlock(&this->rwlock_Cw); - const RI::Tensor C_read = RI::Global_Func::find(this->Cws, it0, it1, R); - pthread_rwlock_unlock(&this->rwlock_Cw); - pthread_rwlock_rdlock(&this->rwlock_dCw); - const std::array,3> dC_read = RI::Global_Func::find(this->dCws, it0, it1, R); - pthread_rwlock_unlock(&this->rwlock_dCw); - const bool flag_finish_dC = (!flags.at("cal_dC")) || LRI_CV_Tools::exist(dC_read); - - if(!C_read.empty() && flag_finish_dC) - { - return std::make_pair(C_read, dC_read); - } - else - { - if( (ModuleBase::Vector3(0,0,0)==R) && (it0==it1) ) - { - const RI::Tensor - A = this->m_abfslcaos_lcaos.template cal_overlap_matrix( - it0, it1, {0,0,0}, {0,0,0}, - this->index_abfs, this->index_lcaos, this->index_lcaos, - Matrix_Orbs21::Matrix_Order::A1A2B); - const RI::Tensor V = this->DPcal_V(it0, it0, {0, 0, 0}, {{"writable_Vws", true}}); - RI::Tensor L; - if (GlobalC::exx_info.info_ri.Cs_inv_thr > 0) - L = LRI_CV_Tools::cal_I(V, Inverse_Matrix::Method::syev, GlobalC::exx_info.info_ri.Cs_inv_thr); - else - L = LRI_CV_Tools::cal_I(V); - - const RI::Tensor C = RI::Global_Func::convert(0.5) * LRI_CV_Tools::mul1(L,A); // Attention 0.5! - if(flags.at("writable_Cws")) - { - pthread_rwlock_wrlock(&this->rwlock_Cw); - this->Cws[it0][it1][{0,0,0}] = C; - pthread_rwlock_unlock(&this->rwlock_Cw); - } - - if(flag_finish_dC) - { - return std::make_pair(C, dC_read); - } - else - { - const RI::Shape_Vector sizes = {this->index_abfs[it0].count_size, - this->index_lcaos[it0].count_size, - this->index_lcaos[it0].count_size}; - const std::array,3> - dC({RI::Tensor({sizes}), RI::Tensor({sizes}), RI::Tensor({sizes})}); - if(flags.at("writable_dCws")) - { - pthread_rwlock_wrlock(&this->rwlock_dCw); - this->dCws[it0][it1][{0,0,0}] = dC; - pthread_rwlock_unlock(&this->rwlock_dCw); - } - return std::make_pair(C, dC); - } - } // end if( (ModuleBase::Vector3(0,0,0)==R) && (it0==it1) ) - else - { - const std::vector> - A = {this->m_abfslcaos_lcaos.template cal_overlap_matrix( - it0, it1, {0,0,0}, R, - this->index_abfs, this->index_lcaos, this->index_lcaos, - Matrix_Orbs21::Matrix_Order::A1A2B), - this->m_abfslcaos_lcaos.template cal_overlap_matrix( - it1, it0, {0,0,0}, Rm, - this->index_abfs, this->index_lcaos, this->index_lcaos, - Matrix_Orbs21::Matrix_Order::A1BA2)}; - - const std::vector>> - V = {{DPcal_V(it0, it0, {0,0,0}, {{"writable_Vws",true}}), - DPcal_V(it0, it1, R, flags)}, - {DPcal_V(it1, it0, Rm, flags), - DPcal_V(it1, it1, {0,0,0}, {{"writable_Vws",true}})}}; - - std::vector>> L; - if (GlobalC::exx_info.info_ri.Cs_inv_thr > 0) - L = LRI_CV_Tools::cal_I(V, Inverse_Matrix::Method::syev, GlobalC::exx_info.info_ri.Cs_inv_thr); - else - L = LRI_CV_Tools::cal_I(V); - - const std::vector> C = LRI_CV_Tools::mul2(L,A); - if(flags.at("writable_Cws")) - { - pthread_rwlock_wrlock(&this->rwlock_Cw); - this->Cws[it0][it1][R] = C[0]; - this->Cws[it1][it0][Rm] = LRI_CV_Tools::transpose12(C[1]); - pthread_rwlock_unlock(&this->rwlock_Cw); - } - - if(flag_finish_dC) - { - return std::make_pair(C[0], dC_read); - } - else - { - const std::vector,3>> - dA = {this->m_abfslcaos_lcaos.template cal_grad_overlap_matrix( - it0, it1, {0,0,0}, R, - this->index_abfs, this->index_lcaos, this->index_lcaos, - Matrix_Orbs21::Matrix_Order::A1A2B), - LRI_CV_Tools::negative( - this->m_abfslcaos_lcaos.template cal_grad_overlap_matrix( - it1, it0, {0,0,0}, Rm, - this->index_abfs, this->index_lcaos, this->index_lcaos, - Matrix_Orbs21::Matrix_Order::A1BA2))}; - - const std::array,3> dV_01 = DPcal_dV(it0, it1, R, flags); - const std::array,3> dV_10 = LRI_CV_Tools::negative(DPcal_dV(it1, it0, Rm, flags)); - - std::array>,3> // dC = L*(dA-dV*C) - dC_tmp = LRI_CV_Tools::mul2( - L, - LRI_CV_Tools::change_order( LRI_CV_Tools::minus( - dA, - std::vector,3>>{ - LRI_CV_Tools::mul1(dV_01, C[1]), - LRI_CV_Tools::mul1(dV_10, C[0])}))); - const std::vector,3>> - dC = LRI_CV_Tools::change_order(std::move(dC_tmp)); - if(flags.at("writable_dCws")) - { - pthread_rwlock_wrlock(&this->rwlock_dCw); - this->dCws[it0][it1][R] = dC[0]; - this->dCws[it1][it0][Rm] = LRI_CV_Tools::negative(LRI_CV_Tools::transpose12(dC[1])); - pthread_rwlock_unlock(&this->rwlock_dCw); - } - return std::make_pair(C[0], dC[0]); - } // end else (!flag_finish_dC) - } // end else ( (ModuleBase::Vector3(0,0,0)!=R) || (it0!=it1) ) - } // end else (!(C_read && flag_finish_dC)) -} - - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef LRI_CV_HPP +#define LRI_CV_HPP + +#include "LRI_CV.h" +#include "LRI_CV_Tools.h" +#include "exx_abfs-construct_orbs.h" +#include "RI_Util.h" +#include "../../source_basis/module_ao/element_basis_index-ORB.h" +#include "../../source_base/tool_title.h" +#include "../../source_base/timer.h" +#include "source_hamilt/module_xc/exx_info.h" // use GlobalC::exx_info +#include +#include + +template +LRI_CV::LRI_CV() +{ + pthread_rwlock_init(&rwlock_Vw,NULL); + pthread_rwlock_init(&rwlock_Cw,NULL); + pthread_rwlock_init(&rwlock_dVw,NULL); + pthread_rwlock_init(&rwlock_dCw,NULL); +} + +template +LRI_CV::~LRI_CV() +{ + pthread_rwlock_destroy(&rwlock_Vw); + pthread_rwlock_destroy(&rwlock_Cw); + pthread_rwlock_destroy(&rwlock_dVw); + pthread_rwlock_destroy(&rwlock_dCw); +} + + +template +void LRI_CV::set_orbitals( + const UnitCell &ucell, + const LCAO_Orbitals& orb, + const std::vector>> &lcaos_in, + const std::vector>> &abfs_in, + const std::vector>> &abfs_ccp_in, + const double &kmesh_times, + std::shared_ptr MGT, + const bool& init_C) +{ + ModuleBase::TITLE("LRI_CV", "set_orbitals"); + ModuleBase::timer::start("LRI_CV", "set_orbitals"); + + this->lcaos = lcaos_in; + this->abfs = abfs_in; + this->abfs_ccp = abfs_ccp_in; + + this->lcaos_rcut = Exx_Abfs::Construct_Orbs::get_Rcut(this->lcaos); + this->abfs_ccp_rcut = Exx_Abfs::Construct_Orbs::get_Rcut(this->abfs_ccp); + + const ModuleBase::Element_Basis_Index::Range + range_lcaos = ModuleBase::Element_Basis_Index::construct_range( lcaos ); + this->index_lcaos = ModuleBase::Element_Basis_Index::construct_index( range_lcaos ); + + const ModuleBase::Element_Basis_Index::Range + range_abfs = ModuleBase::Element_Basis_Index::construct_range( abfs ); + this->index_abfs = ModuleBase::Element_Basis_Index::construct_index( range_abfs ); + + this->m_abfs_abfs.MGT = this->m_abfslcaos_lcaos.MGT = MGT; + this->m_abfs_abfs.init( + this->abfs_ccp, this->abfs, + ucell, orb, kmesh_times); + if (init_C) + this->m_abfslcaos_lcaos.init( + this->abfs_ccp, this->lcaos, this->lcaos, + ucell, orb, kmesh_times); + + this->m_abfs_abfs.init_radial_table(); + if (init_C) { + this->m_abfslcaos_lcaos.init_radial_table(); + } + + ModuleBase::timer::end("LRI_CV", "set_orbitals"); +} + +template +double LRI_CV::cal_V_Rcut(const int it0, const int it1) { + return this->abfs_ccp_rcut[it0] + this->lcaos_rcut[it1]; +} + +template +double LRI_CV::cal_C_Rcut(const int it0, const int it1) { + return std::min(this->abfs_ccp_rcut[it0], this->lcaos_rcut[it0]) + + this->lcaos_rcut[it1]; +} + +template template +auto LRI_CV::cal_datas( + const UnitCell &ucell, + const std::vector& list_A0, + const std::vector& list_A1, + const std::map& flags, + const T_func_cal_Rcut& func_cal_Rcut, + const T_func_DPcal_data& func_DPcal_data) +-> std::map> +{ + ModuleBase::TITLE("LRI_CV","cal_datas"); + ModuleBase::timer::start("LRI_CV", "cal_datas"); + + std::map> Datas; + #pragma omp parallel + for(size_t i0=0; i0 tau0 = ucell.atoms[it0].tau[ia0]; + const ModuleBase::Vector3 tau1 = ucell.atoms[it1].tau[ia1]; + const double Rcut + = std::min(func_cal_Rcut(it0, it1), func_cal_Rcut(it1, it0)); + const Abfs::Vector3_Order R_delta = -tau0+tau1+(RI_Util::array3_to_Vector3(cell1)*ucell.latvec); + if( R_delta.norm()*ucell.lat0 < Rcut ) + { + const Tresult Data = func_DPcal_data(it0, it1, R_delta, flags); + // if(Data.norm(std::numeric_limits::max()) > threshold) + // { + #pragma omp critical(LRI_CV_cal_datas) + Datas[list_A0[i0]][list_A1[i1]] = Data; + // } + } + } + } + ModuleBase::timer::end("LRI_CV", "cal_datas"); + return Datas; +} + + +template +auto LRI_CV::cal_Vs( + const UnitCell &ucell, + const std::vector &list_A0, + const std::vector &list_A1, + const std::map &flags) // + "writable_Vws" +-> std::map>> +{ + ModuleBase::TITLE("LRI_CV","cal_Vs"); + const T_func_DPcal_data> + func_DPcal_V = std::bind( + &LRI_CV::DPcal_V, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); + const T_func_cal_Rcut func_cal_Rcut = std::bind(&LRI_CV::cal_V_Rcut, + this, + std::placeholders::_1, + std::placeholders::_2); + + return this->cal_datas(ucell,list_A0, list_A1, flags, func_cal_Rcut, func_DPcal_V); +} + +template +auto LRI_CV::cal_dVs( + const UnitCell &ucell, + const std::vector &list_A0, + const std::vector &list_A1, + const std::map &flags) // + "writable_dVws" +-> std::map, 3>>> +{ + ModuleBase::TITLE("LRI_CV","cal_dVs"); + const T_func_DPcal_data,3>> + func_DPcal_dV = std::bind( + &LRI_CV::DPcal_dV, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); + + const T_func_cal_Rcut func_cal_Rcut = std::bind(&LRI_CV::cal_V_Rcut, + this, + std::placeholders::_1, + std::placeholders::_2); + + return this->cal_datas(ucell,list_A0, list_A1, flags, func_cal_Rcut, func_DPcal_dV); +} + +template +auto LRI_CV::cal_Cs_dCs( + const UnitCell &ucell, + const std::vector &list_A0, + const std::vector &list_A1, + const std::map &flags) // "cal_dC" + "writable_Cws", "writable_dCws", "writable_Vws", "writable_dVws" +-> std::pair< + std::map>>, + std::map, 3>>>> +{ + ModuleBase::TITLE("LRI_CV","cal_Cs_dCs"); + const T_func_DPcal_data, std::array,3>>> + func_DPcal_C_dC = std::bind( + &LRI_CV::DPcal_C_dC, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); + const T_func_cal_Rcut func_cal_Rcut = std::bind(&LRI_CV::cal_C_Rcut, + this, + std::placeholders::_1, + std::placeholders::_2); + + std::map, std::array,3>>>> + Cs_dCs_tmp = this->cal_datas(ucell,list_A0, list_A1, flags, func_cal_Rcut, func_DPcal_C_dC); + + std::map>> Cs; + std::map, 3>>> dCs; + for (auto& Cs_dCs_A: Cs_dCs_tmp) + for (auto& Cs_dCs_B: Cs_dCs_A.second) { + Cs[Cs_dCs_A.first][Cs_dCs_B.first] + = std::move(std::get<0>(Cs_dCs_B.second)); + if (flags.at("cal_dC")) + dCs[Cs_dCs_A.first][Cs_dCs_B.first] + = std::move(std::get<1>(Cs_dCs_B.second)); + } + return std::make_pair(Cs, dCs); +} + + +template template +To11 LRI_CV::DPcal_o11( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const bool &flag_writable_o11ws, + pthread_rwlock_t &rwlock_o11, + std::map,To11>>> &o11ws, + const Tfunc &func_cal_o11) +{ + const Abfs::Vector3_Order Rm = -R; + pthread_rwlock_rdlock(&rwlock_o11); + const To11 o11_read = RI::Global_Func::find(o11ws, it0, it1, R); + pthread_rwlock_unlock(&rwlock_o11); + + if(LRI_CV_Tools::exist(o11_read)) + { + return o11_read; + } + else + { + pthread_rwlock_rdlock(&rwlock_o11); + const To11 o11_transform_read = RI::Global_Func::find(o11ws, it1, it0, Rm); + pthread_rwlock_unlock(&rwlock_o11); + + if(LRI_CV_Tools::exist(o11_transform_read)) + { + const To11 o11 = LRI_CV_Tools::transform_Rm(o11_transform_read); + if(flag_writable_o11ws) // such write may be deleted for memory saving with transform_Rm() every time + { + pthread_rwlock_wrlock(&rwlock_o11); + o11ws[it0][it1][R] = o11; + pthread_rwlock_unlock(&rwlock_o11); + } + return o11; + } + else + { + const To11 o11 = func_cal_o11( + it0, it1, ModuleBase::Vector3{0,0,0}, R, + this->index_abfs, this->index_abfs, + Matrix_Orbs11::Matrix_Order::AB); + if(flag_writable_o11ws) + { + pthread_rwlock_wrlock(&rwlock_o11); + o11ws[it0][it1][R] = o11; + pthread_rwlock_unlock(&rwlock_o11); + } + return o11; + } // end else (!exist(o11_transform_read)) + } // end else (!exist(o11_read)) +} + +template +RI::Tensor +LRI_CV::DPcal_V( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const std::map &flags) // "writable_Vws" +{ + const auto cal_overlap_matrix = std::bind( + &Matrix_Orbs11::cal_overlap_matrix, + &this->m_abfs_abfs, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7); + return this->DPcal_o11(it0, it1, R, flags.at("writable_Vws"), this->rwlock_Vw, this->Vws, cal_overlap_matrix); +} + +template +std::array, 3> +LRI_CV::DPcal_dV( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const std::map &flags) // "writable_dVws" +{ + if(ModuleBase::Vector3(0,0,0)==R) + { + assert(it0==it1); + const size_t size = this->index_abfs[it0].count_size; + const std::array, 3> dV = { RI::Tensor({size,size}), RI::Tensor({size,size}), RI::Tensor({size,size}) }; + if(flags.at("writable_dVws")) + { + pthread_rwlock_wrlock(&this->rwlock_dVw); + this->dVws[it0][it1][R] = dV; + pthread_rwlock_unlock(&this->rwlock_dVw); + } + return dV; + } + + const auto cal_grad_overlap_matrix = std::bind( + &Matrix_Orbs11::cal_grad_overlap_matrix, + &this->m_abfs_abfs, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7); + return this->DPcal_o11(it0, it1, R, flags.at("writable_dVws"), this->rwlock_dVw, this->dVws, cal_grad_overlap_matrix); +} + + +template +std::pair, std::array,3>> +LRI_CV::DPcal_C_dC( + const int it0, + const int it1, + const Abfs::Vector3_Order &R, + const std::map &flags) // "cal_dC", "writable_Cws", "writable_dCws" + "writable_Vws", "writable_dVws" +{ + using namespace LRI_CV_Tools; + + const Abfs::Vector3_Order Rm = -R; + pthread_rwlock_rdlock(&this->rwlock_Cw); + const RI::Tensor C_read = RI::Global_Func::find(this->Cws, it0, it1, R); + pthread_rwlock_unlock(&this->rwlock_Cw); + pthread_rwlock_rdlock(&this->rwlock_dCw); + const std::array,3> dC_read = RI::Global_Func::find(this->dCws, it0, it1, R); + pthread_rwlock_unlock(&this->rwlock_dCw); + const bool flag_finish_dC = (!flags.at("cal_dC")) || LRI_CV_Tools::exist(dC_read); + + if(!C_read.empty() && flag_finish_dC) + { + return std::make_pair(C_read, dC_read); + } + else + { + if( (ModuleBase::Vector3(0,0,0)==R) && (it0==it1) ) + { + const RI::Tensor + A = this->m_abfslcaos_lcaos.template cal_overlap_matrix( + it0, it1, {0,0,0}, {0,0,0}, + this->index_abfs, this->index_lcaos, this->index_lcaos, + Matrix_Orbs21::Matrix_Order::A1A2B); + const RI::Tensor V = this->DPcal_V(it0, it0, {0, 0, 0}, {{"writable_Vws", true}}); + RI::Tensor L; + if (GlobalC::exx_info.info_ri.Cs_inv_thr > 0) + L = LRI_CV_Tools::cal_I(V, Inverse_Matrix::Method::syev, GlobalC::exx_info.info_ri.Cs_inv_thr); + else + L = LRI_CV_Tools::cal_I(V); + + const RI::Tensor C = RI::Global_Func::convert(0.5) * LRI_CV_Tools::mul1(L,A); // Attention 0.5! + if(flags.at("writable_Cws")) + { + pthread_rwlock_wrlock(&this->rwlock_Cw); + this->Cws[it0][it1][{0,0,0}] = C; + pthread_rwlock_unlock(&this->rwlock_Cw); + } + + if(flag_finish_dC) + { + return std::make_pair(C, dC_read); + } + else + { + const RI::Shape_Vector sizes = {this->index_abfs[it0].count_size, + this->index_lcaos[it0].count_size, + this->index_lcaos[it0].count_size}; + const std::array,3> + dC({RI::Tensor({sizes}), RI::Tensor({sizes}), RI::Tensor({sizes})}); + if(flags.at("writable_dCws")) + { + pthread_rwlock_wrlock(&this->rwlock_dCw); + this->dCws[it0][it1][{0,0,0}] = dC; + pthread_rwlock_unlock(&this->rwlock_dCw); + } + return std::make_pair(C, dC); + } + } // end if( (ModuleBase::Vector3(0,0,0)==R) && (it0==it1) ) + else + { + const std::vector> + A = {this->m_abfslcaos_lcaos.template cal_overlap_matrix( + it0, it1, {0,0,0}, R, + this->index_abfs, this->index_lcaos, this->index_lcaos, + Matrix_Orbs21::Matrix_Order::A1A2B), + this->m_abfslcaos_lcaos.template cal_overlap_matrix( + it1, it0, {0,0,0}, Rm, + this->index_abfs, this->index_lcaos, this->index_lcaos, + Matrix_Orbs21::Matrix_Order::A1BA2)}; + + const std::vector>> + V = {{DPcal_V(it0, it0, {0,0,0}, {{"writable_Vws",true}}), + DPcal_V(it0, it1, R, flags)}, + {DPcal_V(it1, it0, Rm, flags), + DPcal_V(it1, it1, {0,0,0}, {{"writable_Vws",true}})}}; + + std::vector>> L; + if (GlobalC::exx_info.info_ri.Cs_inv_thr > 0) + L = LRI_CV_Tools::cal_I(V, Inverse_Matrix::Method::syev, GlobalC::exx_info.info_ri.Cs_inv_thr); + else + L = LRI_CV_Tools::cal_I(V); + + const std::vector> C = LRI_CV_Tools::mul2(L,A); + if(flags.at("writable_Cws")) + { + pthread_rwlock_wrlock(&this->rwlock_Cw); + this->Cws[it0][it1][R] = C[0]; + this->Cws[it1][it0][Rm] = LRI_CV_Tools::transpose12(C[1]); + pthread_rwlock_unlock(&this->rwlock_Cw); + } + + if(flag_finish_dC) + { + return std::make_pair(C[0], dC_read); + } + else + { + const std::vector,3>> + dA = {this->m_abfslcaos_lcaos.template cal_grad_overlap_matrix( + it0, it1, {0,0,0}, R, + this->index_abfs, this->index_lcaos, this->index_lcaos, + Matrix_Orbs21::Matrix_Order::A1A2B), + LRI_CV_Tools::negative( + this->m_abfslcaos_lcaos.template cal_grad_overlap_matrix( + it1, it0, {0,0,0}, Rm, + this->index_abfs, this->index_lcaos, this->index_lcaos, + Matrix_Orbs21::Matrix_Order::A1BA2))}; + + const std::array,3> dV_01 = DPcal_dV(it0, it1, R, flags); + const std::array,3> dV_10 = LRI_CV_Tools::negative(DPcal_dV(it1, it0, Rm, flags)); + + std::array>,3> // dC = L*(dA-dV*C) + dC_tmp = LRI_CV_Tools::mul2( + L, + LRI_CV_Tools::change_order( LRI_CV_Tools::minus( + dA, + std::vector,3>>{ + LRI_CV_Tools::mul1(dV_01, C[1]), + LRI_CV_Tools::mul1(dV_10, C[0])}))); + const std::vector,3>> + dC = LRI_CV_Tools::change_order(std::move(dC_tmp)); + if(flags.at("writable_dCws")) + { + pthread_rwlock_wrlock(&this->rwlock_dCw); + this->dCws[it0][it1][R] = dC[0]; + this->dCws[it1][it0][Rm] = LRI_CV_Tools::negative(LRI_CV_Tools::transpose12(dC[1])); + pthread_rwlock_unlock(&this->rwlock_dCw); + } + return std::make_pair(C[0], dC[0]); + } // end else (!flag_finish_dC) + } // end else ( (ModuleBase::Vector3(0,0,0)!=R) || (it0!=it1) ) + } // end else (!(C_read && flag_finish_dC)) +} + + +#endif diff --git a/source/source_lcao/module_ri/Matrix_Orbs11.cpp b/source/source_lcao/module_ri/Matrix_Orbs11.cpp index 94af2d29f95..f0ec89daf75 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs11.cpp +++ b/source/source_lcao/module_ri/Matrix_Orbs11.cpp @@ -1,147 +1,147 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#include "Matrix_Orbs11.h" - -#include "exx_abfs-construct_orbs.h" -#include "source_base/timer.h" -#include "source_base/tool_title.h" - -void Matrix_Orbs11::init( - const std::vector>>& orb_A, - const std::vector>>& orb_B, - const UnitCell& ucell, - const LCAO_Orbitals& orb, - const double kmesh_times) -{ - ModuleBase::TITLE("Matrix_Orbs11", "init"); - ModuleBase::timer::start("Matrix_Orbs11", "init"); - - this->lat0 = &ucell.lat0; - - const int Lmax = std::max({ Exx_Abfs::Construct_Orbs::get_Lmax(orb_A), Exx_Abfs::Construct_Orbs::get_Lmax(orb_B) }); - const int Lmax_used = Exx_Abfs::Construct_Orbs::get_Lmax(orb_A) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B); - - //========================================= - // (3) make Gaunt coefficients table - //========================================= - if(!this->MGT) - { this->MGT = std::make_shared(); } - if(this->MGT->get_Lmax_Gaunt_CH() < Lmax) - { this->MGT->init_Gaunt_CH(Lmax); } - if(this->MGT->get_Lmax_Gaunt_Coefficients() < Lmax) - { this->MGT->init_Gaunt(Lmax); } - - const double dr = orb.get_dR(); - const double dk = orb.get_dk(); - const int kmesh = orb.get_kmesh() * kmesh_times + 1; - const double rmax - = Exx_Abfs::Construct_Orbs::get_Rmax(orb_A) - + Exx_Abfs::Construct_Orbs::get_Rmax(orb_B); - int Rmesh = static_cast(rmax / dr) + 4; // extend Rcut, keep dR - Rmesh += 1 - Rmesh % 2; - Center2_Orb::init_Table_Spherical_Bessel(Lmax_used, - dr, - dk, - kmesh, - Rmesh, - psb_); - - for (size_t TA = 0; TA != orb_A.size(); ++TA) { - for (size_t TB = 0; TB != orb_B.size(); ++TB) { - for (int LA = 0; LA != orb_A[TA].size(); ++LA) { - for (size_t NA = 0; NA != orb_A[TA][LA].size(); ++NA) { - for (int LB = 0; LB != orb_B[TB].size(); ++LB) { - for (size_t NB = 0; NB != orb_B[TB][LB].size(); ++NB) { - center2_orb11_s[TA][TB][LA][NA][LB].insert(std::make_pair( - NB, - Center2_Orb::Orb11(orb_A[TA][LA][NA], orb_B[TB][LB][NB], psb_, *this->MGT))); - }}}}}} - - ModuleBase::timer::end("Matrix_Orbs11", "init"); -} - -/* -void Matrix_Orbs11::init_radial(const LCAO_Orbitals& orb_A, const LCAO_Orbitals& orb_B) -{ - ModuleBase::TITLE("Matrix_Orbs11", "init_radial"); - ModuleBase::timer::start("Matrix_Orbs11", "init_radial"); - for (size_t TA = 0; TA != orb_A.get_ntype(); ++TA) { - for (size_t TB = 0; TB != orb_B.get_ntype(); ++TB) { - for (int LA = 0; LA <= orb_A.Phi[TA].getLmax(); ++LA) { - for (size_t NA = 0; NA != orb_A.Phi[TA].getNchi(LA); ++NA) { - for (int LB = 0; LB <= orb_B.Phi[TB].getLmax(); ++LB) { - for (size_t NB = 0; NB != orb_B.Phi[TB].getNchi(LB); ++NB) { - center2_orb11_s[TA][TB][LA][NA][LB].insert( - std::make_pair(NB, - Center2_Orb::Orb11(orb_A.Phi[TA].PhiLN(LA, NA), - orb_B.Phi[TB].PhiLN(LB, NB), - psb_, - *this->MGT))); - } - } - } - } - } - } - ModuleBase::timer::end("Matrix_Orbs11", "init_radial"); -} -*/ - -void Matrix_Orbs11::init_radial_table() -{ - ModuleBase::TITLE("Matrix_Orbs11", "init_radial_table"); - ModuleBase::timer::start("Matrix_Orbs11", "init_radial_table"); - for (auto& coA: center2_orb11_s) { - for (auto& coB: coA.second) { - for (auto& coC: coB.second) { - for (auto& coD: coC.second) { - for (auto& coE: coD.second) { - for (auto& coF: coE.second) { - coF.second.init_radial_table(); - } - } - } - } - } - } - ModuleBase::timer::end("Matrix_Orbs11", "init_radial_table"); -} - -void Matrix_Orbs11::init_radial_table(const std::map>>& Rs) -{ - ModuleBase::TITLE("Matrix_Orbs11", "init_radial_table_Rs"); - ModuleBase::timer::start("Matrix_Orbs11", "init_radial_table"); - const double lat0 = *this->lat0; - for (const auto& RsA: Rs) { - for (const auto& RsB: RsA.second) - { - if (auto* const center2_orb11_sAB = static_cast< - std::map>>>* const>( - ModuleBase::GlobalFunc::MAP_EXIST(center2_orb11_s, RsA.first, RsB.first))) - { - std::set radials; - for (const double& R: RsB.second) - { - const double position = R * lat0 / lcao_dr_; - const size_t iq = static_cast(position); - for (size_t i = 0; i != 4; ++i) { - radials.insert(iq + i); - } - } - for (auto& coC: *center2_orb11_sAB) { - for (auto& coD: coC.second) { - for (auto& coE: coD.second) { - for (auto& coF: coE.second) { - coF.second.init_radial_table(radials); - } - } - } - } - } - } -} - ModuleBase::timer::end("Matrix_Orbs11", "init_radial_table"); -} +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#include "Matrix_Orbs11.h" + +#include "exx_abfs-construct_orbs.h" +#include "source_base/timer.h" +#include "source_base/tool_title.h" + +void Matrix_Orbs11::init( + const std::vector>>& orb_A, + const std::vector>>& orb_B, + const UnitCell& ucell, + const LCAO_Orbitals& orb, + const double kmesh_times) +{ + ModuleBase::TITLE("Matrix_Orbs11", "init"); + ModuleBase::timer::start("Matrix_Orbs11", "init"); + + this->lat0 = &ucell.lat0; + + const int Lmax = std::max({ Exx_Abfs::Construct_Orbs::get_Lmax(orb_A), Exx_Abfs::Construct_Orbs::get_Lmax(orb_B) }); + const int Lmax_used = Exx_Abfs::Construct_Orbs::get_Lmax(orb_A) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B); + + //========================================= + // (3) make Gaunt coefficients table + //========================================= + if(!this->MGT) + { this->MGT = std::make_shared(); } + if(this->MGT->get_Lmax_Gaunt_CH() < Lmax) + { this->MGT->init_Gaunt_CH(Lmax); } + if(this->MGT->get_Lmax_Gaunt_Coefficients() < Lmax) + { this->MGT->init_Gaunt(Lmax); } + + const double dr = orb.get_dR(); + const double dk = orb.get_dk(); + const int kmesh = orb.get_kmesh() * kmesh_times + 1; + const double rmax + = Exx_Abfs::Construct_Orbs::get_Rmax(orb_A) + + Exx_Abfs::Construct_Orbs::get_Rmax(orb_B); + int Rmesh = static_cast(rmax / dr) + 4; // extend Rcut, keep dR + Rmesh += 1 - Rmesh % 2; + Center2_Orb::init_Table_Spherical_Bessel(Lmax_used, + dr, + dk, + kmesh, + Rmesh, + psb_); + + for (size_t TA = 0; TA != orb_A.size(); ++TA) { + for (size_t TB = 0; TB != orb_B.size(); ++TB) { + for (int LA = 0; LA != orb_A[TA].size(); ++LA) { + for (size_t NA = 0; NA != orb_A[TA][LA].size(); ++NA) { + for (int LB = 0; LB != orb_B[TB].size(); ++LB) { + for (size_t NB = 0; NB != orb_B[TB][LB].size(); ++NB) { + center2_orb11_s[TA][TB][LA][NA][LB].insert(std::make_pair( + NB, + Center2_Orb::Orb11(orb_A[TA][LA][NA], orb_B[TB][LB][NB], psb_, *this->MGT))); + }}}}}} + + ModuleBase::timer::end("Matrix_Orbs11", "init"); +} + +/* +void Matrix_Orbs11::init_radial(const LCAO_Orbitals& orb_A, const LCAO_Orbitals& orb_B) +{ + ModuleBase::TITLE("Matrix_Orbs11", "init_radial"); + ModuleBase::timer::start("Matrix_Orbs11", "init_radial"); + for (size_t TA = 0; TA != orb_A.get_ntype(); ++TA) { + for (size_t TB = 0; TB != orb_B.get_ntype(); ++TB) { + for (int LA = 0; LA <= orb_A.Phi[TA].getLmax(); ++LA) { + for (size_t NA = 0; NA != orb_A.Phi[TA].getNchi(LA); ++NA) { + for (int LB = 0; LB <= orb_B.Phi[TB].getLmax(); ++LB) { + for (size_t NB = 0; NB != orb_B.Phi[TB].getNchi(LB); ++NB) { + center2_orb11_s[TA][TB][LA][NA][LB].insert( + std::make_pair(NB, + Center2_Orb::Orb11(orb_A.Phi[TA].PhiLN(LA, NA), + orb_B.Phi[TB].PhiLN(LB, NB), + psb_, + *this->MGT))); + } + } + } + } + } + } + ModuleBase::timer::end("Matrix_Orbs11", "init_radial"); +} +*/ + +void Matrix_Orbs11::init_radial_table() +{ + ModuleBase::TITLE("Matrix_Orbs11", "init_radial_table"); + ModuleBase::timer::start("Matrix_Orbs11", "init_radial_table"); + for (auto& coA: center2_orb11_s) { + for (auto& coB: coA.second) { + for (auto& coC: coB.second) { + for (auto& coD: coC.second) { + for (auto& coE: coD.second) { + for (auto& coF: coE.second) { + coF.second.init_radial_table(); + } + } + } + } + } + } + ModuleBase::timer::end("Matrix_Orbs11", "init_radial_table"); +} + +void Matrix_Orbs11::init_radial_table(const std::map>>& Rs) +{ + ModuleBase::TITLE("Matrix_Orbs11", "init_radial_table_Rs"); + ModuleBase::timer::start("Matrix_Orbs11", "init_radial_table"); + const double lat0 = *this->lat0; + for (const auto& RsA: Rs) { + for (const auto& RsB: RsA.second) + { + if (auto* const center2_orb11_sAB = static_cast< + std::map>>>* const>( + ModuleBase::GlobalFunc::MAP_EXIST(center2_orb11_s, RsA.first, RsB.first))) + { + std::set radials; + for (const double& R: RsB.second) + { + const double position = R * lat0 / lcao_dr_; + const size_t iq = static_cast(position); + for (size_t i = 0; i != 4; ++i) { + radials.insert(iq + i); + } + } + for (auto& coC: *center2_orb11_sAB) { + for (auto& coD: coC.second) { + for (auto& coE: coD.second) { + for (auto& coF: coE.second) { + coF.second.init_radial_table(radials); + } + } + } + } + } + } +} + ModuleBase::timer::end("Matrix_Orbs11", "init_radial_table"); +} diff --git a/source/source_lcao/module_ri/Matrix_Orbs11.h b/source/source_lcao/module_ri/Matrix_Orbs11.h index 7b520fe0f66..db7721673e0 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs11.h +++ b/source/source_lcao/module_ri/Matrix_Orbs11.h @@ -1,83 +1,83 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef MATRIX_ORB11_H -#define MATRIX_ORB11_H - -#include "source_base/element_basis_index.h" -#include "source_base/sph_bessel_recursive.h" -#include "source_base/vector3.h" -#include "source_basis/module_ao/ORB_gaunt_table.h" -#include "source_basis/module_ao/ORB_read.h" -#include "source_lcao/center2_orb-orb11.h" -#include "source_cell/unitcell.h" -#include -#include -#include -#include - -class Matrix_Orbs11 -{ - public: - void init( - const std::vector>>& orb_A, - const std::vector>>& orb_B, - const UnitCell& ucell, - const LCAO_Orbitals& orb, - const double kmesh_times); // extend Kcut, keep dK - - void init_radial_table(); - void init_radial_table(const std::map>>& Rs); // unit: ucell.lat0 - - enum class Matrix_Order - { - AB, - BA - }; - - template - RI::Tensor cal_overlap_matrix(const size_t TA, - const size_t TB, - const ModuleBase::Vector3& tauA, // unit: ucell.lat0 - const ModuleBase::Vector3& tauB, // unit: ucell.lat0 - const ModuleBase::Element_Basis_Index::IndexLNM& index_A, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B, - const Matrix_Order& matrix_order) const; - template - std::array, 3> cal_grad_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3& tauA, // unit: ucell.lat0 - const ModuleBase::Vector3& tauB, // unit: ucell.lat0 - const ModuleBase::Element_Basis_Index::IndexLNM& index_A, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B, - const Matrix_Order& matrix_order) const; - - template - std::map>>>> cal_overlap_matrix_all( - const UnitCell &ucell, - const ModuleBase::Element_Basis_Index::IndexLNM& index_r, - const ModuleBase::Element_Basis_Index::IndexLNM& index_c) const; - - std::shared_ptr MGT; - - private: - ModuleBase::Sph_Bessel_Recursive::D2* psb_ = nullptr; - const double lcao_dr_ = 0.01; - double* lat0=nullptr; // restore ucell.lat0 - std::map>>>>> - center2_orb11_s; - // this->center2_orb11_s[TA][TB][LA][NA][LB][NB] -}; - -#include "Matrix_Orbs11.hpp" - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef MATRIX_ORB11_H +#define MATRIX_ORB11_H + +#include "source_base/element_basis_index.h" +#include "source_base/sph_bessel_recursive.h" +#include "source_base/vector3.h" +#include "source_basis/module_ao/ORB_gaunt_table.h" +#include "source_basis/module_ao/ORB_read.h" +#include "source_lcao/center2_orb-orb11.h" +#include "source_cell/unitcell.h" +#include +#include +#include +#include + +class Matrix_Orbs11 +{ + public: + void init( + const std::vector>>& orb_A, + const std::vector>>& orb_B, + const UnitCell& ucell, + const LCAO_Orbitals& orb, + const double kmesh_times); // extend Kcut, keep dK + + void init_radial_table(); + void init_radial_table(const std::map>>& Rs); // unit: ucell.lat0 + + enum class Matrix_Order + { + AB, + BA + }; + + template + RI::Tensor cal_overlap_matrix(const size_t TA, + const size_t TB, + const ModuleBase::Vector3& tauA, // unit: ucell.lat0 + const ModuleBase::Vector3& tauB, // unit: ucell.lat0 + const ModuleBase::Element_Basis_Index::IndexLNM& index_A, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B, + const Matrix_Order& matrix_order) const; + template + std::array, 3> cal_grad_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3& tauA, // unit: ucell.lat0 + const ModuleBase::Vector3& tauB, // unit: ucell.lat0 + const ModuleBase::Element_Basis_Index::IndexLNM& index_A, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B, + const Matrix_Order& matrix_order) const; + + template + std::map>>>> cal_overlap_matrix_all( + const UnitCell &ucell, + const ModuleBase::Element_Basis_Index::IndexLNM& index_r, + const ModuleBase::Element_Basis_Index::IndexLNM& index_c) const; + + std::shared_ptr MGT; + + private: + ModuleBase::Sph_Bessel_Recursive::D2* psb_ = nullptr; + const double lcao_dr_ = 0.01; + double* lat0=nullptr; // restore ucell.lat0 + std::map>>>>> + center2_orb11_s; + // this->center2_orb11_s[TA][TB][LA][NA][LB][NB] +}; + +#include "Matrix_Orbs11.hpp" + +#endif diff --git a/source/source_lcao/module_ri/Matrix_Orbs11.hpp b/source/source_lcao/module_ri/Matrix_Orbs11.hpp index 7b139203a10..b537b8e207c 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs11.hpp +++ b/source/source_lcao/module_ri/Matrix_Orbs11.hpp @@ -1,160 +1,160 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef MATRIX_ORB11_HPP -#define MATRIX_ORB11_HPP - -#include "Matrix_Orbs11.h" -#include "RI_Util.h" - -template -RI::Tensor Matrix_Orbs11::cal_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3 &tauA, - const ModuleBase::Vector3 &tauB, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B, - const Matrix_Order &matrix_order) const -{ - RI::Tensor m; - const double lat0 = *this->lat0; - const size_t sizeA = index_A[TA].count_size; - const size_t sizeB = index_B[TB].count_size; - switch(matrix_order) - { - case Matrix_Order::AB: m = RI::Tensor({sizeA, sizeB}); break; - case Matrix_Order::BA: m = RI::Tensor({sizeB, sizeA}); break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - - for( const auto &co3 : center2_orb11_s.at(TA).at(TB) ) - { - const int LA = co3.first; - for( const auto &co4 : co3.second ) - { - const size_t NA = co4.first; - for( size_t MA=0; MA!=2*LA+1; ++MA ) - { - for( const auto &co5 : co4.second ) - { - const int LB = co5.first; - for( const auto &co6 : co5.second ) - { - const size_t NB = co6.first; - for( size_t MB=0; MB!=2*LB+1; ++MB ) - { - const Tdata overlap = co6.second.cal_overlap( tauA*lat0, tauB*lat0, MA, MB ); - const size_t iA = index_A[TA][LA][NA][MA]; - const size_t iB = index_B[TB][LB][NB][MB]; - switch(matrix_order) - { - case Matrix_Order::AB: m(iA,iB) = overlap; break; - case Matrix_Order::BA: m(iB,iA) = overlap; break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - } - } - } - } - } - } - return m; -} - -template -std::array,3> Matrix_Orbs11::cal_grad_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3 &tauA, - const ModuleBase::Vector3 &tauB, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B, - const Matrix_Order &matrix_order) const -{ - std::array,3> m; - const double lat0 = *this->lat0; - const size_t sizeA = index_A[TA].count_size; - const size_t sizeB = index_B[TB].count_size; - for(int i=0; i({sizeA, sizeB}); break; - case Matrix_Order::BA: m[i] = RI::Tensor({sizeB, sizeA}); break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - } - - for( const auto &co3 : center2_orb11_s.at(TA).at(TB) ) - { - const int LA = co3.first; - for( const auto &co4 : co3.second ) - { - const size_t NA = co4.first; - for( size_t MA=0; MA!=2*LA+1; ++MA ) - { - for( const auto &co5 : co4.second ) - { - const int LB = co5.first; - for( const auto &co6 : co5.second ) - { - const size_t NB = co6.first; - for( size_t MB=0; MB!=2*LB+1; ++MB ) - { - const std::array grad_overlap = RI_Util::Vector3_to_array3(co6.second.cal_grad_overlap( tauA*lat0, tauB*lat0, MA, MB )); - const size_t iA = index_A[TA][LA][NA][MA]; - const size_t iB = index_B[TB][LB][NB][MB]; - for(size_t i=0; i -std::map>>>> Matrix_Orbs11::cal_overlap_matrix_all( - const UnitCell &ucell, - const ModuleBase::Element_Basis_Index::IndexLNM &index_r, - const ModuleBase::Element_Basis_Index::IndexLNM &index_c ) const -{ - ModuleBase::TITLE("Matrix_Orbs11","cal_overlap_matrix"); - - std::map>>>> matrixes; - - for( const auto &co1 : center2_orb11_s ) - { - const size_t TA = co1.first; - for (size_t IA=0; IA!=ucell.atoms[TA].na; ++IA) - { - const ModuleBase::Vector3 &tauA( ucell.atoms[TA].tau[IA] ); - - for( const auto &co2 : co1.second ) - { - const size_t TB = co2.first; - for (size_t IB=0; IB!=ucell.atoms[TB].na; ++IB) - { - const ModuleBase::Vector3 &tauB( ucell.atoms[TB].tau[IB] ); - - matrixes[TA][IA][TB][IB] = cal_overlap_matrix( TA, TB, tauA, tauB, index_r, index_c, Matrix_Order::AB ); - } - } - } - } - return matrixes; -} - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef MATRIX_ORB11_HPP +#define MATRIX_ORB11_HPP + +#include "Matrix_Orbs11.h" +#include "RI_Util.h" + +template +RI::Tensor Matrix_Orbs11::cal_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3 &tauA, + const ModuleBase::Vector3 &tauB, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B, + const Matrix_Order &matrix_order) const +{ + RI::Tensor m; + const double lat0 = *this->lat0; + const size_t sizeA = index_A[TA].count_size; + const size_t sizeB = index_B[TB].count_size; + switch(matrix_order) + { + case Matrix_Order::AB: m = RI::Tensor({sizeA, sizeB}); break; + case Matrix_Order::BA: m = RI::Tensor({sizeB, sizeA}); break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + + for( const auto &co3 : center2_orb11_s.at(TA).at(TB) ) + { + const int LA = co3.first; + for( const auto &co4 : co3.second ) + { + const size_t NA = co4.first; + for( size_t MA=0; MA!=2*LA+1; ++MA ) + { + for( const auto &co5 : co4.second ) + { + const int LB = co5.first; + for( const auto &co6 : co5.second ) + { + const size_t NB = co6.first; + for( size_t MB=0; MB!=2*LB+1; ++MB ) + { + const Tdata overlap = co6.second.cal_overlap( tauA*lat0, tauB*lat0, MA, MB ); + const size_t iA = index_A[TA][LA][NA][MA]; + const size_t iB = index_B[TB][LB][NB][MB]; + switch(matrix_order) + { + case Matrix_Order::AB: m(iA,iB) = overlap; break; + case Matrix_Order::BA: m(iB,iA) = overlap; break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + } + } + } + } + } + } + return m; +} + +template +std::array,3> Matrix_Orbs11::cal_grad_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3 &tauA, + const ModuleBase::Vector3 &tauB, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B, + const Matrix_Order &matrix_order) const +{ + std::array,3> m; + const double lat0 = *this->lat0; + const size_t sizeA = index_A[TA].count_size; + const size_t sizeB = index_B[TB].count_size; + for(int i=0; i({sizeA, sizeB}); break; + case Matrix_Order::BA: m[i] = RI::Tensor({sizeB, sizeA}); break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + } + + for( const auto &co3 : center2_orb11_s.at(TA).at(TB) ) + { + const int LA = co3.first; + for( const auto &co4 : co3.second ) + { + const size_t NA = co4.first; + for( size_t MA=0; MA!=2*LA+1; ++MA ) + { + for( const auto &co5 : co4.second ) + { + const int LB = co5.first; + for( const auto &co6 : co5.second ) + { + const size_t NB = co6.first; + for( size_t MB=0; MB!=2*LB+1; ++MB ) + { + const std::array grad_overlap = RI_Util::Vector3_to_array3(co6.second.cal_grad_overlap( tauA*lat0, tauB*lat0, MA, MB )); + const size_t iA = index_A[TA][LA][NA][MA]; + const size_t iB = index_B[TB][LB][NB][MB]; + for(size_t i=0; i +std::map>>>> Matrix_Orbs11::cal_overlap_matrix_all( + const UnitCell &ucell, + const ModuleBase::Element_Basis_Index::IndexLNM &index_r, + const ModuleBase::Element_Basis_Index::IndexLNM &index_c ) const +{ + ModuleBase::TITLE("Matrix_Orbs11","cal_overlap_matrix"); + + std::map>>>> matrixes; + + for( const auto &co1 : center2_orb11_s ) + { + const size_t TA = co1.first; + for (size_t IA=0; IA!=ucell.atoms[TA].na; ++IA) + { + const ModuleBase::Vector3 &tauA( ucell.atoms[TA].tau[IA] ); + + for( const auto &co2 : co1.second ) + { + const size_t TB = co2.first; + for (size_t IB=0; IB!=ucell.atoms[TB].na; ++IB) + { + const ModuleBase::Vector3 &tauB( ucell.atoms[TB].tau[IB] ); + + matrixes[TA][IA][TB][IB] = cal_overlap_matrix( TA, TB, tauA, tauB, index_r, index_c, Matrix_Order::AB ); + } + } + } + } + return matrixes; +} + +#endif diff --git a/source/source_lcao/module_ri/Matrix_Orbs21.cpp b/source/source_lcao/module_ri/Matrix_Orbs21.cpp index 1c20325b2c2..2c6c93d01eb 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs21.cpp +++ b/source/source_lcao/module_ri/Matrix_Orbs21.cpp @@ -1,199 +1,199 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#include "Matrix_Orbs21.h" - -#include "exx_abfs-construct_orbs.h" -#include "source_base/timer.h" -#include "source_base/tool_title.h" - -void Matrix_Orbs21::init( - const std::vector>>& orb_A1, - const std::vector>>& orb_A2, - const std::vector>>& orb_B, - const UnitCell& ucell, - const LCAO_Orbitals& orb, - const double kmesh_times) -{ - ModuleBase::TITLE("Matrix_Orbs21", "init"); - ModuleBase::timer::start("Matrix_Orbs21", "init"); - this->lat0 = &ucell.lat0; - - const int Lmax = std::max({ - Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2), - Exx_Abfs::Construct_Orbs::get_Lmax(orb_B) }); - const int Lmax_used = Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B); - - //========================================= - // (3) make Gaunt coefficients table - //========================================= - if(!this->MGT) - { this->MGT = std::make_shared(); } - if(this->MGT->get_Lmax_Gaunt_CH() < Lmax) - { this->MGT->init_Gaunt_CH(Lmax); } - if(this->MGT->get_Lmax_Gaunt_Coefficients() < Lmax) - { this->MGT->init_Gaunt(Lmax); } - - const double dr = orb.get_dR(); - const double dk = orb.get_dk(); - const int kmesh = orb.get_kmesh() * kmesh_times + 1; - const double rmax - = std::min({Exx_Abfs::Construct_Orbs::get_Rmax(orb_A1), Exx_Abfs::Construct_Orbs::get_Rmax(orb_A2)}) - + Exx_Abfs::Construct_Orbs::get_Rmax(orb_B); - int Rmesh = static_cast(rmax / dr) + 4; // extend Rcut, keep dR - Rmesh += 1 - Rmesh % 2; - Center2_Orb::init_Table_Spherical_Bessel(Lmax_used, - dr, - dk, - kmesh, - Rmesh, - psb_); - - assert(orb_A1.size() == orb_A2.size()); - for (size_t TA = 0; TA != orb_A1.size(); ++TA) { - for (size_t TB = 0; TB != orb_B.size(); ++TB) { - for (int LA1 = 0; LA1 != orb_A1[TA].size(); ++LA1) { - for (size_t NA1 = 0; NA1 != orb_A1[TA][LA1].size(); ++NA1) { - for (int LA2 = 0; LA2 != orb_A2[TA].size(); ++LA2) { - for (size_t NA2 = 0; NA2 != orb_A2[TA][LA2].size(); ++NA2) { - for (int LB = 0; LB != orb_B[TB].size(); ++LB) { - for (size_t NB = 0; NB != orb_B[TB][LB].size(); ++NB) { - center2_orb21_s[TA][TB][LA1][NA1][LA2][NA2][LB].insert( - std::make_pair( - NB, - Center2_Orb::Orb21( - orb_A1[TA][LA1][NA1], - orb_A2[TA][LA2][NA2], - orb_B[TB][LB][NB], - psb_, - *this->MGT))); - }}}}}}}} - ModuleBase::timer::end("Matrix_Orbs21", "init"); -} - -/* -void Matrix_Orbs21::init_radial(const std::vector>>& orb_A1, - const LCAO_Orbitals& orb_A2, - const LCAO_Orbitals& orb_B) -{ - ModuleBase::TITLE("Matrix_Orbs21", "init_radial"); - ModuleBase::timer::start("Matrix_Orbs21", "init_radial"); - assert(orb_A1.size() == orb_A2.get_ntype()); - for (size_t TA = 0; TA != orb_A1.size(); ++TA) - { - for (size_t TB = 0; TB != orb_B.get_ntype(); ++TB) - { - for (int LA1 = 0; LA1 != orb_A1[TA].size(); ++LA1) - { - for (size_t NA1 = 0; NA1 != orb_A1[TA][LA1].size(); ++NA1) - { - for (int LA2 = 0; LA2 <= orb_A2.Phi[TA].getLmax(); ++LA2) - { - for (size_t NA2 = 0; NA2 != orb_A2.Phi[TA].getNchi(LA2); ++NA2) - { - for (int LB = 0; LB <= orb_B.Phi[TB].getLmax(); ++LB) - { - for (size_t NB = 0; NB != orb_B.Phi[TB].getNchi(LB); ++NB) - { - center2_orb21_s[TA][TB][LA1][NA1][LA2][NA2][LB].insert( - std::make_pair(NB, - Center2_Orb::Orb21(orb_A1[TA][LA1][NA1], - orb_A2.Phi[TA].PhiLN(LA2, NA2), - orb_B.Phi[TB].PhiLN(LB, NB), - psb_, - *this->MGT))); - } - } - } - } - } - } - } - } - ModuleBase::timer::end("Matrix_Orbs21", "init_radial"); -} -*/ - -void Matrix_Orbs21::init_radial_table() -{ - ModuleBase::TITLE("Matrix_Orbs21", "init_radial_table"); - ModuleBase::timer::start("Matrix_Orbs21", "init_radial_table"); - for (auto& coA: center2_orb21_s) - { - for (auto& coB: coA.second) - { - for (auto& coC: coB.second) - { - for (auto& coD: coC.second) - { - for (auto& coE: coD.second) - { - for (auto& coF: coE.second) - { - for (auto& coG: coF.second) - { - for (auto& coH: coG.second) - { - coH.second.init_radial_table(); - } - } - } - } - } - } - } - } - ModuleBase::timer::end("Matrix_Orbs21", "init_radial_table"); -} - -void Matrix_Orbs21::init_radial_table(const std::map>>& Rs) -{ - ModuleBase::TITLE("Matrix_Orbs21", "init_radial_table_Rs"); - ModuleBase::timer::start("Matrix_Orbs21", "init_radial_table"); - const double lat0 = *this->lat0; - for (const auto& RsA: Rs) { - for (const auto& RsB: RsA.second) - { - if (auto* const center2_orb21_sAB = static_cast>>>>>* const>( - ModuleBase::GlobalFunc::MAP_EXIST(center2_orb21_s, RsA.first, RsB.first))) - { - std::set radials; - for (const double& R: RsB.second) - { - const double position = R * lat0 / lcao_dr_; - const size_t iq = static_cast(position); - for (size_t i = 0; i != 4; ++i) - { - radials.insert(iq + i); - } - } - for (auto& coC: *center2_orb21_sAB) - { - for (auto& coD: coC.second) - { - for (auto& coE: coD.second) - { - for (auto& coF: coE.second) - { - for (auto& coG: coF.second) - { - for (auto& coH: coG.second) - { - coH.second.init_radial_table(radials); - } - } - } - } - } - } - } - } - } - ModuleBase::timer::end("Matrix_Orbs21", "init_radial_table"); -} +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#include "Matrix_Orbs21.h" + +#include "exx_abfs-construct_orbs.h" +#include "source_base/timer.h" +#include "source_base/tool_title.h" + +void Matrix_Orbs21::init( + const std::vector>>& orb_A1, + const std::vector>>& orb_A2, + const std::vector>>& orb_B, + const UnitCell& ucell, + const LCAO_Orbitals& orb, + const double kmesh_times) +{ + ModuleBase::TITLE("Matrix_Orbs21", "init"); + ModuleBase::timer::start("Matrix_Orbs21", "init"); + this->lat0 = &ucell.lat0; + + const int Lmax = std::max({ + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2), + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B) }); + const int Lmax_used = Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B); + + //========================================= + // (3) make Gaunt coefficients table + //========================================= + if(!this->MGT) + { this->MGT = std::make_shared(); } + if(this->MGT->get_Lmax_Gaunt_CH() < Lmax) + { this->MGT->init_Gaunt_CH(Lmax); } + if(this->MGT->get_Lmax_Gaunt_Coefficients() < Lmax) + { this->MGT->init_Gaunt(Lmax); } + + const double dr = orb.get_dR(); + const double dk = orb.get_dk(); + const int kmesh = orb.get_kmesh() * kmesh_times + 1; + const double rmax + = std::min({Exx_Abfs::Construct_Orbs::get_Rmax(orb_A1), Exx_Abfs::Construct_Orbs::get_Rmax(orb_A2)}) + + Exx_Abfs::Construct_Orbs::get_Rmax(orb_B); + int Rmesh = static_cast(rmax / dr) + 4; // extend Rcut, keep dR + Rmesh += 1 - Rmesh % 2; + Center2_Orb::init_Table_Spherical_Bessel(Lmax_used, + dr, + dk, + kmesh, + Rmesh, + psb_); + + assert(orb_A1.size() == orb_A2.size()); + for (size_t TA = 0; TA != orb_A1.size(); ++TA) { + for (size_t TB = 0; TB != orb_B.size(); ++TB) { + for (int LA1 = 0; LA1 != orb_A1[TA].size(); ++LA1) { + for (size_t NA1 = 0; NA1 != orb_A1[TA][LA1].size(); ++NA1) { + for (int LA2 = 0; LA2 != orb_A2[TA].size(); ++LA2) { + for (size_t NA2 = 0; NA2 != orb_A2[TA][LA2].size(); ++NA2) { + for (int LB = 0; LB != orb_B[TB].size(); ++LB) { + for (size_t NB = 0; NB != orb_B[TB][LB].size(); ++NB) { + center2_orb21_s[TA][TB][LA1][NA1][LA2][NA2][LB].insert( + std::make_pair( + NB, + Center2_Orb::Orb21( + orb_A1[TA][LA1][NA1], + orb_A2[TA][LA2][NA2], + orb_B[TB][LB][NB], + psb_, + *this->MGT))); + }}}}}}}} + ModuleBase::timer::end("Matrix_Orbs21", "init"); +} + +/* +void Matrix_Orbs21::init_radial(const std::vector>>& orb_A1, + const LCAO_Orbitals& orb_A2, + const LCAO_Orbitals& orb_B) +{ + ModuleBase::TITLE("Matrix_Orbs21", "init_radial"); + ModuleBase::timer::start("Matrix_Orbs21", "init_radial"); + assert(orb_A1.size() == orb_A2.get_ntype()); + for (size_t TA = 0; TA != orb_A1.size(); ++TA) + { + for (size_t TB = 0; TB != orb_B.get_ntype(); ++TB) + { + for (int LA1 = 0; LA1 != orb_A1[TA].size(); ++LA1) + { + for (size_t NA1 = 0; NA1 != orb_A1[TA][LA1].size(); ++NA1) + { + for (int LA2 = 0; LA2 <= orb_A2.Phi[TA].getLmax(); ++LA2) + { + for (size_t NA2 = 0; NA2 != orb_A2.Phi[TA].getNchi(LA2); ++NA2) + { + for (int LB = 0; LB <= orb_B.Phi[TB].getLmax(); ++LB) + { + for (size_t NB = 0; NB != orb_B.Phi[TB].getNchi(LB); ++NB) + { + center2_orb21_s[TA][TB][LA1][NA1][LA2][NA2][LB].insert( + std::make_pair(NB, + Center2_Orb::Orb21(orb_A1[TA][LA1][NA1], + orb_A2.Phi[TA].PhiLN(LA2, NA2), + orb_B.Phi[TB].PhiLN(LB, NB), + psb_, + *this->MGT))); + } + } + } + } + } + } + } + } + ModuleBase::timer::end("Matrix_Orbs21", "init_radial"); +} +*/ + +void Matrix_Orbs21::init_radial_table() +{ + ModuleBase::TITLE("Matrix_Orbs21", "init_radial_table"); + ModuleBase::timer::start("Matrix_Orbs21", "init_radial_table"); + for (auto& coA: center2_orb21_s) + { + for (auto& coB: coA.second) + { + for (auto& coC: coB.second) + { + for (auto& coD: coC.second) + { + for (auto& coE: coD.second) + { + for (auto& coF: coE.second) + { + for (auto& coG: coF.second) + { + for (auto& coH: coG.second) + { + coH.second.init_radial_table(); + } + } + } + } + } + } + } + } + ModuleBase::timer::end("Matrix_Orbs21", "init_radial_table"); +} + +void Matrix_Orbs21::init_radial_table(const std::map>>& Rs) +{ + ModuleBase::TITLE("Matrix_Orbs21", "init_radial_table_Rs"); + ModuleBase::timer::start("Matrix_Orbs21", "init_radial_table"); + const double lat0 = *this->lat0; + for (const auto& RsA: Rs) { + for (const auto& RsB: RsA.second) + { + if (auto* const center2_orb21_sAB = static_cast>>>>>* const>( + ModuleBase::GlobalFunc::MAP_EXIST(center2_orb21_s, RsA.first, RsB.first))) + { + std::set radials; + for (const double& R: RsB.second) + { + const double position = R * lat0 / lcao_dr_; + const size_t iq = static_cast(position); + for (size_t i = 0; i != 4; ++i) + { + radials.insert(iq + i); + } + } + for (auto& coC: *center2_orb21_sAB) + { + for (auto& coD: coC.second) + { + for (auto& coE: coD.second) + { + for (auto& coF: coE.second) + { + for (auto& coG: coF.second) + { + for (auto& coH: coG.second) + { + coH.second.init_radial_table(radials); + } + } + } + } + } + } + } + } + } + ModuleBase::timer::end("Matrix_Orbs21", "init_radial_table"); +} diff --git a/source/source_lcao/module_ri/Matrix_Orbs21.h b/source/source_lcao/module_ri/Matrix_Orbs21.h index efd561a00f3..4520a300e9f 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs21.h +++ b/source/source_lcao/module_ri/Matrix_Orbs21.h @@ -1,92 +1,92 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef MATRIX_ORB21_H -#define MATRIX_ORB21_H - -#include "source_base/element_basis_index.h" -#include "source_base/vector3.h" -#include "source_basis/module_ao/ORB_gaunt_table.h" -#include "source_basis/module_ao/ORB_read.h" -#include "source_lcao/center2_orb-orb21.h" -#include "source_cell/unitcell.h" -#include -#include -#include -#include - -class Matrix_Orbs21 -{ - public: - void init( - const std::vector>>& orb_A1, - const std::vector>>& orb_A2, - const std::vector>>& orb_B, - const UnitCell& ucell, - const LCAO_Orbitals& orb, - const double kmesh_times); // extend Kcut, keep dK - - void init_radial_table(); - void init_radial_table(const std::map>>& Rs); // unit: ucell.lat0 - - enum class Matrix_Order - { - A1A2B, - A1BA2, - A2A1B, - A2BA1, - BA1A2, - BA2A1 - }; - - template - RI::Tensor cal_overlap_matrix(const size_t TA, - const size_t TB, - const ModuleBase::Vector3& tauA, // unit: ucell.lat0 - const ModuleBase::Vector3& tauB, // unit: ucell.lat0 - const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B, - const Matrix_Order& matrix_order) const; - template - std::array, 3> cal_grad_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3& tauA, // unit: ucell.lat0 - const ModuleBase::Vector3& tauB, // unit: ucell.lat0 - const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B, - const Matrix_Order& matrix_order) const; - - template - std::map>>>>> - cal_overlap_matrix_all(const UnitCell& ucell, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B) const; - - std::shared_ptr MGT; - - private: - ModuleBase::Sph_Bessel_Recursive::D2* psb_ = nullptr; - const double lcao_dr_ = 0.01; - double* lat0 = nullptr; // restore ucell.lat0 - std::map>>>>>>> - center2_orb21_s; - // this->center2_orb21_s[TA][TB][LA1][NA1][LA2][NA2][LB][NB] -}; - -#include "Matrix_Orbs21.hpp" - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef MATRIX_ORB21_H +#define MATRIX_ORB21_H + +#include "source_base/element_basis_index.h" +#include "source_base/vector3.h" +#include "source_basis/module_ao/ORB_gaunt_table.h" +#include "source_basis/module_ao/ORB_read.h" +#include "source_lcao/center2_orb-orb21.h" +#include "source_cell/unitcell.h" +#include +#include +#include +#include + +class Matrix_Orbs21 +{ + public: + void init( + const std::vector>>& orb_A1, + const std::vector>>& orb_A2, + const std::vector>>& orb_B, + const UnitCell& ucell, + const LCAO_Orbitals& orb, + const double kmesh_times); // extend Kcut, keep dK + + void init_radial_table(); + void init_radial_table(const std::map>>& Rs); // unit: ucell.lat0 + + enum class Matrix_Order + { + A1A2B, + A1BA2, + A2A1B, + A2BA1, + BA1A2, + BA2A1 + }; + + template + RI::Tensor cal_overlap_matrix(const size_t TA, + const size_t TB, + const ModuleBase::Vector3& tauA, // unit: ucell.lat0 + const ModuleBase::Vector3& tauB, // unit: ucell.lat0 + const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B, + const Matrix_Order& matrix_order) const; + template + std::array, 3> cal_grad_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3& tauA, // unit: ucell.lat0 + const ModuleBase::Vector3& tauB, // unit: ucell.lat0 + const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B, + const Matrix_Order& matrix_order) const; + + template + std::map>>>>> + cal_overlap_matrix_all(const UnitCell& ucell, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B) const; + + std::shared_ptr MGT; + + private: + ModuleBase::Sph_Bessel_Recursive::D2* psb_ = nullptr; + const double lcao_dr_ = 0.01; + double* lat0 = nullptr; // restore ucell.lat0 + std::map>>>>>>> + center2_orb21_s; + // this->center2_orb21_s[TA][TB][LA1][NA1][LA2][NA2][LB][NB] +}; + +#include "Matrix_Orbs21.hpp" + +#endif diff --git a/source/source_lcao/module_ri/Matrix_Orbs21.hpp b/source/source_lcao/module_ri/Matrix_Orbs21.hpp index af92d7aeddc..109179ce277 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs21.hpp +++ b/source/source_lcao/module_ri/Matrix_Orbs21.hpp @@ -1,220 +1,220 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef MATRIX_ORB21_HPP -#define MATRIX_ORB21_HPP - -#include "Matrix_Orbs21.h" -#include "RI_Util.h" - -template -RI::Tensor Matrix_Orbs21::cal_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3 &tauA, - const ModuleBase::Vector3 &tauB, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B, - const Matrix_Order &matrix_order) const -{ - RI::Tensor m; - const double lat0 = *this->lat0; - const size_t sizeA1 = index_A1[TA].count_size; - const size_t sizeA2 = index_A2[TA].count_size; - const size_t sizeB = index_B[TB].count_size; - switch(matrix_order) - { - case Matrix_Order::A1A2B: m = RI::Tensor({sizeA1, sizeA2, sizeB}); break; - case Matrix_Order::A1BA2: m = RI::Tensor({sizeA1, sizeB, sizeA2}); break; - case Matrix_Order::BA1A2: m = RI::Tensor({sizeB, sizeA1, sizeA2}); break; - case Matrix_Order::BA2A1: m = RI::Tensor({sizeB, sizeA2, sizeA1}); break; - case Matrix_Order::A2A1B: m = RI::Tensor({sizeA2, sizeA1, sizeB}); break; - case Matrix_Order::A2BA1: m = RI::Tensor({sizeA2, sizeB, sizeA1}); break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - - for( const auto &co3 : center2_orb21_s.at(TA).at(TB) ) - { - const int LA1 = co3.first; - for( const auto &co4 : co3.second ) - { - const size_t NA1 = co4.first; - for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) - { - for( const auto &co5 : co4.second ) - { - const int LA2 = co5.first; - for( const auto &co6 : co5.second ) - { - const size_t NA2 = co6.first; - for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) - { - for( const auto &co7 : co6.second ) - { - const int LB = co7.first; - for( const auto &co8 : co7.second ) - { - const size_t NB = co8.first; - for( size_t MB=0; MB!=2*LB+1; ++MB ) - { - const Tdata overlap = co8.second.cal_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB ); - const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; - const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; - const size_t iB = index_B[TB][LB][NB][MB]; - switch(matrix_order) - { - case Matrix_Order::A1A2B: m(iA1,iA2,iB) = overlap; break; - case Matrix_Order::A1BA2: m(iA1,iB,iA2) = overlap; break; - case Matrix_Order::A2A1B: m(iA2,iA1,iB) = overlap; break; - case Matrix_Order::A2BA1: m(iA2,iB,iA1) = overlap; break; - case Matrix_Order::BA1A2: m(iB,iA1,iA2) = overlap; break; - case Matrix_Order::BA2A1: m(iB,iA2,iA1) = overlap; break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - } - } - } - } - } - } - } - } - } - return m; -} - -template -std::array,3> Matrix_Orbs21::cal_grad_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3 &tauA, - const ModuleBase::Vector3 &tauB, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B, - const Matrix_Order &matrix_order) const -{ - std::array,3> m; - const double lat0 = *this->lat0; - const size_t sizeA1 = index_A1[TA].count_size; - const size_t sizeA2 = index_A2[TA].count_size; - const size_t sizeB = index_B[TB].count_size; - for(int i=0; i({sizeA1, sizeA2, sizeB}); break; - case Matrix_Order::A1BA2: m[i] = RI::Tensor({sizeA1, sizeB, sizeA2}); break; - case Matrix_Order::BA1A2: m[i] = RI::Tensor({sizeB, sizeA1, sizeA2}); break; - case Matrix_Order::BA2A1: m[i] = RI::Tensor({sizeB, sizeA2, sizeA1}); break; - case Matrix_Order::A2A1B: m[i] = RI::Tensor({sizeA2, sizeA1, sizeB}); break; - case Matrix_Order::A2BA1: m[i] = RI::Tensor({sizeA2, sizeB, sizeA1}); break; - default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); - } - } - - for( const auto &co3 : center2_orb21_s.at(TA).at(TB) ) - { - const int LA1 = co3.first; - for( const auto &co4 : co3.second ) - { - const size_t NA1 = co4.first; - for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) - { - for( const auto &co5 : co4.second ) - { - const int LA2 = co5.first; - for( const auto &co6 : co5.second ) - { - const size_t NA2 = co6.first; - for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) - { - for( const auto &co7 : co6.second ) - { - const int LB = co7.first; - for( const auto &co8 : co7.second ) - { - const size_t NB = co8.first; - for( size_t MB=0; MB!=2*LB+1; ++MB ) - { - const std::array grad_overlap = RI_Util::Vector3_to_array3(co8.second.cal_grad_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB )); - const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; - const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; - const size_t iB = index_B[TB][LB][NB][MB]; - for(size_t i=0; i -std::map>>>>> Matrix_Orbs21::cal_overlap_matrix_all( - const UnitCell &ucell, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM &index_B) const -{ - ModuleBase::TITLE("Matrix_Orbs21","cal_overlap_matrix"); - - std::map>>>>> matrixes; - - for( const auto &co1 : center2_orb21_s ) - { - const size_t TA = co1.first; - for( size_t IA=0; IA!=ucell.atoms[TA].na; ++IA ) - { - const ModuleBase::Vector3 &tauA( ucell.atoms[TA].tau[IA] ); - - for( const auto &co2 : co1.second ) - { - const size_t TB = co2.first; - for( size_t IB=0; IB!=ucell.atoms[TB].na; ++IB ) - { - const ModuleBase::Vector3 &tauB( ucell.atoms[TB].tau[IB] ); - - const RI::Tensor &&m = cal_overlap_matrix( TA, TB, tauA, tauB, index_A1, index_A2, index_B, Matrix_Order::A2BA1 ); - matrixes[TA][IA][TB][IB].resize(2); - matrixes[TA][IA][TB][IB][0] = std::move(m); - const RI::Tensor &&n = cal_overlap_matrix( TA, TB, tauA, tauB, index_A1, index_A2, index_B, Matrix_Order::BA2A1 ); - matrixes[TB][IB][TA][IA].resize(2); - matrixes[TB][IB][TA][IA][1] = std::move(n); - } - } - } - } - // matrixes[T][I][T][I][0] = matrixes[T][I][T][I][1], so delete repeat - for (auto m1 : matrixes) - { - const size_t T = m1.first; - for( auto m2 : m1.second ) - { - const size_t I = m2.first; - matrixes[T][I][T][I].resize(1); - } - } - - return matrixes; -} -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef MATRIX_ORB21_HPP +#define MATRIX_ORB21_HPP + +#include "Matrix_Orbs21.h" +#include "RI_Util.h" + +template +RI::Tensor Matrix_Orbs21::cal_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3 &tauA, + const ModuleBase::Vector3 &tauB, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B, + const Matrix_Order &matrix_order) const +{ + RI::Tensor m; + const double lat0 = *this->lat0; + const size_t sizeA1 = index_A1[TA].count_size; + const size_t sizeA2 = index_A2[TA].count_size; + const size_t sizeB = index_B[TB].count_size; + switch(matrix_order) + { + case Matrix_Order::A1A2B: m = RI::Tensor({sizeA1, sizeA2, sizeB}); break; + case Matrix_Order::A1BA2: m = RI::Tensor({sizeA1, sizeB, sizeA2}); break; + case Matrix_Order::BA1A2: m = RI::Tensor({sizeB, sizeA1, sizeA2}); break; + case Matrix_Order::BA2A1: m = RI::Tensor({sizeB, sizeA2, sizeA1}); break; + case Matrix_Order::A2A1B: m = RI::Tensor({sizeA2, sizeA1, sizeB}); break; + case Matrix_Order::A2BA1: m = RI::Tensor({sizeA2, sizeB, sizeA1}); break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + + for( const auto &co3 : center2_orb21_s.at(TA).at(TB) ) + { + const int LA1 = co3.first; + for( const auto &co4 : co3.second ) + { + const size_t NA1 = co4.first; + for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) + { + for( const auto &co5 : co4.second ) + { + const int LA2 = co5.first; + for( const auto &co6 : co5.second ) + { + const size_t NA2 = co6.first; + for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) + { + for( const auto &co7 : co6.second ) + { + const int LB = co7.first; + for( const auto &co8 : co7.second ) + { + const size_t NB = co8.first; + for( size_t MB=0; MB!=2*LB+1; ++MB ) + { + const Tdata overlap = co8.second.cal_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB ); + const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; + const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; + const size_t iB = index_B[TB][LB][NB][MB]; + switch(matrix_order) + { + case Matrix_Order::A1A2B: m(iA1,iA2,iB) = overlap; break; + case Matrix_Order::A1BA2: m(iA1,iB,iA2) = overlap; break; + case Matrix_Order::A2A1B: m(iA2,iA1,iB) = overlap; break; + case Matrix_Order::A2BA1: m(iA2,iB,iA1) = overlap; break; + case Matrix_Order::BA1A2: m(iB,iA1,iA2) = overlap; break; + case Matrix_Order::BA2A1: m(iB,iA2,iA1) = overlap; break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + } + } + } + } + } + } + } + } + } + return m; +} + +template +std::array,3> Matrix_Orbs21::cal_grad_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3 &tauA, + const ModuleBase::Vector3 &tauB, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B, + const Matrix_Order &matrix_order) const +{ + std::array,3> m; + const double lat0 = *this->lat0; + const size_t sizeA1 = index_A1[TA].count_size; + const size_t sizeA2 = index_A2[TA].count_size; + const size_t sizeB = index_B[TB].count_size; + for(int i=0; i({sizeA1, sizeA2, sizeB}); break; + case Matrix_Order::A1BA2: m[i] = RI::Tensor({sizeA1, sizeB, sizeA2}); break; + case Matrix_Order::BA1A2: m[i] = RI::Tensor({sizeB, sizeA1, sizeA2}); break; + case Matrix_Order::BA2A1: m[i] = RI::Tensor({sizeB, sizeA2, sizeA1}); break; + case Matrix_Order::A2A1B: m[i] = RI::Tensor({sizeA2, sizeA1, sizeB}); break; + case Matrix_Order::A2BA1: m[i] = RI::Tensor({sizeA2, sizeB, sizeA1}); break; + default: throw std::invalid_argument(std::string(__FILE__)+" line "+std::to_string(__LINE__)); + } + } + + for( const auto &co3 : center2_orb21_s.at(TA).at(TB) ) + { + const int LA1 = co3.first; + for( const auto &co4 : co3.second ) + { + const size_t NA1 = co4.first; + for( size_t MA1=0; MA1!=2*LA1+1; ++MA1 ) + { + for( const auto &co5 : co4.second ) + { + const int LA2 = co5.first; + for( const auto &co6 : co5.second ) + { + const size_t NA2 = co6.first; + for( size_t MA2=0; MA2!=2*LA2+1; ++MA2 ) + { + for( const auto &co7 : co6.second ) + { + const int LB = co7.first; + for( const auto &co8 : co7.second ) + { + const size_t NB = co8.first; + for( size_t MB=0; MB!=2*LB+1; ++MB ) + { + const std::array grad_overlap = RI_Util::Vector3_to_array3(co8.second.cal_grad_overlap( tauA*lat0, tauB*lat0, MA1, MA2, MB )); + const size_t iA1 = index_A1[TA][LA1][NA1][MA1]; + const size_t iA2 = index_A2[TA][LA2][NA2][MA2]; + const size_t iB = index_B[TB][LB][NB][MB]; + for(size_t i=0; i +std::map>>>>> Matrix_Orbs21::cal_overlap_matrix_all( + const UnitCell &ucell, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM &index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM &index_B) const +{ + ModuleBase::TITLE("Matrix_Orbs21","cal_overlap_matrix"); + + std::map>>>>> matrixes; + + for( const auto &co1 : center2_orb21_s ) + { + const size_t TA = co1.first; + for( size_t IA=0; IA!=ucell.atoms[TA].na; ++IA ) + { + const ModuleBase::Vector3 &tauA( ucell.atoms[TA].tau[IA] ); + + for( const auto &co2 : co1.second ) + { + const size_t TB = co2.first; + for( size_t IB=0; IB!=ucell.atoms[TB].na; ++IB ) + { + const ModuleBase::Vector3 &tauB( ucell.atoms[TB].tau[IB] ); + + const RI::Tensor &&m = cal_overlap_matrix( TA, TB, tauA, tauB, index_A1, index_A2, index_B, Matrix_Order::A2BA1 ); + matrixes[TA][IA][TB][IB].resize(2); + matrixes[TA][IA][TB][IB][0] = std::move(m); + const RI::Tensor &&n = cal_overlap_matrix( TA, TB, tauA, tauB, index_A1, index_A2, index_B, Matrix_Order::BA2A1 ); + matrixes[TB][IB][TA][IA].resize(2); + matrixes[TB][IB][TA][IA][1] = std::move(n); + } + } + } + } + // matrixes[T][I][T][I][0] = matrixes[T][I][T][I][1], so delete repeat + for (auto m1 : matrixes) + { + const size_t T = m1.first; + for( auto m2 : m1.second ) + { + const size_t I = m2.first; + matrixes[T][I][T][I].resize(1); + } + } + + return matrixes; +} +#endif diff --git a/source/source_lcao/module_ri/Matrix_Orbs22.cpp b/source/source_lcao/module_ri/Matrix_Orbs22.cpp index 4a7856b4b2f..7c526328c90 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs22.cpp +++ b/source/source_lcao/module_ri/Matrix_Orbs22.cpp @@ -1,173 +1,173 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2023-02-23 -//======================= - -#include "Matrix_Orbs22.h" - -#include "exx_abfs-construct_orbs.h" -#include "source_base/timer.h" -#include "source_base/tool_title.h" - -void Matrix_Orbs22::init( - const std::vector>>& orb_A1, - const std::vector>>& orb_A2, - const std::vector>>& orb_B1, - const std::vector>>& orb_B2, - const UnitCell& ucell, - const LCAO_Orbitals& orb, - const double kmesh_times) -{ - ModuleBase::TITLE("Matrix_Orbs22", "init"); - ModuleBase::timer::start("Matrix_Orbs22", "init"); - - this->lat0 = &ucell.lat0; - - const int Lmax = std::max({ - Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2), - Exx_Abfs::Construct_Orbs::get_Lmax(orb_B1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B2) }); - const int Lmax_used = Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B2); - - //========================================= - // (3) make Gaunt coefficients table - //========================================= - if(!this->MGT) - { this->MGT = std::make_shared(); } - if(this->MGT->get_Lmax_Gaunt_CH() < Lmax) - { this->MGT->init_Gaunt_CH(Lmax); } - if(this->MGT->get_Lmax_Gaunt_Coefficients() < Lmax) - { this->MGT->init_Gaunt(Lmax); } - - const double dr = orb.get_dR(); - const double dk = orb.get_dk(); - const int kmesh = orb.get_kmesh() * kmesh_times + 1; - const double rmax - = std::min({Exx_Abfs::Construct_Orbs::get_Rmax(orb_A1), Exx_Abfs::Construct_Orbs::get_Rmax(orb_A2)}) - + std::min({Exx_Abfs::Construct_Orbs::get_Rmax(orb_B1), Exx_Abfs::Construct_Orbs::get_Rmax(orb_B2)}); - int Rmesh = static_cast(rmax / dr) + 4; // extend Rcut, keep dR - Rmesh += 1 - Rmesh % 2; - Center2_Orb::init_Table_Spherical_Bessel(Lmax_used, - dr, - dk, - kmesh, - Rmesh, - psb_); - - assert(orb_A1.size() == orb_A2.size()); - assert(orb_B1.size() == orb_B2.size()); - for (size_t TA = 0; TA != orb_A1.size(); ++TA) { - for (size_t TB = 0; TB != orb_B1.size(); ++TB) { - for (int LA1 = 0; LA1 != orb_A1[TA].size(); ++LA1) { - for (size_t NA1 = 0; NA1 != orb_A1[TA][LA1].size(); ++NA1) { - for (int LA2 = 0; LA2 != orb_A2[TA].size(); ++LA2) { - for (size_t NA2 = 0; NA2 != orb_A2[TA][LA2].size(); ++NA2) { - for (int LB1 = 0; LB1 != orb_B1[TB].size(); ++LB1) { - for (size_t NB1 = 0; NB1 != orb_B1[TB][LB1].size(); ++NB1) { - for (int LB2 = 0; LB2 != orb_B2[TB].size(); ++LB2) { - for (size_t NB2 = 0; NB2 != orb_B2[TB][LB2].size(); ++NB2) { - center2_orb22_s[TA][TB][LA1][NA1][LA2][NA2][LB1][NB1][LB2].insert( - std::make_pair( - NB2, - Center2_Orb::Orb22( - orb_A1[TA][LA1][NA1], - orb_A2[TA][LA2][NA2], - orb_B1[TB][LB1][NB1], - orb_B2[TB][LB2][NB2], - psb_, - *this->MGT))); - }}}}}}}}}} - ModuleBase::timer::end("Matrix_Orbs22", "init"); -} - -/* -void Matrix_Orbs22::init_radial(const LCAO_Orbitals& orb_A1, - const LCAO_Orbitals& orb_A2, - const LCAO_Orbitals& orb_B1, - const LCAO_Orbitals& orb_B2) -{ - ModuleBase::TITLE("Matrix_Orbs22", "init_radial"); - ModuleBase::timer::start("Matrix_Orbs22", "init_radial"); - assert(orb_A1.get_ntype() == orb_A2.get_ntype()); - assert(orb_B1.get_ntype() == orb_B2.get_ntype()); - for (size_t TA = 0; TA != orb_A1.get_ntype(); ++TA) - for (size_t TB = 0; TB != orb_B1.get_ntype(); ++TB) - for (int LA1 = 0; LA1 != orb_A1.Phi[TA].getLmax(); ++LA1) - for (size_t NA1 = 0; NA1 != orb_A1.Phi[TA].getNchi(LA1); ++NA1) - for (int LA2 = 0; LA2 <= orb_A2.Phi[TA].getLmax(); ++LA2) - for (size_t NA2 = 0; NA2 != orb_A2.Phi[TA].getNchi(LA2); ++NA2) - for (int LB1 = 0; LB1 <= orb_B1.Phi[TB].getLmax(); ++LB1) - for (size_t NB1 = 0; NB1 != orb_B1.Phi[TB].getNchi(LB1); ++NB1) - for (int LB2 = 0; LB2 <= orb_B2.Phi[TB].getLmax(); ++LB2) - for (size_t NB2 = 0; NB2 != orb_B2.Phi[TB].getNchi(LB2); ++NB2) - center2_orb22_s[TA][TB][LA1][NA1][LA2][NA2][LB1][NB1][LB2].insert( - std::make_pair(NB2, - Center2_Orb::Orb22(orb_A1.Phi[TA].PhiLN(LA1, NA1), - orb_A2.Phi[TA].PhiLN(LA2, NA2), - orb_B1.Phi[TB].PhiLN(LB1, NB1), - orb_B2.Phi[TB].PhiLN(LB2, NB2), - psb_, - *this->MGT))); - ModuleBase::timer::end("Matrix_Orbs22", "init_radial"); -} -*/ - -void Matrix_Orbs22::init_radial_table() -{ - ModuleBase::TITLE("Matrix_Orbs22", "init_radial_table"); - ModuleBase::timer::start("Matrix_Orbs22", "init_radial_table"); - for (auto& coA: center2_orb22_s) - for (auto& coB: coA.second) - for (auto& coC: coB.second) - for (auto& coD: coC.second) - for (auto& coE: coD.second) - for (auto& coF: coE.second) - for (auto& coG: coF.second) - for (auto& coH: coG.second) - for (auto& coI: coH.second) - for (auto& coJ: coI.second) - coJ.second.init_radial_table(); - ModuleBase::timer::end("Matrix_Orbs22", "init_radial_table"); -} - -void Matrix_Orbs22::init_radial_table(const std::map>>& Rs) -{ - ModuleBase::TITLE("Matrix_Orbs22", "init_radial_table_Rs"); - ModuleBase::timer::start("Matrix_Orbs22", "init_radial_table"); - const double lat0 = *this->lat0; - for (const auto& RsA: Rs) - for (const auto& RsB: RsA.second) - { - if (auto* const center2_orb22_sAB = static_cast>>>>>>>* const>( - ModuleBase::GlobalFunc::MAP_EXIST(center2_orb22_s, RsA.first, RsB.first))) - { - std::set radials; - for (const double& R: RsB.second) - { - const double position = R * lat0 / lcao_dr_; - const size_t iq = static_cast(position); - for (size_t i = 0; i != 4; ++i) - radials.insert(iq + i); - } - for (auto& coC: *center2_orb22_sAB) - for (auto& coD: coC.second) - for (auto& coE: coD.second) - for (auto& coF: coE.second) - for (auto& coG: coF.second) - for (auto& coH: coG.second) - for (auto& coI: coH.second) - for (auto& coJ: coI.second) - coJ.second.init_radial_table(); - } - } - ModuleBase::timer::end("Matrix_Orbs22", "init_radial_table"); -} +//======================= +// AUTHOR : Peize Lin +// DATE : 2023-02-23 +//======================= + +#include "Matrix_Orbs22.h" + +#include "exx_abfs-construct_orbs.h" +#include "source_base/timer.h" +#include "source_base/tool_title.h" + +void Matrix_Orbs22::init( + const std::vector>>& orb_A1, + const std::vector>>& orb_A2, + const std::vector>>& orb_B1, + const std::vector>>& orb_B2, + const UnitCell& ucell, + const LCAO_Orbitals& orb, + const double kmesh_times) +{ + ModuleBase::TITLE("Matrix_Orbs22", "init"); + ModuleBase::timer::start("Matrix_Orbs22", "init"); + + this->lat0 = &ucell.lat0; + + const int Lmax = std::max({ + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2), + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B2) }); + const int Lmax_used = Exx_Abfs::Construct_Orbs::get_Lmax(orb_A1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_A2) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B1) + Exx_Abfs::Construct_Orbs::get_Lmax(orb_B2); + + //========================================= + // (3) make Gaunt coefficients table + //========================================= + if(!this->MGT) + { this->MGT = std::make_shared(); } + if(this->MGT->get_Lmax_Gaunt_CH() < Lmax) + { this->MGT->init_Gaunt_CH(Lmax); } + if(this->MGT->get_Lmax_Gaunt_Coefficients() < Lmax) + { this->MGT->init_Gaunt(Lmax); } + + const double dr = orb.get_dR(); + const double dk = orb.get_dk(); + const int kmesh = orb.get_kmesh() * kmesh_times + 1; + const double rmax + = std::min({Exx_Abfs::Construct_Orbs::get_Rmax(orb_A1), Exx_Abfs::Construct_Orbs::get_Rmax(orb_A2)}) + + std::min({Exx_Abfs::Construct_Orbs::get_Rmax(orb_B1), Exx_Abfs::Construct_Orbs::get_Rmax(orb_B2)}); + int Rmesh = static_cast(rmax / dr) + 4; // extend Rcut, keep dR + Rmesh += 1 - Rmesh % 2; + Center2_Orb::init_Table_Spherical_Bessel(Lmax_used, + dr, + dk, + kmesh, + Rmesh, + psb_); + + assert(orb_A1.size() == orb_A2.size()); + assert(orb_B1.size() == orb_B2.size()); + for (size_t TA = 0; TA != orb_A1.size(); ++TA) { + for (size_t TB = 0; TB != orb_B1.size(); ++TB) { + for (int LA1 = 0; LA1 != orb_A1[TA].size(); ++LA1) { + for (size_t NA1 = 0; NA1 != orb_A1[TA][LA1].size(); ++NA1) { + for (int LA2 = 0; LA2 != orb_A2[TA].size(); ++LA2) { + for (size_t NA2 = 0; NA2 != orb_A2[TA][LA2].size(); ++NA2) { + for (int LB1 = 0; LB1 != orb_B1[TB].size(); ++LB1) { + for (size_t NB1 = 0; NB1 != orb_B1[TB][LB1].size(); ++NB1) { + for (int LB2 = 0; LB2 != orb_B2[TB].size(); ++LB2) { + for (size_t NB2 = 0; NB2 != orb_B2[TB][LB2].size(); ++NB2) { + center2_orb22_s[TA][TB][LA1][NA1][LA2][NA2][LB1][NB1][LB2].insert( + std::make_pair( + NB2, + Center2_Orb::Orb22( + orb_A1[TA][LA1][NA1], + orb_A2[TA][LA2][NA2], + orb_B1[TB][LB1][NB1], + orb_B2[TB][LB2][NB2], + psb_, + *this->MGT))); + }}}}}}}}}} + ModuleBase::timer::end("Matrix_Orbs22", "init"); +} + +/* +void Matrix_Orbs22::init_radial(const LCAO_Orbitals& orb_A1, + const LCAO_Orbitals& orb_A2, + const LCAO_Orbitals& orb_B1, + const LCAO_Orbitals& orb_B2) +{ + ModuleBase::TITLE("Matrix_Orbs22", "init_radial"); + ModuleBase::timer::start("Matrix_Orbs22", "init_radial"); + assert(orb_A1.get_ntype() == orb_A2.get_ntype()); + assert(orb_B1.get_ntype() == orb_B2.get_ntype()); + for (size_t TA = 0; TA != orb_A1.get_ntype(); ++TA) + for (size_t TB = 0; TB != orb_B1.get_ntype(); ++TB) + for (int LA1 = 0; LA1 != orb_A1.Phi[TA].getLmax(); ++LA1) + for (size_t NA1 = 0; NA1 != orb_A1.Phi[TA].getNchi(LA1); ++NA1) + for (int LA2 = 0; LA2 <= orb_A2.Phi[TA].getLmax(); ++LA2) + for (size_t NA2 = 0; NA2 != orb_A2.Phi[TA].getNchi(LA2); ++NA2) + for (int LB1 = 0; LB1 <= orb_B1.Phi[TB].getLmax(); ++LB1) + for (size_t NB1 = 0; NB1 != orb_B1.Phi[TB].getNchi(LB1); ++NB1) + for (int LB2 = 0; LB2 <= orb_B2.Phi[TB].getLmax(); ++LB2) + for (size_t NB2 = 0; NB2 != orb_B2.Phi[TB].getNchi(LB2); ++NB2) + center2_orb22_s[TA][TB][LA1][NA1][LA2][NA2][LB1][NB1][LB2].insert( + std::make_pair(NB2, + Center2_Orb::Orb22(orb_A1.Phi[TA].PhiLN(LA1, NA1), + orb_A2.Phi[TA].PhiLN(LA2, NA2), + orb_B1.Phi[TB].PhiLN(LB1, NB1), + orb_B2.Phi[TB].PhiLN(LB2, NB2), + psb_, + *this->MGT))); + ModuleBase::timer::end("Matrix_Orbs22", "init_radial"); +} +*/ + +void Matrix_Orbs22::init_radial_table() +{ + ModuleBase::TITLE("Matrix_Orbs22", "init_radial_table"); + ModuleBase::timer::start("Matrix_Orbs22", "init_radial_table"); + for (auto& coA: center2_orb22_s) + for (auto& coB: coA.second) + for (auto& coC: coB.second) + for (auto& coD: coC.second) + for (auto& coE: coD.second) + for (auto& coF: coE.second) + for (auto& coG: coF.second) + for (auto& coH: coG.second) + for (auto& coI: coH.second) + for (auto& coJ: coI.second) + coJ.second.init_radial_table(); + ModuleBase::timer::end("Matrix_Orbs22", "init_radial_table"); +} + +void Matrix_Orbs22::init_radial_table(const std::map>>& Rs) +{ + ModuleBase::TITLE("Matrix_Orbs22", "init_radial_table_Rs"); + ModuleBase::timer::start("Matrix_Orbs22", "init_radial_table"); + const double lat0 = *this->lat0; + for (const auto& RsA: Rs) + for (const auto& RsB: RsA.second) + { + if (auto* const center2_orb22_sAB = static_cast>>>>>>>* const>( + ModuleBase::GlobalFunc::MAP_EXIST(center2_orb22_s, RsA.first, RsB.first))) + { + std::set radials; + for (const double& R: RsB.second) + { + const double position = R * lat0 / lcao_dr_; + const size_t iq = static_cast(position); + for (size_t i = 0; i != 4; ++i) + radials.insert(iq + i); + } + for (auto& coC: *center2_orb22_sAB) + for (auto& coD: coC.second) + for (auto& coE: coD.second) + for (auto& coF: coE.second) + for (auto& coG: coF.second) + for (auto& coH: coG.second) + for (auto& coI: coH.second) + for (auto& coJ: coI.second) + coJ.second.init_radial_table(); + } + } + ModuleBase::timer::end("Matrix_Orbs22", "init_radial_table"); +} diff --git a/source/source_lcao/module_ri/Matrix_Orbs22.h b/source/source_lcao/module_ri/Matrix_Orbs22.h index 7451f80ed6e..fa11445e9e6 100644 --- a/source/source_lcao/module_ri/Matrix_Orbs22.h +++ b/source/source_lcao/module_ri/Matrix_Orbs22.h @@ -1,118 +1,118 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2023-02-23 -//======================= - -#ifndef MATRIX_ORB22_H -#define MATRIX_ORB22_H - -#include "source_base/element_basis_index.h" -#include "source_base/vector3.h" -#include "source_basis/module_ao/ORB_gaunt_table.h" -#include "source_basis/module_ao/ORB_read.h" -#include "source_lcao/center2_orb-orb22.h" -#include "source_cell/unitcell.h" - -#include -#include -#include -#include - -class Matrix_Orbs22 -{ - public: - void init( - const std::vector>>& orb_A1, - const std::vector>>& orb_A2, - const std::vector>>& orb_B1, - const std::vector>>& orb_B2, - const UnitCell& ucell, - const LCAO_Orbitals& orb, - const double kmesh_times); // extend Kcut, keep dK - - void init_radial_table(); - void init_radial_table(const std::map>>& Rs); // unit: ucell.lat0 - - enum class Matrix_Order - { - A1A2B1B2, - A1A2B2B1, - A1B1A2B2, - A1B1B2A2, - A1B2A2B1, - A1B2B1A2, - A2A1B1B2, - A2A1B2B1, - A2B1A1B2, - A2B1B2A1, - A2B2A1B1, - A2B2B1A1, - B1A1A2B2, - B1A1B2A2, - B1A2A1B2, - B1A2B2A1, - B1B2A1A2, - B1B2A2A1, - B2A1A2B1, - B2A1B1A2, - B2A2A1B1, - B2A2B1A1, - B2B1A1A2, - B2B1A2A1 - }; - - template - RI::Tensor cal_overlap_matrix(const size_t TA, - const size_t TB, - const ModuleBase::Vector3& tauA, // unit: ucell.lat0 - const ModuleBase::Vector3& tauB, // unit: ucell.lat0 - const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B2, - const Matrix_Order& matrix_order) const; - template - std::array, 3> cal_grad_overlap_matrix( - const size_t TA, - const size_t TB, - const ModuleBase::Vector3& tauA, // unit: ucell.lat0 - const ModuleBase::Vector3& tauB, // unit: ucell.lat0 - const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B2, - const Matrix_Order& matrix_order) const; - - template - std::map>>>> cal_overlap_matrix_all( - const UnitCell &ucell, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B1, - const ModuleBase::Element_Basis_Index::IndexLNM& index_B2) const; - - std::shared_ptr MGT; - - private: - ModuleBase::Sph_Bessel_Recursive::D2* psb_ = nullptr; - const double lcao_dr_ = 0.01; - double* lat0 = nullptr; // restore ucell.lat0 - std::map< - size_t, // TA - std::map>>>>>>>>> - center2_orb22_s; - // this->center2_orb22_s[TA][TB][LA1][NA1][LA2][NA2][LB1][NB1][LB2][NB2] -}; - -#include "Matrix_Orbs22.hpp" - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2023-02-23 +//======================= + +#ifndef MATRIX_ORB22_H +#define MATRIX_ORB22_H + +#include "source_base/element_basis_index.h" +#include "source_base/vector3.h" +#include "source_basis/module_ao/ORB_gaunt_table.h" +#include "source_basis/module_ao/ORB_read.h" +#include "source_lcao/center2_orb-orb22.h" +#include "source_cell/unitcell.h" + +#include +#include +#include +#include + +class Matrix_Orbs22 +{ + public: + void init( + const std::vector>>& orb_A1, + const std::vector>>& orb_A2, + const std::vector>>& orb_B1, + const std::vector>>& orb_B2, + const UnitCell& ucell, + const LCAO_Orbitals& orb, + const double kmesh_times); // extend Kcut, keep dK + + void init_radial_table(); + void init_radial_table(const std::map>>& Rs); // unit: ucell.lat0 + + enum class Matrix_Order + { + A1A2B1B2, + A1A2B2B1, + A1B1A2B2, + A1B1B2A2, + A1B2A2B1, + A1B2B1A2, + A2A1B1B2, + A2A1B2B1, + A2B1A1B2, + A2B1B2A1, + A2B2A1B1, + A2B2B1A1, + B1A1A2B2, + B1A1B2A2, + B1A2A1B2, + B1A2B2A1, + B1B2A1A2, + B1B2A2A1, + B2A1A2B1, + B2A1B1A2, + B2A2A1B1, + B2A2B1A1, + B2B1A1A2, + B2B1A2A1 + }; + + template + RI::Tensor cal_overlap_matrix(const size_t TA, + const size_t TB, + const ModuleBase::Vector3& tauA, // unit: ucell.lat0 + const ModuleBase::Vector3& tauB, // unit: ucell.lat0 + const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B2, + const Matrix_Order& matrix_order) const; + template + std::array, 3> cal_grad_overlap_matrix( + const size_t TA, + const size_t TB, + const ModuleBase::Vector3& tauA, // unit: ucell.lat0 + const ModuleBase::Vector3& tauB, // unit: ucell.lat0 + const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B2, + const Matrix_Order& matrix_order) const; + + template + std::map>>>> cal_overlap_matrix_all( + const UnitCell &ucell, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_A2, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B1, + const ModuleBase::Element_Basis_Index::IndexLNM& index_B2) const; + + std::shared_ptr MGT; + + private: + ModuleBase::Sph_Bessel_Recursive::D2* psb_ = nullptr; + const double lcao_dr_ = 0.01; + double* lat0 = nullptr; // restore ucell.lat0 + std::map< + size_t, // TA + std::map>>>>>>>>> + center2_orb22_s; + // this->center2_orb22_s[TA][TB][LA1][NA1][LA2][NA2][LB1][NB1][LB2][NB2] +}; + +#include "Matrix_Orbs22.hpp" + +#endif diff --git a/source/source_lcao/module_ri/RI_2D_Comm.h b/source/source_lcao/module_ri/RI_2D_Comm.h index 001f8969b57..69e8abf4f72 100644 --- a/source/source_lcao/module_ri/RI_2D_Comm.h +++ b/source/source_lcao/module_ri/RI_2D_Comm.h @@ -1,139 +1,139 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef RI_2D_COMM_H -#define RI_2D_COMM_H - -#include "source_basis/module_ao/parallel_orbitals.h" -#include "source_lcao/module_hcontainer/hcontainer.h" -#include "source_cell/klist.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace RI_2D_Comm -{ -using TA = int; -using Tcell = int; -static const size_t Ndim = 3; -using TC = std::array; -using TAC = std::pair; - -// public: -template -extern std::vector>>> split_m2D_ktoR( - const UnitCell& ucell, - const K_Vectors& kv, - const std::vector& mks_2D, - const Parallel_2D& pv, - const int nspin, - const bool spgsym = false); - -template -extern std::vector>>> split_m2D_ktoR_gamma( - const UnitCell& ucell, - const std::vector& mks_2D, - const Parallel_2D& pv, - const int nspin); - -template -extern std::vector>>> split_m2D_ktoR_k( - const UnitCell& ucell, - const K_Vectors& kv, - const std::vector& mks_2D, - const Parallel_2D& pv, - const int nspin, - const bool spgsym = false); - - // judge[is] = {s0, s1} - extern std::vector, std::set>> - get_2D_judge(const UnitCell& ucell, const Parallel_2D& pv); - - template - extern void add_Hexx( - const UnitCell& ucell, - const K_Vectors& kv, - const int ik, - const double alpha, - const std::vector>>>& Hs, - const Parallel_Orbitals& pv, - TK* hk); - - - template - extern void add_Hexx_td( - const UnitCell& ucell, - const K_Vectors& kv, - const int ik, - const double alpha, - const std::vector>>>& Hs, - const Parallel_Orbitals& pv, - const ModuleBase::Vector3& At, - const std::map, std::complex>& phase_hybrid, - TK* hk); - - template - extern void add_HexxR( - const int current_spin, - const double alpha, - const std::vector>>>& Hs, - const Parallel_Orbitals& pv, - const int npol, - hamilt::HContainer& HlocR, - const RI::Cell_Nearest* const cell_nearest = nullptr); - - template - extern std::vector> Hexxs_to_Hk( - const K_Vectors &kv, - const Parallel_Orbitals &pv, - const std::vector< std::map>>> &Hexxs, - const int ik); - template - std::vector> pulay_mixing( - const Parallel_Orbitals &pv, - std::deque>> &Hk_seq, - const std::vector> &Hk_new, - const double mixing_beta, - const std::string mixing_mode); - -//private: - extern std::vector get_ik_list(const K_Vectors &kv, const int is_k); - extern inline std::tuple get_iat_iw_is_block(const UnitCell& ucell,const int& iwt); - extern inline int get_is_block(const int is_k, const int is_row_b, const int is_col_b); - extern inline std::tuple split_is_block(const int is_b); - extern inline int get_iwt(const UnitCell& ucell, const int iat, const int iw_b, const int is_b); - - template - extern std::map> comm_map2_first(const MPI_Comm& mpi_comm, - const std::map>& Ds_in, - const std::set& s0, - const std::set& s1); - template - extern std::map> comm_map2(const MPI_Comm& mpi_comm, - const std::map>& Ds_in, - const Tjudge& judge); - template - extern void set_value_add(Tkey&& key, Tvalue&& value, std::map& data); - template - extern void set_value_add(std::tuple&& key, - Tvalue&& value, - std::map>& data); - template - extern void add_datas(std::map&& data_local, std::map& data_recv); - template - extern void add_datas(std::map>&& data_local, - std::map>& data_recv); -} // namespace RI_2D_Comm - -#include "RI_2D_Comm.hpp" - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef RI_2D_COMM_H +#define RI_2D_COMM_H + +#include "source_basis/module_ao/parallel_orbitals.h" +#include "source_lcao/module_hcontainer/hcontainer.h" +#include "source_cell/klist.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace RI_2D_Comm +{ +using TA = int; +using Tcell = int; +static const size_t Ndim = 3; +using TC = std::array; +using TAC = std::pair; + +// public: +template +extern std::vector>>> split_m2D_ktoR( + const UnitCell& ucell, + const K_Vectors& kv, + const std::vector& mks_2D, + const Parallel_2D& pv, + const int nspin, + const bool spgsym = false); + +template +extern std::vector>>> split_m2D_ktoR_gamma( + const UnitCell& ucell, + const std::vector& mks_2D, + const Parallel_2D& pv, + const int nspin); + +template +extern std::vector>>> split_m2D_ktoR_k( + const UnitCell& ucell, + const K_Vectors& kv, + const std::vector& mks_2D, + const Parallel_2D& pv, + const int nspin, + const bool spgsym = false); + + // judge[is] = {s0, s1} + extern std::vector, std::set>> + get_2D_judge(const UnitCell& ucell, const Parallel_2D& pv); + + template + extern void add_Hexx( + const UnitCell& ucell, + const K_Vectors& kv, + const int ik, + const double alpha, + const std::vector>>>& Hs, + const Parallel_Orbitals& pv, + TK* hk); + + + template + extern void add_Hexx_td( + const UnitCell& ucell, + const K_Vectors& kv, + const int ik, + const double alpha, + const std::vector>>>& Hs, + const Parallel_Orbitals& pv, + const ModuleBase::Vector3& At, + const std::map, std::complex>& phase_hybrid, + TK* hk); + + template + extern void add_HexxR( + const int current_spin, + const double alpha, + const std::vector>>>& Hs, + const Parallel_Orbitals& pv, + const int npol, + hamilt::HContainer& HlocR, + const RI::Cell_Nearest* const cell_nearest = nullptr); + + template + extern std::vector> Hexxs_to_Hk( + const K_Vectors &kv, + const Parallel_Orbitals &pv, + const std::vector< std::map>>> &Hexxs, + const int ik); + template + std::vector> pulay_mixing( + const Parallel_Orbitals &pv, + std::deque>> &Hk_seq, + const std::vector> &Hk_new, + const double mixing_beta, + const std::string mixing_mode); + +//private: + extern std::vector get_ik_list(const K_Vectors &kv, const int is_k); + extern inline std::tuple get_iat_iw_is_block(const UnitCell& ucell,const int& iwt); + extern inline int get_is_block(const int is_k, const int is_row_b, const int is_col_b); + extern inline std::tuple split_is_block(const int is_b); + extern inline int get_iwt(const UnitCell& ucell, const int iat, const int iw_b, const int is_b); + + template + extern std::map> comm_map2_first(const MPI_Comm& mpi_comm, + const std::map>& Ds_in, + const std::set& s0, + const std::set& s1); + template + extern std::map> comm_map2(const MPI_Comm& mpi_comm, + const std::map>& Ds_in, + const Tjudge& judge); + template + extern void set_value_add(Tkey&& key, Tvalue&& value, std::map& data); + template + extern void set_value_add(std::tuple&& key, + Tvalue&& value, + std::map>& data); + template + extern void add_datas(std::map&& data_local, std::map& data_recv); + template + extern void add_datas(std::map>&& data_local, + std::map>& data_recv); +} // namespace RI_2D_Comm + +#include "RI_2D_Comm.hpp" + +#endif diff --git a/source/source_lcao/module_ri/RI_Util.h b/source/source_lcao/module_ri/RI_Util.h index 48a6fe196c5..0b24834a426 100644 --- a/source/source_lcao/module_ri/RI_Util.h +++ b/source/source_lcao/module_ri/RI_Util.h @@ -1,84 +1,84 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef RI_UTIL_H -#define RI_UTIL_H - -#include "source_cell/klist.h" +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef RI_UTIL_H +#define RI_UTIL_H + +#include "source_cell/klist.h" #include "source_lcao/module_ri/conv_coulomb_pot_k.h" - -#include -#include -#include - -#include -#include -#include -#include - -namespace RI_Util -{ - inline extern std::array - get_Born_vonKarmen_period(const K_Vectors &kv); - - template - extern std::vector> - get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ); - - template - inline std::array - Vector3_to_array3(const ModuleBase::Vector3 &v) - { - return std::array {v.x, v.y, v.z}; - } - template - inline ModuleBase::Vector3 - array3_to_Vector3(const std::array &v) - { - return ModuleBase::Vector3 {v[0], v[1], v[2]}; - } - - template - RI::Tensor - Matrix_to_Tensor(const Tmatrix &m_old) - { - RI::Tensor m_new({static_cast(m_old.nr), static_cast(m_old.nc)}); - for(int ir=0; ir(m_old(ir,ic)); - return m_new; - } - - template - RI::Tensor - Vector_to_Tensor(const std::vector& m_old, const int nr, const int nc) - { - assert(nr * nc == m_old.size()); - RI::Tensor m_new({ static_cast(nr), static_cast(nc) }); - for (int ir = 0; ir < nr; ++ir) - for (int ic = 0; ic < nc; ++ic) - m_new(ir, ic) = RI::Global_Func::convert(m_old[ir * nc + ic]); - return m_new; - } - - std::map>> - update_coulomb_param( - const std::map>> &coulomb_param, - const UnitCell &ucell, - const K_Vectors *p_kv); - - std::map>>>> - update_coulomb_settings( - const std::map>> &coulomb_param, - const UnitCell &ucell, - const K_Vectors *p_kv); -} - -#include "RI_Util.hpp" - + +#include +#include +#include + +#include +#include +#include +#include + +namespace RI_Util +{ + inline extern std::array + get_Born_vonKarmen_period(const K_Vectors &kv); + + template + extern std::vector> + get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ); + + template + inline std::array + Vector3_to_array3(const ModuleBase::Vector3 &v) + { + return std::array {v.x, v.y, v.z}; + } + template + inline ModuleBase::Vector3 + array3_to_Vector3(const std::array &v) + { + return ModuleBase::Vector3 {v[0], v[1], v[2]}; + } + + template + RI::Tensor + Matrix_to_Tensor(const Tmatrix &m_old) + { + RI::Tensor m_new({static_cast(m_old.nr), static_cast(m_old.nc)}); + for(int ir=0; ir(m_old(ir,ic)); + return m_new; + } + + template + RI::Tensor + Vector_to_Tensor(const std::vector& m_old, const int nr, const int nc) + { + assert(nr * nc == m_old.size()); + RI::Tensor m_new({ static_cast(nr), static_cast(nc) }); + for (int ir = 0; ir < nr; ++ir) + for (int ic = 0; ic < nc; ++ic) + m_new(ir, ic) = RI::Global_Func::convert(m_old[ir * nc + ic]); + return m_new; + } + + std::map>> + update_coulomb_param( + const std::map>> &coulomb_param, + const UnitCell &ucell, + const K_Vectors *p_kv); + + std::map>>>> + update_coulomb_settings( + const std::map>> &coulomb_param, + const UnitCell &ucell, + const K_Vectors *p_kv); +} + +#include "RI_Util.hpp" + #endif \ No newline at end of file diff --git a/source/source_lcao/module_ri/RI_Util.hpp b/source/source_lcao/module_ri/RI_Util.hpp index a5bb67e4e71..0e71e5143a2 100644 --- a/source/source_lcao/module_ri/RI_Util.hpp +++ b/source/source_lcao/module_ri/RI_Util.hpp @@ -1,172 +1,172 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef RI_UTIL_HPP -#define RI_UTIL_HPP - -#include "RI_Util.h" -#include "source_base/global_function.h" -#include "source_io/module_parameter/parameter.h" - -namespace RI_Util -{ - inline std::array - get_Born_vonKarmen_period(const K_Vectors &kv) - { - return std::array{kv.nmp[0], kv.nmp[1], kv.nmp[2]}; - } - - template - std::vector> - get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ) - { - using namespace RI::Array_Operator; - std::vector> Born_von_Karman_cells; - for( int c=0; c{c} % Born_von_Karman_period ); - return Born_von_Karman_cells; - } - - template - std::vector> - get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ) - { - using namespace RI::Array_Operator; - - std::array sub_Born_von_Karman_period; - for(int i=0; i> Born_von_Karman_cells; - for( const std::array &sub_cell : get_Born_von_Karmen_cells(sub_Born_von_Karman_period) ) - for( Tcell c=0; c cell; - for(int i=0; i{c} % std::array{Born_von_Karman_period.back()})[0]; - Born_von_Karman_cells.emplace_back(std::move(cell)); - } - return Born_von_Karman_cells; - } - - /* example for Ndim=3: - template - std::vector> - get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ) - { - using namespace Array_Operator; - std::vector> Born_von_Karman_cells; - for( int ix=0; ix{ix,iy,iz} % Born_von_Karman_period ); - return Born_von_Karman_cells; - } - */ - - inline std::map>> - update_coulomb_param( - const std::map>> &coulomb_param, - const UnitCell &ucell, - const K_Vectors *p_kv) - { - std::map>> coulomb_param_updated = coulomb_param; - for(auto ¶m_list : coulomb_param_updated) - { - for(auto ¶m : param_list.second) - { - if(param.at("singularity_correction") == "spencer") - { - // 4/3 * pi * Rcut^3 = V_{supercell} = V_{unitcell} * Nk - const int nspin0 = (PARAM.inp.nspin==2) ? 2 : 1; - const double Rcut = std::pow(0.75 * p_kv->get_nkstot_full() * ucell.omega / (ModuleBase::PI), 1.0/3.0); - param["Rcut"] = ModuleBase::GlobalFunc::TO_STRING(Rcut); - } - else if(param.at("singularity_correction") == "revised_spencer") - { - const double bvk_a1 = ucell.a1.norm() * p_kv->nmp[0]; - const double bvk_a2 = ucell.a2.norm() * p_kv->nmp[1]; - const double bvk_a3 = ucell.a3.norm() * p_kv->nmp[2]; - const double Rcut = 0.5 * std::min({bvk_a1, bvk_a2, bvk_a3}); - param["Rcut"] = ModuleBase::GlobalFunc::TO_STRING(Rcut); - } - } - } - return coulomb_param_updated; - } - - inline std::map>>>> - update_coulomb_settings( - const std::map>> &coulomb_param, - const UnitCell &ucell, - const K_Vectors *p_kv) - { - const std::map>> - coulomb_param_updated = update_coulomb_param(coulomb_param, ucell, p_kv); - - // Separate the parameters into Center2 and Ewald methods - std::map>> coulomb_param_center2; - std::map>> coulomb_param_ewald; - for(auto ¶m_list : coulomb_param_updated) - { - switch(param_list.first) - { - case Conv_Coulomb_Pot_K::Coulomb_Type::Fock: - { - for(auto ¶m : param_list.second) - { - if(param.at("singularity_correction") == "spencer" || param.at("singularity_correction") == "limits" - || param.at("singularity_correction") == "revised_spencer") - { - coulomb_param_center2[param_list.first].push_back(param); - } - else if (param.at("singularity_correction") == "massidda" || param.at("singularity_correction") == "carrier" ) - { - coulomb_param_ewald[param_list.first].push_back(param); - } - } - break; - } - case Conv_Coulomb_Pot_K::Coulomb_Type::Erfc: - { - coulomb_param_center2[param_list.first] = param_list.second; // Erfc is always calculated with Center2 method. - break; - } - default: - { - throw std::invalid_argument( std::string(__FILE__) + " line " + std::to_string(__LINE__) ); - } - } - } - - std::map>>>> coulomb_settings; - - const bool cal_center = !coulomb_param_center2.empty(); - const bool cal_ewald = !coulomb_param_ewald.empty(); - if(cal_center) - { - coulomb_settings[Conv_Coulomb_Pot_K::Coulomb_Method::Center2] = std::make_pair(cal_center, coulomb_param_center2); - } - if(cal_ewald) - { - coulomb_settings[Conv_Coulomb_Pot_K::Coulomb_Method::Ewald] = std::make_pair(cal_ewald, coulomb_param_ewald); - } - if(cal_center && cal_ewald) - { - coulomb_settings[Conv_Coulomb_Pot_K::Coulomb_Method::Center2].first = false; // If both methods are available, only HF for C is needed. - } - - return coulomb_settings; - } -} - -#endif +//======================= +// AUTHOR : Peize Lin +// DATE : 2022-08-17 +//======================= + +#ifndef RI_UTIL_HPP +#define RI_UTIL_HPP + +#include "RI_Util.h" +#include "source_base/global_function.h" +#include "source_io/module_parameter/parameter.h" + +namespace RI_Util +{ + inline std::array + get_Born_vonKarmen_period(const K_Vectors &kv) + { + return std::array{kv.nmp[0], kv.nmp[1], kv.nmp[2]}; + } + + template + std::vector> + get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ) + { + using namespace RI::Array_Operator; + std::vector> Born_von_Karman_cells; + for( int c=0; c{c} % Born_von_Karman_period ); + return Born_von_Karman_cells; + } + + template + std::vector> + get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ) + { + using namespace RI::Array_Operator; + + std::array sub_Born_von_Karman_period; + for(int i=0; i> Born_von_Karman_cells; + for( const std::array &sub_cell : get_Born_von_Karmen_cells(sub_Born_von_Karman_period) ) + for( Tcell c=0; c cell; + for(int i=0; i{c} % std::array{Born_von_Karman_period.back()})[0]; + Born_von_Karman_cells.emplace_back(std::move(cell)); + } + return Born_von_Karman_cells; + } + + /* example for Ndim=3: + template + std::vector> + get_Born_von_Karmen_cells( const std::array &Born_von_Karman_period ) + { + using namespace Array_Operator; + std::vector> Born_von_Karman_cells; + for( int ix=0; ix{ix,iy,iz} % Born_von_Karman_period ); + return Born_von_Karman_cells; + } + */ + + inline std::map>> + update_coulomb_param( + const std::map>> &coulomb_param, + const UnitCell &ucell, + const K_Vectors *p_kv) + { + std::map>> coulomb_param_updated = coulomb_param; + for(auto ¶m_list : coulomb_param_updated) + { + for(auto ¶m : param_list.second) + { + if(param.at("singularity_correction") == "spencer") + { + // 4/3 * pi * Rcut^3 = V_{supercell} = V_{unitcell} * Nk + const int nspin0 = (PARAM.inp.nspin==2) ? 2 : 1; + const double Rcut = std::pow(0.75 * p_kv->get_nkstot_full() * ucell.omega / (ModuleBase::PI), 1.0/3.0); + param["Rcut"] = ModuleBase::GlobalFunc::TO_STRING(Rcut); + } + else if(param.at("singularity_correction") == "revised_spencer") + { + const double bvk_a1 = ucell.a1.norm() * p_kv->nmp[0]; + const double bvk_a2 = ucell.a2.norm() * p_kv->nmp[1]; + const double bvk_a3 = ucell.a3.norm() * p_kv->nmp[2]; + const double Rcut = 0.5 * std::min({bvk_a1, bvk_a2, bvk_a3}); + param["Rcut"] = ModuleBase::GlobalFunc::TO_STRING(Rcut); + } + } + } + return coulomb_param_updated; + } + + inline std::map>>>> + update_coulomb_settings( + const std::map>> &coulomb_param, + const UnitCell &ucell, + const K_Vectors *p_kv) + { + const std::map>> + coulomb_param_updated = update_coulomb_param(coulomb_param, ucell, p_kv); + + // Separate the parameters into Center2 and Ewald methods + std::map>> coulomb_param_center2; + std::map>> coulomb_param_ewald; + for(auto ¶m_list : coulomb_param_updated) + { + switch(param_list.first) + { + case Conv_Coulomb_Pot_K::Coulomb_Type::Fock: + { + for(auto ¶m : param_list.second) + { + if(param.at("singularity_correction") == "spencer" || param.at("singularity_correction") == "limits" + || param.at("singularity_correction") == "revised_spencer") + { + coulomb_param_center2[param_list.first].push_back(param); + } + else if (param.at("singularity_correction") == "massidda" || param.at("singularity_correction") == "carrier" ) + { + coulomb_param_ewald[param_list.first].push_back(param); + } + } + break; + } + case Conv_Coulomb_Pot_K::Coulomb_Type::Erfc: + { + coulomb_param_center2[param_list.first] = param_list.second; // Erfc is always calculated with Center2 method. + break; + } + default: + { + throw std::invalid_argument( std::string(__FILE__) + " line " + std::to_string(__LINE__) ); + } + } + } + + std::map>>>> coulomb_settings; + + const bool cal_center = !coulomb_param_center2.empty(); + const bool cal_ewald = !coulomb_param_ewald.empty(); + if(cal_center) + { + coulomb_settings[Conv_Coulomb_Pot_K::Coulomb_Method::Center2] = std::make_pair(cal_center, coulomb_param_center2); + } + if(cal_ewald) + { + coulomb_settings[Conv_Coulomb_Pot_K::Coulomb_Method::Ewald] = std::make_pair(cal_ewald, coulomb_param_ewald); + } + if(cal_center && cal_ewald) + { + coulomb_settings[Conv_Coulomb_Pot_K::Coulomb_Method::Center2].first = false; // If both methods are available, only HF for C is needed. + } + + return coulomb_settings; + } +} + +#endif diff --git a/source/source_lcao/module_ri/test_code/Inverse_Matrix-test.h b/source/source_lcao/module_ri/test_code/Inverse_Matrix-test.h index d73262c5208..fdf01f17912 100644 --- a/source/source_lcao/module_ri/test_code/Inverse_Matrix-test.h +++ b/source/source_lcao/module_ri/test_code/Inverse_Matrix-test.h @@ -1,138 +1,138 @@ -//======================= -// AUTHOR : Peize Lin -// DATE : 2022-08-17 -//======================= - -#ifndef INVERSE_MATRIX_TEST_H -#define INVERSE_MATRIX_TEST_H - -#include "source_lcao/module_ri/Inverse_Matrix.h" -#include - -namespace Inverse_Matrix_Test -{ - template - Tensor init_Tensor(const std::vector &shape) - { - Tensor t(shape); - for(size_t i=0; isize(); ++i) - t.ptr()[i] = i; - return t; - } - - template - Tensor init_Tensor2(const std::vector &shape) - { - Tensor t(shape); - for(size_t i0=0; i0 - void test_input_output() - { - Inverse_Matrix inv; - - const size_t n_all = 5; - const std::vector n0 = {2,3}; - const std::vector n1 = {1,2,2}; - - Tensor m = init_Tensor({n_all,n_all}); - - std::vector>> ms(n0.size(), std::vector>(n1.size())); - for(size_t Im0=0; Im0({n0[Im0], n1[Im1]}); - - inv.input(m); - std::cout< - void test_inverse() - { - Tensor t = init_Tensor2({5,5}); - Inverse_Matrix inv; - inv.input(t); - inv.cal_inverse(Inverse_Matrix::Method::potrf); - //inv.cal_inverse(Inverse_Matrix::Method::syev); - Tensor tI = inv.output(); - - std::cout< + +namespace Inverse_Matrix_Test +{ + template + Tensor init_Tensor(const std::vector &shape) + { + Tensor t(shape); + for(size_t i=0; isize(); ++i) + t.ptr()[i] = i; + return t; + } + + template + Tensor init_Tensor2(const std::vector &shape) + { + Tensor t(shape); + for(size_t i0=0; i0 + void test_input_output() + { + Inverse_Matrix inv; + + const size_t n_all = 5; + const std::vector n0 = {2,3}; + const std::vector n1 = {1,2,2}; + + Tensor m = init_Tensor({n_all,n_all}); + + std::vector>> ms(n0.size(), std::vector>(n1.size())); + for(size_t Im0=0; Im0({n0[Im0], n1[Im1]}); + + inv.input(m); + std::cout< + void test_inverse() + { + Tensor t = init_Tensor2({5,5}); + Inverse_Matrix inv; + inv.input(t); + inv.cal_inverse(Inverse_Matrix::Method::potrf); + //inv.cal_inverse(Inverse_Matrix::Method::syev); + Tensor tI = inv.output(); + + std::cout< *in, std::complex *inout,int *len,MPI_Datatype *dptr) -{ - for(int i=0;i<*len;i++) - { - (*inout).real()=(*inout).real()+(*in).real(); - (*inout).imag()=(*inout).imag()+(*in).imag(); - in++; - inout++; - } - return; -} -#endif - -void Parallel_Global::read_pal_param(int argc,char **argv) -{ -#if defined __MPI -//for test -/* - cout << "\n Hello! Test MPI NOW : argc = "< *in, std::complex *inout,int *len,MPI_Datatype *dptr) +{ + for(int i=0;i<*len;i++) + { + (*inout).real()=(*inout).real()+(*in).real(); + (*inout).imag()=(*inout).imag()+(*in).imag(); + in++; + inout++; + } + return; +} +#endif + +void Parallel_Global::read_pal_param(int argc,char **argv) +{ +#if defined __MPI +//for test +/* + cout << "\n Hello! Test MPI NOW : argc = "< threshold: - return inverse_DC( M[:1,:1], M[:1,1:], M[1:,:1], M[1:,1:] ) - elif M[2,2].abs() > threshold: - return inverse_DC( M[:2,:2], M[:2,2:], M[2:,:2], M[2:,2:] ) - else: - raise ZeroDivisionError("matrix inverse") - - else: - L2 = L//2 - return inverse_DC( M[:L2,:L2], M[:L2,L2:], M[L2:,:L2], M[L2:,L2:] ) \ No newline at end of file +import torch + + +def inverse_DC(A,B,C,D): + tmp_A = inverse(A) # A^{-1} + #print("tmp_A",tmp_A) + tmp_AB = torch.mm(tmp_A,B) # A^{-1} B + #print("tmp_AB",tmp_AB) + tmp_CA = torch.mm(C,tmp_A) # C A^{-1} + #print("tmp_CA",tmp_CA) + tmp_X = inverse(D-torch.mm(tmp_CA,B)) # ( D - C A^{-1} B )^{-1} + #print("tmp_X",tmp_X) + tmp_ABX = torch.mm(tmp_AB,tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} + #print("tmp_ABX",tmp_ABX) + tmp_XCA = torch.mm(tmp_X,tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} + #print("tmp_XCA",tmp_XCA) + tmp_ABXCA = torch.mm(tmp_ABX,tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} + #print("tmp_ABXCA",tmp_ABXCA) + + tmp_up = torch.cat( [ tmp_A+tmp_ABXCA, -tmp_ABX ], dim=1 ) + tmp_down = torch.cat( [ -tmp_XCA, tmp_X ], dim=1 ) + I = torch.cat( [tmp_up,tmp_down], dim=0 ) + return I + + + +def inverse(M): + +# assert len(M.size()) == 2, "inverse must be 2D" +# assert M.size()[0] == M.size()[1], "inverse row != column" + + L = M.size()[0] + + if L==1: + return 1/M + + elif L==2: + det = torch.cat(list( M[:1,:1]*M[1:,1:] - M[:1,1:]*M[1:,:1] )*4).view(2,2) + I_up = torch.cat([M[1:,1:],-M[:1,1:]],dim=1) + I_down = torch.cat([-M[1:,:1],M[:1,:1]],dim=1) + I_all = torch.cat([I_up,I_down],dim=0) + return I_all/det + + elif L==3: + threshold = 1e-10 + if M[0,0].abs() > threshold: + return inverse_DC( M[:1,:1], M[:1,1:], M[1:,:1], M[1:,1:] ) + elif M[2,2].abs() > threshold: + return inverse_DC( M[:2,:2], M[:2,2:], M[2:,:2], M[2:,2:] ) + else: + raise ZeroDivisionError("matrix inverse") + + else: + L2 = L//2 + return inverse_DC( M[:L2,:L2], M[:L2,L2:], M[L2:,:L2], M[L2:,L2:] ) \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch/opt_orbital.py_real b/tools/01_NAO_generation/pytorch/opt_orbital.py_real index 5ade0f90fc4..bc2075bd4d1 100644 --- a/tools/01_NAO_generation/pytorch/opt_orbital.py_real +++ b/tools/01_NAO_generation/pytorch/opt_orbital.py_real @@ -1,86 +1,86 @@ -from global_function import ND_list -import inverse -import torch - -class SIA: - - def cal_Q(self,QI,C): - """ - Q[ist][it][il][ib,ia*im*iu] - = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = ND_list(self.Nst) - for ist in range(self.Nst): - Q[ist] = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q[ist][it] = ND_list(self.Nl[it]) - - for ist in range(self.Nst): - for it in range(self.Nt[ist]): - for il in range(self.Nl[it]): - Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) - return Q - - - - def cal_S(self,SI,C): - """ - S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] - = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] - """ - S = ND_list(self.Nst) - for ist in range(self.Nst): - S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) - - for ist in range(self.Nst): - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - for il1 in range(self.Nl[it1]): - for il2 in range(self.Nl[it2]): - S[ist][it1][it2][il1][il2] = torch.mm( - C[it1][il1].t(), - torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) - ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) - return S - - - - def cal_V(self,Q,S): - """ - V[ist][ib] - = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} - Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] - """ - V = ND_list(self.Nst) - for ist in range(self.Nst): - V[ist] = ND_list(self.Nb[ist]) - - for ist in range(self.Nst): - - S_s = ND_list(self.Nt[ist]) - for it1 in range(self.Nt[ist]): - S_st = ND_list(self.Nt[ist]) - for it2 in range(self.Nt[ist]): - S_stt = ND_list(self.Nl[it1]) - for il1 in range(self.Nl[it1]): - S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) - S_st[it2] = torch.cat( S_stt, dim=0 ) - S_s[it1] = torch.cat( S_st, dim=1 ) - S_cat = torch.cat( S_s, dim=0 ) - - S_I = inverse.inverse(S_cat) -# S_I = 1/S_cat - - for ib in range(self.Nb[ist]): - - Q_s = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) - Q_cat = torch.cat(Q_s) - - V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) - +from global_function import ND_list +import inverse +import torch + +class SIA: + + def cal_Q(self,QI,C): + """ + Q[ist][it][il][ib,ia*im*iu] + = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = ND_list(self.Nst) + for ist in range(self.Nst): + Q[ist] = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q[ist][it] = ND_list(self.Nl[it]) + + for ist in range(self.Nst): + for it in range(self.Nt[ist]): + for il in range(self.Nl[it]): + Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) + return Q + + + + def cal_S(self,SI,C): + """ + S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] + = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] + """ + S = ND_list(self.Nst) + for ist in range(self.Nst): + S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) + + for ist in range(self.Nst): + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + for il1 in range(self.Nl[it1]): + for il2 in range(self.Nl[it2]): + S[ist][it1][it2][il1][il2] = torch.mm( + C[it1][il1].t(), + torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) + ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) + return S + + + + def cal_V(self,Q,S): + """ + V[ist][ib] + = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} + Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] + """ + V = ND_list(self.Nst) + for ist in range(self.Nst): + V[ist] = ND_list(self.Nb[ist]) + + for ist in range(self.Nst): + + S_s = ND_list(self.Nt[ist]) + for it1 in range(self.Nt[ist]): + S_st = ND_list(self.Nt[ist]) + for it2 in range(self.Nt[ist]): + S_stt = ND_list(self.Nl[it1]) + for il1 in range(self.Nl[it1]): + S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) + S_st[it2] = torch.cat( S_stt, dim=0 ) + S_s[it1] = torch.cat( S_st, dim=1 ) + S_cat = torch.cat( S_s, dim=0 ) + + S_I = inverse.inverse(S_cat) +# S_I = 1/S_cat + + for ib in range(self.Nb[ist]): + + Q_s = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) + Q_cat = torch.cat(Q_s) + + V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) + return V \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch/torch_complex.py b/tools/01_NAO_generation/pytorch/torch_complex.py index d5f338d5d74..48430b6871b 100644 --- a/tools/01_NAO_generation/pytorch/torch_complex.py +++ b/tools/01_NAO_generation/pytorch/torch_complex.py @@ -1,83 +1,83 @@ -import torch - -class ComplexTensor: - def __init__(self,real,imag): - self.real = real - self.imag = imag - - def view(self,*args,**kwargs): - return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) - def t(self,*args,**kwargs): - return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) -# def transpose(self,*args,**kwargs): -# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) - def __getitem__(self,*args,**kwargs): - return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) - def __str__(self): - return "<{0};{1}>".format(self.real, self.imag) - __repr__=__str__ -# def size(self,*args,**kwargs): -# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) - - def conj(self): - return ComplexTensor( self.real, -self.imag ) - - - -def dot( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.dot( x1,x2, *args,**kwargs ) -def mv( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mv( x1,x2, *args,**kwargs ) -def mm( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mm( x1,x2, *args,**kwargs ) - - -def cat( xs, *args,**kwargs ): - if isinstance(xs[0],ComplexTensor): - xs_real = []; xs_imag = [] - for x in xs: - xs_real.append(x.real) - xs_imag.append(x.imag) - return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) - else: - return torch.cat(xs,*args,**kwargs) - - - -import inverse as inverse_real -def inverse(M): - if isinstance(M,ComplexTensor): - A=M.real - B=M.imag - tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B - tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} - return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) - else: +import torch + +class ComplexTensor: + def __init__(self,real,imag): + self.real = real + self.imag = imag + + def view(self,*args,**kwargs): + return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) + def t(self,*args,**kwargs): + return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) +# def transpose(self,*args,**kwargs): +# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) + def __getitem__(self,*args,**kwargs): + return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) + def __str__(self): + return "<{0};{1}>".format(self.real, self.imag) + __repr__=__str__ +# def size(self,*args,**kwargs): +# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) + + def conj(self): + return ComplexTensor( self.real, -self.imag ) + + + +def dot( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.dot( x1,x2, *args,**kwargs ) +def mv( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.mv( x1,x2, *args,**kwargs ) +def mm( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.mm( x1,x2, *args,**kwargs ) + + +def cat( xs, *args,**kwargs ): + if isinstance(xs[0],ComplexTensor): + xs_real = []; xs_imag = [] + for x in xs: + xs_real.append(x.real) + xs_imag.append(x.imag) + return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) + else: + return torch.cat(xs,*args,**kwargs) + + + +import inverse as inverse_real +def inverse(M): + if isinstance(M,ComplexTensor): + A=M.real + B=M.imag + tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B + tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} + return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) + else: return M.inverse() \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch/unittest_inverse.py b/tools/01_NAO_generation/pytorch/unittest_inverse.py index f4d43156108..d0e26b65e7a 100644 --- a/tools/01_NAO_generation/pytorch/unittest_inverse.py +++ b/tools/01_NAO_generation/pytorch/unittest_inverse.py @@ -1,29 +1,29 @@ -import unittest -import inverse -import torch - -class unittest_inverse(unittest.TestCase): - - def inverse_test(self,a,ai_true): - - a=torch.Tensor(a) - a=torch.autograd.Variable(a) - - ai_test=inverse.inverse(a) - - ai_true = torch.Tensor(ai_true) - ai_true=torch.autograd.Variable(ai_true) - - self.assertFalse((ai_test!=ai_true).data.sum()) - - def test_inverse_1(self): - self.inverse_test( - [[1,2],[2,3]], - [[-3,2],[2,-1]] ) - def test_inverse_2(self): - self.inverse_test( - [[1,2,3],[2,4,5],[3,5,6]], - [[1,-3,2],[-3,3,-1],[2,-1,0]] ) - -if __name__ == '__main__': +import unittest +import inverse +import torch + +class unittest_inverse(unittest.TestCase): + + def inverse_test(self,a,ai_true): + + a=torch.Tensor(a) + a=torch.autograd.Variable(a) + + ai_test=inverse.inverse(a) + + ai_true = torch.Tensor(ai_true) + ai_true=torch.autograd.Variable(ai_true) + + self.assertFalse((ai_test!=ai_true).data.sum()) + + def test_inverse_1(self): + self.inverse_test( + [[1,2],[2,3]], + [[-3,2],[2,-1]] ) + def test_inverse_2(self): + self.inverse_test( + [[1,2,3],[2,4,5],[3,5,6]], + [[1,-3,2],[-3,3,-1],[2,-1,0]] ) + +if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch_dpsi/IO/change_info.py b/tools/01_NAO_generation/pytorch_dpsi/IO/change_info.py index e9012042dde..a5e88abea85 100644 --- a/tools/01_NAO_generation/pytorch_dpsi/IO/change_info.py +++ b/tools/01_NAO_generation/pytorch_dpsi/IO/change_info.py @@ -1,98 +1,98 @@ -import addict -import util -import itertools - -def change_info(info_old, weight_old): - info_stru = [None] * info_old.Nst - for ist in range(len(info_stru)): - info_stru[ist] = addict.Dict() - for ist,Na in enumerate(info_old.Na): - info_stru[ist].Na = Na - for ist,weight in enumerate(weight_old): - info_stru[ist].weight = weight - info_stru[ist].Nb = weight.shape[0] - for ib in range(weight.shape[0], 0, -1): - if weight[ib-1]>0: - info_stru[ist].Nb_true = ib - break - - info_element = addict.Dict() - for it_index,it in enumerate(info_old.Nt_all): - info_element[it].index = it_index - for it,Nu in info_old.Nu.items(): - info_element[it].Nu = Nu - info_element[it].Nl = len(Nu) - for it,Rcut in info_old.Rcut.items(): - info_element[it].Rcut = Rcut - for it,dr in info_old.dr.items(): - info_element[it].dr = dr - for it,Ecut in info_old.Ecut.items(): - info_element[it].Ecut = Ecut - for it,Ne in info_old.Ne.items(): - info_element[it].Ne = Ne - - info_opt = addict.Dict() - info_opt.lr = info_old.lr - info_opt.cal_T = info_old.cal_T - info_opt.cal_smooth = info_old.cal_smooth - - return info_stru, info_element, info_opt - - """ - info_stru = - [{'Na': {'C': 1}, - 'Nb': 6, - 'Nb_true': 4, - 'weight': tensor([0.0333, 0.0111, 0.0111, 0.0111, 0.0000, 0.0000])}, - {'Na': {'C': 1}, - 'Nb': 6, - 'Nb_true': 2, - 'weight': tensor([0.0667, 0.0667, 0.0000, 0.0000, 0.0000, 0.0000])}, - {'Na': {'C': 1, 'O': 2}, - 'Nb': 10, - 'Nb_true': 8, - 'weight': tensor([0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.0000, 0.0000])}] - - info_element = - {'C': { - 'Ecut': 200, - 'Ne': 19, - 'Nl': 3, - 'Nu': [2, 2, 1], - 'Rcut': 6, - 'dr': 0.01, - 'index': 0}, - 'O': { - 'Ecut': 200, - 'Ne': 19, - 'Nl': 3, - 'Nu': [3, 2, 1], - 'Rcut': 6, - 'dr': 0.01, - 'index': 1}} - - info_opt = - {'cal_T': False, - 'cal_smooth': False, - 'lr': 0.01} - """ - - -def get_info_max(info_stru, info_element): - info_max = [None] * len(info_stru) - for ist in range(len(info_stru)): - Nt = info_stru[ist].Na.keys() - info_max[ist] = addict.Dict() - info_max[ist].Nt = len(Nt) - info_max[ist].Na = max((info_stru[ist].Na[it] for it in Nt)) - info_max[ist].Nl = max([info_element[it].Nl for it in Nt]) - info_max[ist].Nm = max((util.Nm(info_element[it].Nl-1) for it in Nt)) - info_max[ist].Nu = max(itertools.chain.from_iterable([info_element[it].Nu for it in Nt])) - info_max[ist].Ne = max((info_element[it].Ne for it in Nt)) - info_max[ist].Nb = info_stru[ist].Nb - return info_max - - """ - [{'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}, - {'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}] - """ +import addict +import util +import itertools + +def change_info(info_old, weight_old): + info_stru = [None] * info_old.Nst + for ist in range(len(info_stru)): + info_stru[ist] = addict.Dict() + for ist,Na in enumerate(info_old.Na): + info_stru[ist].Na = Na + for ist,weight in enumerate(weight_old): + info_stru[ist].weight = weight + info_stru[ist].Nb = weight.shape[0] + for ib in range(weight.shape[0], 0, -1): + if weight[ib-1]>0: + info_stru[ist].Nb_true = ib + break + + info_element = addict.Dict() + for it_index,it in enumerate(info_old.Nt_all): + info_element[it].index = it_index + for it,Nu in info_old.Nu.items(): + info_element[it].Nu = Nu + info_element[it].Nl = len(Nu) + for it,Rcut in info_old.Rcut.items(): + info_element[it].Rcut = Rcut + for it,dr in info_old.dr.items(): + info_element[it].dr = dr + for it,Ecut in info_old.Ecut.items(): + info_element[it].Ecut = Ecut + for it,Ne in info_old.Ne.items(): + info_element[it].Ne = Ne + + info_opt = addict.Dict() + info_opt.lr = info_old.lr + info_opt.cal_T = info_old.cal_T + info_opt.cal_smooth = info_old.cal_smooth + + return info_stru, info_element, info_opt + + """ + info_stru = + [{'Na': {'C': 1}, + 'Nb': 6, + 'Nb_true': 4, + 'weight': tensor([0.0333, 0.0111, 0.0111, 0.0111, 0.0000, 0.0000])}, + {'Na': {'C': 1}, + 'Nb': 6, + 'Nb_true': 2, + 'weight': tensor([0.0667, 0.0667, 0.0000, 0.0000, 0.0000, 0.0000])}, + {'Na': {'C': 1, 'O': 2}, + 'Nb': 10, + 'Nb_true': 8, + 'weight': tensor([0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.0000, 0.0000])}] + + info_element = + {'C': { + 'Ecut': 200, + 'Ne': 19, + 'Nl': 3, + 'Nu': [2, 2, 1], + 'Rcut': 6, + 'dr': 0.01, + 'index': 0}, + 'O': { + 'Ecut': 200, + 'Ne': 19, + 'Nl': 3, + 'Nu': [3, 2, 1], + 'Rcut': 6, + 'dr': 0.01, + 'index': 1}} + + info_opt = + {'cal_T': False, + 'cal_smooth': False, + 'lr': 0.01} + """ + + +def get_info_max(info_stru, info_element): + info_max = [None] * len(info_stru) + for ist in range(len(info_stru)): + Nt = info_stru[ist].Na.keys() + info_max[ist] = addict.Dict() + info_max[ist].Nt = len(Nt) + info_max[ist].Na = max((info_stru[ist].Na[it] for it in Nt)) + info_max[ist].Nl = max([info_element[it].Nl for it in Nt]) + info_max[ist].Nm = max((util.Nm(info_element[it].Nl-1) for it in Nt)) + info_max[ist].Nu = max(itertools.chain.from_iterable([info_element[it].Nu for it in Nt])) + info_max[ist].Ne = max((info_element[it].Ne for it in Nt)) + info_max[ist].Nb = info_stru[ist].Nb + return info_max + + """ + [{'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}, + {'Na': 2, 'Nb': 6, 'Ne': 19, 'Nl': 3, 'Nm': 5, 'Nt': 1, 'Nu': 2}] + """ diff --git a/tools/01_NAO_generation/pytorch_dpsi/torch_complex_bak.py b/tools/01_NAO_generation/pytorch_dpsi/torch_complex_bak.py index f08be745a3a..464deb0eb03 100644 --- a/tools/01_NAO_generation/pytorch_dpsi/torch_complex_bak.py +++ b/tools/01_NAO_generation/pytorch_dpsi/torch_complex_bak.py @@ -1,84 +1,84 @@ -import torch - -class ComplexTensor: - def __init__(self,real,imag): - self.real = real - self.imag = imag - - def view(self,*args,**kwargs): - return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) - def t(self,*args,**kwargs): - return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) -# def transpose(self,*args,**kwargs): -# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) - def __getitem__(self,*args,**kwargs): - return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) - def __str__(self): - return "<{0};{1}>".format(self.real, self.imag) - __repr__=__str__ -# def size(self,*args,**kwargs): -# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) - - def conj(self): - return ComplexTensor( self.real, -self.imag ) - - def mm( self,x2, *args,**kwargs ): - return mm( self,x2, *args,**kwargs ) - - -def dot( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.dot( x1,x2, *args,**kwargs ) -def mv( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mv( x1,x2, *args,**kwargs ) -def mm( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mm( x1,x2, *args,**kwargs ) - - -def cat( xs, *args,**kwargs ): - if isinstance(xs[0],ComplexTensor): - xs_real = []; xs_imag = [] - for x in xs: - xs_real.append(x.real) - xs_imag.append(x.imag) - return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) - else: - return torch.cat(xs,*args,**kwargs) - - - -def inverse(M): - if isinstance(M,ComplexTensor): - A=M.real - B=M.imag - tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B - tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} - return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) - else: +import torch + +class ComplexTensor: + def __init__(self,real,imag): + self.real = real + self.imag = imag + + def view(self,*args,**kwargs): + return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) + def t(self,*args,**kwargs): + return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) +# def transpose(self,*args,**kwargs): +# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) + def __getitem__(self,*args,**kwargs): + return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) + def __str__(self): + return "<{0};{1}>".format(self.real, self.imag) + __repr__=__str__ +# def size(self,*args,**kwargs): +# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) + + def conj(self): + return ComplexTensor( self.real, -self.imag ) + + def mm( self,x2, *args,**kwargs ): + return mm( self,x2, *args,**kwargs ) + + +def dot( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.dot( x1,x2, *args,**kwargs ) +def mv( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.mv( x1,x2, *args,**kwargs ) +def mm( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.mm( x1,x2, *args,**kwargs ) + + +def cat( xs, *args,**kwargs ): + if isinstance(xs[0],ComplexTensor): + xs_real = []; xs_imag = [] + for x in xs: + xs_real.append(x.real) + xs_imag.append(x.imag) + return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) + else: + return torch.cat(xs,*args,**kwargs) + + + +def inverse(M): + if isinstance(M,ComplexTensor): + A=M.real + B=M.imag + tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B + tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} + return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) + else: return M.inverse() \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch_gradient_source/inverse.py b/tools/01_NAO_generation/pytorch_gradient_source/inverse.py index 311519fae15..57d0d9d6da4 100644 --- a/tools/01_NAO_generation/pytorch_gradient_source/inverse.py +++ b/tools/01_NAO_generation/pytorch_gradient_source/inverse.py @@ -1,55 +1,55 @@ -import torch - - -def inverse_DC(A,B,C,D): - tmp_A = inverse(A) # A^{-1} - #print("tmp_A",tmp_A) - tmp_AB = torch.mm(tmp_A,B) # A^{-1} B - #print("tmp_AB",tmp_AB) - tmp_CA = torch.mm(C,tmp_A) # C A^{-1} - #print("tmp_CA",tmp_CA) - tmp_X = inverse(D-torch.mm(tmp_CA,B)) # ( D - C A^{-1} B )^{-1} - #print("tmp_X",tmp_X) - tmp_ABX = torch.mm(tmp_AB,tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} - #print("tmp_ABX",tmp_ABX) - tmp_XCA = torch.mm(tmp_X,tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} - #print("tmp_XCA",tmp_XCA) - tmp_ABXCA = torch.mm(tmp_ABX,tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} - #print("tmp_ABXCA",tmp_ABXCA) - - tmp_up = torch.cat( [ tmp_A+tmp_ABXCA, -tmp_ABX ], dim=1 ) - tmp_down = torch.cat( [ -tmp_XCA, tmp_X ], dim=1 ) - I = torch.cat( [tmp_up,tmp_down], dim=0 ) - return I - - - -def inverse(M): - -# assert len(M.size()) == 2, "inverse must be 2D" -# assert M.size()[0] == M.size()[1], "inverse row != column" - - L = M.size()[0] - - if L==1: - return 1/M - - elif L==2: - det = torch.cat(list( M[:1,:1]*M[1:,1:] - M[:1,1:]*M[1:,:1] )*4).view(2,2) - I_up = torch.cat([M[1:,1:],-M[:1,1:]],dim=1) - I_down = torch.cat([-M[1:,:1],M[:1,:1]],dim=1) - I_all = torch.cat([I_up,I_down],dim=0) - return I_all/det - - elif L==3: - threshold = 1e-10 - if M[0,0].abs() > threshold: - return inverse_DC( M[:1,:1], M[:1,1:], M[1:,:1], M[1:,1:] ) - elif M[2,2].abs() > threshold: - return inverse_DC( M[:2,:2], M[:2,2:], M[2:,:2], M[2:,2:] ) - else: - raise ZeroDivisionError("matrix inverse") - - else: - L2 = L//2 - return inverse_DC( M[:L2,:L2], M[:L2,L2:], M[L2:,:L2], M[L2:,L2:] ) \ No newline at end of file +import torch + + +def inverse_DC(A,B,C,D): + tmp_A = inverse(A) # A^{-1} + #print("tmp_A",tmp_A) + tmp_AB = torch.mm(tmp_A,B) # A^{-1} B + #print("tmp_AB",tmp_AB) + tmp_CA = torch.mm(C,tmp_A) # C A^{-1} + #print("tmp_CA",tmp_CA) + tmp_X = inverse(D-torch.mm(tmp_CA,B)) # ( D - C A^{-1} B )^{-1} + #print("tmp_X",tmp_X) + tmp_ABX = torch.mm(tmp_AB,tmp_X) # A^{-1} B ( D - C A^{-1} B )^{-1} + #print("tmp_ABX",tmp_ABX) + tmp_XCA = torch.mm(tmp_X,tmp_CA) # ( D - C A^{-1} B )^{-1} C A^{-1} + #print("tmp_XCA",tmp_XCA) + tmp_ABXCA = torch.mm(tmp_ABX,tmp_CA) # A^{-1} B ( D - C A^{-1} B )^{-1} C A^{-1} + #print("tmp_ABXCA",tmp_ABXCA) + + tmp_up = torch.cat( [ tmp_A+tmp_ABXCA, -tmp_ABX ], dim=1 ) + tmp_down = torch.cat( [ -tmp_XCA, tmp_X ], dim=1 ) + I = torch.cat( [tmp_up,tmp_down], dim=0 ) + return I + + + +def inverse(M): + +# assert len(M.size()) == 2, "inverse must be 2D" +# assert M.size()[0] == M.size()[1], "inverse row != column" + + L = M.size()[0] + + if L==1: + return 1/M + + elif L==2: + det = torch.cat(list( M[:1,:1]*M[1:,1:] - M[:1,1:]*M[1:,:1] )*4).view(2,2) + I_up = torch.cat([M[1:,1:],-M[:1,1:]],dim=1) + I_down = torch.cat([-M[1:,:1],M[:1,:1]],dim=1) + I_all = torch.cat([I_up,I_down],dim=0) + return I_all/det + + elif L==3: + threshold = 1e-10 + if M[0,0].abs() > threshold: + return inverse_DC( M[:1,:1], M[:1,1:], M[1:,:1], M[1:,1:] ) + elif M[2,2].abs() > threshold: + return inverse_DC( M[:2,:2], M[:2,2:], M[2:,:2], M[2:,2:] ) + else: + raise ZeroDivisionError("matrix inverse") + + else: + L2 = L//2 + return inverse_DC( M[:L2,:L2], M[:L2,L2:], M[L2:,:L2], M[L2:,L2:] ) \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch_gradient_source/opt_orbital.py_real b/tools/01_NAO_generation/pytorch_gradient_source/opt_orbital.py_real index 5ade0f90fc4..bc2075bd4d1 100644 --- a/tools/01_NAO_generation/pytorch_gradient_source/opt_orbital.py_real +++ b/tools/01_NAO_generation/pytorch_gradient_source/opt_orbital.py_real @@ -1,86 +1,86 @@ -from global_function import ND_list -import inverse -import torch - -class SIA: - - def cal_Q(self,QI,C): - """ - Q[ist][it][il][ib,ia*im*iu] - = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] - """ - Q = ND_list(self.Nst) - for ist in range(self.Nst): - Q[ist] = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q[ist][it] = ND_list(self.Nl[it]) - - for ist in range(self.Nst): - for it in range(self.Nt[ist]): - for il in range(self.Nl[it]): - Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) - return Q - - - - def cal_S(self,SI,C): - """ - S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] - = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] - """ - S = ND_list(self.Nst) - for ist in range(self.Nst): - S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) - - for ist in range(self.Nst): - for it1 in range(self.Nt[ist]): - for it2 in range(self.Nt[ist]): - for il1 in range(self.Nl[it1]): - for il2 in range(self.Nl[it2]): - S[ist][it1][it2][il1][il2] = torch.mm( - C[it1][il1].t(), - torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) - ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) - return S - - - - def cal_V(self,Q,S): - """ - V[ist][ib] - = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} - Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] - """ - V = ND_list(self.Nst) - for ist in range(self.Nst): - V[ist] = ND_list(self.Nb[ist]) - - for ist in range(self.Nst): - - S_s = ND_list(self.Nt[ist]) - for it1 in range(self.Nt[ist]): - S_st = ND_list(self.Nt[ist]) - for it2 in range(self.Nt[ist]): - S_stt = ND_list(self.Nl[it1]) - for il1 in range(self.Nl[it1]): - S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) - S_st[it2] = torch.cat( S_stt, dim=0 ) - S_s[it1] = torch.cat( S_st, dim=1 ) - S_cat = torch.cat( S_s, dim=0 ) - - S_I = inverse.inverse(S_cat) -# S_I = 1/S_cat - - for ib in range(self.Nb[ist]): - - Q_s = ND_list(self.Nt[ist]) - for it in range(self.Nt[ist]): - Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) - Q_cat = torch.cat(Q_s) - - V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) - +from global_function import ND_list +import inverse +import torch + +class SIA: + + def cal_Q(self,QI,C): + """ + Q[ist][it][il][ib,ia*im*iu] + = sum_{q} QI[ist][it][il][ib*ia*im,ie] * C[it][il][ie,iu] + """ + Q = ND_list(self.Nst) + for ist in range(self.Nst): + Q[ist] = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q[ist][it] = ND_list(self.Nl[it]) + + for ist in range(self.Nst): + for it in range(self.Nt[ist]): + for il in range(self.Nl[it]): + Q[ist][it][il] = torch.mm( QI[ist][it][il], C[it][il] ).view(self.Nb[ist],-1) + return Q + + + + def cal_S(self,SI,C): + """ + S[ist][it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2] + = sum_{ie1 ie2} C[it1][il1][ie1,in1] * SI[ist][it1][it2][il1][il2][ie1,ia1,im1,ia2,im2,ie2] * C[it2][[il2][ie2,in2] + """ + S = ND_list(self.Nst) + for ist in range(self.Nst): + S[ist] = ND_list(self.Nt[ist],self.Nt[ist]) + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + S[ist][it1][it2] = ND_list(self.Nl[it1],self.Nl[it2]) + + for ist in range(self.Nst): + for it1 in range(self.Nt[ist]): + for it2 in range(self.Nt[ist]): + for il1 in range(self.Nl[it1]): + for il2 in range(self.Nl[it2]): + S[ist][it1][it2][il1][il2] = torch.mm( + C[it1][il1].t(), + torch.mm( SI[ist][it1][it2][il1][il2].view(-1,self.Ne), C[it2][il2] ).view(self.Ne,-1) + ).view(self.Nn[it1][il1],self.Na[ist][it1]*self.Nm[il1],-1).transpose(0,1).view(self.Na[ist][it1]*self.Nm[il1]*self.Nn[it1][il1],-1) + return S + + + + def cal_V(self,Q,S): + """ + V[ist][ib] + = sum_{it1,ia1,il1,im1,in1} sum_{it2,ia2,il2,im2,in2} + Q[ist][it1][il1][ib,ia1*im1*in1] * S[ist]{[it1][it2][il1][il2][ia1*im1*in1,ia2*im2*in2]}^{-1} * Q[ist][it2][il2][ib,ia2*im2*in2] + """ + V = ND_list(self.Nst) + for ist in range(self.Nst): + V[ist] = ND_list(self.Nb[ist]) + + for ist in range(self.Nst): + + S_s = ND_list(self.Nt[ist]) + for it1 in range(self.Nt[ist]): + S_st = ND_list(self.Nt[ist]) + for it2 in range(self.Nt[ist]): + S_stt = ND_list(self.Nl[it1]) + for il1 in range(self.Nl[it1]): + S_stt[il1] = torch.cat( S[ist][it1][it2][il1], dim=1 ) + S_st[it2] = torch.cat( S_stt, dim=0 ) + S_s[it1] = torch.cat( S_st, dim=1 ) + S_cat = torch.cat( S_s, dim=0 ) + + S_I = inverse.inverse(S_cat) +# S_I = 1/S_cat + + for ib in range(self.Nb[ist]): + + Q_s = ND_list(self.Nt[ist]) + for it in range(self.Nt[ist]): + Q_s[it] = torch.cat([ Q_st[ib] for Q_st in Q[ist][it] ]) + Q_cat = torch.cat(Q_s) + + V[ist][ib] = torch.dot( Q_cat, torch.mv( S_I, Q_cat ) ) + return V \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch_gradient_source/torch_complex.py b/tools/01_NAO_generation/pytorch_gradient_source/torch_complex.py index d5f338d5d74..48430b6871b 100644 --- a/tools/01_NAO_generation/pytorch_gradient_source/torch_complex.py +++ b/tools/01_NAO_generation/pytorch_gradient_source/torch_complex.py @@ -1,83 +1,83 @@ -import torch - -class ComplexTensor: - def __init__(self,real,imag): - self.real = real - self.imag = imag - - def view(self,*args,**kwargs): - return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) - def t(self,*args,**kwargs): - return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) -# def transpose(self,*args,**kwargs): -# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) - def __getitem__(self,*args,**kwargs): - return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) - def __str__(self): - return "<{0};{1}>".format(self.real, self.imag) - __repr__=__str__ -# def size(self,*args,**kwargs): -# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) - - def conj(self): - return ComplexTensor( self.real, -self.imag ) - - - -def dot( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.dot( x1,x2, *args,**kwargs ) -def mv( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mv( x1,x2, *args,**kwargs ) -def mm( x1,x2, *args,**kwargs ): - if isinstance(x1,ComplexTensor): - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) - else: - return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) - else: - if isinstance(x2,ComplexTensor): - return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) - else: - return torch.mm( x1,x2, *args,**kwargs ) - - -def cat( xs, *args,**kwargs ): - if isinstance(xs[0],ComplexTensor): - xs_real = []; xs_imag = [] - for x in xs: - xs_real.append(x.real) - xs_imag.append(x.imag) - return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) - else: - return torch.cat(xs,*args,**kwargs) - - - -import inverse as inverse_real -def inverse(M): - if isinstance(M,ComplexTensor): - A=M.real - B=M.imag - tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B - tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} - return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) - else: +import torch + +class ComplexTensor: + def __init__(self,real,imag): + self.real = real + self.imag = imag + + def view(self,*args,**kwargs): + return ComplexTensor( self.real.view(*args,**kwargs), self.imag.view(*args,**kwargs) ) + def t(self,*args,**kwargs): + return ComplexTensor( self.real.t(*args,**kwargs), self.imag.t(*args,**kwargs) ) +# def transpose(self,*args,**kwargs): +# return ComplexTensor( self.real.transpose(*args,**kwargs), self.imag.transpose(*args,**kwargs) ) + def __getitem__(self,*args,**kwargs): + return ComplexTensor( self.real.__getitem__(*args,**kwargs), self.imag.__getitem__(*args,**kwargs) ) + def __str__(self): + return "<{0};{1}>".format(self.real, self.imag) + __repr__=__str__ +# def size(self,*args,**kwargs): +# return ComplexTensor( self.real.size(*args,**kwargs), self.imag.size(*args,**kwargs) ) + + def conj(self): + return ComplexTensor( self.real, -self.imag ) + + + +def dot( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.dot( x1.real,x2.real, *args,**kwargs ) - torch.dot( x1.imag,x2.imag, *args,**kwargs ), torch.dot( x1.real,x2.imag, *args,**kwargs ) + torch.dot( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.dot( x1.real,x2, *args,**kwargs ), torch.dot( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.dot( x1,x2.real, *args,**kwargs ), torch.dot( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.dot( x1,x2, *args,**kwargs ) +def mv( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mv( x1.real,x2.real, *args,**kwargs ) - torch.mv( x1.imag,x2.imag, *args,**kwargs ), torch.mv( x1.real,x2.imag, *args,**kwargs ) + torch.mv( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.mv( x1.real,x2, *args,**kwargs ), torch.mv( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mv( x1,x2.real, *args,**kwargs ), torch.mv( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.mv( x1,x2, *args,**kwargs ) +def mm( x1,x2, *args,**kwargs ): + if isinstance(x1,ComplexTensor): + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mm( x1.real,x2.real, *args,**kwargs ) - torch.mm( x1.imag,x2.imag, *args,**kwargs ), torch.mm( x1.real,x2.imag, *args,**kwargs ) + torch.mm( x1.imag,x2.real, *args,**kwargs ) ) + else: + return ComplexTensor( torch.mm( x1.real,x2, *args,**kwargs ), torch.mm( x1.imag,x2, *args,**kwargs ) ) + else: + if isinstance(x2,ComplexTensor): + return ComplexTensor( torch.mm( x1,x2.real, *args,**kwargs ), torch.mm( x1,x2.imag, *args,**kwargs ) ) + else: + return torch.mm( x1,x2, *args,**kwargs ) + + +def cat( xs, *args,**kwargs ): + if isinstance(xs[0],ComplexTensor): + xs_real = []; xs_imag = [] + for x in xs: + xs_real.append(x.real) + xs_imag.append(x.imag) + return ComplexTensor( torch.cat(xs_real,*args,**kwargs), torch.cat(xs_imag,*args,**kwargs) ) + else: + return torch.cat(xs,*args,**kwargs) + + + +import inverse as inverse_real +def inverse(M): + if isinstance(M,ComplexTensor): + A=M.real + B=M.imag + tmp_AB = torch.mm(A.inverse(),B) # A^{-1} B + tmp_X = (A+torch.mm(B,tmp_AB)).inverse() # ( A + B A^{-1} B )^{-1} + return ComplexTensor( tmp_X, -torch.mm(tmp_AB,tmp_X) ) + else: return M.inverse() \ No newline at end of file diff --git a/tools/01_NAO_generation/pytorch_gradient_source/unittest_inverse.py b/tools/01_NAO_generation/pytorch_gradient_source/unittest_inverse.py index f4d43156108..d0e26b65e7a 100644 --- a/tools/01_NAO_generation/pytorch_gradient_source/unittest_inverse.py +++ b/tools/01_NAO_generation/pytorch_gradient_source/unittest_inverse.py @@ -1,29 +1,29 @@ -import unittest -import inverse -import torch - -class unittest_inverse(unittest.TestCase): - - def inverse_test(self,a,ai_true): - - a=torch.Tensor(a) - a=torch.autograd.Variable(a) - - ai_test=inverse.inverse(a) - - ai_true = torch.Tensor(ai_true) - ai_true=torch.autograd.Variable(ai_true) - - self.assertFalse((ai_test!=ai_true).data.sum()) - - def test_inverse_1(self): - self.inverse_test( - [[1,2],[2,3]], - [[-3,2],[2,-1]] ) - def test_inverse_2(self): - self.inverse_test( - [[1,2,3],[2,4,5],[3,5,6]], - [[1,-3,2],[-3,3,-1],[2,-1,0]] ) - -if __name__ == '__main__': +import unittest +import inverse +import torch + +class unittest_inverse(unittest.TestCase): + + def inverse_test(self,a,ai_true): + + a=torch.Tensor(a) + a=torch.autograd.Variable(a) + + ai_test=inverse.inverse(a) + + ai_true = torch.Tensor(ai_true) + ai_true=torch.autograd.Variable(ai_true) + + self.assertFalse((ai_test!=ai_true).data.sum()) + + def test_inverse_1(self): + self.inverse_test( + [[1,2],[2,3]], + [[-3,2],[2,-1]] ) + def test_inverse_2(self): + self.inverse_test( + [[1,2,3],[2,4,5],[3,5,6]], + [[1,-3,2],[-3,3,-1],[2,-1,0]] ) + +if __name__ == '__main__': unittest.main() \ No newline at end of file From 2687b7fdf90eb976c568ba8051c7eb81417d92a9 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 18:05:24 +0800 Subject: [PATCH 03/13] Update SIAB author reference --- .../SIAB/src_parallel/parallel_global.h | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tools/01_NAO_generation/SIAB/src_parallel/parallel_global.h b/tools/01_NAO_generation/SIAB/src_parallel/parallel_global.h index b73b4de4971..474e125e4f8 100644 --- a/tools/01_NAO_generation/SIAB/src_parallel/parallel_global.h +++ b/tools/01_NAO_generation/SIAB/src_parallel/parallel_global.h @@ -1,27 +1,27 @@ -//========================================================== -// AUTHOR : Fang Wei, Mohan Chen -// DATE : 2008 -// LAST UPDATE : 2009-3-23 mohan add GATHER_MINIMUM_DOUBLE -//========================================================== -#ifndef PARALLEL_GLOBAL_H -#define PARALLEL_GLOBAL_H -#include "../src_spillage/common.h" - -#ifdef __MPI -#include -extern MPI_Comm POOL_WORLD; -#endif - -//void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); - -namespace Parallel_Global -{ - void read_pal_param(int argc, char **argv); - -#ifdef __MPI - void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); -#endif -} - - -#endif // GMPI +//========================================================== +// AUTHOR : Fang Wei, @mohanchen +// DATE : 2008 +// LAST UPDATE : 2009-3-23 mohan add GATHER_MINIMUM_DOUBLE +//========================================================== +#ifndef PARALLEL_GLOBAL_H +#define PARALLEL_GLOBAL_H +#include "../src_spillage/common.h" + +#ifdef __MPI +#include +extern MPI_Comm POOL_WORLD; +#endif + +//void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); + +namespace Parallel_Global +{ + void read_pal_param(int argc, char **argv); + +#ifdef __MPI + void myProd(complex *in, std::complex *inout,int *len,MPI_Datatype *dptr); +#endif +} + + +#endif // GMPI From 5e241763191e218112b7cda5fff48b56bce03642 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 18:07:25 +0800 Subject: [PATCH 04/13] Add agent governance checks --- .coderabbit.yaml | 44 ++ .gitattributes | 9 +- .github/pull_request_template.md | 40 +- .github/workflows/agent_governance.yml | 43 ++ .gitignore | 1 + .pre-commit-config.yaml | 13 + AGENTS.md | 53 ++ docs/CONTRIBUTING.md | 20 +- docs/community/contribution_guide.md | 7 + docs/developers_guide/agent_governance.md | 177 +++++ docs/developers_guide/index.rst | 1 + .../agent_governance_check.py | 719 ++++++++++++++++++ .../test_agent_governance_check.py | 508 +++++++++++++ 13 files changed, 1622 insertions(+), 13 deletions(-) create mode 100644 .coderabbit.yaml create mode 100644 .github/workflows/agent_governance.yml create mode 100644 AGENTS.md create mode 100644 docs/developers_guide/agent_governance.md create mode 100644 tools/03_code_analysis/agent_governance_check.py create mode 100644 tools/03_code_analysis/test_agent_governance_check.py diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000000..11eb7b46b88 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +language: en-US + +reviews: + auto_review: + enabled: true + drafts: false + request_changes_workflow: false + high_level_summary: true + poem: false + path_instructions: + - path: "source/**" + instructions: | + Apply the ABACUS agent governance rules before general style feedback. + Focus on newly introduced GlobalV/GlobalC/PARAM dependencies, default + parameters in headers, module placement, CMakeLists.txt linkage, C++11 + compatibility, and focused tests for behavior changes. + - path: "source/source_io/module_parameter/**" + instructions: | + Treat INPUT parameter metadata, parsing, defaults, descriptions, and + availability changes as user-visible behavior. Require matching updates + to docs/parameters.yaml and docs/advanced/input_files/input-main.md, or + a clear no-update explanation in the PR. + - path: "docs/**" + instructions: | + Check that documentation changes match the implementation and do not + weaken the rule grading matrix without an explicit rationale. + - path: ".github/**" + instructions: | + Check workflow and PR-template changes for consistency with AGENTS.md + and docs/developers_guide/agent_governance.md. + - path: "tools/03_code_analysis/**" + instructions: | + Review governance checker changes for false positives, missing + diff-scoping, test coverage, and consistency with the GitHub Actions + summary output. Prefer deterministic checks for low-noise blockers and + leave semantic ownership decisions to AI and human review. + +knowledge_base: + code_guidelines: + enabled: true + filePatterns: + - "AGENTS.md" + - "docs/developers_guide/agent_governance.md" diff --git a/.gitattributes b/.gitattributes index 035167aaf71..ae65b67d4cb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,8 @@ -# Shell scripts and the bash-parsed integration-test case lists must keep LF -# endings so they run under bash, including MSYS2/Git-Bash on Windows where -# core.autocrlf may rewrite them to CRLF (which breaks `#!/bin/bash` and adds -# stray \r to parsed lines such as the case names in CASES_*.txt). +# Text files use LF by default. Windows command scripts keep CRLF because +# cmd.exe and installer tooling may depend on it. +* text=auto eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf *.sh text eol=lf CASES_*.txt text eol=lf diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a504f55794b..39c41ed9e09 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,8 +1,10 @@ ### Reminder -- [ ] Have you linked an issue with this pull request? -- [ ] Have you added adequate unit tests and/or case tests for your pull request? -- [ ] Have you noticed possible changes of behavior below or in the linked issue? -- [ ] Have you explained the changes of codes in core modules of ESolver, HSolver, ElecState, Hamilt, Operator or Psi? (ignore if not applicable) +- [ ] I have read `AGENTS.md` and `docs/developers_guide/agent_governance.md`. +- [ ] I have linked an issue or explained why this PR does not need one. +- [ ] I have added adequate unit tests and/or case tests, or explained why not. +- [ ] I have described user-visible behavior changes, including INPUT parameter changes. +- [ ] I have explained core-module impact for ESolver, HSolver, ElecState, Hamilt, Operator, Psi, or other `source/` changes. +- [ ] I have requested any needed governance exception below. ### Linked Issue Fix #... @@ -13,5 +15,31 @@ Fix #... ### What's changed? - Example: My changes might affect the performance of the application under certain conditions, and I have tested the impact on various scenarios... -### Any changes of core modules? (ignore if not applicable) -- Example: I have added a new virtual function in the esolver base class in order to ... +### Governance Checklist +- Global dependencies: no new `GlobalV`, `GlobalC`, or `PARAM` cross-layer control, or exception requested below. +- Default parameters: no new default arguments added to existing interfaces, or exception requested below. +- Headers: no unnecessary header dependencies or `.hpp` propagation, or rationale provided below. +- Line endings: text files use LF; only `.bat` and `.cmd` use CRLF. +- Build linkage: new source files are listed in the relevant `CMakeLists.txt`, or rationale provided below. +- Documentation: behavior/interface changes include documentation updates, or no documentation update is required because ... +- CodeRabbit: if automatic review has not started and the repository has CodeRabbit installed, request `@coderabbitai review`. + +### INPUT Parameter Changes +- Parameters added/removed/changed: +- `docs/parameters.yaml` updated: yes/no/not applicable +- `docs/advanced/input_files/input-main.md` updated: yes/no/not applicable +- If not updated, explain why no INPUT documentation update is required: + +### Core Module Impact +- Affected core modules: +- Risk summary: +- Compatibility or performance impact: + +### Governance Exception +- Rule: +- Reason: +- Scope: +- User or maintenance risk: +- Why the normal rule cannot be followed now: +- Follow-up cleanup plan: +- Requested approver: diff --git a/.github/workflows/agent_governance.yml b/.github/workflows/agent_governance.yml new file mode 100644 index 00000000000..980519814a8 --- /dev/null +++ b/.github/workflows/agent_governance.yml @@ -0,0 +1,43 @@ +name: Agent Governance + +on: + pull_request: + types: [opened, synchronize, reopened, edited, ready_for_review] + +permissions: + contents: read + pull-requests: read + +jobs: + governance: + name: Governance checks + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run ABACUS governance checker + id: governance + run: | + set +e + python3 tools/03_code_analysis/agent_governance_check.py \ + --base "${{ github.event.pull_request.base.sha }}" \ + --head "${{ github.event.pull_request.head.sha }}" \ + --event-path "$GITHUB_EVENT_PATH" \ + --format markdown | tee agent_governance_summary.md + status=${PIPESTATUS[0]} + if [ ! -s agent_governance_summary.md ]; then + { + echo "## Agent Governance Check" + echo + echo "Checker failed before producing a summary." + } > agent_governance_summary.md + fi + exit "$status" + + - name: Publish governance summary + if: always() + run: | + cat agent_governance_summary.md >> "$GITHUB_STEP_SUMMARY" diff --git a/.gitignore b/.gitignore index ad33721f56e..e63c8d3ed3e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,5 @@ abacus.json toolchain/install/ toolchain/abacus_env.sh .trae +.codex compile_commands.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c03332257c..8873791f2ce 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,11 @@ fail_fast: false repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: mixed-line-ending + args: [--fix=lf] + exclude: '(\.bat|\.cmd)$' - repo: https://github.com/pocc/pre-commit-hooks rev: v1.3.5 hooks: @@ -12,3 +18,10 @@ repos: # - id: cppcheck # - id: cpplint # - id: include-what-you-use + - repo: local + hooks: + - id: abacus-agent-governance + name: ABACUS agent governance checks + entry: python3 tools/03_code_analysis/agent_governance_check.py --staged + language: system + pass_filenames: false diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..1584334bf3d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,53 @@ +# ABACUS Agent Instructions + +This file is the entry point for AI agents, automated review tools, and human +contributors who want the short operational version of the ABACUS development +rules. Read the complete governance document before making or reviewing changes: + +- `docs/developers_guide/agent_governance.md` + +## Required Baseline + +- Follow the seven ABACUS coding rules summarized from the project governance: + 1. Do not introduce new cross-layer control through `GlobalV`, `GlobalC`, or + `PARAM`; pass dependencies explicitly. + 2. Do not hide workflow switches in mutable member variables that can be + changed from multiple places. + 3. Keep header dependencies minimal. + 4. Avoid adding `.hpp` implementation headers or propagating them through + other headers unless there is a narrow reason. + 5. Do not add default arguments to existing interfaces; update call sites or + design a clearer extension. + 6. Add focused tests for key features, bug fixes, INPUT behavior changes, + heterogeneous kernels, and core-module refactors. + 7. Keep code compatible with the repository C++11 baseline. +- Use LF line endings for text files. Only `.bat` and `.cmd` files may use CRLF. +- Keep source file additions deterministic: update the relevant `CMakeLists.txt` + or explain why the file is generated or included indirectly. +- INPUT parameter behavior changes must update `docs/parameters.yaml` and + `docs/advanced/input_files/input-main.md`, or the PR must state why no update + is required. +- Report the exact verification performed. Do not claim completion without + fresh test or check output. + +## Review And Exception Flow + +- Mechanical blockers are enforced by hook and CI only for new files, changed + files, or diff-added lines. Historical untouched code is not a default blocker. +- Warnings from CI or AI review require reviewer attention but do not block by + themselves. +- Semantic questions such as module ownership, member-variable workflow state, + test sufficiency, and exception approval require human review. +- Exceptions must be recorded in the PR with reason, scope, risk, and a follow-up + cleanup plan. + +## Local Commands + +```bash +python3 tools/03_code_analysis/agent_governance_check.py --staged +pre-commit run abacus-agent-governance --all-files +``` + +The repository text files have been normalized to LF once. Day-to-day line +ending enforcement should rely on staged/changed-file hooks and CI; rerun the +full mixed-line-ending hook only for intentional repository-wide normalization. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 9839f4c81e8..5ada0540ef8 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -9,6 +9,7 @@ For more non-technical aspects, please refer to the [ABACUS Contribution Guide]( - [Got a question?](#got-a-question) - [Structure of the package](#structure-of-the-package) - [Submitting an Issue](#submitting-an-issue) +- [Agent governance and automated review](#agent-governance-and-automated-review) - [Comment style for documentation](#comment-style-for-documentation) - [Documenting INPUT parameters](#documenting-input-parameters) - [Code formatting style](#code-formatting-style) @@ -91,6 +92,19 @@ For those who are interested in the source code, the following figure shows the Before you submit an issue, please search the issue tracker, and maybe your problem has been discussed and fixed. You can [submit new issues](https://github.com/deepmodeling/abacus-develop/issues/new/choose) by filling our issue forms. To help us reproduce and confirm a bug, please provide a test case and building environment in your issue. +## Agent governance and automated review + +Before coding or requesting review, read the repository governance entry point +[`AGENTS.md`](../AGENTS.md) and the full +[ABACUS Agent Governance](./developers_guide/agent_governance.md) guide. +These rules apply to human contributors, AI agents, GitHub CI, and CodeRabbit. + +Pull requests must complete the governance checklist in the PR template, +including issue linkage, test evidence, behavior-change notes, INPUT parameter +documentation linkage, core-module impact, and any requested exceptions. Local +pre-commit checks cover deterministic rules such as LF line endings and staged +diff checks; CI repeats the governance check against the PR diff and PR body. + ## Comment style for documentation ABACUS uses Doxygen to generate docs directly from `.h` and `.cpp` code files. @@ -368,13 +382,13 @@ To add a unit test: ## Adding an integrate test The integrate test is a test suite for testing the whole ABACUS package. The examples are located in the `tests/integrate` directory. Before adding a new test, please firstly read `README.md` in `tests/integrate` to understand the structure of the integrate test. To add an integrate test: 1. Add a new directory under `tests/integrate` for the new test. -2. Prepare the input files for the new test. +2. Prepare the input files for the new test. - The input files should be placed in the new directory. Pseudopotential files and orbital files should be placed in `tests/PP_ORB`. You should define the correct `pseudo_dir` and `orb_dir`(if need orbital files) in INPUT with the relative path to the `tests/PP_ORB` directory, and be sure the new test can be run successfully. - The running time of the new test should not exceed 20 seconds. You can try to reduce the time by below methods (on the premise of ensuring the effectiveness of the test): - Reduce the number of atoms in the unit cell (1~2 atoms). - Reduce the number of k-points (`1 1 1` or `2 2 2`). - Reduce ecutwfc (20~50 Ry). - - Reduce the number of steps for relax or md job (2~3 steps). + - Reduce the number of steps for relax or md job (2~3 steps). - Reduce the basis set for LCAO calculations (DZP orbital and 6 a.u. cutoff). - For PW calculations, should set `pw_seed 1` in INPUT file to ensure the reproducibility of the test. 3. Generate the reference results for the new test. @@ -385,7 +399,7 @@ The integrate test is a test suite for testing the whole ABACUS package. The exa etotref -3439.007931317310 etotperatomref -3439.0079313173 totaltimeref 2.78 - ``` + ``` - If you want to test the correctness of some output files, you need to do extra below steps: 1. add the corresponding comparison method in `catch_properties.sh`. For example, to verify whether the output of the BANDS_1.dat file is correct, you need to add the following code in `catch_properties.sh`: ```bash diff --git a/docs/community/contribution_guide.md b/docs/community/contribution_guide.md index f64d7d8eb8d..33fc82e8400 100644 --- a/docs/community/contribution_guide.md +++ b/docs/community/contribution_guide.md @@ -10,6 +10,13 @@ We assume you already have a good idea on what to do, otherwise the [issue track - **Approach the issue.** It is suggested to [submit new issues](https://github.com/deepmodeling/abacus-develop/issues/new/choose) before coding out changes to involve more discussions and suggestions from development team. Refer to the technical guide in [Contributing to ABACUS](../CONTRIBUTING.md) when needed. +- **Follow governance rules.** +Before implementation and review, read [`AGENTS.md`](../../AGENTS.md) and the +[ABACUS Agent Governance](../developers_guide/agent_governance.md) guide. New +code is reviewed against the shared rules for global dependencies, default +parameters, header dependencies, tests, INPUT documentation linkage, LF line +endings, C++11 compatibility, and exception handling. + - **Open a pull request.** The ABACUS developers review the pull request (PR) list regularly. If the work is not ready, convert it to draft until finished, then you can mark it as "Ready for review". It is suggested to open a new PR through forking a repo and creating a new branch on you Github account. A new PR should include as much information as possible in `description` when submmited. Unittests or CI tests are required for new PRs. - **Iterate the pull request.** diff --git a/docs/developers_guide/agent_governance.md b/docs/developers_guide/agent_governance.md new file mode 100644 index 00000000000..e4d83321864 --- /dev/null +++ b/docs/developers_guide/agent_governance.md @@ -0,0 +1,177 @@ +# ABACUS Agent Governance + +This document is the shared development and review contract for human +contributors, general AI agents, CodeRabbit, and GitHub CI. `AGENTS.md` is the +short entry point; this file is the complete rule source for implementation and +review. + +## Source Materials + +The governance rules consolidate project guidance from @mohanchen's coding +rules, the developer guide, contribution guide, PR template, existing CI, and +historical Chinese development notes. Historical notes are used only after path +modernization and rule grading; they are not copied directly into automated +checks. + +## Diff Scope + +Automated checks default to the PR diff: + +- New files. +- Diff-added lines. +- Newly introduced symbols or includes. +- Changed text files for line-ending checks. + +Untouched historical code is not a default blocker. Review tools may mention +historical debt when it is relevant to the changed area, but they must separate +that from blocking findings on new changes. + +## Core Coding Rules + +- Do not introduce new cross-layer control through `GlobalV`, `GlobalC`, or + `PARAM`. Prefer explicit parameters or narrow local interfaces. +- Do not store workflow switches in mutable member variables that can be changed + implicitly from multiple places. +- Keep header dependencies minimal; avoid adding includes to headers unless the + declaration truly requires them. +- Avoid adding `.hpp` implementation headers and avoid including `.hpp` files + from other headers unless the PR explains why header-only implementation is + needed. +- Do not add default arguments to existing interfaces. Update call sites + explicitly or design a clearer overload/configuration object. +- Add short, focused tests for key functionality, bug fixes, INPUT behavior + changes, heterogeneous kernels, and core-module refactors. +- Keep default and general-purpose C++ changes compatible with the repository + C++11 baseline. Backend-specific or dependency-constrained paths may use the + higher standard already selected by existing CMake configuration. +- Use LF line endings for text files. `.bat` and `.cmd` are the CRLF exception. + +AI agents have additional workflow obligations: + +- Inspect existing interfaces before using them. +- State uncertainty instead of inventing business rules or APIs. +- Report exact verification results and any checks that could not be run. + +## Rule Grading Matrix + +The first implementation phase separates deterministic mechanical checks from +review-only rules. "Phase-one mechanical" means the local hook or CI checker can +act on the PR diff without semantic judgment. "AI review" and "human +confirmation" items must be reviewed, but the checker does not hard-code those +decisions. + +| Rule category | Typical rule | Phase-one status | Default executor | Severity | Default action | Detection scope | Notes | +| --- | --- | --- | --- | --- | --- | --- | --- | +| Basic text format | LF line endings | phase-one mechanical | hook + CI | medium | block | full changed text file | `.bat` and `.cmd` keep CRLF | +| Language baseline | C++11 compatibility | build/toolchain | CI | high | block | build/static tooling | Actual compiler/toolchain result wins | +| New global dependency | Added `GlobalV`/`GlobalC`/`PARAM` as cross-layer control | phase-one mechanical + AI review | CI + AI review | high | block | added code lines | Historical untouched usage and documentation mentions are not blocked | +| New default parameter | Header declaration adds a default argument | phase-one mechanical + AI review | CI + AI review | high | block | header diff | High misuse risk | +| `.hpp` propagation | New `.hpp` or header includes `.hpp` | phase-one mechanical warning | CI + AI review | medium | warn | new files and added includes | Exception can be recorded in PR | +| Header dependency growth | Header diff adds includes | phase-one mechanical warning + AI review | CI + AI review | medium | warn | added header includes | Necessity is semantic and not mechanically decided | +| Member variable workflow switch | Key flow state hidden as mutable member state | AI review + human confirmation | AI + human review | high | human confirmation | semantic review | Static matching is unreliable | +| Module path and build linkage | New source path and `CMakeLists.txt` linkage | phase-one mechanical | CI | medium | block | new source files and build-script diff | Deterministic path/build check only | +| Module semantic ownership | Best module/submodule placement | AI review + human confirmation | AI + human review | medium | human confirmation | semantic review | Final call belongs to maintainers | +| Heterogeneous code linkage | CUDA/ROCM/kernel source and `CMakeLists.txt` linkage | phase-one mechanical | CI + AI review | medium | block | new heterogeneous files and linkage | Mechanical path/linkage only | +| Heterogeneous test evidence | CUDA/ROCM/kernel change has test evidence or reason | phase-one mechanical warning + AI review | CI + AI review | high | warn | changed paths and PR body | Sufficiency is human-reviewed | +| Test existence | Source change has test evidence or reason | phase-one mechanical warning + AI review | CI + AI review | high | warn | PR body and changed paths | Sufficiency is human-reviewed | +| Test sufficiency | Tests cover important behavior | AI review + human confirmation | AI + human review | medium | human confirmation | semantic review | Not mechanically blocked | +| INPUT behavior linkage | Parameter metadata/default/type/parser behavior updates YAML and docs | phase-one mechanical + AI review | CI + AI review | high | block | behavior-field diff plus docs/PR body | Comment-only parameter-file changes are not blocked | +| Documentation sync | Behavior/interface docs updated | phase-one mechanical warning + AI review | CI + AI review | medium | warn | changed paths and PR body | Major behavior changes escalate to reviewers | +| PR metadata completeness | Issue, tests, behavior, INPUT, core impact, exceptions | phase-one mechanical | CI or GitHub bot | medium | block | PR template fields | Not run by local hook | +| AI workflow | Interface lookup, uncertainty, verification report | AI review | AI review | high | warn | review transcript/output | Applies to AI agents | +| Exceptions | Reason, scope, risk, follow-up plan | human confirmation | human review + CI | high | human confirmation | PR exception section | CI checks presence, not approval | + +Implementations must use this matrix as the default baseline. Upgrading warnings +to blockers or converting human-confirmation rules into mechanical blockers +requires an explicit governance change. + +## Automation Responsibilities + +Local hooks: + +- Fix or block deterministic local issues such as mixed line endings. +- Run staged governance checks with `agent_governance_check.py --staged`. +- Do not require PR metadata because it is unavailable locally. + +CI: + +- Run diff-level governance checks with PR base/head SHAs. +- Check PR body completeness and INPUT documentation linkage. +- Publish Markdown summaries that humans and AI reviewers can consume. + +AI review: + +- Explain governance findings in actionable terms. +- Add semantic review for module ownership, header dependency growth, test + sufficiency, documentation sync, and AI workflow discipline. +- Use the output format below for actionable findings. + +Human review: + +- Approve or reject exceptions. +- Confirm module boundaries and high-risk design decisions. +- Decide whether tests are sufficient for the scientific and numerical risk. + +## AI PR Review Integration + +ABACUS uses a layered review model: + +- `Agent Governance` is the deterministic GitHub Actions check for low-noise + diff rules. Repository maintainers may make this workflow a required check in + branch protection. +- CodeRabbit is the minimal PR-triggered AI reviewer for semantic review hints. + Its repository configuration lives in `.coderabbit.yaml` and uses this + document plus `AGENTS.md` as review guidelines. +- CodeRabbit comments are advisory by default. They do not replace maintainer + approval, exception approval, or numerical/test sufficiency review. + +To activate CodeRabbit on real PRs, a repository or organization administrator +must install the CodeRabbit GitHub App for `deepmodeling/abacus-develop` and +grant it pull request review access. After installation, non-draft pull requests +and new commits should receive automatic review according to `.coderabbit.yaml`; +if automatic review does not start, maintainers may request it with +`@coderabbitai review`. + +Copilot code review, Copilot coding-agent setup steps, Qodo, and PR-Agent are +not part of the phase-one baseline. They require separate organization settings, +secrets, or setup workflows and should be added only through a later governance +change. + +## INPUT Parameter Changes + +Changes to parameter metadata, default values, type, availability, description, +or parsing behavior must include both: + +- `docs/parameters.yaml` +- `docs/advanced/input_files/input-main.md` + +If the diff touches parameter internals but does not change user-visible INPUT +behavior, the PR must state why no documentation update is required. + +## Exception Template + +Use this template in the PR when a rule must be bypassed temporarily: + +```markdown +### Governance Exception +- Rule: +- Reason: +- Scope: +- User or maintenance risk: +- Why the normal rule cannot be followed now: +- Follow-up cleanup plan: +- Requested approver: +``` + +## AI Review Finding Format + +AI and bot review findings should use this shape: + +```markdown +Rule: +Severity: error | warning | info +Location: +Reason: +Suggested action: +Exception: allowed | not allowed | human approval required +``` diff --git a/docs/developers_guide/index.rst b/docs/developers_guide/index.rst index 089deee90ab..f346894be47 100644 --- a/docs/developers_guide/index.rst +++ b/docs/developers_guide/index.rst @@ -10,3 +10,4 @@ This section provides guidelines and resources for developers working on the ABA :caption: Developer Resources basic_types_class.md + agent_governance.md diff --git a/tools/03_code_analysis/agent_governance_check.py b/tools/03_code_analysis/agent_governance_check.py new file mode 100644 index 00000000000..e6e2ac838de --- /dev/null +++ b/tools/03_code_analysis/agent_governance_check.py @@ -0,0 +1,719 @@ +#!/usr/bin/env python3 +"""Diff-oriented governance checks for ABACUS agent and PR review.""" + +from __future__ import annotations + +import argparse +import json +import re +import subprocess +import sys +from dataclasses import dataclass, asdict +from pathlib import Path +from typing import Dict, Iterable, List, Optional, Sequence, Tuple + + +BLOCK = "error" +WARN = "warning" +INFO = "info" + +TEXT_EXTENSIONS = { + ".c", + ".cc", + ".cpp", + ".cxx", + ".cu", + ".cuh", + ".h", + ".hh", + ".hpp", + ".hxx", + ".md", + ".rst", + ".txt", + ".yaml", + ".yml", + ".py", + ".sh", + ".cmake", + ".json", +} +HEADER_EXTENSIONS = {".h", ".hh", ".hpp", ".hxx"} +SOURCE_EXTENSIONS = {".c", ".cc", ".cpp", ".cxx", ".cu"} +SOURCE_REVIEW_EXTENSIONS = SOURCE_EXTENSIONS | HEADER_EXTENSIONS | {".cuh"} +CODE_EXTENSIONS = SOURCE_EXTENSIONS | HEADER_EXTENSIONS | {".cuh", ".py", ".cmake"} +WINDOWS_SCRIPT_EXTENSIONS = {".bat", ".cmd"} +TEST_PATH_PREFIXES = ("tests/", "test/", "unit_test/", "examples/") +TEST_NAME_PATTERNS = ("test", "tests", "unittest", "pytest", "ctest", "case") +HETEROGENEOUS_MARKERS = ("/cuda/", "/rocm/", "/kernels/", "cuda/", "rocm/", "kernels/") +PR_SECTION_RE = re.compile(r"^###\s+(.+?)\s*$", re.MULTILINE) + + +@dataclass +class Finding: + rule: str + severity: str + path: str + line: Optional[int] + reason: str + suggestion: str + allow_exception: bool + + +@dataclass +class DiffLine: + path: str + line: Optional[int] + content: str + + +class GitError(RuntimeError): + pass + + +def git(args: Sequence[str], cwd: Path, *, text: bool = True) -> subprocess.CompletedProcess: + result = subprocess.run( + ["git", *args], + cwd=str(cwd), + text=text, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + if result.returncode != 0: + raise GitError(result.stderr.strip() or "git command failed") + return result + + +def repo_root() -> Path: + result = subprocess.run( + ["git", "rev-parse", "--show-toplevel"], + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + if result.returncode != 0: + return Path.cwd() + return Path(result.stdout.strip()) + + +def parse_name_status(output: str) -> Tuple[Dict[str, str], List[str]]: + statuses: Dict[str, str] = {} + changed: List[str] = [] + for raw in output.splitlines(): + if not raw: + continue + parts = raw.split("\t") + status = parts[0] + path = parts[-1] + statuses[path] = status + changed.append(path) + return statuses, changed + + +def changed_paths(root: Path, args: argparse.Namespace) -> Tuple[Dict[str, str], List[str]]: + if args.staged: + output = git(["diff", "--cached", "--name-status"], root).stdout + elif args.base and args.head: + output = git(["diff", "--name-status", args.base, args.head], root).stdout + else: + output = "" + return parse_name_status(output) + + +def parse_added_lines(diff_text: str) -> List[DiffLine]: + lines: List[DiffLine] = [] + path = "" + new_line: Optional[int] = None + hunk_re = re.compile(r"@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@") + for raw in diff_text.splitlines(): + if raw.startswith("+++ b/"): + path = raw[6:] + continue + if raw.startswith("+++ "): + path = raw[4:] + continue + match = hunk_re.match(raw) + if match: + new_line = int(match.group(1)) + continue + if new_line is None: + continue + if raw.startswith("+") and not raw.startswith("+++"): + lines.append(DiffLine(path, new_line, raw[1:])) + new_line += 1 + elif raw.startswith("-") and not raw.startswith("---"): + continue + else: + new_line += 1 + return lines + + +def added_lines(root: Path, args: argparse.Namespace) -> List[DiffLine]: + if args.staged: + output = git(["diff", "--cached", "-U0"], root).stdout + elif args.base and args.head: + output = git(["diff", "-U0", args.base, args.head], root).stdout + else: + output = "" + return parse_added_lines(output) + + +def read_changed_file_bytes(root: Path, path: str, args: argparse.Namespace) -> bytes: + if args.staged: + result = subprocess.run( + ["git", "show", f":{path}"], + cwd=str(root), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + if result.returncode == 0: + return result.stdout + if args.head: + result = subprocess.run( + ["git", "show", f"{args.head}:{path}"], + cwd=str(root), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + if result.returncode == 0: + return result.stdout + with open(root / path, "rb") as handle: + return handle.read() + + +def is_text_path(path: str) -> bool: + suffix = Path(path).suffix.lower() + if suffix in WINDOWS_SCRIPT_EXTENSIONS: + return False + return suffix in TEXT_EXTENSIONS or path in {".gitattributes", ".gitignore"} + + +def add_finding( + findings: List[Finding], + rule: str, + severity: str, + path: str, + line: Optional[int], + reason: str, + suggestion: str, + allow_exception: bool = True, +) -> None: + findings.append(Finding(rule, severity, path, line, reason, suggestion, allow_exception)) + + +def check_line_endings( + findings: List[Finding], + root: Path, + paths: Iterable[str], + statuses: Dict[str, str], + args: argparse.Namespace, +) -> None: + for path in paths: + if statuses.get(path, "").startswith("D") or not is_text_path(path): + continue + try: + content = read_changed_file_bytes(root, path, args) + except OSError: + continue + if b"\r\n" in content: + add_finding( + findings, + "LF line endings", + BLOCK, + path, + None, + "Changed text file contains CRLF line endings.", + "Convert the file to LF. Windows .bat and .cmd scripts are the only CRLF exception.", + allow_exception=False, + ) + + +def check_global_dependencies(findings: List[Finding], lines: Iterable[DiffLine]) -> None: + pattern = re.compile(r"\b(GlobalV::|GlobalC::|PARAM(?:\.|->|::|\b))") + for line in lines: + if line.path.startswith("tools/03_code_analysis/"): + continue + if Path(line.path).suffix.lower() not in CODE_EXTENSIONS: + continue + if pattern.search(line.content): + add_finding( + findings, + "No new cross-layer globals", + BLOCK, + line.path, + line.line, + "Added line introduces GlobalV, GlobalC, or PARAM as a dependency.", + "Prefer explicit parameters or a narrow local interface. Document any required exception in the PR.", + ) + + +def check_default_parameters(findings: List[Finding], lines: Iterable[DiffLine]) -> None: + default_arg = re.compile(r"[(,]\s*[^()=;,{}]+\b\w+\s*=\s*[^,);{}]+") + control_flow = re.compile(r"^(for|if|while|switch|catch)\s*\(") + for line in lines: + if Path(line.path).suffix.lower() not in HEADER_EXTENSIONS: + continue + stripped = line.content.strip() + if not stripped or stripped.startswith("//") or stripped.startswith("*"): + continue + if control_flow.match(stripped): + continue + if "(" in stripped and ")" in stripped and default_arg.search(stripped): + add_finding( + findings, + "No new default parameters", + BLOCK, + line.path, + line.line, + "Header diff adds a function declaration with a default argument.", + "Update call sites explicitly or introduce a clearer overload/configuration object.", + ) + + +def check_hpp_warnings( + findings: List[Finding], + statuses: Dict[str, str], + lines: Iterable[DiffLine], +) -> None: + for path, status in statuses.items(): + if status.startswith("A") and Path(path).suffix.lower() == ".hpp": + add_finding( + findings, + "Avoid new .hpp propagation", + WARN, + path, + None, + "New .hpp files are discouraged unless they are narrowly justified.", + "Prefer .h declarations with .cpp implementation, or explain why header-only implementation is needed.", + ) + include_hpp = re.compile(r'^\s*#\s*include\s+[<"][^>"]+\.hpp[>"]') + for line in lines: + if Path(line.path).suffix.lower() in HEADER_EXTENSIONS and include_hpp.search(line.content): + add_finding( + findings, + "Avoid new .hpp propagation", + WARN, + line.path, + line.line, + "Header diff includes a .hpp file.", + "Avoid propagating implementation-heavy headers, or document why this include is necessary.", + ) + + +def check_header_include_warnings(findings: List[Finding], lines: Iterable[DiffLine]) -> None: + include_re = re.compile(r"^\s*#\s*include\s+[<\"][^>\"]+[>\"]") + for line in lines: + if Path(line.path).suffix.lower() in HEADER_EXTENSIONS and include_re.search(line.content): + add_finding( + findings, + "Header dependency review", + WARN, + line.path, + line.line, + "Header diff adds an include dependency.", + "Confirm the declaration requires this include; prefer forward declarations where practical.", + ) + + +def is_source_under_source_tree(path: str) -> bool: + p = Path(path) + return path.startswith("source/") and p.suffix.lower() in (SOURCE_EXTENSIONS | {".cuh"}) + + +def is_heterogeneous_path(path: str) -> bool: + lowered = path.lower() + suffix = Path(lowered).suffix + return ( + suffix in {".cu", ".cuh"} + or lowered.endswith(".hip.cu") + or any(marker in lowered for marker in HETEROGENEOUS_MARKERS) + ) + + +def has_related_cmake_change(path: str, changed: Sequence[str]) -> bool: + changed_cmake_dirs = { + str(Path(changed_path).parent) + for changed_path in changed + if Path(changed_path).name == "CMakeLists.txt" + } + if not changed_cmake_dirs: + return False + parent = Path(path).parent + parent_chain = [str(parent)] + parent_chain.extend(str(p) for p in parent.parents if str(p) not in {".", ""}) + return any(directory in changed_cmake_dirs for directory in parent_chain) + + +def check_cmake_linkage(findings: List[Finding], statuses: Dict[str, str], changed: Sequence[str]) -> None: + for path, status in statuses.items(): + if not status.startswith("A") or not is_source_under_source_tree(path): + continue + if is_heterogeneous_path(path): + if not has_related_cmake_change(path, changed): + add_finding( + findings, + "CMake linkage for heterogeneous sources", + BLOCK, + path, + None, + "New heterogeneous source has no related CMakeLists.txt change.", + "Update the same-directory or parent CMakeLists.txt, or explain generated/indirect inclusion in the PR.", + ) + continue + if not has_related_cmake_change(path, changed): + add_finding( + findings, + "CMake linkage for new sources", + BLOCK, + path, + None, + "New source file under source/ has no related CMakeLists.txt change.", + "Update the relevant CMakeLists.txt or explain why the file is generated or included indirectly.", + ) + + +def input_parameter_changed(paths: Sequence[str], lines: Sequence[DiffLine]) -> bool: + parameter_paths = [ + path + for path in paths + if path.startswith("source/source_io/module_parameter/") + and Path(path).suffix.lower() in {".cpp", ".h", ".hpp"} + ] + if parameter_paths: + sensitive = re.compile( + r"\b(Input_Item|add_item|default_value|description|category|availability|read_value|reset_value|check_value|type)\b" + ) + return any( + line.path in parameter_paths + and not line.content.lstrip().startswith("//") + and sensitive.search(line.content) + for line in lines + ) + return any( + line.path.startswith("source/") + and re.search(r"\bInput_Item\s+\w+|add_item\s*\(", line.content) + for line in lines + ) + + +def pr_body_allows_no_input_doc_update(body: str) -> bool: + lowered = body.lower() + needles = [ + "input parameter documentation: not needed", + "input docs: not needed", + "no input documentation update required", + "无需更新 input", + ] + return any(needle in lowered for needle in needles) + + +def check_input_parameter_docs( + findings: List[Finding], + changed: Sequence[str], + statuses: Dict[str, str], + lines: Sequence[DiffLine], + pr_body: str, +) -> None: + if not input_parameter_changed(changed, lines): + return + has_yaml = "docs/parameters.yaml" in changed and not statuses.get("docs/parameters.yaml", "").startswith("D") + has_markdown = ( + "docs/advanced/input_files/input-main.md" in changed + and not statuses.get("docs/advanced/input_files/input-main.md", "").startswith("D") + ) + if has_yaml and has_markdown: + return + if pr_body and pr_body_allows_no_input_doc_update(pr_body): + return + add_finding( + findings, + "INPUT parameter documentation linkage", + BLOCK, + "source/source_io/module_parameter", + None, + "INPUT parameter behavior appears to change without both docs/parameters.yaml and input-main.md updates.", + "Regenerate docs/parameters.yaml and docs/advanced/input_files/input-main.md, or state why no INPUT documentation update is required in the PR.", + ) + + +def read_pr_body(event_path: Optional[str]) -> str: + if not event_path: + return "" + try: + with open(event_path, "r", encoding="utf-8") as handle: + payload = json.load(handle) + except (OSError, json.JSONDecodeError): + return "" + pr = payload.get("pull_request") or {} + return pr.get("body") or "" + + +def pr_sections(body: str) -> Dict[str, str]: + matches = list(PR_SECTION_RE.finditer(body)) + sections: Dict[str, str] = {} + for index, match in enumerate(matches): + start = match.end() + end = matches[index + 1].start() if index + 1 < len(matches) else len(body) + sections[match.group(1).strip()] = body[start:end].strip() + return sections + + +def section_is_placeholder(content: str) -> bool: + stripped = content.strip() + if not stripped: + return True + lowered = stripped.lower() + placeholder_patterns = [ + r"fix #\.\.\.", + r"example:", + r"ignore if not applicable", + r"\byes/no/not applicable\b", + r"a unit test is added for each new feature or bug fix", + r"my changes might affect", + r"because \.\.\.", + ] + if any(re.search(pattern, lowered) for pattern in placeholder_patterns): + return True + meaningful = [ + line.strip() + for line in stripped.splitlines() + if line.strip() and not re.match(r"^[-*]\s*[^:]+:\s*$", line.strip()) + ] + return not meaningful + + +def check_pr_metadata(findings: List[Finding], body: str) -> None: + if not body: + return + required_sections = [ + "Linked Issue", + "Unit Tests and/or Case Tests for my changes", + "What's changed?", + "Governance Checklist", + "INPUT Parameter Changes", + "Core Module Impact", + "Governance Exception", + ] + sections = pr_sections(body) + missing = [section for section in required_sections if section not in sections] + placeholders = [ + section + for section in required_sections + if section in sections and section_is_placeholder(sections[section]) + ] + if missing or placeholders: + reason_parts = [] + if missing: + reason_parts.append("missing sections: " + ", ".join(missing)) + if placeholders: + reason_parts.append("empty or placeholder sections: " + ", ".join(placeholders)) + add_finding( + findings, + "PR metadata completeness", + BLOCK, + "pull_request.body", + None, + "; ".join(reason_parts), + "Fill the PR template with issue linkage, test evidence, behavior impact, governance notes, and exception details.", + allow_exception=False, + ) + + +def pr_test_section_has_evidence(pr_body: str) -> bool: + if not pr_body: + return False + sections = pr_sections(pr_body) + content = sections.get("Unit Tests and/or Case Tests for my changes", "") + if section_is_placeholder(content): + return False + lowered = content.lower() + explicit_no_test_rationale = ( + re.search(r"\btests?\s+(?:are\s+)?not required\b.+\bbecause\b", lowered) + or re.search(r"\bnot applicable\b\s*:?.*\b(?:docs|documentation) only\b", lowered) + or "docs only" in lowered + or "documentation only" in lowered + ) + if explicit_no_test_rationale: + return True + missing_test_phrases = [ + r"\bno tests? (?:were )?run\b", + r"\bno tests? (?:were )?added\b", + r"\bno tests? added yet\b", + r"\bnot run tests?\b", + r"\btests? (?:were )?not run\b", + ] + if any(re.search(pattern, lowered) for pattern in missing_test_phrases): + return False + no_test_reason = ( + "not required" in lowered + or "not applicable" in lowered + ) + command_or_test = any(pattern in lowered for pattern in TEST_NAME_PATTERNS) + return no_test_reason or command_or_test + + +def path_is_test(path: str) -> bool: + lowered = path.lower() + name = Path(lowered).name + return lowered.startswith(TEST_PATH_PREFIXES) or any(pattern in name for pattern in TEST_NAME_PATTERNS) + + +def source_code_changed(changed: Sequence[str]) -> bool: + return any(path.startswith("source/") and Path(path).suffix.lower() in SOURCE_REVIEW_EXTENSIONS for path in changed) + + +def check_test_evidence_warning(findings: List[Finding], changed: Sequence[str], pr_body: str) -> None: + if not source_code_changed(changed): + return + if any(path_is_test(path) for path in changed) or pr_test_section_has_evidence(pr_body): + return + add_finding( + findings, + "Test evidence review", + WARN, + "pull_request.body", + None, + "Source code changed without test path changes or PR test evidence.", + "Add focused tests, update a relevant case, or document why tests are not required.", + ) + + +def check_heterogeneous_test_warning(findings: List[Finding], changed: Sequence[str], pr_body: str) -> None: + hetero_changed = any(path.startswith("source/") and is_heterogeneous_path(path) for path in changed) + if not hetero_changed: + return + if any(path_is_test(path) for path in changed) or pr_test_section_has_evidence(pr_body): + return + add_finding( + findings, + "Heterogeneous test evidence review", + WARN, + "pull_request.body", + None, + "Heterogeneous source changed without test path changes or PR test evidence.", + "Add backend-specific test evidence or explain why existing coverage is sufficient.", + ) + + +def check_documentation_warning(findings: List[Finding], changed: Sequence[str], pr_body: str) -> None: + code_changed = source_code_changed(changed) + docs_changed = any(path.startswith("docs/") for path in changed) + if code_changed and not docs_changed and "no documentation update required" not in pr_body.lower(): + add_finding( + findings, + "Documentation sync review", + WARN, + "pull_request.body", + None, + "Source changes have no docs change or explicit no-docs-needed statement.", + "Add documentation updates for behavior/interface changes, or state why documentation is not required.", + ) + + +def collect_findings(root: Path, args: argparse.Namespace) -> List[Finding]: + findings: List[Finding] = [] + statuses, changed = changed_paths(root, args) + lines = added_lines(root, args) + body = read_pr_body(args.event_path) + + check_line_endings(findings, root, changed, statuses, args) + check_global_dependencies(findings, lines) + check_default_parameters(findings, lines) + check_hpp_warnings(findings, statuses, lines) + check_header_include_warnings(findings, lines) + check_cmake_linkage(findings, statuses, changed) + check_input_parameter_docs(findings, changed, statuses, lines, body) + check_pr_metadata(findings, body) + check_test_evidence_warning(findings, changed, body) + check_heterogeneous_test_warning(findings, changed, body) + check_documentation_warning(findings, changed, body) + return findings + + +def finding_location(finding: Finding) -> str: + if finding.line is None: + return finding.path + return f"{finding.path}:{finding.line}" + + +def render_text(findings: Sequence[Finding]) -> str: + if not findings: + return "Agent governance check: no findings.\n" + chunks = ["Agent governance check findings:"] + for finding in findings: + chunks.append( + f"- [{finding.severity.upper()}] {finding.rule} at {finding_location(finding)}\n" + f" Reason: {finding.reason}\n" + f" Suggested action: {finding.suggestion}\n" + f" Exception allowed: {'yes' if finding.allow_exception else 'no'}" + ) + return "\n".join(chunks) + "\n" + + +def render_markdown(findings: Sequence[Finding]) -> str: + if not findings: + return "## Agent Governance Check\n\nNo findings.\n" + lines = [ + "## Agent Governance Check", + "", + "| Severity | Rule | Location | Reason | Suggested action | Exception |", + "| --- | --- | --- | --- | --- | --- |", + ] + for finding in findings: + lines.append( + "| {severity} | {rule} | `{location}` | {reason} | {suggestion} | {exception} |".format( + severity=finding.severity, + rule=finding.rule, + location=finding_location(finding), + reason=finding.reason.replace("|", "\\|"), + suggestion=finding.suggestion.replace("|", "\\|"), + exception="allowed" if finding.allow_exception else "not allowed", + ) + ) + return "\n".join(lines) + "\n" + + +def render_json(findings: Sequence[Finding]) -> str: + return json.dumps([asdict(finding) for finding in findings], indent=2, ensure_ascii=False) + "\n" + + +def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + diff_group = parser.add_mutually_exclusive_group() + diff_group.add_argument("--staged", action="store_true", help="Check staged changes.") + parser.add_argument("--base", help="Base commit for diff checks.") + parser.add_argument("--head", help="Head commit for diff checks.") + parser.add_argument("--event-path", help="GitHub event JSON path for PR body checks.") + parser.add_argument( + "--format", + choices=("text", "markdown", "json"), + default="text", + help="Output format.", + ) + args = parser.parse_args(argv) + if bool(args.base) ^ bool(args.head): + parser.error("--base and --head must be provided together") + return args + + +def main(argv: Optional[Sequence[str]] = None) -> int: + args = parse_args(argv) + root = repo_root() + try: + findings = collect_findings(root, args) + except GitError as exc: + print(f"agent_governance_check.py: {exc}", file=sys.stderr) + return 2 + + if args.format == "markdown": + sys.stdout.write(render_markdown(findings)) + elif args.format == "json": + sys.stdout.write(render_json(findings)) + else: + sys.stdout.write(render_text(findings)) + + return 1 if any(finding.severity == BLOCK for finding in findings) else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/03_code_analysis/test_agent_governance_check.py b/tools/03_code_analysis/test_agent_governance_check.py new file mode 100644 index 00000000000..1dcf41c3961 --- /dev/null +++ b/tools/03_code_analysis/test_agent_governance_check.py @@ -0,0 +1,508 @@ +import json +import os +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +CHECKER = REPO_ROOT / "tools" / "03_code_analysis" / "agent_governance_check.py" + + +class AgentGovernanceCheckTest(unittest.TestCase): + def setUp(self): + self.tmp = tempfile.TemporaryDirectory() + self.repo = Path(self.tmp.name) + self.git("init") + self.git("config", "user.email", "agent-governance@example.com") + self.git("config", "user.name", "Agent Governance Test") + self.write("README.md", "baseline\n") + self.write( + "source/source_io/module_parameter/read_input_item_model.cpp", + 'Input_Item item("old_switch");\n', + ) + self.git("add", ".") + self.git("commit", "-m", "baseline") + self.base = self.git("rev-parse", "HEAD").stdout.strip() + + def tearDown(self): + self.tmp.cleanup() + + def git(self, *args): + return subprocess.run( + ["git", *args], + cwd=self.repo, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=True, + ) + + def write(self, path, content, mode="w"): + target = self.repo / path + target.parent.mkdir(parents=True, exist_ok=True) + with open(target, mode) as handle: + handle.write(content) + + def commit_change(self): + self.git("add", ".") + self.git("commit", "-m", "change") + return self.git("rev-parse", "HEAD").stdout.strip() + + def run_checker(self, *args): + return subprocess.run( + [sys.executable, str(CHECKER), *args], + cwd=self.repo, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + def assert_blocked_by(self, result, rule): + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn(rule, result.stdout) + + def assert_warns_with_success(self, result, rule): + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn(rule, result.stdout) + + def test_detects_crlf_in_changed_text_file(self): + self.write("source/source_base/crlf.cpp", b"int x = 1;\r\n", mode="wb") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "LF line endings") + + def test_allows_crlf_in_windows_scripts(self): + self.write("tools/install.bat", b"echo ok\r\n", mode="wb") + self.write("tools/install.cmd", b"echo ok\r\n", mode="wb") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_blocks_new_global_dependencies_on_added_lines(self): + self.write("source/source_base/global.cpp", "int n = GlobalV::NPROC + PARAM.inp.nbands;\n") + self.write("source/source_base/CMakeLists.txt", "add_library(global global.cpp)\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "No new cross-layer globals") + + def test_allows_global_names_in_documentation(self): + self.write("docs/governance-notes.md", "Mention GlobalV::NPROC and PARAM.inp in documentation.\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_allows_global_names_in_governance_checker_tests(self): + self.write("tools/03_code_analysis/checker_fixture.py", 'pattern = "GlobalV::NPROC and PARAM.inp"\n') + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_blocks_default_parameters_added_to_headers(self): + self.write("source/source_base/defaults.h", "void update_solver(int step = 0);\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "No new default parameters") + + def test_allows_for_loop_initializer_in_header(self): + self.write( + "source/source_base/loop_header.h", + "inline int sum(int n) {\n" + " int total = 0;\n" + " for (int i = 0; i < n; ++i) {\n" + " total += i;\n" + " }\n" + " return total;\n" + "}\n", + ) + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertNotIn("No new default parameters", result.stdout) + + def test_warns_but_does_not_block_for_new_hpp_files(self): + self.write("source/source_base/detail.hpp", "inline int value() { return 1; }\n") + self.write("source/source_base/CMakeLists.txt", "# listed elsewhere\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("Avoid new .hpp propagation", result.stdout) + + def test_blocks_new_source_file_without_cmake_linkage(self): + self.write("source/source_base/new_feature.cpp", "int new_feature() { return 1; }\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "CMake linkage for new sources") + + def test_blocks_input_parameter_changes_without_docs_linkage(self): + self.write( + "source/source_io/module_parameter/read_input_item_model.cpp", + 'Input_Item item("new_switch");\nitem.default_value = "0";\n', + ) + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "INPUT parameter documentation linkage") + + def test_allows_parameter_file_comment_only_change_without_docs(self): + self.write( + "source/source_io/module_parameter/read_input_item_model.cpp", + 'Input_Item item("old_switch");\n// Keep legacy input switch documented nearby.\n', + ) + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_allows_input_item_test_fixture_without_docs(self): + self.write("tools/03_code_analysis/input_fixture.py", 'fixture = "Input_Item item(\\"old_switch\\");"\n') + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_allows_input_parameter_changes_with_required_docs(self): + self.write( + "source/source_io/module_parameter/read_input_item_model.cpp", + 'Input_Item item("new_switch");\nitem.default_value = "0";\n', + ) + self.write("docs/parameters.yaml", "parameters: []\n") + self.write("docs/advanced/input_files/input-main.md", "# INPUT\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_blocks_input_parameter_change_when_required_docs_are_deleted(self): + self.write("docs/parameters.yaml", "parameters: []\n") + self.write("docs/advanced/input_files/input-main.md", "# INPUT\n") + self.git("add", ".") + self.git("commit", "-m", "add input docs") + base = self.git("rev-parse", "HEAD").stdout.strip() + self.write( + "source/source_io/module_parameter/read_input_item_model.cpp", + 'Input_Item item("new_switch");\nitem.default_value = "0";\n', + ) + (self.repo / "docs" / "parameters.yaml").unlink() + (self.repo / "docs" / "advanced" / "input_files" / "input-main.md").unlink() + head = self.commit_change() + + result = self.run_checker("--base", base, "--head", head) + + self.assert_blocked_by(result, "INPUT parameter documentation linkage") + + def test_blocks_unfilled_pr_template_fields_from_event_payload(self): + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nFix #...\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "- A unit test is added for each new feature or bug fix.\n" + } + } + ) + ) + + result = self.run_checker("--event-path", str(event)) + + self.assert_blocked_by(result, "PR metadata completeness") + + def test_accepts_filled_pr_template_fields_from_event_payload(self): + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue; governance bootstrap.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "Ran python3 -m unittest tools/03_code_analysis/test_agent_governance_check.py.\n\n" + "### What's changed?\n" + "Adds governance checks only; no runtime behavior change.\n\n" + "### Governance Checklist\n" + "Line endings, CMake linkage, and docs rules reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "No core module impact.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--event-path", str(event)) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_warns_for_source_change_without_test_evidence(self): + self.write("source/source_base/new_feature.cpp", "int new_feature() { return 1; }\n") + self.write("source/source_base/CMakeLists.txt", "add_library(new_feature new_feature.cpp)\n") + head = self.commit_change() + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "Not filled yet.\n\n" + "### What's changed?\n" + "Adds a source file.\n\n" + "### Governance Checklist\n" + "Reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "source/source_base helper only.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--base", self.base, "--head", head, "--event-path", str(event)) + + self.assert_warns_with_success(result, "Test evidence review") + + def test_warns_when_pr_says_no_tests_were_run(self): + self.write("source/source_base/new_feature.cpp", "int new_feature() { return 1; }\n") + self.write("source/source_base/CMakeLists.txt", "add_library(new_feature new_feature.cpp)\n") + head = self.commit_change() + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "No tests were run.\n\n" + "### What's changed?\n" + "Adds a source file.\n\n" + "### Governance Checklist\n" + "Reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "source/source_base helper only.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--base", self.base, "--head", head, "--event-path", str(event)) + + self.assert_warns_with_success(result, "Test evidence review") + + def test_warns_when_pr_says_no_tests_added_yet(self): + self.write("source/source_base/new_feature.cpp", "int new_feature() { return 1; }\n") + self.write("source/source_base/CMakeLists.txt", "add_library(new_feature new_feature.cpp)\n") + head = self.commit_change() + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "No tests added yet.\n\n" + "### What's changed?\n" + "Adds a source file.\n\n" + "### Governance Checklist\n" + "Reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "source/source_base helper only.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--base", self.base, "--head", head, "--event-path", str(event)) + + self.assert_warns_with_success(result, "Test evidence review") + + def test_accepts_explicit_no_test_rationale(self): + self.write("source/source_base/new_feature.cpp", "int new_feature() { return 1; }\n") + self.write("source/source_base/CMakeLists.txt", "add_library(new_feature new_feature.cpp)\n") + head = self.commit_change() + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "Tests not required because documentation only.\n\n" + "### What's changed?\n" + "Adds a source file.\n\n" + "### Governance Checklist\n" + "Reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "source/source_base helper only.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--base", self.base, "--head", head, "--event-path", str(event)) + + self.assertNotIn("Test evidence review", result.stdout) + + def test_warns_for_source_change_without_docs_or_no_docs_reason(self): + self.write("source/source_base/new_feature.cpp", "int new_feature() { return 1; }\n") + self.write("source/source_base/CMakeLists.txt", "add_library(new_feature new_feature.cpp)\n") + head = self.commit_change() + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "Ran focused unit tests.\n\n" + "### What's changed?\n" + "Adds a source file.\n\n" + "### Governance Checklist\n" + "Reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "source/source_base helper only.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--base", self.base, "--head", head, "--event-path", str(event)) + + self.assert_warns_with_success(result, "Documentation sync review") + + def test_warns_for_source_header_change_without_test_evidence(self): + self.write("source/source_base/api.h", "void api();\n") + self.git("add", ".") + self.git("commit", "-m", "add header") + base = self.git("rev-parse", "HEAD").stdout.strip() + self.write("source/source_base/api.h", "#include \nvoid api();\n") + head = self.commit_change() + + result = self.run_checker("--base", base, "--head", head) + + self.assert_warns_with_success(result, "Test evidence review") + + def test_warns_for_source_header_change_without_docs_or_no_docs_reason(self): + self.write("source/source_base/api.h", "void api();\n") + self.git("add", ".") + self.git("commit", "-m", "add header") + base = self.git("rev-parse", "HEAD").stdout.strip() + self.write("source/source_base/api.h", "#include \nvoid api();\n") + head = self.commit_change() + event = self.repo / "event.json" + event.write_text( + json.dumps( + { + "pull_request": { + "body": "### Linked Issue\nNo issue.\n\n" + "### Unit Tests and/or Case Tests for my changes\n" + "Ran focused unit tests.\n\n" + "### What's changed?\n" + "Updates a source header.\n\n" + "### Governance Checklist\n" + "Reviewed.\n\n" + "### INPUT Parameter Changes\n" + "No INPUT parameter changes.\n\n" + "### Core Module Impact\n" + "source/source_base API only.\n\n" + "### Governance Exception\n" + "No exceptions requested.\n" + } + } + ) + ) + + result = self.run_checker("--base", base, "--head", head, "--event-path", str(event)) + + self.assert_warns_with_success(result, "Documentation sync review") + + def test_warns_for_new_header_include(self): + self.write("source/source_base/include_growth.h", "#include \nclass IncludeGrowth {};\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_warns_with_success(result, "Header dependency review") + + def test_blocks_new_heterogeneous_file_without_cmake_linkage(self): + self.write("source/module_hamilt/kernels/new_kernel.cu", "__global__ void k() {}\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "CMake linkage for heterogeneous sources") + + def test_blocks_new_cuh_file_without_cmake_linkage(self): + self.write("source/module_hamilt/kernels/new_kernel.cuh", "__device__ int k();\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_blocked_by(result, "CMake linkage for heterogeneous sources") + + def test_warns_for_heterogeneous_file_without_test_evidence(self): + self.write("source/module_hamilt/kernels/new_kernel.cu", "__global__ void k() {}\n") + self.write("source/module_hamilt/CMakeLists.txt", "add_library(new_kernel kernels/new_kernel.cu)\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assert_warns_with_success(result, "Heterogeneous test evidence review") + + def test_staged_mode_checks_index_content(self): + self.write("source/source_base/staged.cpp", "int n = GlobalC::ucell.nat;\n") + self.write("source/source_base/CMakeLists.txt", "add_library(staged staged.cpp)\n") + self.git("add", ".") + + result = self.run_checker("--staged") + + self.assert_blocked_by(result, "No new cross-layer globals") + + +if __name__ == "__main__": + unittest.main() From c0dc966e063cb8f6e4550d808a407f9a0a77c0fe Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 18:40:48 +0800 Subject: [PATCH 05/13] Document agent governance review fixes --- ...21-agent-governance-review-fixes-design.md | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md diff --git a/docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md b/docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md new file mode 100644 index 00000000000..6962a071982 --- /dev/null +++ b/docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md @@ -0,0 +1,144 @@ +# Agent Governance Review Fixes Design + +## Context + +The governance checker added in `tools/03_code_analysis/agent_governance_check.py` +is intended to block deterministic issues only on changed files or diff-added +lines. Three review findings were verified locally: + +- CRLF-only normalization diffs are treated as semantic added lines by + `git diff -U0`, so historical default arguments and global dependencies can + be reported as new changes. +- A pull request event with an empty `pull_request.body` is treated the same as + no pull request event, so required PR metadata can be skipped. +- The GitHub Actions workflow passes the PR base tip directly as `--base`. + After the target branch advances, that two-dot comparison no longer matches + the merge-base-to-head PR diff that GitHub presents. + +## Goals + +- Keep semantic governance rules scoped to meaningful diff-added lines. +- Keep full changed-file LF enforcement intact, including detection of CRLF in + the target file content. +- Treat an empty PR description in a PR event as incomplete metadata. +- Scope CI governance checks to the PR merge base and head commit. +- Add focused regression tests for each verified failure mode. + +## Non-Goals + +- Do not redesign the checker CLI or change the meaning of `--base` and + `--head`. +- Do not convert warning-only governance rules into blockers. +- Do not change the PR template or governance policy text beyond what is needed + to align implementation behavior with the existing policy. + +## Recommended Approach + +Use the minimal complete fix: + +1. Make `added_lines()` use a CR-at-EOL-insensitive diff: + - For staged mode, run `git diff --cached --ignore-cr-at-eol -U0`. + - For base/head mode, run `git diff --ignore-cr-at-eol -U0 `. +2. Leave `changed_paths()` and `check_line_endings()` unchanged so changed-file + discovery and byte-level LF enforcement still see files whose content changed + only by line endings. +3. Make PR body reading distinguish these cases: + - No `--event-path`: skip PR metadata completeness, because local/staged runs + do not have PR metadata. + - Invalid or non-PR event payload: skip PR metadata completeness. + - PR event with `body: ""` or `body: null`: run metadata completeness and + block as incomplete. +4. In `.github/workflows/agent_governance.yml`, compute + `merge_base=$(git merge-base "$base_sha" "$head_sha")` after checkout and pass + that value as `--base`. + +This keeps responsibilities simple: the workflow chooses the correct comparison +range for PR CI, while the checker continues to compare two explicit commits. + +## Component Changes + +### Semantic Diff Collection + +`added_lines()` is the only source of diff-added lines for semantic rules such +as no new globals, no new default parameters, `.hpp` propagation, header include +growth, and INPUT behavior checks. Adding `--ignore-cr-at-eol` there prevents +line-ending normalization from fabricating added semantic lines. + +The separate changed-file path list remains based on regular `git diff +--name-status`. This is important because line-ending-only changes still need to +be included in the full-file LF check. + +### PR Metadata Reading + +Introduce a small internal distinction between "metadata unavailable" and +"metadata available but empty". A simple option is to let `read_pr_body()` return +`Optional[str]`, where `None` means no PR metadata is available and `""` means +the PR body is blank. + +`check_pr_metadata()` should skip only when the body is `None`. For an empty +string, it should report all required sections as missing, using the existing +`PR metadata completeness` finding and `allow_exception=False`. + +Other PR-body consumers should handle `None` as an empty string for warning +logic, because test evidence and documentation evidence cannot be inferred when +metadata is unavailable. + +### Workflow Diff Base + +The workflow already uses `actions/checkout@v4` with `fetch-depth: 0`, so the +merge base can be computed locally: + +```bash +base_sha="${{ github.event.pull_request.base.sha }}" +head_sha="${{ github.event.pull_request.head.sha }}" +merge_base="$(git merge-base "$base_sha" "$head_sha")" +python3 tools/03_code_analysis/agent_governance_check.py \ + --base "$merge_base" \ + --head "$head_sha" \ + --event-path "$GITHUB_EVENT_PATH" \ + --format markdown +``` + +If `git merge-base` fails, the workflow should naturally fail before publishing +a misleading clean governance result. The existing summary fallback can still +report that the checker failed before producing a summary. + +## Error Handling + +- Git command failures inside the checker should continue to surface through + `GitError` and exit code 2. +- Invalid JSON or non-PR event payloads should not block local or accidental + non-PR invocations. +- Blank PR bodies in valid PR payloads should block with the existing metadata + completeness rule. + +## Tests + +Add focused tests to `tools/03_code_analysis/test_agent_governance_check.py`: + +- A CRLF-to-LF-only change in a header containing a historical default argument + should not trigger `No new default parameters`. +- A valid PR event with `pull_request.body` set to an empty string should trigger + `PR metadata completeness` and return non-zero. +- A merge-base-scoped comparison in a diverged history should not include + base-branch-only changes, while the existing two-dot base-tip comparison would + demonstrate the risk. + +Existing tests for CRLF detection in changed text files must continue to pass. + +## Verification + +After implementation, run: + +```bash +python3 -m unittest tools/03_code_analysis/test_agent_governance_check.py +python3 tools/03_code_analysis/agent_governance_check.py --staged +``` + +If dependencies are available, also run: + +```bash +pre-commit run abacus-agent-governance --all-files +``` + +Report exact command output or failure details before claiming completion. From 8e0690ee39f6c10a835715805046a89e2949b421 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 19:21:31 +0800 Subject: [PATCH 06/13] fix: tighten agent governance diff scope --- .github/workflows/agent_governance.yml | 16 ++++- .../agent_governance_check.py | 29 ++++---- .../test_agent_governance_check.py | 72 +++++++++++++++++++ 3 files changed, 103 insertions(+), 14 deletions(-) diff --git a/.github/workflows/agent_governance.yml b/.github/workflows/agent_governance.yml index 980519814a8..2dc36d49f4c 100644 --- a/.github/workflows/agent_governance.yml +++ b/.github/workflows/agent_governance.yml @@ -22,9 +22,21 @@ jobs: id: governance run: | set +e + base_sha="${{ github.event.pull_request.base.sha }}" + head_sha="${{ github.event.pull_request.head.sha }}" + merge_base="$(git merge-base "$base_sha" "$head_sha")" + merge_base_status=$? + if [ "$merge_base_status" -ne 0 ]; then + { + echo "## Agent Governance Check" + echo + echo "Failed to compute the pull request merge base." + } > agent_governance_summary.md + exit "$merge_base_status" + fi python3 tools/03_code_analysis/agent_governance_check.py \ - --base "${{ github.event.pull_request.base.sha }}" \ - --head "${{ github.event.pull_request.head.sha }}" \ + --base "$merge_base" \ + --head "$head_sha" \ --event-path "$GITHUB_EVENT_PATH" \ --format markdown | tee agent_governance_summary.md status=${PIPESTATUS[0]} diff --git a/tools/03_code_analysis/agent_governance_check.py b/tools/03_code_analysis/agent_governance_check.py index e6e2ac838de..960dc47b00c 100644 --- a/tools/03_code_analysis/agent_governance_check.py +++ b/tools/03_code_analysis/agent_governance_check.py @@ -150,9 +150,9 @@ def parse_added_lines(diff_text: str) -> List[DiffLine]: def added_lines(root: Path, args: argparse.Namespace) -> List[DiffLine]: if args.staged: - output = git(["diff", "--cached", "-U0"], root).stdout + output = git(["diff", "--cached", "--ignore-cr-at-eol", "-U0"], root).stdout elif args.base and args.head: - output = git(["diff", "-U0", args.base, args.head], root).stdout + output = git(["diff", "--ignore-cr-at-eol", "-U0", args.base, args.head], root).stdout else: output = "" return parse_added_lines(output) @@ -436,16 +436,20 @@ def check_input_parameter_docs( ) -def read_pr_body(event_path: Optional[str]) -> str: +def read_pr_body(event_path: Optional[str]) -> Optional[str]: if not event_path: - return "" + return None try: with open(event_path, "r", encoding="utf-8") as handle: payload = json.load(handle) except (OSError, json.JSONDecodeError): + return None + if "pull_request" not in payload or not isinstance(payload["pull_request"], dict): + return None + body = payload["pull_request"].get("body") + if body is None: return "" - pr = payload.get("pull_request") or {} - return pr.get("body") or "" + return str(body) def pr_sections(body: str) -> Dict[str, str]: @@ -482,8 +486,8 @@ def section_is_placeholder(content: str) -> bool: return not meaningful -def check_pr_metadata(findings: List[Finding], body: str) -> None: - if not body: +def check_pr_metadata(findings: List[Finding], body: Optional[str]) -> None: + if body is None: return required_sections = [ "Linked Issue", @@ -615,6 +619,7 @@ def collect_findings(root: Path, args: argparse.Namespace) -> List[Finding]: statuses, changed = changed_paths(root, args) lines = added_lines(root, args) body = read_pr_body(args.event_path) + body_text = body or "" check_line_endings(findings, root, changed, statuses, args) check_global_dependencies(findings, lines) @@ -622,11 +627,11 @@ def collect_findings(root: Path, args: argparse.Namespace) -> List[Finding]: check_hpp_warnings(findings, statuses, lines) check_header_include_warnings(findings, lines) check_cmake_linkage(findings, statuses, changed) - check_input_parameter_docs(findings, changed, statuses, lines, body) + check_input_parameter_docs(findings, changed, statuses, lines, body_text) check_pr_metadata(findings, body) - check_test_evidence_warning(findings, changed, body) - check_heterogeneous_test_warning(findings, changed, body) - check_documentation_warning(findings, changed, body) + check_test_evidence_warning(findings, changed, body_text) + check_heterogeneous_test_warning(findings, changed, body_text) + check_documentation_warning(findings, changed, body_text) return findings diff --git a/tools/03_code_analysis/test_agent_governance_check.py b/tools/03_code_analysis/test_agent_governance_check.py index 1dcf41c3961..b7645767053 100644 --- a/tools/03_code_analysis/test_agent_governance_check.py +++ b/tools/03_code_analysis/test_agent_governance_check.py @@ -118,6 +118,31 @@ def test_blocks_default_parameters_added_to_headers(self): self.assert_blocked_by(result, "No new default parameters") + def test_ignores_crlf_to_lf_only_changes_for_semantic_added_lines(self): + self.write("source/source_base/defaults.h", b"void update_solver(int step = 0);\r\n", mode="wb") + self.git("add", ".") + self.git("commit", "-m", "add crlf header") + base = self.git("rev-parse", "HEAD").stdout.strip() + self.write("source/source_base/defaults.h", "void update_solver(int step = 0);\n") + head = self.commit_change() + + result = self.run_checker("--base", base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("No new default parameters", result.stdout) + + def test_staged_mode_ignores_crlf_to_lf_only_semantic_added_lines(self): + self.write("source/source_base/defaults.h", b"void update_solver(int step = 0);\r\n", mode="wb") + self.git("add", ".") + self.git("commit", "-m", "add crlf header") + self.write("source/source_base/defaults.h", "void update_solver(int step = 0);\n") + self.git("add", ".") + + result = self.run_checker("--staged") + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("No new default parameters", result.stdout) + def test_allows_for_loop_initializer_in_header(self): self.write( "source/source_base/loop_header.h", @@ -232,6 +257,33 @@ def test_blocks_unfilled_pr_template_fields_from_event_payload(self): self.assert_blocked_by(result, "PR metadata completeness") + def test_blocks_empty_pr_template_from_event_payload(self): + for body in ("", None): + with self.subTest(body=body): + event = self.repo / "event.json" + event.write_text(json.dumps({"pull_request": {"body": body}})) + + result = self.run_checker("--event-path", str(event)) + + self.assert_blocked_by(result, "PR metadata completeness") + + def test_blocks_missing_pr_body_from_event_payload(self): + event = self.repo / "event.json" + event.write_text(json.dumps({"pull_request": {}})) + + result = self.run_checker("--event-path", str(event)) + + self.assert_blocked_by(result, "PR metadata completeness") + + def test_skips_pr_metadata_when_event_payload_is_not_a_pull_request(self): + event = self.repo / "event.json" + event.write_text(json.dumps({"workflow_run": {"name": "Agent Governance"}})) + + result = self.run_checker("--event-path", str(event)) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertNotIn("PR metadata completeness", result.stdout) + def test_accepts_filled_pr_template_fields_from_event_payload(self): event = self.repo / "event.json" event.write_text( @@ -469,6 +521,26 @@ def test_warns_for_new_header_include(self): self.assert_warns_with_success(result, "Header dependency review") + def test_merge_base_scoped_comparison_excludes_base_branch_only_changes(self): + self.write("source/source_base/api.h", "void update_solver(int step = 0);\n") + self.git("add", ".") + self.git("commit", "-m", "add legacy default") + base_branch = self.git("branch", "--show-current").stdout.strip() + merge_base = self.git("rev-parse", "HEAD").stdout.strip() + self.git("checkout", "-b", "feature") + self.write("docs/feature.md", "feature docs\n") + head = self.commit_change() + self.git("checkout", base_branch) + self.write("source/source_base/api.h", "void update_solver(int step);\n") + base_tip = self.commit_change() + + base_tip_result = self.run_checker("--base", base_tip, "--head", head) + merge_base_result = self.run_checker("--base", merge_base, "--head", head) + + self.assertIn("No new default parameters", base_tip_result.stdout) + self.assertNotIn("No new default parameters", merge_base_result.stdout) + self.assertEqual(merge_base_result.returncode, 0, merge_base_result.stdout + merge_base_result.stderr) + def test_blocks_new_heterogeneous_file_without_cmake_linkage(self): self.write("source/module_hamilt/kernels/new_kernel.cu", "__global__ void k() {}\n") head = self.commit_change() From ca223793e6c52cb004e4b7f4778dfc56be25cad9 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Sun, 21 Jun 2026 23:55:52 +0800 Subject: [PATCH 07/13] remove useless plan file --- ...21-agent-governance-review-fixes-design.md | 144 ------------------ 1 file changed, 144 deletions(-) delete mode 100644 docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md diff --git a/docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md b/docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md deleted file mode 100644 index 6962a071982..00000000000 --- a/docs/superpowers/specs/2026-06-21-agent-governance-review-fixes-design.md +++ /dev/null @@ -1,144 +0,0 @@ -# Agent Governance Review Fixes Design - -## Context - -The governance checker added in `tools/03_code_analysis/agent_governance_check.py` -is intended to block deterministic issues only on changed files or diff-added -lines. Three review findings were verified locally: - -- CRLF-only normalization diffs are treated as semantic added lines by - `git diff -U0`, so historical default arguments and global dependencies can - be reported as new changes. -- A pull request event with an empty `pull_request.body` is treated the same as - no pull request event, so required PR metadata can be skipped. -- The GitHub Actions workflow passes the PR base tip directly as `--base`. - After the target branch advances, that two-dot comparison no longer matches - the merge-base-to-head PR diff that GitHub presents. - -## Goals - -- Keep semantic governance rules scoped to meaningful diff-added lines. -- Keep full changed-file LF enforcement intact, including detection of CRLF in - the target file content. -- Treat an empty PR description in a PR event as incomplete metadata. -- Scope CI governance checks to the PR merge base and head commit. -- Add focused regression tests for each verified failure mode. - -## Non-Goals - -- Do not redesign the checker CLI or change the meaning of `--base` and - `--head`. -- Do not convert warning-only governance rules into blockers. -- Do not change the PR template or governance policy text beyond what is needed - to align implementation behavior with the existing policy. - -## Recommended Approach - -Use the minimal complete fix: - -1. Make `added_lines()` use a CR-at-EOL-insensitive diff: - - For staged mode, run `git diff --cached --ignore-cr-at-eol -U0`. - - For base/head mode, run `git diff --ignore-cr-at-eol -U0 `. -2. Leave `changed_paths()` and `check_line_endings()` unchanged so changed-file - discovery and byte-level LF enforcement still see files whose content changed - only by line endings. -3. Make PR body reading distinguish these cases: - - No `--event-path`: skip PR metadata completeness, because local/staged runs - do not have PR metadata. - - Invalid or non-PR event payload: skip PR metadata completeness. - - PR event with `body: ""` or `body: null`: run metadata completeness and - block as incomplete. -4. In `.github/workflows/agent_governance.yml`, compute - `merge_base=$(git merge-base "$base_sha" "$head_sha")` after checkout and pass - that value as `--base`. - -This keeps responsibilities simple: the workflow chooses the correct comparison -range for PR CI, while the checker continues to compare two explicit commits. - -## Component Changes - -### Semantic Diff Collection - -`added_lines()` is the only source of diff-added lines for semantic rules such -as no new globals, no new default parameters, `.hpp` propagation, header include -growth, and INPUT behavior checks. Adding `--ignore-cr-at-eol` there prevents -line-ending normalization from fabricating added semantic lines. - -The separate changed-file path list remains based on regular `git diff ---name-status`. This is important because line-ending-only changes still need to -be included in the full-file LF check. - -### PR Metadata Reading - -Introduce a small internal distinction between "metadata unavailable" and -"metadata available but empty". A simple option is to let `read_pr_body()` return -`Optional[str]`, where `None` means no PR metadata is available and `""` means -the PR body is blank. - -`check_pr_metadata()` should skip only when the body is `None`. For an empty -string, it should report all required sections as missing, using the existing -`PR metadata completeness` finding and `allow_exception=False`. - -Other PR-body consumers should handle `None` as an empty string for warning -logic, because test evidence and documentation evidence cannot be inferred when -metadata is unavailable. - -### Workflow Diff Base - -The workflow already uses `actions/checkout@v4` with `fetch-depth: 0`, so the -merge base can be computed locally: - -```bash -base_sha="${{ github.event.pull_request.base.sha }}" -head_sha="${{ github.event.pull_request.head.sha }}" -merge_base="$(git merge-base "$base_sha" "$head_sha")" -python3 tools/03_code_analysis/agent_governance_check.py \ - --base "$merge_base" \ - --head "$head_sha" \ - --event-path "$GITHUB_EVENT_PATH" \ - --format markdown -``` - -If `git merge-base` fails, the workflow should naturally fail before publishing -a misleading clean governance result. The existing summary fallback can still -report that the checker failed before producing a summary. - -## Error Handling - -- Git command failures inside the checker should continue to surface through - `GitError` and exit code 2. -- Invalid JSON or non-PR event payloads should not block local or accidental - non-PR invocations. -- Blank PR bodies in valid PR payloads should block with the existing metadata - completeness rule. - -## Tests - -Add focused tests to `tools/03_code_analysis/test_agent_governance_check.py`: - -- A CRLF-to-LF-only change in a header containing a historical default argument - should not trigger `No new default parameters`. -- A valid PR event with `pull_request.body` set to an empty string should trigger - `PR metadata completeness` and return non-zero. -- A merge-base-scoped comparison in a diverged history should not include - base-branch-only changes, while the existing two-dot base-tip comparison would - demonstrate the risk. - -Existing tests for CRLF detection in changed text files must continue to pass. - -## Verification - -After implementation, run: - -```bash -python3 -m unittest tools/03_code_analysis/test_agent_governance_check.py -python3 tools/03_code_analysis/agent_governance_check.py --staged -``` - -If dependencies are available, also run: - -```bash -pre-commit run abacus-agent-governance --all-files -``` - -Report exact command output or failure details before claiming completion. From 5e20c31747f06ad9b991de41aa9c8655e9ef6089 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Mon, 22 Jun 2026 00:12:15 +0800 Subject: [PATCH 08/13] fix: preserve LiRh integration input bytes --- tests/01_PW/074_PW_SY_LiRH/INPUT | 81 +++++++++++++++----------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/tests/01_PW/074_PW_SY_LiRH/INPUT b/tests/01_PW/074_PW_SY_LiRH/INPUT index 02c121865e8..241b9d09ec7 100644 --- a/tests/01_PW/074_PW_SY_LiRH/INPUT +++ b/tests/01_PW/074_PW_SY_LiRH/INPUT @@ -1,45 +1,38 @@ -INPUT_PARAMETERS - -#Parameters (1.General) -suffix autotest -calculation scf -pseudo_dir ../../PP_ORB - - -#ntype 1 -symmetry 1 -dft_functional pbe -#vdw_method d3_bj - - -#Parameters (2.Iteration) -ecutwfc 20 -scf_thr 1e-10 -scf_nmax 128 - - -cal_force 1 -cal_stress 1 - - -#Parameters (3.Basis) -basis_type pw -#Parameters (4.Smearing) -smearing_method mp -smearing_sigma 0.010 - - -#Parameters (5.Mixing) -mixing_type pulay -mixing_beta 0.2 -# kspacing 0.05 -mixing_gg0 1.5 -ks_solver dav - - -#relaxation (6.cell_relax) -force_thr_ev 0.01 -stress_thr 2 -relax_nmax 32 -out_stru 1 +INPUT_PARAMETERS +#Parameters (1.General) +suffix autotest +calculation scf +pseudo_dir ../../PP_ORB + +#ntype 1 +symmetry 1 +dft_functional pbe +#vdw_method d3_bj + +#Parameters (2.Iteration) +ecutwfc 20 +scf_thr 1e-10 +scf_nmax 128 + +cal_force 1 +cal_stress 1 + +#Parameters (3.Basis) +basis_type pw +#Parameters (4.Smearing) +smearing_method mp +smearing_sigma 0.010 + +#Parameters (5.Mixing) +mixing_type pulay +mixing_beta 0.2 +# kspacing 0.05 +mixing_gg0 1.5 +ks_solver dav + +#relaxation (6.cell_relax) +force_thr_ev 0.01 +stress_thr 2 +relax_nmax 32 +out_stru 1 symmetry_prec 1e-5 From 76de6f780f6a29d12ecd1b67914ced344bc341c6 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Mon, 22 Jun 2026 00:33:55 +0800 Subject: [PATCH 09/13] test: normalize LiRh integration input --- tests/01_PW/074_PW_SY_LiRH/INPUT | 74 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/01_PW/074_PW_SY_LiRH/INPUT b/tests/01_PW/074_PW_SY_LiRH/INPUT index 241b9d09ec7..f2460cc707c 100644 --- a/tests/01_PW/074_PW_SY_LiRH/INPUT +++ b/tests/01_PW/074_PW_SY_LiRH/INPUT @@ -1,38 +1,38 @@ -INPUT_PARAMETERS -#Parameters (1.General) -suffix autotest -calculation scf -pseudo_dir ../../PP_ORB - -#ntype 1 -symmetry 1 -dft_functional pbe -#vdw_method d3_bj - -#Parameters (2.Iteration) -ecutwfc 20 -scf_thr 1e-10 -scf_nmax 128 - -cal_force 1 -cal_stress 1 - -#Parameters (3.Basis) -basis_type pw -#Parameters (4.Smearing) -smearing_method mp -smearing_sigma 0.010 - -#Parameters (5.Mixing) -mixing_type pulay -mixing_beta 0.2 -# kspacing 0.05 -mixing_gg0 1.5 -ks_solver dav - -#relaxation (6.cell_relax) -force_thr_ev 0.01 -stress_thr 2 -relax_nmax 32 -out_stru 1 +INPUT_PARAMETERS +#Parameters (1.General) +suffix autotest +calculation scf +pseudo_dir ../../PP_ORB + +#ntype 1 +symmetry 1 +dft_functional pbe +#vdw_method d3_bj + +#Parameters (2.Iteration) +ecutwfc 20 +scf_thr 1e-10 +scf_nmax 128 + +cal_force 1 +cal_stress 1 + +#Parameters (3.Basis) +basis_type pw +#Parameters (4.Smearing) +smearing_method mp +smearing_sigma 0.010 + +#Parameters (5.Mixing) +mixing_type pulay +mixing_beta 0.2 +# kspacing 0.05 +mixing_gg0 1.5 +ks_solver dav + +#relaxation (6.cell_relax) +force_thr_ev 0.01 +stress_thr 2 +relax_nmax 32 +out_stru 1 symmetry_prec 1e-5 From c5e0d42c6b3e901a35ccd76218eee19377b35954 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Mon, 22 Jun 2026 10:10:16 +0800 Subject: [PATCH 10/13] test: report integration fatal deviations --- tests/integrate/Autotest.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/integrate/Autotest.sh b/tests/integrate/Autotest.sh index 6dd4b5b382f..e1feb19c017 100755 --- a/tests/integrate/Autotest.sh +++ b/tests/integrate/Autotest.sh @@ -146,6 +146,7 @@ check_out(){ echo -e "\e[0;31m[ERROR ] Fatal Error: key $key not found in output.\e[0m" let fatal++ fatal_case_list+=$dir'\n' + fatal_detail_list+="$dir: key $key not found in output\n" break else compare_thr=$thr @@ -179,6 +180,7 @@ check_out(){ if [ $(check_deviation_pass $deviation $fatal_thr) = 0 ]; then ifatal=1 + fatal_detail_list+="$dir: $key cal=$cal ref=$ref deviation=$deviation\n" fi else echo -e "\e[0;32m[ OK ] \e[0m $key" @@ -239,6 +241,7 @@ failed_case_list=() ok=0 fatal=0 fatal_case_list=() +fatal_detail_list=() case_status=() # record if the test case passed or not fatal_threshold=1 report="" @@ -343,6 +346,8 @@ else then echo -e "\e[0;31m[ERROR ]\e[0m $fatal test cases out of $[ $failed + $ok ] produced fatal error." echo -e $fatal_case_list + echo -e "\e[0;31m[ERROR ]\e[0m Fatal deviation details:" + echo -e $fatal_detail_list fi exit 1 fi From 697e190e3c220080a8e42c6ed7d78b056c35a6a0 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Mon, 22 Jun 2026 13:31:54 +0800 Subject: [PATCH 11/13] test: disable force stress in LiRh symmetry case --- tests/01_PW/074_PW_SY_LiRH/INPUT | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/01_PW/074_PW_SY_LiRH/INPUT b/tests/01_PW/074_PW_SY_LiRH/INPUT index f2460cc707c..a3f71a6474f 100644 --- a/tests/01_PW/074_PW_SY_LiRH/INPUT +++ b/tests/01_PW/074_PW_SY_LiRH/INPUT @@ -14,9 +14,6 @@ ecutwfc 20 scf_thr 1e-10 scf_nmax 128 -cal_force 1 -cal_stress 1 - #Parameters (3.Basis) basis_type pw #Parameters (4.Smearing) From 0ae6faabcdeb2d4366ef40022df938b15dc9b9e4 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Mon, 22 Jun 2026 16:10:52 +0800 Subject: [PATCH 12/13] test: refresh LiRh symmetry reference --- tests/01_PW/074_PW_SY_LiRH/INPUT | 2 ++ tests/01_PW/074_PW_SY_LiRH/result.ref | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/01_PW/074_PW_SY_LiRH/INPUT b/tests/01_PW/074_PW_SY_LiRH/INPUT index a3f71a6474f..16ed12585c4 100644 --- a/tests/01_PW/074_PW_SY_LiRH/INPUT +++ b/tests/01_PW/074_PW_SY_LiRH/INPUT @@ -8,6 +8,8 @@ pseudo_dir ../../PP_ORB symmetry 1 dft_functional pbe #vdw_method d3_bj +cal_force 1 +cal_stress 1 #Parameters (2.Iteration) ecutwfc 20 diff --git a/tests/01_PW/074_PW_SY_LiRH/result.ref b/tests/01_PW/074_PW_SY_LiRH/result.ref index 2cc31e80bc8..547a2fdac0d 100644 --- a/tests/01_PW/074_PW_SY_LiRH/result.ref +++ b/tests/01_PW/074_PW_SY_LiRH/result.ref @@ -1,3 +1,8 @@ -etotref -9579.8929275948266877 -etotperatomref -2394.9732318987 -totaltimeref 4.35 +etotref -9579.8929275938553474 +etotperatomref -2394.9732318985 +totalforceref 2.833926 +totalstressref 26747.868435 +pointgroupref C_2v +spacegroupref C_2v +nksibzref 5 +totaltimeref 0.74 From d1bab43341c23ad2c931f8d01d87c963fa1e9251 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Mon, 22 Jun 2026 23:32:21 +0800 Subject: [PATCH 13/13] fix: address copilot governance review --- .coderabbit.yaml | 7 ++-- .github/copilot-instructions.md | 23 +++++++++++++ .../abacus-governance.instructions.md | 33 +++++++++++++++++++ docs/developers_guide/agent_governance.md | 29 +++++++++++----- source/source_estate/module_pot/pot_cosikr.h | 4 +-- tests/integrate/Autotest.sh | 16 ++++----- .../agent_governance_check.py | 8 ++++- .../test_agent_governance_check.py | 15 +++++++++ 8 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/instructions/abacus-governance.instructions.md diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 11eb7b46b88..8f6bb860612 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -27,8 +27,9 @@ reviews: weaken the rule grading matrix without an explicit rationale. - path: ".github/**" instructions: | - Check workflow and PR-template changes for consistency with AGENTS.md - and docs/developers_guide/agent_governance.md. + Check workflow, PR-template, CodeRabbit, and Copilot instruction + changes for consistency with AGENTS.md and + docs/developers_guide/agent_governance.md. - path: "tools/03_code_analysis/**" instructions: | Review governance checker changes for false positives, missing @@ -42,3 +43,5 @@ knowledge_base: filePatterns: - "AGENTS.md" - "docs/developers_guide/agent_governance.md" + - ".github/copilot-instructions.md" + - ".github/instructions/*.instructions.md" diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000000..afe203f9a91 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,23 @@ +# ABACUS Copilot Instructions + +Before generating code or reviewing pull requests in this repository, follow +the ABACUS development baseline in: + +- `AGENTS.md` +- `docs/developers_guide/agent_governance.md` + +Treat `AGENTS.md` as the short entry point and +`docs/developers_guide/agent_governance.md` as the complete rule source. Review +the pull request diff before general style feedback, and separate blocking +diff-scoped issues from historical or advisory observations. + +Use the ABACUS review finding format for actionable findings: + +```markdown +Rule: +Severity: error | warning | info +Location: +Reason: +Suggested action: +Exception: allowed | not allowed | human approval required +``` diff --git a/.github/instructions/abacus-governance.instructions.md b/.github/instructions/abacus-governance.instructions.md new file mode 100644 index 00000000000..e1585ec9761 --- /dev/null +++ b/.github/instructions/abacus-governance.instructions.md @@ -0,0 +1,33 @@ +--- +applyTo: "**" +--- + +# ABACUS Governance Review Instructions + +Apply these instructions when reviewing or changing ABACUS code: + +- Use `AGENTS.md` and `docs/developers_guide/agent_governance.md` as the + authoritative project baseline. +- Keep review scope diff-oriented: new files, diff-added lines, new includes, + newly introduced symbols, and changed text files for line-ending checks. +- Do not treat untouched historical debt as a default blocker. Mention it only + when it affects the changed area, and label it as advisory. +- Flag newly introduced `GlobalV`, `GlobalC`, or `PARAM` cross-layer control. + Prefer explicit dependencies or narrow local interfaces. +- Flag new default arguments in existing header interfaces. Prefer explicit + call-site updates, overloads, or a clearer configuration object. +- Review header include growth and `.hpp` propagation carefully. These are + usually warnings unless the PR records a narrow reason. +- Require LF line endings for text files. `.bat` and `.cmd` files are the CRLF + exceptions. +- For INPUT parameter behavior changes, require synchronized updates to + `docs/parameters.yaml` and `docs/advanced/input_files/input-main.md`, or a + clear no-update explanation in the PR. +- Check that new source files are linked through the relevant `CMakeLists.txt` + unless the PR explains generated or indirect inclusion. +- Keep default C++ changes compatible with the repository C++11 baseline. +- Ask for focused tests or explicit test rationale for feature changes, bug + fixes, INPUT behavior changes, heterogeneous kernels, and core-module + refactors. +- Treat CI governance findings as deterministic evidence and semantic review + findings as advisory until maintainers approve them. diff --git a/docs/developers_guide/agent_governance.md b/docs/developers_guide/agent_governance.md index e4d83321864..5ff87c16a0d 100644 --- a/docs/developers_guide/agent_governance.md +++ b/docs/developers_guide/agent_governance.md @@ -119,11 +119,16 @@ ABACUS uses a layered review model: - `Agent Governance` is the deterministic GitHub Actions check for low-noise diff rules. Repository maintainers may make this workflow a required check in branch protection. -- CodeRabbit is the minimal PR-triggered AI reviewer for semantic review hints. - Its repository configuration lives in `.coderabbit.yaml` and uses this - document plus `AGENTS.md` as review guidelines. -- CodeRabbit comments are advisory by default. They do not replace maintainer - approval, exception approval, or numerical/test sufficiency review. +- CodeRabbit is a PR-triggered AI reviewer for semantic review hints. Its + repository configuration lives in `.coderabbit.yaml` and uses this document + plus `AGENTS.md` as review guidelines. +- GitHub Copilot code review is also present on upstream PRs. Repository-level + Copilot guidance lives in `.github/copilot-instructions.md`, and path-level + review guidance lives in `.github/instructions/*.instructions.md`. These + files point Copilot back to this governance document and the short + `AGENTS.md` entry point. +- CodeRabbit and Copilot comments are advisory by default. They do not replace + maintainer approval, exception approval, or numerical/test sufficiency review. To activate CodeRabbit on real PRs, a repository or organization administrator must install the CodeRabbit GitHub App for `deepmodeling/abacus-develop` and @@ -132,10 +137,16 @@ and new commits should receive automatic review according to `.coderabbit.yaml`; if automatic review does not start, maintainers may request it with `@coderabbitai review`. -Copilot code review, Copilot coding-agent setup steps, Qodo, and PR-Agent are -not part of the phase-one baseline. They require separate organization settings, -secrets, or setup workflows and should be added only through a later governance -change. +To make Copilot follow the governance baseline, keep the Copilot custom +instruction files synchronized with this document whenever the review contract +changes. Copilot review behavior still depends on GitHub organization and +repository settings, and pull request reviews use the custom instructions from +the target base branch. New or changed instruction files therefore take effect +for later reviews after they are present on the base branch. + +Copilot coding-agent setup steps, Qodo, and PR-Agent are not part of the +phase-one baseline. They require separate organization settings, secrets, or +setup workflows and should be added only through a later governance change. ## INPUT Parameter Changes diff --git a/source/source_estate/module_pot/pot_cosikr.h b/source/source_estate/module_pot/pot_cosikr.h index 7e144e548ea..1cdbd72c35e 100644 --- a/source/source_estate/module_pot/pot_cosikr.h +++ b/source/source_estate/module_pot/pot_cosikr.h @@ -13,7 +13,7 @@ namespace elecstate { -// ampitude * cos( 2pi*( k * r + phase ) ) +// amplitude * cos( 2pi*( k * r + phase ) ) class Pot_Cosikr : public PotBase { public: @@ -33,4 +33,4 @@ class Pot_Cosikr : public PotBase } -#endif \ No newline at end of file +#endif diff --git a/tests/integrate/Autotest.sh b/tests/integrate/Autotest.sh index e1feb19c017..ad00e05ec12 100755 --- a/tests/integrate/Autotest.sh +++ b/tests/integrate/Autotest.sh @@ -237,12 +237,12 @@ which $abacus > /dev/null || (echo "No ABACUS executable was found." && exit 1) testdir=`cat $cases_file | grep -E $case` failed=0 -failed_case_list=() +failed_case_list="" ok=0 fatal=0 -fatal_case_list=() -fatal_detail_list=() -case_status=() # record if the test case passed or not +fatal_case_list="" +fatal_detail_list="" +case_status="" # record if the test case passed or not fatal_threshold=1 report="" repo="$(realpath ..)/" @@ -335,19 +335,19 @@ fi if [ -z $g ] then -echo -e $case_status > test.sum +printf "%b" "$case_status" > test.sum if [[ "$failed" -eq 0 && "$fatal" -eq 0 ]] then echo -e "\e[0;32m[ PASSED ] \e[0m $ok test cases passed." else echo -e "[WARNING]\e[0m $failed test cases out of $[ $failed + $ok ] failed." - echo -e $failed_case_list + printf "%b" "$failed_case_list" if [ $fatal -gt 0 ] then echo -e "\e[0;31m[ERROR ]\e[0m $fatal test cases out of $[ $failed + $ok ] produced fatal error." - echo -e $fatal_case_list + printf "%b" "$fatal_case_list" echo -e "\e[0;31m[ERROR ]\e[0m Fatal deviation details:" - echo -e $fatal_detail_list + printf "%b" "$fatal_detail_list" fi exit 1 fi diff --git a/tools/03_code_analysis/agent_governance_check.py b/tools/03_code_analysis/agent_governance_check.py index 960dc47b00c..d6049139255 100644 --- a/tools/03_code_analysis/agent_governance_check.py +++ b/tools/03_code_analysis/agent_governance_check.py @@ -188,6 +188,10 @@ def is_text_path(path: str) -> bool: return suffix in TEXT_EXTENSIONS or path in {".gitattributes", ".gitignore"} +def has_crlf_line_endings(content: bytes) -> bool: + return any(line.endswith(b"\r\n") for line in content.splitlines(keepends=True)) + + def add_finding( findings: List[Finding], rule: str, @@ -215,7 +219,7 @@ def check_line_endings( content = read_changed_file_bytes(root, path, args) except OSError: continue - if b"\r\n" in content: + if has_crlf_line_endings(content): add_finding( findings, "LF line endings", @@ -696,6 +700,8 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace: help="Output format.", ) args = parser.parse_args(argv) + if args.staged and (args.base or args.head): + parser.error("--staged cannot be combined with --base/--head") if bool(args.base) ^ bool(args.head): parser.error("--base and --head must be provided together") return args diff --git a/tools/03_code_analysis/test_agent_governance_check.py b/tools/03_code_analysis/test_agent_governance_check.py index b7645767053..a62273127d6 100644 --- a/tools/03_code_analysis/test_agent_governance_check.py +++ b/tools/03_code_analysis/test_agent_governance_check.py @@ -76,6 +76,15 @@ def test_detects_crlf_in_changed_text_file(self): self.assert_blocked_by(result, "LF line endings") + def test_allows_escaped_crlf_text_in_changed_text_file(self): + self.write("source/source_base/escaped.cpp", 'const char* eol = "\\r\\n";\n') + self.write("source/source_base/CMakeLists.txt", "add_library(escaped escaped.cpp)\n") + head = self.commit_change() + + result = self.run_checker("--base", self.base, "--head", head) + + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + def test_allows_crlf_in_windows_scripts(self): self.write("tools/install.bat", b"echo ok\r\n", mode="wb") self.write("tools/install.cmd", b"echo ok\r\n", mode="wb") @@ -575,6 +584,12 @@ def test_staged_mode_checks_index_content(self): self.assert_blocked_by(result, "No new cross-layer globals") + def test_rejects_staged_with_base_head(self): + result = self.run_checker("--staged", "--base", self.base, "--head", self.base) + + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("--staged cannot be combined with --base/--head", result.stderr) + if __name__ == "__main__": unittest.main()