Skip to content

Commit 38ae309

Browse files
author
abacus_fixer
committed
refactor(rhog_io): use namespace elecstate, replace ZEROS with std::fill, add input validation
- Rename namespace ModuleIO -> elecstate to match source_estate convention (rhog_io was the only source_estate file still using ModuleIO) - Replace 3x ModuleBase::GlobalFunc::ZEROS with std::fill, remove global_function.h dependency, add <algorithm> - Add defensive parameter checks at the top of read_rhog and write_rhog: - pw_basis null check - rhog null check - nspin range check (1-4) - read_rhog: nx/ny/nz > 0 check - Update all call sites in esolver_fp.cpp, charge_init.cpp, test_rhog_io.cpp - Update test expected warning strings to match new namespace
1 parent b6cc3c2 commit 38ae309

6 files changed

Lines changed: 257 additions & 32 deletions

File tree

README20260902

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# para* 重构计划(分支 2026-09-02-b)
2+
3+
## 背景与起点
4+
5+
- **分支**:`2026-09-02-b`,起点 commit `2a7696f5d`(step-0 cleanup source_base parallel_*)
6+
- **基线状态**:`source_base/` 下有 14 个 `parallel_*` 文件(2d/cell/comm/common/device/global/grid/reduce),**没有** `module_parallel/` 目录,**没有** ParallelPartition——从 0 开始
7+
- 之前分支上尝试过 ParallelPartition(8 个裸 MPI_Comm 成员)和 ParaTag enum 两套方案,都已推倒
8+
9+
## 核心设计(已定)
10+
11+
**两个类,放在 `source/source_base/module_parallel/` 下:**
12+
13+
### 1. `ParaWorld` —— 单个通信域
14+
- 内容:`tag`(字符串常量)+ `comm`(MPI_Comm,串行下不存在)+ `rank` + `size`
15+
- 把原本散在 GlobalV 的并行参数(NPROC_IN_POOL、RANK_IN_POOL 等)收进对应域对象
16+
- 方法:`tag()` / `rank()` / `size()` / `comm()`(仅 __MPI)/ `valid()` / `static serial(tag)` 安全退化(size=1, rank=0)
17+
- 串行编译:`comm()` 用 `#ifdef __MPI` 包住,`rank()`/`size()`/`tag()` 总可用
18+
- 域特有参数(如 npw_per_proc、2D 网格行列)**不放进类**,由函数按需另外传
19+
20+
### 2. `ParaCollection` —— 全域容器
21+
- 内容:`std::vector<ParaWorld>`
22+
- 查找:`find(tag)` 按字符串 tag 线性查找,**找不到返回静态空域(安全退化,不抛异常)**
23+
- tag 用常量(避免裸字符串拼写错误运行时才暴露)
24+
25+
### 3. `ParaTag` —— 域标签常量
26+
- 8 大域:`pw` / `kmesh` / `bsame_kdiff` / `bdiff_ksame` / `rgrid` / `diag` / `matrix` / `atom`
27+
- 对应原全局:POOL_WORLD / KP_WORLD / INT_BGROUP / BP_WORLD / GRID_WORLD / DIAG_WORLD / matrix / atom
28+
29+
## 目标
30+
31+
- 函数通过**注入** `const ParaWorld&` 或 `const ParaCollection&` 获取通信域,不再读裸全局 POOL_WORLD/GlobalV
32+
- wrapper(Parallel_Common::bcast_* / Parallel_Reduce::reduce_*)加 `ParaWorld` 重载,`#ifdef __MPI` 收进 wrapper 内部,调用点无 `#ifdef`、无 MPI_Comm,串行并行都能编译跑
33+
- 测试用 `ParaWorld::serial(tag)` 或一行工厂构造,**去掉 GlobalV/divide_pools/set_global_partition 样板**
34+
35+
## 分步计划(每步一个 commit,确认合理再进下一步)
36+
37+
| 步骤 | 内容 | commit 信息 |
38+
|---|---|---|
39+
| **step 1** | 建 `module_parallel/` 目录 + `ParaWorld` 类(tag 常量 + comm/rank/size + `serial()` + `valid()`),含单元测试 + CMake/Makefile.Objects 接线 | `feat(parallel): add ParaWorld comm-domain value type` |
40+
| **step 2** | `ParaCollection`(`vector<ParaWorld>` + `find(tag)` 安全退化返回静态空域),含单元测试 | `feat(parallel): add ParaCollection domain container` |
41+
| **step 3** | 用 `ParaWorld`/`ParaCollection` 表达 8 大域装配(替代旧 divide_pools 全局写法),接进 driver 初始化 | `feat(parallel): assemble domains into ParaCollection at driver` |
42+
| **step 4** | `Parallel_Common::bcast_bool` 加 `ParaWorld` 重载(`#ifdef __MPI` 收进 wrapper,串行 no-op,旧签名保留) | `feat(parallel): bcast_bool overload taking ParaWorld` |
43+
| **step 5** | rhog_io.cpp 打样:注入 `ParaWorld`,`bcast_bool(error, pw)` 一行无 `#ifdef`;read_rhog_test 改一行构造去 GlobalV | `refactor(io): inject ParaWorld into read_rhog` |
44+
45+
## 命名与规范约束
46+
47+
- 文件名小写+下划线:`para_world.h/.cpp`、`para_collection.h/.cpp`
48+
- C++11,4 空格缩进,大括号独占一行,不用 `using namespace std`,注释用英文 doxygen 格式
49+
- 不加默认参数,不用全局变量(ParaCollection 通过注入传递,不做全局单例)
50+
- include guard 用短名,与同目录其它文件一致
51+
- 不用 goto,不用宏做域替换,struct 不裸露公有成员
52+
- 函数参数带校验(指针非空、int 范围合理)
53+
54+
## 验证方式
55+
56+
- 编译目录:`/home/510Group/6_abacus_mc/abacus-mc/build_max_para_test`,命令 `make -j 30`
57+
- 测试:`OMP_NUM_THREADS=1 ctest -V -R <pattern>`
58+
- 注意:沙箱内 MPI 测试会因 `/dev/nvidiactl` 受限误报崩溃,需看 ctest 日志实际结果
59+
- 每步 commit 前确认编译 0 错误 + 相关测试通过
60+
61+
## 待确认细节(开工前)
62+
63+
1. 文件路径 `source/source_base/module_parallel/para_world.h/.cpp` 是否 OK
64+
2. `ParaWorld` 串行下 `comm()` 不存在(`#ifdef __MPI`),`rank()`/`size()` 返回 0/1,`tag()` 总可用——是否 OK
65+
3. 从 step 1 开始,还是想先调整步骤划分

