|
5 | 5 | #include "source_basis/module_pw/pw_basis_k.h" |
6 | 6 | #include "source_cell/klist.h" |
7 | 7 | #include "source_cell/unitcell.h" |
| 8 | +#include "source_pw/module_pwdft/onsite_proj.h" |
8 | 9 | #include <iomanip> |
9 | 10 | #include <iostream> |
10 | 11 |
|
@@ -141,25 +142,9 @@ void deltap_iter_finish( |
141 | 142 | if (gamma_total == 0.0) |
142 | 143 | return; // no valid k-strings (Gamma-only grid) |
143 | 144 |
|
144 | | - // For Phase B2: assign gamma equally to constrained atoms |
145 | | - // Phase B3 will add proper per-atom decomposition via becp weights |
146 | | - int nconstrained = 0; |
147 | | - for (int iat = 0; iat < nat; iat++) |
148 | | - { |
149 | | - bool ok = (constrain.empty() || static_cast<size_t>(iat) >= constrain.size() || constrain[iat] != 0); |
150 | | - if (ok) nconstrained++; |
151 | | - } |
152 | | - if (nconstrained == 0) return; |
153 | | - |
154 | | - double gamma_per_atom = gamma_total / nconstrained; |
155 | | - |
156 | | - // Build per-atom gamma and update lambda via gradient descent |
| 145 | + // Phase B3: decompose total gamma per atom via becp weights |
157 | 146 | std::vector<double> gamma_1d(nat, 0.0); |
158 | | - for (int iat = 0; iat < nat; iat++) |
159 | | - { |
160 | | - bool ok = (constrain.empty() || static_cast<size_t>(iat) >= constrain.size() || constrain[iat] != 0); |
161 | | - gamma_1d[iat] = ok ? gamma_per_atom : 0.0; |
162 | | - } |
| 147 | + compute_per_atom_gamma_from_becp(ucell, nocc, gamma_total, gamma_1d); |
163 | 148 |
|
164 | 149 | // Target values (fixed, from STRU at initialization) |
165 | 150 | const std::vector<double>& targets = get_deltap_pw_targets(); |
@@ -189,7 +174,66 @@ void deltap_iter_finish( |
189 | 174 | for (int iat = 0; iat < nat; iat++) lam_avg += lambda[iat]; |
190 | 175 | lam_avg /= nat; |
191 | 176 | std::cout << std::scientific << std::setprecision(3) << lam_avg |
192 | | - << " |res|=" << max_res << std::endl; |
| 177 | + << " |res|=" << max_res |
| 178 | + << " γ/atom=(" << std::fixed << std::setprecision(4); |
| 179 | + for (int iat = 0; iat < nat; iat++) |
| 180 | + { |
| 181 | + if (iat > 0) std::cout << ", "; |
| 182 | + std::cout << gamma_1d[iat]; |
| 183 | + } |
| 184 | + std::cout << ")" << std::endl; |
| 185 | +} |
| 186 | + |
| 187 | +void compute_per_atom_gamma_from_becp( |
| 188 | + const UnitCell& ucell, |
| 189 | + int nocc, |
| 190 | + double gamma_total, |
| 191 | + std::vector<double>& gamma_per_atom) |
| 192 | +{ |
| 193 | + int nat = ucell.nat; |
| 194 | + gamma_per_atom.assign(nat, 0.0); |
| 195 | + |
| 196 | + auto* onsite_p = projectors::OnsiteProjector<double, base_device::DEVICE_CPU>::get_instance(); |
| 197 | + if (onsite_p == nullptr) return; |
| 198 | + |
| 199 | + int tot_nproj = onsite_p->get_tot_nproj(); |
| 200 | + if (tot_nproj == 0) return; |
| 201 | + |
| 202 | + const std::complex<double>* becp = onsite_p->get_becp(); |
| 203 | + if (becp == nullptr) return; |
| 204 | + |
| 205 | + // Compute per-atom weights: w[I] = Σ_n Σ_{α∈I} |<alpha|psi_n>|^2 |
| 206 | + std::vector<double> w(nat, 0.0); |
| 207 | + int iproj = 0; |
| 208 | + for (int iat = 0; iat < nat; iat++) |
| 209 | + { |
| 210 | + int nh = onsite_p->get_nh(iat); |
| 211 | + for (int ip = 0; ip < nh; ip++) |
| 212 | + { |
| 213 | + double w_ip = 0.0; |
| 214 | + for (int ib = 0; ib < nocc; ib++) |
| 215 | + { |
| 216 | + std::complex<double> b = becp[ib * tot_nproj + iproj]; |
| 217 | + w_ip += b.real() * b.real() + b.imag() * b.imag(); |
| 218 | + } |
| 219 | + w[iat] += w_ip; |
| 220 | + iproj++; |
| 221 | + } |
| 222 | + } |
| 223 | + |
| 224 | + double w_total = 0.0; |
| 225 | + for (int iat = 0; iat < nat; iat++) w_total += w[iat]; |
| 226 | + |
| 227 | + if (w_total < 1e-30) |
| 228 | + { |
| 229 | + // Fallback: equal division |
| 230 | + for (int iat = 0; iat < nat; iat++) |
| 231 | + gamma_per_atom[iat] = gamma_total / nat; |
| 232 | + return; |
| 233 | + } |
| 234 | + |
| 235 | + for (int iat = 0; iat < nat; iat++) |
| 236 | + gamma_per_atom[iat] = gamma_total * w[iat] / w_total; |
193 | 237 | } |
194 | 238 |
|
195 | 239 | } // namespace pw_deltap |
0 commit comments