Skip to content

Commit d4eced0

Browse files
committed
Fix get_pchg_pw and get_wf_pw under bndpar
1 parent 6a6d349 commit d4eced0

24 files changed

Lines changed: 2759 additions & 182 deletions

File tree

source/source_io/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ list(APPEND objects
1212
module_dos/cal_ldos.cpp
1313
module_ml/cal_mlkedf_desc.cpp
1414
module_dos/write_dos_pw.cpp
15-
module_energy/band_parallel_output.cpp
15+
module_output/band_parallel_output.cpp
1616
module_energy/write_bands.cpp
1717
module_energy/nscf_fermi_surf.cpp
1818
module_energy/write_eig_occ.cpp

source/source_io/module_chgpot/get_pchg_pw.h

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#define GET_PCHG_PW_H
33

44
#include "source_base/module_container/ATen/core/tensor.h"
5+
#include "source_base/parallel_comm.h"
56
#include "source_estate/module_charge/symm_rho.h"
7+
#include "source_io/module_output/band_parallel_output.h"
68
#include "source_io/module_output/cube_io.h"
79

810
namespace ModuleIO
@@ -18,6 +20,7 @@ namespace ModuleIO
1820
template <typename Device>
1921
void get_pchg_pw(const std::vector<int>& out_pchg,
2022
const int nspin,
23+
const int global_nbands,
2124
UnitCell* ucell,
2225
const psi::Psi<std::complex<double>, Device>* kspw_psi,
2326
const ModulePW::PW_Basis* pw_rho,
@@ -31,7 +34,9 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
3134
{
3235
const int nks = kv.get_nks(); // current process pool k-point count
3336
const int nkstot = kv.get_nkstot(); // total k-point count
34-
const int nbands = kspw_psi->get_nbands();
37+
// INPUT selectors and file labels use global bands, while BPCG Psi storage uses a
38+
// contiguous local shard. Constructing the layout collectively reconciles both views.
39+
const BandParallelLayout band_layout(kspw_psi->get_nbands(), global_nbands);
3540

3641
const int nks_without_spin = nspin == 2 ? nkstot / 2 : nkstot;
3742
const int smooth_nrxx = pw_wfc->nrxx;
@@ -40,8 +45,8 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
4045
const bool needs_interpolation = pw_rhod != pw_rho;
4146

4247
// Expand the INPUT selection into a fixed-size mask indexed directly by band.
43-
std::vector<int> bands_picked(nbands, 0);
44-
if (static_cast<int>(out_pchg.size()) > nbands)
48+
std::vector<int> bands_picked(global_nbands, 0);
49+
if (static_cast<int>(out_pchg.size()) > global_nbands)
4550
{
4651
ModuleBase::WARNING_QUIT("ModuleIO::get_pchg_pw",
4752
"The number of bands specified by `out_pchg` in the "
@@ -56,7 +61,7 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
5661
"Invalid values found!");
5762
}
5863
}
59-
const int length = std::min(static_cast<int>(out_pchg.size()), nbands);
64+
const int length = std::min(static_cast<int>(out_pchg.size()), global_nbands);
6065
for (int i = 0; i < length; ++i)
6166
{
6267
bands_picked[i] = static_cast<int>(out_pchg[i]);
@@ -117,6 +122,35 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
117122
return dense_host.data<std::complex<double>>();
118123
};
119124

125+
// Each buffer stores one rank-local dense-grid slab. It is global with respect to
126+
// band ownership, not spatial decomposition: POOL_WORLD still distributes the grid.
127+
std::vector<std::complex<double>> wfcr_up_global(dense_nrxx);
128+
std::vector<std::complex<double>> wfcr_down_global(is_spinor ? dense_nrxx : 0);
129+
// Only the owning band group may index the local Psi shard. After its FFT, BP_WORLD
130+
// broadcasts the slab to the corresponding plane-wave rank in every band group.
131+
// Every group must call this lambda in the same band/k-point/component order.
132+
auto transform_global_band = [&](const int global_band,
133+
const int basis_offset,
134+
const int ik,
135+
ct::Tensor& smooth,
136+
ct::Tensor& smooth_host,
137+
ct::Tensor& dense_host,
138+
std::vector<std::complex<double>>& global_wfcr) -> const std::complex<double>* {
139+
const int owner = band_layout.owner_group(global_band);
140+
if (band_layout.band_group() == owner)
141+
{
142+
const int local_band = band_layout.local_index(global_band);
143+
kspw_psi->fix_k(ik);
144+
const std::complex<double>* owner_wfcr
145+
= transform_wfc(&kspw_psi[0](local_band, basis_offset), ik, smooth, smooth_host, dense_host);
146+
std::copy(owner_wfcr, owner_wfcr + dense_nrxx, global_wfcr.begin());
147+
}
148+
#ifdef __MPI
149+
MPI_Bcast(global_wfcr.data(), dense_nrxx, MPI_DOUBLE_COMPLEX, owner, BP_WORLD);
150+
#endif
151+
return global_wfcr.data();
152+
};
153+
120154
std::vector<std::vector<double>> rho_band(nspin, std::vector<double>(dense_nrxx));
121155
// Convert a two-component spinor into the Pauli-basis fields (rho, m_x, m_y, m_z).
122156
// Per-k output overwrites the fields, whereas k-summed output accumulates weighted fields.
@@ -147,7 +181,9 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
147181
}
148182
};
149183

