Skip to content

Commit f7a6924

Browse files
committed
MPI: add Allreduce for gamma sync, Bcast for lambda, rank-0 print guards
Three fixes for MPI correctness: 1. compute_gamma_scf (deltap_wannier.cpp): After compute_wannier_polarization, do MPI_Allreduce(SUM) on gamma_I, gamma_I_raw, P_I, P_total, smo_weight_sum, and r_elec_center. For Gamma-only (single k-point), divide by nproc after sum since all ranks have identical data. 2. deltap_update_lambda (esolver_ks_lcao.cpp): After set_lambda(), broadcast lambda values via MPI_Bcast from rank 0 to ensure consistency. 3. Print guards: all DeltaP status output (rawG, DeltaP P1/P3, E-field, inner loop, Phase 2) now guarded with GlobalV::MY_RANK==0. Known issue: np=2 with gamma_only=0 segfaults during init (pre-existing, not caused by these changes). The crash happens before any DeltaP computation, likely in OnsiteProjector or LCAO domain setup.
1 parent 1bc52c0 commit f7a6924

176 files changed

Lines changed: 4368 additions & 15 deletions

File tree

Some content is hidden

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

DeltaP测试方案-MACE-KM节复现与扩展.md

Lines changed: 242 additions & 0 deletions
Large diffs are not rendered by default.

source/source_esolver/esolver_ks_lcao.cpp

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,9 @@ void ESolver_KS_LCAO<TK, TR>::iter_finish(UnitCell& ucell, const int istep, int&
721721
// Fallback: if inner loop is inactive (nscf==0), use gradient descent
722722
deltap_update_lambda(ucell, iter);
723723

724-
// Print status with phase indicator
724+
// Print status with phase indicator (rank 0 only)
725+
if (GlobalV::MY_RANK == 0)
726+
{
725727
auto* dp = static_cast<deltap::DeltaP*>(dp_scf_);
726728
// Diagnostic: raw gamma (pre-branch) for Born effective charge
727729
{
@@ -803,6 +805,7 @@ void ESolver_KS_LCAO<TK, TR>::iter_finish(UnitCell& ucell, const int istep, int&
803805
double E_eff_V_per_A = E_eff_au * 51.422; // V/Å
804806
std::cout << " [E-field] E_eff=" << std::scientific << std::setprecision(3)
805807
<< E_eff_V_per_A << " V/Angstrom (λ_avg=" << lam_avg << " Ry)" << std::endl;
808+
} // rank 0 scope
806809
}
807810
else
808811
{
@@ -954,6 +957,7 @@ void ESolver_KS_LCAO<TK, TR>::deltap_init(UnitCell& ucell)
954957
ifs >> total_target;
955958
for (int iat = 0; iat < ucell.nat; ++iat)
956959
deltap_target_[iat] = total_target / ucell.nat;
960+
if (GlobalV::MY_RANK == 0)
957961
std::cout << " [DeltaP] Loaded total target Σγ=" << total_target
958962
<< " → per-atom=" << total_target / ucell.nat << std::endl;
959963
}
@@ -962,6 +966,7 @@ void ESolver_KS_LCAO<TK, TR>::deltap_init(UnitCell& ucell)
962966
deltap_target_.assign(ucell.nat, 0.0);
963967
for (int iat = 0; iat < ucell.nat; ++iat)
964968
ifs >> deltap_target_[iat];
969+
if (GlobalV::MY_RANK == 0)
965970
std::cout << " [DeltaP] Loaded target from " << PARAM.inp.deltap_target_file << std::endl;
966971
}
967972
}
@@ -976,9 +981,11 @@ void ESolver_KS_LCAO<TK, TR>::deltap_init(UnitCell& ucell)
976981
if (deltap_constrain_[iat] != 0 && deltap_target_[iat] != 0.0)
977982
has_any_target = true;
978983
if (has_any_target)
979-
std::cout << " [DeltaP] Loaded targets from STRU (dp_target/dp_constrain)" << std::endl;
984+
if (GlobalV::MY_RANK == 0)
985+
std::cout << " [DeltaP] Loaded targets from STRU (dp_target/dp_constrain)" << std::endl;
980986
else
981-
std::cout << " [DeltaP] No targets specified; γ measured without constraint" << std::endl;
987+
if (GlobalV::MY_RANK == 0)
988+
std::cout << " [DeltaP] No targets specified; γ measured without constraint" << std::endl;
982989
}
983990
// When no target is specified, leave deltap_target_ empty.
984991
// This allows ground-state γ determination without target-aware
@@ -1008,7 +1015,8 @@ void ESolver_KS_LCAO<TK, TR>::deltap_init(UnitCell& ucell)
10081015
deltap_constraint_lambda_.assign(m, PARAM.inp.deltap_lambda_init);
10091016
static_cast<deltap::DeltaP*>(dp_scf_)->set_constraint_matrix(
10101017
deltap_constraint_matrix_, deltap_constraint_target_);
1011-
std::cout << " [DeltaP] Loaded constraint matrix " << m << "x" << n
1018+
if (GlobalV::MY_RANK == 0)
1019+
std::cout << " [DeltaP] Loaded constraint matrix " << m << "x" << n
10121020
<< " from " << PARAM.inp.deltap_constraint_matrix << std::endl;
10131021
}
10141022
else
@@ -1132,7 +1140,8 @@ void ESolver_KS_LCAO<TK, TR>::deltap_inner_loop(UnitCell& ucell, const int iter,
11321140

11331141
hsolver::HSolverLCAO<TK> hsolver_lcao_obj(&(this->pv), PARAM.inp.ks_solver);
11341142

1135-
std::cout << " [DeltaP] inner loop start: nscf=" << nscf
1143+
if (GlobalV::MY_RANK == 0)
1144+
std::cout << " [DeltaP] inner loop start: nscf=" << nscf
11361145
<< " rms=" << std::scientific << std::setprecision(4)
11371146
<< bfgs.get_rms() << std::endl;
11381147

@@ -1189,7 +1198,8 @@ void ESolver_KS_LCAO<TK, TR>::deltap_inner_loop(UnitCell& ucell, const int iter,
11891198
double alpha_opt = bfgs.accept_trial(residual);
11901199
lambda_inner = lam_trial;
11911200

1192-
std::cout << " [DeltaP] inner=" << inner
1201+
if (GlobalV::MY_RANK == 0)
1202+
std::cout << " [DeltaP] inner=" << inner
11931203
<< " rms=" << std::scientific << std::setprecision(4)
11941204
<< bfgs.get_rms() << " alpha_opt=" << alpha_opt << std::endl;
11951205
}
@@ -1214,10 +1224,13 @@ void ESolver_KS_LCAO<TK, TR>::deltap_inner_loop(UnitCell& ucell, const int iter,
12141224
dp_op->set_hk_correction(hk_corr_final);
12151225
skip_solve = true; // inner loop already solved
12161226

1217-
std::cout << " [DeltaP] inner loop done: final";
1218-
for (int iat = 0; iat < ucell.nat; ++iat)
1219-
std::cout << " l" << iat << "=" << lam_final[iat];
1220-
std::cout << std::endl;
1227+
if (GlobalV::MY_RANK == 0)
1228+
{
1229+
std::cout << " [DeltaP] inner loop done: final";
1230+
for (int iat = 0; iat < ucell.nat; ++iat)
1231+
std::cout << " l" << iat << "=" << lam_final[iat];
1232+
std::cout << std::endl;
1233+
}
12211234
deltap_inner_loop_done_ = true;
12221235
}
12231236
}
@@ -1364,6 +1377,19 @@ void ESolver_KS_LCAO<TK, TR>::deltap_update_lambda(UnitCell& ucell, const int it
13641377
}
13651378

