99#include " source_hsolver/diago_iter_assist.h"
1010#include " source_hamilt/hamilt.h"
1111#include " source_base/constants.h"
12- #include " source_base/kernels/math_kernel_op.h"
1312#include < iomanip>
1413#include < iostream>
1514
@@ -22,6 +21,7 @@ namespace {
2221 std::vector<double > s_targets; // target per-atom gamma (rad)
2322 std::vector<int > s_constrain; // per-atom constrain flags
2423 double s_gamma_total = 0.0 ; // cached total gamma from last computation
24+ void * s_hamilt = nullptr ; // stored HamiltPW pointer for inner loop
2525
2626 // Subspace data for inner lambda loop (saved once per SCF, reused across inner steps)
2727 bool s_sub_saved = false ;
@@ -64,6 +64,12 @@ bool is_deltap_pw_active()
6464 return s_active;
6565}
6666
67+ void set_deltap_pw_hamilt (void * hamilt)
68+ {
69+ s_hamilt = hamilt;
70+ s_sub_saved = false ; // reset subspace cache when hamilt changes (new SCF)
71+ }
72+
6773bool run_deltap_lambda_loop (const int iter,
6874 const double drho,
6975 const Input_para& inp)
@@ -113,7 +119,6 @@ void deltap_iter_finish(
113119 const K_Vectors& kv,
114120 const ModulePW::PW_Basis_K* wfcpw,
115121 const ModulePW::PW_Basis* rhopw,
116- hamilt::Hamilt<std::complex <double >>* p_hamilt,
117122 const Input_para& inp)
118123{
119124 if (!inp.deltap_switch || !inp.deltap_corr )
@@ -157,10 +162,9 @@ void deltap_iter_finish(
157162 if (mixing > 1.0 ) mixing = 1.0 ;
158163 if (mixing == 0.0 ) mixing = 1.0 ;
159164
160- // ---- Subspace inner loop (only if deltap_inner_nmax > 0) ----
161165 int inner_nmax = inp.deltap_inner_nmax ;
162166 bool inner_loop_ok = false ;
163- if (inner_nmax > 0 && p_hamilt != nullptr && psi_cpu != nullptr )
167+ if (inner_nmax > 0 && s_hamilt != nullptr && psi_cpu != nullptr )
164168 {
165169 auto * onsite_p = projectors::OnsiteProjector<double , base_device::DEVICE_CPU >::get_instance ();
166170 if (onsite_p != nullptr )
@@ -173,6 +177,7 @@ void deltap_iter_finish(
173177 {
174178 inner_loop_ok = true ;
175179 const int * nh_iat = &onsite_p->get_nh (0 );
180+ auto * hamilt_t = static_cast <hamilt::Hamilt<std::complex <double >, base_device::DEVICE_CPU >*>(s_hamilt);
176181
177182 // Save subspace data (once per SCF)
178183 if (!s_sub_saved)
@@ -190,88 +195,23 @@ void deltap_iter_finish(
190195 auto * h_k = s_sub_h.data () + ik * nbands * nbands;
191196 auto * s_k = s_sub_s.data () + ik * nbands * nbands;
192197 auto * becp_k = s_becp.data () + ik * size_becp;
193- p_hamilt ->updateHk (ik);
198+ hamilt_t ->updateHk (ik);
194199 hsolver::DiagoIterAssist<std::complex <double >>::cal_hs_subspace (
195- p_hamilt , *psi_nc, h_k, s_k);
200+ hamilt_t , *psi_nc, h_k, s_k);
196201 memcpy (becp_k, onsite_p->get_becp (),
197202 sizeof (std::complex <double >) * size_becp);
198203 }
199204 s_sub_saved = true ;
200205 }
201206
202- // Inner loop: gradient descent with subspace re-solve
207+ // Inner loop: re-compute gamma via becp re-weighting
208+ // Phase D.1: simple gradient descent, no subspace diagonalization
209+ // Phase D.2 (TODO): subspace diag with GEMM + diag_responce
203210 for (int inner = 0 ; inner < inner_nmax; inner++)
204211 {
205- int size_becp = s_nbands * s_nproj * s_npol;
206- std::vector<std::complex <double >> h_tmp (s_nbands * s_nbands);
207- std::vector<std::complex <double >> s_tmp (s_nbands * s_nbands);
208- std::vector<std::complex <double >> becp_tmp (size_becp);
209- std::vector<std::complex <double >> ps (size_becp, 0.0 );
210- std::vector<double > w_tot (nat, 0.0 );
211-
212- for (int ik = 0 ; ik < s_nk; ik++)
213- {
214- auto * h_k = s_sub_h.data () + ik * s_nbands * s_nbands;
215- auto * s_k = s_sub_s.data () + ik * s_nbands * s_nbands;
216- auto * becp_k = s_becp.data () + ik * size_becp;
217-
218- // Build ps = diag(lambda[atom_of(proj)]) * becp
219- std::fill (ps.begin (), ps.end (), std::complex <double >(0.0 , 0.0 ));
220- int iproj = 0 ;
221- for (int iat = 0 ; iat < nat; iat++)
222- {
223- int nh = nh_iat[iat];
224- std::complex <double > coeff (lambda[iat], 0.0 );
225- for (int ip = 0 ; ip < nh; ip++)
226- {
227- for (int ib = 0 ; ib < s_nbands; ib++)
228- ps[ib * s_nproj + iproj] += coeff * becp_k[ib * s_nproj + iproj];
229- iproj++;
230- }
231- }
232-
233- // H_sub(lambda) = H_sub(0) + becp† * ps
234- memcpy (h_tmp.data (), h_k, sizeof (std::complex <double >) * s_nbands * s_nbands);
235- memcpy (s_tmp.data (), s_k, sizeof (std::complex <double >) * s_nbands * s_nbands);
236- memcpy (becp_tmp.data (), becp_k, sizeof (std::complex <double >) * size_becp);
237-
238- ModuleBase::gemm_op<std::complex <double >, base_device::DEVICE_CPU >()(
239- ' C' , ' N' , s_nbands, s_nbands, s_nproj * s_npol,
240- &ModuleBase::ONE , becp_k, s_nproj * s_npol,
241- ps.data (), s_nproj * s_npol,
242- &ModuleBase::ONE , h_tmp.data (), s_nbands);
243-
244- // Subspace diagonalization: H·V = S·V·E
245- hsolver::DiagoIterAssist<std::complex <double >>::diag_responce (
246- h_tmp.data (), s_tmp.data (), s_nbands,
247- becp_tmp.data (), becp_tmp.data (), s_nproj * s_npol, nullptr );
248-
249- // Compute per-atom weights from rotated becp
250- iproj = 0 ;
251- for (int iat = 0 ; iat < nat; iat++)
252- {
253- int nh = nh_iat[iat];
254- for (int ip = 0 ; ip < nh; ip++)
255- {
256- for (int ib = 0 ; ib < nocc; ib++)
257- {
258- auto b = becp_tmp[ib * s_nproj + iproj];
259- w_tot[iat] += b.real () * b.real () + b.imag () * b.imag ();
260- }
261- iproj++;
262- }
263- }
264- } // end k-point loop
265-
266- // Normalize per-atom gamma
267212 std::vector<double > gamma_trial (nat, 0.0 );
268- double w_sum = 0.0 ;
269- for (int iat = 0 ; iat < nat; iat++) w_sum += w_tot[iat];
270- if (w_sum < 1e-30 ) break ;
271- for (int iat = 0 ; iat < nat; iat++)
272- gamma_trial[iat] = gamma_total * w_tot[iat] / w_sum;
213+ compute_per_atom_gamma_from_becp (ucell, nocc, gamma_total, gamma_trial);
273214
274- // Compute residual and update lambda
275215 double max_res_inner = 0.0 ;
276216 for (int iat = 0 ; iat < nat; iat++)
277217 {
@@ -284,7 +224,7 @@ void deltap_iter_finish(
284224
285225 if (max_res_inner < inp.deltap_inner_thr )
286226 break ;
287- } // end inner loop
227+ }
288228 }
289229 }
290230 }
0 commit comments