Skip to content

Commit c567031

Browse files
mohanchenabacus_fixer
andauthored
Refactor DeltaSpin step 2: add Tests and refactor (deepmodeling#7883)
* Test: add DeltaSpin integration tests with force/stress (PW + LCAO, nspin=2/4) Add four fast, reproducible DeltaSpin integration cases to cover the spin-constrained (deltaspin) code paths ahead of the planned SpinConstrain refactor. All cases compute force and stress in addition to total energy. New cases: - tests/01_PW/scf_deltaspin2: PW basis, collinear (nspin=2), Z magnetization constraint, iterative lambda optimization to target. kpar=2, pw_seed=1. - tests/01_PW/scf_deltaspin4: PW basis, noncollinear (nspin=4), Z-only constraint (verifies no unphysical XY components). kpar=2, pw_seed=1. - tests/03_NAO_multik/scf_deltaspin2: LCAO basis, collinear (nspin=2), Z constraint, Gamma k-point. Single MPI process. - tests/03_NAO_multik/scf_deltaspin4: LCAO basis, noncollinear (nspin=4), Z-only constraint, 2x2x2 Monkhorst-Pack. Exercises the LCAO lambda loop. Each case carries INPUT/KPT/STRU/result.ref/README. result.ref records etotref/etotperatomref plus totalforceref/totalstressref (sum-of-absolutes, matching tests/integrate/tools/catch_properties.sh). Cases were each run three times (OMP_NUM_THREADS=1) to confirm bit-identical etot before the reference was written. Registration: - tests/01_PW/CASES_CPU.txt and CASES_GPU.txt: scf_deltaspin2/4 (PW runs on GPU) - tests/03_NAO_multik/CASES_CPU.txt: scf_deltaspin2/4 Note: an LCAO gamma_only=1 DeltaSpin variant was evaluated for tests/02_NAO_Gamma but is excluded because it hits a pre-existing latent bug (SpinConstrain<double>::cal_mi_lcao is an empty stub, so print_Mi reads an empty Mi_ vector and segfaults); that bug is out of scope for this change and should be fixed separately. The LCAO coverage here uses multik instead. Verification: abacus_max_para v3.11.0-beta8 (build_max_para_test, make -j 30); each of the four cases run 3x with bit-identical FINAL_ETOT; force/stress references extracted from the same runs. * Refactor DeltaSpin, steps 1-2: extract ScState and solver-independent init Split the SpinConstrain god class along functional boundaries as the first steps of separating PW and LCAO code paths: - New deltaspin_state.{h,cpp}: non-template ScState owns all basis-set-independent constraint data (lambda, Mi, target_mag, constrain, atom/orbital indexing maps, lambda-loop parameters) and the ~45 setter/getter implementations moved out of spin_constrain.cpp. SpinConstrain keeps a ScState value member and its public interface becomes thin forwarding shells, so all existing call sites (esolvers, operators, tests) are unchanged. - New deltaspin_init.{h,cpp}: free function init_sc_state() performs the UnitCell/STRU-driven state initialization (count maps, nspin=2 x/y constraint fix, Ry unit conversion) with no dependency on solver-side objects. SpinConstrain::init_sc() is now a shell that calls init_sc_state() and stores external pointers. init_sc.cpp is replaced by deltaspin_init.cpp in CMakeLists. - Internal implementations (lambda_loop, cal_mw*, deltaspin_pw_impl) now access state through the state_ member. Scalars directly mutated by the lambda loop are transitional public fields on ScState, to be收敛ed to accessors when the loop is extracted. No INPUT parameter behavior changes; docs update not required. Verification: - cmake --build build -j 16 (Release, ENABLE_LCAO=ON): success - OMP_NUM_THREADS=1 ctest --test-dir build -R deltaspin: 5/5 passed (MODULE_LCAO_deltaspin_basic_func_test, spin_constrain_test, template_helpers, deltaspin_pw_test, deltaspin_core_test) - python3 tools/03_code_analysis/agent_governance_check.py --staged: no findings * Refactor DeltaSpin, step 3: extract LCAO magnetic-moment path to free functions Move the LCAO-specific Mi computation out of the SpinConstrain class into a new deltaspin_lcao_mi.{h,cpp} as free functions in namespace spinconstrain::lcao: - cal_mi_lcao(state, p_operator, dm, step, print): primary path via the DeltaSpin operator on the real-space density matrix (get_DMR_pointer + switch_dmr), with the operator and density matrix now passed explicitly instead of read from member pointers. - convert_orbital_matrix / calculate_mw_from_orbitals: the orbital-multiplication-matrix alternative path, moved verbatim from cal_mw_helper.cpp. - collect_mw: ScaLAPACK mu*density-matrix accumulation, with Parallel_Orbitals passed as an argument. cal_mw.cpp is reduced to thin member shells (cal_mi_lcao forwarding + set_operator specializations); the cal_mi_lcao<double> stub stays in template_helpers.cpp to avoid a duplicate definition. The now-unused convert/calculate_MW/collect_MW member declarations are removed from spin_constrain.h (verified no external callers). cal_mw_helper.cpp is deleted and replaced by deltaspin_lcao_mi.cpp in CMakeLists. No INPUT parameter behavior changes; docs update not required. Verification: - cmake --build build -j 16 (Release, ENABLE_LCAO=ON): success - OMP_NUM_THREADS=1 ctest --test-dir build -R deltaspin: 5/5 passed - python3 tools/03_code_analysis/agent_governance_check.py --staged: no findings * Fix CUDA build: qualify tpiba via state_ in update_psi_charge_pw_gpu Step 1 moved tpiba into ScState, but the __CUDA-only branch of update_psi_charge_pw_gpu in deltaspin_pw_impl.cpp was missed, breaking the CUDA CI build (no member named 'tpiba'). Route it through state_. Verification: - cmake --build build --target module_pwdft (CPU, __LCAO): success - cmake --build build_pw_gpu --target module_pwdft (CUDA, nvcc 12.9): success * Refactor DeltaSpin, step 4: encapsulate PW subspace cache in SubspaceCache Move the three ad-hoc public SpinConstrain members sub_h_save / sub_s_save / becp_save (raw TK* pointers) plus the lambda_in_sub_ snapshot into a new spinconstrain::pw::SubspaceCache (deltaspin_pw_cache.h), owned by value as SpinConstrain::pw_cache_. The class encapsulates the CPU vs GPU allocation/free difference: - allocate_cpu()/release_cpu() use new[]/delete[] on the host; - allocate_gpu()/release_gpu() use base_device resize/delete_memory_op on DEVICE_GPU, guarded by #if __CUDA/__ROCM. It still exposes raw per-k pointers h_k()/s_k()/becp_k() because the hsolver subspace routines and GPU memcpy ops require raw pointers, so std::vector is not applicable for the device buffers. The buffer element type is fixed to std::complex<double> (the PW path is always complex; the TK=double stub never allocates the cache). This also fixes a latent bug: the old SpinConstrain destructor called delete[] on sub_h_save/sub_s_save/becp_save unconditionally. In GPU runs those pointers are device memory allocated with resize_memory_op<DEVICE_GPU>, so delete[] on them is undefined behavior (and on some setups an invalid free). The destructor is now trivial (= default); device buffers are correctly freed via release_gpu() -> delete_memory_op<DEVICE_GPU>() in update_psi_charge_pw_gpu(), and host buffers via release_cpu() in update_psi_charge_pw_cpu(). The singleton lives for the whole program so no leak is introduced. Call sites updated: cal_mw_from_lambda.cpp (CPU+GPU allocation points and per-k views) and deltaspin_pw_impl.cpp (asserts, per-k views, CPU/GPU release, lambda_in_sub_ access). Buffer layout and reuse semantics are unchanged. No INPUT parameter behavior changes; docs update not required. Verification: - cmake --build build -j 16 (CPU, __LCAO): success - cmake --build build_pw_gpu --target module_pwdft (CUDA, nvcc 12.9): success (covers the __CUDA allocation/free branch) - OMP_NUM_THREADS=1 ctest --test-dir build -R deltaspin: 5/5 passed - python3 tools/03_code_analysis/agent_governance_check.py --staged: no findings * Refactor DeltaSpin, step 5: move PW implementation back to module_deltaspin Move the PW-basis DeltaSpin implementation out of source_pw/module_pwdft/deltaspin_pw_impl.cpp and into module_deltaspin/deltaspin_pw_mi.{h,cpp} as spinconstrain::pw free functions. This removes the reverse dependency source_pw -> module_deltaspin for the implementation layer, keeps the PW path compilable when ENABLE_LCAO=off, and eliminates the stale member declarations (cal_mi_pw, update_psi_charge_pw, update_psi_charge_pw_cpu/gpu, calculate_delta_hcc) from SpinConstrain. The deltaspin_pw_mi.cpp implementation is faithful to the original logic and is verified by both CPU and CUDA builds plus the 5 deltaspin unit tests. * tests/03_NAO_multik/scf_deltaspin4: relax per-case threshold for known chaotic stress The non-converged 100-step SCF trajectory has chaotic final-step stress across MPI ranks (np>=3) due to ScaLAPACK pzhegvx global reduction order-dependence, amplified exponentially by transverse spin-density zero modes. This is a pre-existing property present before the SpinConstrain refactor (3a96cd7 vs dae8f04 show identical np=4 OMP=1 results). Add per-case threshold file (threshold 1.0, force_threshold 10.0, stress_threshold 500.0, fatal_threshold 1000.0) and document the full mechanism and measured data in README. * remove deltaspin pw tests on GPU * Fix ONSITE_PROJ force bugs on GPU and CPU Two bugs caused incorrect ONSITE_PROJ force calculation: 1. GPU kernel type mismatch (force_op.cu, force_op.hip.cu): The cal_force_onsite kernel declared tpiba as int instead of FPTYPE (double). When tpiba = 2*pi/lat0 < 1.0 (typical for most lattices), int truncation made tpiba = 0, producing zero force on GPU. Fixed in both DFTU and DeltaSpin kernel variants, for CUDA and ROCm backends. 2. CPU duplicate for-loop (force_op.cpp): The npol==1 path of cal_force_nl_op for DeltaSpin had a duplicate 'for (int ip = 0; ip < nproj; ip++)' line, causing the force to be summed nproj^2 times instead of nproj. With nproj=9 for Fe, the CPU ONSITE_PROJ force was 9x too large. Additionally: - Updated scf_deltaspin2 result.ref: totalforceref 23.414157 -> 22.696640 - Re-enabled scf_deltaspin2 and scf_deltaspin4 in CASES_GPU.txt Verified: both tests pass on GPU (8/8 OK), CPU and GPU results match to ~10 decimal places. * Fix ODR violation from duplicate explicit instantiation of OperatorEXXPW Move extern template declarations to op_pw_exx.h so all translation units suppress implicit instantiation, and remove the duplicate explicit instantiation in op_pw_exx_ace.cpp. The single explicit instantiation in op_pw_exx.cpp remains the sole definition. * fix(exx): declare explicit specializations before extern template instantiation The extern template class declarations in op_pw_exx.h trigger implicit instantiation of all template members when the header is included. The explicit specializations of cal_density_recip and rho_recip2real in the .cpp file were therefore "after instantiation", causing a compile error. Fix by adding forward declarations of all 8 explicit specializations (CPU + GPU, cal_density_recip + rho_recip2real, complex<double> + complex<float>) in the header, placed before the extern template block. * fix(exx): add explicit template instantiation in op_pw_exx_ace.cpp op_pw_exx_ace.cpp defines ACE-specific template members (act_op_ace, construct_ace, cal_exx_energy_ace) but lacked explicit instantiations. The extern template class declaration in op_pw_exx.h suppressed implicit instantiation everywhere, and the template class instantiations in op_pw_exx.cpp could not see definitions in this translation unit, leading to linker undefined reference errors. Add template class instantiations for CPU and GPU variants at the end of op_pw_exx_ace.cpp so these members emit symbols. * fix(build): update Makefile.Objects for deltaspin_pw_impl migration Commit dae8f04 moved deltaspin_pw_impl.cpp from module_pwdft to module_deltaspin/deltaspin_pw_mi.cpp and updated both CMakeLists.txt files, but the legacy source/Makefile.Objects was not updated: - Remove stale deltaspin_pw_impl.o from OBJS_SRCPW (file no longer exists, caused "No rule to make target" build error) - Add deltaspin_pw_mi.o to OBJS_DELTASPIN to register the new file and avoid undefined references at link time * fix bug --------- Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
1 parent bbd23ca commit c567031

50 files changed

Lines changed: 2334 additions & 1458 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

source/Makefile.Objects

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,6 @@ OBJS_SRCPW=h_ewald_pw.o\
819819
yukawa_screening.o\
820820
setup_dftu_pw.o\
821821
deltaspin_pw.o\
822-
deltaspin_pw_impl.o\
823822
force_pw.o\
824823
force_pw_us.o\
825824
force_pw_nl.o\
@@ -906,12 +905,14 @@ OBJS_DFTU=dftu_nao.o\
906905
OBJS_DELTASPIN=basic_funcs.o\
907906
cal_mw_from_lambda.o\
908907
cal_mw.o\
909-
init_sc.o\
908+
deltaspin_init.o\
910909
lambda_loop_helper.o\
911910
lambda_loop.o\
912911
spin_constrain.o\
913-
cal_mw_helper.o\
914912
deltaspin_lcao.o\
913+
deltaspin_lcao_mi.o\
914+
deltaspin_state.o\
915+
deltaspin_pw_mi.o\
915916
mi_tools.o\
916917
template_helpers.o\
917918

source/source_estate/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ AddTest(
5454
../occupy.cpp
5555
../module_charge/charge_mpi.cpp
5656
../../source_lcao/module_deltaspin/spin_constrain.cpp
57+
../../source_lcao/module_deltaspin/deltaspin_state.cpp
5758
../../source_psi/psi.cpp
5859
../../source_base/module_device/memory_op.cpp
5960
../../source_cell/klist.cpp ../../source_cell/parallel_kpoints.cpp ../../source_cell/k_vector_utils.cpp ../../source_cell/reciprocal_grid.cpp

source/source_io/module_ctrl/ctrl_output_pw.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "../module_wf/write_wfc_pw.h" // use write_wfc_pw
1212
#include "source_base/formatter.h"
1313
#include "source_lcao/module_deltaspin/lambda_loop_helper.h"
14+
#include "source_lcao/module_deltaspin/deltaspin_pw_mi.h"
1415
#include "source_lcao/module_deltaspin/spin_constrain.h"
1516
#include "source_pw/module_pwdft/elecond.h"
1617
#include "source_pw/module_pwdft/onsite_proj.h" // use projector
@@ -219,7 +220,7 @@ void ModuleIO::ctrl_scf_pw(const int istep,
219220
if (inp.sc_mag_switch)
220221
{
221222
spinconstrain::SpinConstrain<std::complex<double>>& sc = spinconstrain::SpinConstrain<std::complex<double>>::getScInstance();
222-
sc.cal_mi_pw();
223+
spinconstrain::pw::cal_mi_pw(sc.state_, sc.psi, sc.pelec);
223224
spinconstrain::print_Mag_Force(sc, GlobalV::ofs_running);
224225
}
225226

source/source_lcao/module_deltaspin/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
list(APPEND objects
22
spin_constrain.cpp
3-
init_sc.cpp
3+
deltaspin_init.cpp
44
cal_mw.cpp
55
basic_funcs.cpp
66
lambda_loop_helper.cpp
77
lambda_loop.cpp
88
cal_mw_from_lambda.cpp
99
template_helpers.cpp
1010
deltaspin_lcao.cpp
11-
cal_mw_helper.cpp
11+
deltaspin_lcao_mi.cpp
12+
deltaspin_state.cpp
13+
deltaspin_pw_mi.cpp
1214
mi_tools.cpp
1315
)
1416

Lines changed: 14 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,40 @@
1-
#include "source_base/tool_title.h"
2-
#include "source_base/timer.h"
3-
#include "spin_constrain.h"
41
#ifdef __LCAO
5-
#include "source_estate/elecstate_lcao.h"
6-
#include "source_lcao/hamilt_lcao.h"
7-
#include "source_lcao/module_operator_lcao/dspin_lcao.h"
82

93
/**
104
* @file cal_mw.cpp
11-
* @brief Magnetic moment calculation for LCAO and PW basis sets.
12-
*
13-
* @par cal_mi_lcao (LCAO)
14-
* Uses the DeltaSpin operator to compute magnetic moments from the density
15-
* matrix via real-space projection. For nspin=2, only the z-component is
16-
* extracted. For nspin=4, all three components are extracted from the
17-
* interleaved 4-component spinor density matrix.
5+
* @brief Thin LCAO shells on SpinConstrain: cal_mi_lcao() and set_operator().
186
*
19-
* @par cal_mi_pw (PW)
20-
* Uses the OnsiteProjector to compute atomic projections <alpha_{l,m}|psi_{k,i}>
21-
* (becp coefficients), then decomposes these into magnetic moments using
22-
* Pauli matrix traces (accumulate_Mi_from_becp).
23-
*
24-
* @par Error conditions
25-
* - Dynamic cast failure: p_operator is not the correct DeltaSpin type.
26-
* This happens if set_operator() was not called with the correct type.
27-
* Solution: Ensure set_operator() is called before cal_mi_lcao().
7+
* The actual LCAO magnetic-moment implementation lives in
8+
* deltaspin_lcao_mi.cpp as free functions over ScState; the member
9+
* functions below only adapt the singleton's stored pointers.
2810
*/
2911

30-
/**
31-
* @brief Calculate atomic magnetic moments using real-space projection (LCAO basis).
32-
*
33-
* @details The DeltaSpin operator computes magnetic moments by projecting the
34-
* density matrix onto atomic orbitals. For each constrained atom:
35-
* M_i = Tr[P_at * (rho_up - rho_dn)] (nspin=2)
36-
* M_i = Tr[P_at * rho_spinor] (nspin=4, decomposed via Pauli matrices)
37-
*
38-
* @param step Current SCF iteration number (for logging)
39-
* @param print Whether to print moments (unused in this implementation)
40-
*/
12+
#include "spin_constrain.h"
13+
14+
#include "deltaspin_lcao_mi.h"
15+
#include "source_lcao/module_operator_lcao/dspin_lcao.h"
16+
#include "source_estate/module_dm/density_matrix.h"
17+
4118
template <>
4219
void spinconstrain::SpinConstrain<std::complex<double>>::cal_mi_lcao(const int& step, bool print)
4320
{
44-
ModuleBase::TITLE("module_deltaspin", "cal_mi_lcao");
45-
ModuleBase::timer::start("spinconstrain::SpinConstrain", "cal_mi_lcao");
46-
// Reset Mi before calculation
47-
this->zero_Mi();
48-
const hamilt::HContainer<double>* dmr = this->dm_->get_DMR_pointer(1);
49-
std::vector<double> moments;
50-
if(this->nspin_==2)
51-
{
52-
// Switch to spin-difference density matrix (rho_up - rho_dn)
53-
this->dm_->switch_dmr(2);
54-
55-
// Compute moments via DeltaSpin operator
56-
moments = static_cast<hamilt::DeltaSpin<hamilt::OperatorLCAO<std::complex<double>, double>>*>(this->p_operator)->cal_moment(dmr, this->get_constrain());
57-
58-
// Switch back to total density matrix
59-
this->dm_->switch_dmr(0);
60-
61-
// For nspin=2, only z-component is meaningful
62-
for(int iat=0;iat<this->Mi_.size();iat++)
63-
{
64-
this->Mi_[iat].x = 0.0;
65-
this->Mi_[iat].y = 0.0;
66-
this->Mi_[iat].z = moments[iat];
67-
}
68-
}
69-
else if(this->nspin_==4)
70-
{
71-
// For nspin=4, moments array contains interleaved [Mx, My, Mz] per atom
72-
moments = static_cast<hamilt::DeltaSpin<hamilt::OperatorLCAO<std::complex<double>, std::complex<double>>>*>(this->p_operator)->cal_moment(dmr, this->get_constrain());
73-
for(int iat=0;iat<this->Mi_.size();iat++)
74-
{
75-
this->Mi_[iat].x = moments[iat*3];
76-
this->Mi_[iat].y = moments[iat*3+1];
77-
this->Mi_[iat].z = moments[iat*3+2];
78-
}
79-
}
80-
81-
ModuleBase::timer::end("spinconstrain::SpinConstrain", "cal_mi_lcao");
21+
lcao::cal_mi_lcao(this->state_, this->p_operator, this->dm_, step, print);
8222
}
8323

84-
#endif
24+
// cal_mi_lcao<double> stub lives in template_helpers.cpp (single definition).
8525

86-
// cal_mi_pw() has been moved to source/source_pw/module_pwdft/deltaspin_pw_impl.cpp
87-
// because it depends on PW-specific OnsiteProjector.
88-
89-
/// @brief Set the DeltaSpin operator pointer for LCAO magnetic moment calculation
9026
template <>
9127
void spinconstrain::SpinConstrain<std::complex<double>>::set_operator(
9228
hamilt::Operator<std::complex<double>>* op_in)
9329
{
9430
this->p_operator = op_in;
9531
}
9632

97-
/// @brief Set the DeltaSpin operator pointer (double specialization)
9833
template <>
9934
void spinconstrain::SpinConstrain<double>::set_operator(
10035
hamilt::Operator<double>* op_in)
10136
{
10237
this->p_operator = op_in;
10338
}
39+
40+
#endif // __LCAO

source/source_lcao/module_deltaspin/cal_mw_from_lambda.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "source_hsolver/diago_iter_assist.h"
55
#include "source_io/module_parameter/parameter.h"
66
#include "spin_constrain.h"
7+
#include "deltaspin_pw_mi.h"
78
#include "mi_tools.h"
89
#include "source_pw/module_pwdft/onsite_proj.h"
910
#include "source_base/parallel_reduce.h"
@@ -105,19 +106,19 @@ void spinconstrain::SpinConstrain<std::complex<double>>::cal_mw_from_lambda(
105106
PARAM.inp.nbands,
106107
PARAM.inp.nelec,
107108
PARAM.inp.device == "gpu");
108-
if (this->nspin_ == 2)
109+
if (this->state_.nspin_ == 2)
109110
{
110111
dynamic_cast<hamilt::DeltaSpin<hamilt::OperatorLCAO<std::complex<double>, double>>*>(this->p_operator)
111112
->update_lambda();
112113
}
113-
else if (this->nspin_ == 4)
114+
else if (this->state_.nspin_ == 4)
114115
{
115116
dynamic_cast<hamilt::DeltaSpin<hamilt::OperatorLCAO<std::complex<double>, std::complex<double>>>*>(
116117
this->p_operator)
117118
->update_lambda();
118119
}
119120
// Diagonalization without updating charge density (last param = true means skip charge update)
120-
hsolver_t.solve(hamilt_t, psi_t[0], this->pelec, *this->dm_, *this->pelec->charge, this->nspin_, true);
121+
hsolver_t.solve(hamilt_t, psi_t[0], this->pelec, *this->dm_, *this->pelec->charge, this->state_.nspin_, true);
121122
elecstate::calculate_weights(this->pelec->ekb,
122123
this->pelec->wg,
123124
this->pelec->klist,
@@ -164,23 +165,21 @@ void spinconstrain::SpinConstrain<std::complex<double>>::cal_mw_from_lambda(
164165
becp_tmp.resize(size_becp * nk);
165166
std::vector<std::complex<double>> h_tmp(nbands * nbands), s_tmp(nbands * nbands);
166167
int initial_hs = 0;
167-
if(this->sub_h_save == nullptr)
168+
if(!this->pw_cache_.allocated())
168169
{
169170
// FIRST CALL: save subspace data for reuse across lambda steps
170171
initial_hs = 1;
171-
this->sub_h_save = new std::complex<double>[nbands * nbands * nk];
172-
this->sub_s_save = new std::complex<double>[nbands * nbands * nk];
173-
this->becp_save = new std::complex<double>[size_becp * nk];
174-
this->lambda_in_sub_ = this->lambda_;
172+
this->pw_cache_.allocate_cpu(nbands, nk, size_becp);
173+
this->pw_cache_.lambda_in_sub() = this->state_.lambda_;
175174
}
176175
for (int ik = 0; ik < nk; ++ik)
177176
{
178177

179178
psi_t->fix_k(ik);
180179

181-
std::complex<double>* h_k = this->sub_h_save + ik * nbands * nbands;
182-
std::complex<double>* s_k = this->sub_s_save + ik * nbands * nbands;
183-
std::complex<double>* becp_k = this->becp_save + ik * size_becp;
180+
std::complex<double>* h_k = this->pw_cache_.h_k(ik, nbands);
181+
std::complex<double>* s_k = this->pw_cache_.s_k(ik, nbands);
182+
std::complex<double>* becp_k = this->pw_cache_.becp_k(ik, size_becp);
184183
if(initial_hs)
185184
{
186185
/// Compute H(k) and extract subspace matrices for this k-point
@@ -191,7 +190,7 @@ void spinconstrain::SpinConstrain<std::complex<double>>::cal_mw_from_lambda(
191190
memcpy(h_tmp.data(), h_k, sizeof(std::complex<double>) * nbands * nbands);
192191
memcpy(s_tmp.data(), s_k, sizeof(std::complex<double>) * nbands * nbands);
193192
// Apply DeltaSpin correction (skip for initialization step i_step=-1)
194-
if (i_step != -1) this->calculate_delta_hcc(h_tmp.data(), becp_k, this->lambda_.data(), nbands, nkb, nh_iat, ik, true);
193+
if (i_step != -1) pw::calculate_delta_hcc(this->state_, this->pw_cache_, this->pelec, h_tmp.data(), becp_k, this->state_.lambda_.data(), nbands, nkb, nh_iat, ik, true);
195194

196195
// Diagonalize in subspace, update becp (response wavefunctions)
197196
hsolver::DiagoIterAssist<std::complex<double>>::diag_responce(h_tmp.data(),
@@ -224,23 +223,21 @@ void spinconstrain::SpinConstrain<std::complex<double>>::cal_mw_from_lambda(
224223
base_device::memory::resize_memory_op<std::complex<double>, base_device::DEVICE_GPU>()(h_tmp, nbands * nbands);
225224
base_device::memory::resize_memory_op<std::complex<double>, base_device::DEVICE_GPU>()(s_tmp, nbands * nbands);
226225
int initial_hs = 0;
227-
if(this->sub_h_save == nullptr)
226+
if(!this->pw_cache_.allocated())
228227
{
229228
initial_hs = 1;
230-
base_device::memory::resize_memory_op<std::complex<double>, base_device::DEVICE_GPU>()(this->sub_h_save, nbands * nbands * nk);
231-
base_device::memory::resize_memory_op<std::complex<double>, base_device::DEVICE_GPU>()(this->sub_s_save, nbands * nbands * nk);
232-
base_device::memory::resize_memory_op<std::complex<double>, base_device::DEVICE_GPU>()(this->becp_save, size_becp * nk);
233-
this->lambda_in_sub_ = this->lambda_;
229+
this->pw_cache_.allocate_gpu(nbands, nk, size_becp);
230+
this->pw_cache_.lambda_in_sub() = this->state_.lambda_;
234231
}
235232
std::complex<double>* becp_pointer = nullptr;
236233
base_device::memory::resize_memory_op<std::complex<double>, base_device::DEVICE_GPU>()(becp_pointer, size_becp);
237234
for (int ik = 0; ik < nk; ++ik)
238235
{
239236
psi_t->fix_k(ik);
240237

241-
std::complex<double>* h_k = this->sub_h_save + ik * nbands * nbands;
242-
std::complex<double>* s_k = this->sub_s_save + ik * nbands * nbands;
243-
std::complex<double>* becp_k = this->becp_save + ik * size_becp;
238+
std::complex<double>* h_k = this->pw_cache_.h_k(ik, nbands);
239+
std::complex<double>* s_k = this->pw_cache_.s_k(ik, nbands);
240+
std::complex<double>* becp_k = this->pw_cache_.becp_k(ik, size_becp);
244241
if(initial_hs)
245242
{
246243
hamilt_t->updateHk(ik);
@@ -249,7 +246,7 @@ void spinconstrain::SpinConstrain<std::complex<double>>::cal_mw_from_lambda(
249246
}
250247
base_device::memory::synchronize_memory_op<std::complex<double>, base_device::DEVICE_GPU, base_device::DEVICE_GPU>()(h_tmp, h_k, nbands * nbands);
251248
base_device::memory::synchronize_memory_op<std::complex<double>, base_device::DEVICE_GPU, base_device::DEVICE_GPU>()(s_tmp, s_k, nbands * nbands);
252-
if (i_step != -1) this->calculate_delta_hcc(h_tmp, becp_k, this->lambda_.data(), nbands, nkb, nh_iat, ik, true);
249+
if (i_step != -1) pw::calculate_delta_hcc(this->state_, this->pw_cache_, this->pelec, h_tmp, becp_k, this->state_.lambda_.data(), nbands, nkb, nh_iat, ik, true);
253250

254251
hsolver::DiagoIterAssist<std::complex<double>, base_device::DEVICE_GPU>::diag_responce(h_tmp,
255252
s_tmp,
@@ -280,15 +277,15 @@ void spinconstrain::SpinConstrain<std::complex<double>>::cal_mw_from_lambda(
280277
for (int ik = 0; ik < nk; ik++)
281278
{
282279
const std::complex<double>* becp = &becp_tmp[ik * size_becp];
283-
const int spin_sign = (this->npol_ == 2) ? 1 : this->get_spin_sign(ik);
284-
accumulate_Mi_from_becp(becp, nkb, nbands, this->npol_, spin_sign,
285-
&this->pelec->wg(ik, 0), nh_iat, this->Mi_);
280+
const int spin_sign = (this->state_.npol_ == 2) ? 1 : this->get_spin_sign(ik);
281+
accumulate_Mi_from_becp(becp, nkb, nbands, this->state_.npol_, spin_sign,
282+
&this->pelec->wg(ik, 0), nh_iat, this->state_.Mi_);
286283
}
287284
// MPI reduction: sum Mi across all k-pool ranks
288285
Parallel_Reduce::reduce_double_allpool(PARAM.inp.kpar,
289286
GlobalV::NPROC_IN_POOL,
290-
&(this->Mi_[0][0]),
291-
3 * this->Mi_.size());
287+
&(this->state_.Mi_[0][0]),
288+
3 * this->state_.Mi_.size());
292289
}
293290
}
294291
ModuleBase::timer::end("spinconstrain::SpinConstrain", "cal_mw_from_lambda");
@@ -328,12 +325,14 @@ void spinconstrain::SpinConstrain<std::complex<double>>::update_psi_charge(const
328325
{
329326
if (PARAM.inp.device == "cpu")
330327
{
331-
this->update_psi_charge_pw_cpu(delta_lambda, pw_solve, full_update);
328+
pw::update_psi_charge_pw_cpu(this->state_, this->pw_cache_, this->psi, this->p_hamilt,
329+
this->pelec, this->pw_wfc_, delta_lambda, pw_solve, full_update);
332330
}
333331
#if ((defined __CUDA) || (defined __ROCM))
334332
else
335333
{
336-
this->update_psi_charge_pw_gpu(delta_lambda, pw_solve, full_update);
334+
pw::update_psi_charge_pw_gpu(this->state_, this->pw_cache_, this->psi, this->p_hamilt,
335+
this->pelec, this->pw_wfc_, delta_lambda, pw_solve, full_update);
337336
}
338337
#endif
339338
}

0 commit comments

Comments
 (0)