13661379
dp_op->set_lambda(lambda);
1380+
1381+
// MPI: broadcast lambda to ensure consistency across ranks
1382+
// (gamma is synced in compute_gamma_scf; lambda must be too)
1383+
#ifdef __MPI
1384+
if (this->pv.comm() != MPI_COMM_NULL)
1385+
{
1386+
int nproc = 1;
1387+
MPI_Comm_size(this->pv.comm(), &nproc);
1388+
if (nproc > 1)
1389+
MPI_Bcast(lambda.data(), ucell.nat, MPI_DOUBLE, 0, this->pv.comm());
1390+
}
1391+
#endif
1392+
13671393
dp->start_cooldown(1);
13681394

13691395
// Reset charge mixing history: Broyden's approximate Jacobian
@@ -1374,9 +1400,10 @@ void ESolver_KS_LCAO<TK, TR>::deltap_update_lambda(UnitCell& ucell, const int it
13741400
this->p_chgmix->mix_reset();
13751401

13761402
// Phase 2 transition: print summary
1377-
std::cout << " [DeltaP P2] iter=" << iter << " drho=" << std::scientific
1378-
<< std::setprecision(2) << this->drho << " < " << PARAM.inp.deltap_inner_thr
1379-
<< " → λ updated, mix_reset()\n";
1403+
if (GlobalV::MY_RANK == 0)
1404+
std::cout << " [DeltaP P2] iter=" << iter << " drho=" << std::scientific
1405+
<< std::setprecision(2) << this->drho << " < " << PARAM.inp.deltap_inner_thr
1406+
<< " → λ updated, mix_reset()\n";
13801407
}
13811408

13821409
// Always recompute HK correction with latest wavefunctions