150-
for (int ib = 0; ib < nbands; ++ib)
184+
// Traverse global bands on every rank so that owner broadcasts remain collective-safe
185+
// even when the selected band belongs to a nonzero band group.
186+
for (int ib = 0; ib < global_nbands; ++ib)
151187
{
152188
if (!bands_picked[ib])
153189
{
@@ -162,23 +198,26 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
162198
if (if_separate_k)
163199
{
164200
// Preserve each Bloch state's contribution; no Brillouin-zone weight is applied here.
201+
// Each KPAR pool writes only the global k-points it owns.
165202
for (int ik = 0; ik < nks; ++ik)
166203
{
167204
const int ikstot = kv.ik2iktot[ik];
168205
const int spin_index = kv.isk[ik];
169206
// In collinear calculations the two spin channels share the same k-point numbering.
170207
const int k_number = ikstot % nks_without_spin + 1;
171208

172-
kspw_psi->fix_k(ik);
173-
const std::complex<double>* wfcr_up
174-
= transform_wfc(&kspw_psi[0](ib, 0), ik, wfcr_up_smooth, wfcr_up_smooth_host, wfcr_up_dense_host);
175-
const std::complex<double>* wfcr_up_host_data = wfcr_up;
209+
const std::complex<double>* wfcr_up_host_data
210+
= transform_global_band(ib, 0, ik, wfcr_up_smooth, wfcr_up_smooth_host, wfcr_up_dense_host, wfcr_up_global);
176211
const std::complex<double>* wfcr_down_host_data = nullptr;
177212
if (is_spinor)
178213
{
179-
const std::complex<double>* wfcr_down
180-
= transform_wfc(&kspw_psi[0](ib, npwx), ik, wfcr_down_smooth, wfcr_down_smooth_host, wfcr_down_dense_host);
181-
wfcr_down_host_data = wfcr_down;
214+
wfcr_down_host_data = transform_global_band(ib,
215+
npwx,
216+
ik,
217+
wfcr_down_smooth,
218+
wfcr_down_smooth_host,
219+
wfcr_down_dense_host,
220+
wfcr_down_global);
182221
}
183222

184223
const double spin_degeneracy = nspin == 1 ? 2.0 : 1.0;
@@ -218,21 +257,24 @@ void get_pchg_pw(const std::vector<int>& out_pchg,
218257
}
219258
else
220259
{
221-
// Form a Brillouin-zone weighted partial density for the selected band.
260+
// Form the pool-local part of the Brillouin-zone weighted density. Owner
261+
// broadcasts make this contribution identical across band groups.
222262
for (int ik = 0; ik < nks; ++ik)
223263
{
224264
const int spin_index = kv.isk[ik];
225265

226-
kspw_psi->fix_k(ik);
227-
const std::complex<double>* wfcr_up
228-
= transform_wfc(&kspw_psi[0](ib, 0), ik, wfcr_up_smooth, wfcr_up_smooth_host, wfcr_up_dense_host);
229-
const std::complex<double>* wfcr_up_host_data = wfcr_up;
266+
const std::complex<double>* wfcr_up_host_data
267+
= transform_global_band(ib, 0, ik, wfcr_up_smooth, wfcr_up_smooth_host, wfcr_up_dense_host, wfcr_up_global);
230268
const std::complex<double>* wfcr_down_host_data = nullptr;
231269
if (is_spinor)
232270
{
233-
const std::complex<double>* wfcr_down
234-
= transform_wfc(&kspw_psi[0](ib, npwx), ik, wfcr_down_smooth, wfcr_down_smooth_host, wfcr_down_dense_host);
235-
wfcr_down_host_data = wfcr_down;
271+
wfcr_down_host_data = transform_global_band(ib,
272+
npwx,
273+
ik,
274+
wfcr_down_smooth,
275+
wfcr_down_smooth_host,
276+
wfcr_down_dense_host,
277+
wfcr_down_global);
236278
}
237279

238280
const double weight = static_cast<double>(kv.wk[ik] / ucell->omega);

source/source_io/module_ctrl/ctrl_output_pw.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ void ModuleIO::ctrl_scf_pw(const int istep,
164164

165165
ModuleIO::get_pchg_pw(inp.out_pchg,
166166
inp.nspin,
167+
inp.nbands,
167168
&ucell,
168169
stp.template get_psi_d<T, Device>(),
169170
pw_rho,
@@ -288,6 +289,7 @@ void ModuleIO::ctrl_runner_pw(UnitCell& ucell,
288289
ModuleIO::get_wf_pw(inp.out_wfc_norm,
289290
inp.out_wfc_re_im,
290291
inp.nspin,
292+
inp.nbands,
291293
&ucell,
292294
stp.template get_psi_d<T, Device>(),
293295
pw_wfc,

source/source_io/module_energy/band_parallel_output.cpp

Lines changed: 0 additions & 79 deletions
This file was deleted.

source/source_io/module_energy/band_parallel_output.h

Lines changed: 0 additions & 24 deletions
This file was deleted.

source/source_io/module_energy/write_bands.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "write_bands.h"
2-
#include "band_parallel_output.h"
2+
#include "source_io/module_output/band_parallel_output.h"
33
#include "source_base/global_function.h"
44
#include "source_base/global_variable.h"
55
#include "source_base/timer.h"

source/source_io/module_energy/write_eig_occ.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "write_eig_occ.h"
22

3-
#include "band_parallel_output.h"
3+
#include "source_io/module_output/band_parallel_output.h"
44
#include "source_io/module_parameter/parameter.h"
55
#include "source_base/global_function.h"
66
#include "source_base/global_variable.h"

0 commit comments

Comments
 (0)