source/source_esolver/esolver_fp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ void ESolver_FP::iter_finish(UnitCell& ucell, const int istep, int& iter, bool&
243243
// Only pool 0 writes the rhog file (rhog is identical across pools).
244244
if (GlobalV::MY_POOL == 0)
245245
{
246-
ModuleIO::write_rhog(PARAM.globalv.global_out_dir + this->inp_->suffix + "-CHARGE-DENSITY.restart",
246+
elecstate::write_rhog(PARAM.globalv.global_out_dir + this->inp_->suffix + "-CHARGE-DENSITY.restart",
247247
PARAM.globalv.gamma_only_pw,
248248
this->pw_rhod,
249249
this->inp_->nspin,
@@ -264,7 +264,7 @@ void ESolver_FP::iter_finish(UnitCell& ucell, const int istep, int& iter, bool&
264264
}
265265
if (GlobalV::MY_POOL == 0)
266266
{
267-
ModuleIO::write_rhog(PARAM.globalv.global_out_dir + this->inp_->suffix + "-TAU-DENSITY.restart",
267+
elecstate::write_rhog(PARAM.globalv.global_out_dir + this->inp_->suffix + "-TAU-DENSITY.restart",
268268
PARAM.globalv.gamma_only_pw,
269269
this->pw_rhod,
270270
this->inp_->nspin,

source/source_estate/module_charge/charge_init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void Charge::init_rho(const UnitCell& ucell,
5555
binary << PARAM.globalv.global_readin_dir << PARAM.inp.suffix + "-CHARGE-DENSITY.restart";
5656
// Temporary bridge: use factory until ParaCollection is wired into driver.
5757
Parallel::ParaWorld pw_world = Parallel::make_pw_world();
58-
if (ModuleIO::read_rhog(binary.str(), rhopw, nspin, rhog, pw_world, &GlobalV::ofs_warning))
58+
if (elecstate::read_rhog(binary.str(), rhopw, nspin, rhog, pw_world, &GlobalV::ofs_warning))
5959
{
6060
GlobalV::ofs_running << " Read electron density from file: " << binary.str() << std::endl;
6161
for (int is = 0; is < nspin; ++is)
@@ -152,7 +152,7 @@ void Charge::init_rho(const UnitCell& ucell,
152152

153153
std::stringstream binary;
154154
binary << PARAM.globalv.global_readin_dir << PARAM.inp.suffix + "-TAU-DENSITY.restart";
155-
if (ModuleIO::read_rhog(binary.str(), rhopw, nspin, kin_g.data(), pw_world, &GlobalV::ofs_warning))
155+
if (elecstate::read_rhog(binary.str(), rhopw, nspin, kin_g.data(), pw_world, &GlobalV::ofs_warning))
156156
{
157157
GlobalV::ofs_running << " Read in the kinetic energy density: " << binary.str() << std::endl;
158158
for (int is = 0; is < nspin; ++is)

source/source_estate/rhog_io.cpp

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#include "source_base/module_out/binstream.h"
2-
#include "source_base/global_function.h"
32
#include "source_base/vector3.h"
43
#include "source_base/module_parallel/para_mpi_func.h"
54
#include "rhog_io.h"
5+
#include <algorithm>
66
#include <numeric>
77
#include <unistd.h>
88

@@ -20,13 +20,34 @@ inline void warn(std::ostream* os,
2020
}
2121
} // namespace
2222

23-
bool ModuleIO::read_rhog(const std::string& filename,
23+
bool elecstate::read_rhog(const std::string& filename,
2424
const ModulePW::PW_Basis* pw_rhod,
2525
const int nspin,
2626
std::complex<double>** rhog,
2727
const Parallel::ParaWorld& pw_world,
2828
std::ostream* os_warning)
2929
{
30+
if (pw_rhod == nullptr)
31+
{
32+
warn(os_warning, pw_world, "elecstate::read_rhog", "pw_rhod is null");
33+
return false;
34+
}
35+
if (rhog == nullptr)
36+
{
37+
warn(os_warning, pw_world, "elecstate::read_rhog", "rhog is null");
38+
return false;
39+
}
40+
if (nspin <= 0 || nspin > 4)
41+
{
42+
warn(os_warning, pw_world, "elecstate::read_rhog", "nspin must be 1, 2, or 4");
43+
return false;
44+
}
45+
if (pw_rhod->nx <= 0 || pw_rhod->ny <= 0 || pw_rhod->nz <= 0)
46+
{
47+
warn(os_warning, pw_world, "elecstate::read_rhog", "PW_Basis grid dimensions must be positive");
48+
return false;
49+
}
50+
3051
const int nx = pw_rhod->nx;
3152
const int ny = pw_rhod->ny;
3253
const int nz = pw_rhod->nz;
@@ -52,7 +73,7 @@ bool ModuleIO::read_rhog(const std::string& filename,
5273

5374
if (error)
5475
{
55-
warn(os_warning, pw_world, "ModuleIO::read_rhog", "Can't open file " + filename);
76+
warn(os_warning, pw_world, "elecstate::read_rhog", "Can't open file " + filename);
5677
return false;
5778
}
5879

@@ -69,23 +90,23 @@ bool ModuleIO::read_rhog(const std::string& filename,
6990
}
7091
if (npwtot_in > pw_rhod->npwtot)
7192
{
72-
warn(os_warning, pw_world, "ModuleIO::read_rhog", "some planewaves in file are not used");
93+
warn(os_warning, pw_world, "elecstate::read_rhog", "some planewaves in file are not used");
7394
}
7495
else if (npwtot_in < pw_rhod->npwtot)
7596
{
76-
warn(os_warning, pw_world, "ModuleIO::read_rhog", "some planewaves in file are missing");
97+
warn(os_warning, pw_world, "elecstate::read_rhog", "some planewaves in file are missing");
7798
}
7899
if (nspin_in < nspin)
79100
{
80-
warn(os_warning, pw_world, "ModuleIO::read_rhog", "some spin channels in file are missing");
101+
warn(os_warning, pw_world, "elecstate::read_rhog", "some spin channels in file are missing");
81102
}
82103
}
83104

84105
Parallel::bcast_bool(error, pw_world);
85106

86107
if (error)
87108
{
88-
warn(os_warning, pw_world, "ModuleIO::read_rhog", "gamma_only read from file is inconsistent with INPUT");
109+
warn(os_warning, pw_world, "elecstate::read_rhog", "gamma_only read from file is inconsistent with INPUT");
89110
return false;
90111
}
91112

@@ -115,7 +136,7 @@ bool ModuleIO::read_rhog(const std::string& filename,
115136
// set to zero
116137
for (int is = 0; is < nspin; ++is)
117138
{
118-
ModuleBase::GlobalFunc::ZEROS(rhog[is], pw_rhod->npw);
139+
std::fill(rhog[is], rhog[is] + pw_rhod->npw, std::complex<double>(0.0, 0.0));
119140
}
120141
// maps ixyz tp ig
121142
std::vector<int> fftixyz2ig(pw_rhod->nxyz, -1); // map isz to ig.
@@ -176,8 +197,8 @@ bool ModuleIO::read_rhog(const std::string& filename,
176197
{
177198
rhog[3][ig] = rhog[1][ig];
178199
}
179-
ModuleBase::GlobalFunc::ZEROS(rhog[1], pw_rhod->npw);
180-
ModuleBase::GlobalFunc::ZEROS(rhog[2], pw_rhod->npw);
200+
std::fill(rhog[1], rhog[1] + pw_rhod->npw, std::complex<double>(0.0, 0.0));
201+
std::fill(rhog[2], rhog[2] + pw_rhod->npw, std::complex<double>(0.0, 0.0));
181202
}
182203
}
183204

@@ -188,7 +209,7 @@ bool ModuleIO::read_rhog(const std::string& filename,
188209
return true;
189210
}
190211

191-
bool ModuleIO::write_rhog(const std::string& fchg,
212+
bool elecstate::write_rhog(const std::string& fchg,
192213
const bool gamma_only,
193214
const ModulePW::PW_Basis* pw_rho,
194215
const int nspin,
@@ -197,6 +218,22 @@ bool ModuleIO::write_rhog(const std::string& fchg,
197218
const Parallel::ParaWorld& pw_world,
198219
std::ostream* os_warning)
199220
{
221+
if (pw_rho == nullptr)
222+
{
223+
warn(os_warning, pw_world, "elecstate::write_rhog", "pw_rho is null");
224+
return false;
225+
}
226+
if (rhog == nullptr)
227+
{
228+
warn(os_warning, pw_world, "elecstate::write_rhog", "rhog is null");
229+
return false;
230+
}
231+
if (nspin <= 0 || nspin > 4)
232+
{
233+
warn(os_warning, pw_world, "elecstate::write_rhog", "nspin must be 1, 2, or 4");
234+
return false;
235+
}
236+
200237
// only rank 0 in the domain writes the header; all ranks cooperate
201238
// on sequential writes synchronized by barriers.
202239
const int irank = pw_world.rank();
@@ -216,7 +253,7 @@ bool ModuleIO::write_rhog(const std::string& fchg,
216253
ofs.open(fchg, std::ios::binary);
217254
if (!ofs)
218255
{
219-
warn(os_warning, pw_world, "ModuleIO::write_rhog", "File I/O failure: cannot open file " + fchg);
256+
warn(os_warning, pw_world, "elecstate::write_rhog", "File I/O failure: cannot open file " + fchg);
220257
return false;
221258
}
222259
ofs.write(reinterpret_cast<char*>(&size), sizeof(size));

source/source_estate/rhog_io.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* rho
4343
*/
4444

45-
namespace ModuleIO
45+
namespace elecstate
4646
{
4747

4848
bool read_rhog(const std::string& filename,
@@ -61,6 +61,6 @@ bool write_rhog(const std::string& fchg,
6161
const Parallel::ParaWorld& pw_world,
6262
std::ostream* os_warning);
6363

64-
} // namespace ModuleIO
64+
} // namespace elecstate
6565

6666
#endif

0 commit comments

Comments
 (0)