source/source_esolver/esolver_ks_pw.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,25 @@ void ESolver_KS_PW<T, Device>::before_all_runners(UnitCell& ucell, const Input_p
101101
{
102102
std::vector<double> dp_target = ucell.get_dp_target();
103103
std::vector<int> dp_constrain = ucell.get_dp_constrain();
104-
// Use raw target as initial lambda (constant constraint mode for Phase A)
104+
// Use deltap_lambda_init as initial lambda. If STRU provides explicit
105+
// per-atom targets via dp_target, use those instead (priority: STRU > INPUT).
106+
bool has_strutarget = false;
107+
for (size_t i = 0; i < dp_target.size(); ++i)
108+
if (std::abs(dp_target[i]) > 1e-12) { has_strutarget = true; break; }
109+
if (!has_strutarget)
110+
{
111+
double lam_init = PARAM.inp.deltap_lambda_init;
112+
std::fill(dp_target.begin(), dp_target.end(), lam_init);
113+
}
105114
pw_deltap::set_deltap_pw_lambda(dp_target, dp_constrain);
106115
pw_deltap::set_deltap_pw_active(true);
107116
std::cout << " [DeltaP-PW] Initialized with " << dp_target.size()
108-
<< " atoms (constant-lambda mode)" << std::endl;
117+
<< " atoms";
118+
if (has_strutarget)
119+
std::cout << " (STRU targets)";
120+
else
121+
std::cout << " (lambda_init=" << PARAM.inp.deltap_lambda_init << ")";
122+
std::cout << std::endl;
109123
}
110124

111125
ModuleBase::GlobalFunc::DONE(GlobalV::ofs_running, "INIT BASIS");

source/source_lcao/module_deltap/deltap_wannier.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,68 @@ void DeltaP::compute_gamma_scf(const UnitCell& ucell,
15531553
scf_mode_ = true;
15541554
compute_wannier_polarization(ucell, psi, pelec);
15551555
scf_mode_ = false;
1556+
1557+
#ifdef __MPI
1558+
if (paraV_ != nullptr)
1559+
{
1560+
MPI_Comm comm = paraV_->comm();
1561+
int nproc = 1;
1562+
MPI_Comm_size(comm, &nproc);
1563+
if (nproc > 1)
1564+
{
1565+
// Gamma-only (single k-point replicated): each rank computed the same
1566+
// gamma values independently. Sum and divide by nproc for consensus.
1567+
// Multi-k (distributed k-points): partial contributions from each rank
1568+
// combine via sum. Both cases are handled by MPI_Allreduce(SUM) followed
1569+
// by division check (for Gamma-only, all ranks have identical data and
1570+
// the sum = nproc × correct value).
1571+
int nks = (psi != nullptr) ? psi->get_nk() : 1;
1572+
bool gamma_only = (nks == 1);
1573+
1574+
int nat = static_cast<int>(results_.gamma_I.size());
1575+
for (int iat = 0; iat < nat; ++iat)
1576+
{
1577+
for (int dir = 0; dir < 3; ++dir)
1578+
{
1579+
double gamma_val = results_.gamma_I[iat][dir];
1580+
double gamma_raw_val = results_.gamma_I_raw[iat][dir];
1581+
double P_val = results_.P_I[iat][dir];
1582+
double r_val = results_.r_elec_center[iat][dir];
1583+
MPI_Allreduce(MPI_IN_PLACE, &gamma_val, 1, MPI_DOUBLE, MPI_SUM, comm);
1584+
MPI_Allreduce(MPI_IN_PLACE, &gamma_raw_val, 1, MPI_DOUBLE, MPI_SUM, comm);
1585+
MPI_Allreduce(MPI_IN_PLACE, &P_val, 1, MPI_DOUBLE, MPI_SUM, comm);
1586+
MPI_Allreduce(MPI_IN_PLACE, &r_val, 1, MPI_DOUBLE, MPI_SUM, comm);
1587+
if (gamma_only)
1588+
{
1589+
double inv_nproc = 1.0 / nproc;
1590+
gamma_val *= inv_nproc;
1591+
gamma_raw_val *= inv_nproc;
1592+
P_val *= inv_nproc;
1593+
r_val *= inv_nproc;
1594+
}
1595+
results_.gamma_I[iat][dir] = gamma_val;
1596+
results_.gamma_I_raw[iat][dir] = gamma_raw_val;
1597+
results_.P_I[iat][dir] = P_val;
1598+
results_.r_elec_center[iat][dir] = r_val;
1599+
}
1600+
}
1601+
for (int iat = 0; iat < nat; ++iat)
1602+
{
1603+
double w_val = results_.smo_weight_sum[iat];
1604+
MPI_Allreduce(MPI_IN_PLACE, &w_val, 1, MPI_DOUBLE, MPI_SUM, comm);
1605+
if (gamma_only) w_val /= nproc;
1606+
results_.smo_weight_sum[iat] = w_val;
1607+
}
1608+
for (int dir = 0; dir < 3; ++dir)
1609+
{
1610+
double ptot = results_.P_total[dir];
1611+
MPI_Allreduce(MPI_IN_PLACE, &ptot, 1, MPI_DOUBLE, MPI_SUM, comm);
1612+
if (gamma_only) ptot /= nproc;
1613+
results_.P_total[dir] = ptot;
1614+
}
1615+
}
1616+
}
1617+
#endif
15561618
}
15571619

15581620
void DeltaP::compute_hk_correction(const UnitCell& ucell,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
INPUT_PARAMETERS
2+
suffix autotest
3+
calculation scf
4+
basis_type lcao
5+
ecutwfc 100
6+
gamma_only 0
7+
nspin 1
8+
scf_thr 1.0e-6
9+
scf_nmax 30
10+
smearing_method gauss
11+
smearing_sigma 0.01
12+
mixing_type broyden
13+
mixing_beta 0.4
14+
mixing_restart 5e-4
15+
ks_solver genelpa
16+
symmetry -1
17+
deltap_switch 1
18+
deltap_corr 1
19+
deltap_inner_nmax 0
20+
deltap_lambda_init 0.0
21+
deltap_lambda_step 0.0
22+
deltap_lambda_mixing 0.0
23+
deltap_inner_thr 1.0e-2
24+
deltap_constraint_mode total
25+
deltap_gdir 3
26+
deltap_rm 6.0
27+
onsite_radius 6.0
28+
pseudo_dir ../PP_ORB
29+
orbital_dir ../PP_ORB
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
INPUT_PARAMETERS
2+
suffix autotest
3+
calculation scf
4+
basis_type lcao
5+
ecutwfc 100
6+
gamma_only 0
7+
nspin 1
8+
scf_thr 1.0e-6
9+
scf_nmax 30
10+
smearing_method gauss
11+
smearing_sigma 0.01
12+
mixing_type broyden
13+
mixing_beta 0.4
14+
mixing_restart 5e-4
15+
ks_solver genelpa
16+
symmetry 1
17+
deltap_switch 1
18+
deltap_corr 1
19+
deltap_inner_nmax 0
20+
deltap_lambda_init 0.0
21+
deltap_lambda_step 0.01
22+
deltap_lambda_mixing 0.1
23+
deltap_inner_thr 1.0e-3
24+
deltap_gdir 3
25+
deltap_rm 6.0
26+
onsite_radius 6.0
27+
pseudo_dir ../PP_ORB
28+
orbital_dir ../PP_ORB
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
K_POINTS
2+
0
3+
Gamma
4+
1 1 2 0 0 0
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
ATOMIC_SPECIES
2+
O 15.999 O.upf
3+
H 1.008 H_ONCV_PBE-1.0.upf
4+
5+
NUMERICAL_ORBITAL
6+
8_O_gga_100Ry_7au_2s2p1d.orb
7+
1_H_gga_100Ry_7au_2s1p.orb
8+
9+
LATTICE_CONSTANT
10+
1.8897261254578284
11+
12+
LATTICE_VECTORS
13+
10.0 0.0 0.0
14+
0.0 10.0 0.0
15+
0.0 0.0 10.0
16+
17+
ATOMIC_POSITIONS
18+
Cartesian_angstrom
19+
20+
O
21+
0.0
22+
1
23+
2.646 2.646 2.646
24+
25+
H
26+
0.0
27+
2
28+
2.246 2.646 2.957
29+
3.046 2.646 2.957
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
INPUT_PARAMETERS
2+
suffix autotest
3+
calculation scf
4+
init_wfc random
5+
nbands 8
6+
symmetry 0
7+
pseudo_dir /root/abacus-develop/tests/PP_ORB
8+
orbital_dir /root/abacus-develop/tests/PP_ORB
9+
nelec 8
10+
ecutwfc 20
11+
scf_thr 1e-04
12+
scf_nmax 25
13+
basis_type pw
14+
smearing_method gauss
15+
smearing_sigma 0.002
16+
mixing_type broyden
17+
mixing_beta 0.7
18+
berry_phase 1
19+
deltap_switch true
20+
deltap_corr 1
21+
deltap_gdir 3
22+
deltap_lambda_init 0.0
23+
deltap_lambda_step 0.0
24+
deltap_inner_thr 1e-2
25+
deltap_inner_nmax 0
26+
onsite_radius 6.0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
K_POINTS
2+
0
3+
Gamma
4+
1 1 1 0 0 0

0 commit comments

Comments
 (0)