From 292c3d0b7e3d6671e4d21bdaa43e316e62f257aa Mon Sep 17 00:00:00 2001 From: Zanthoxylum <105619360+Zanthoxylum@users.noreply.github.com> Date: Mon, 2 Nov 2026 22:20:51 +0800 Subject: [PATCH 1/2] feat(pw): expose the serial basis assembly as PW_Basis::init_serial The plain serial assembly chain (initgrids -> initparameters -> default FFT mode -> setuptransform -> collect_local_pw) was duplicated in every serial test scaffolding because the production wrappers setup_pwrho / setup_pwwfc bundle it with global parallel state (GlobalV::NPROC_IN_ POOL / RANK_IN_POOL / ofs_running), the full Input_para, K_Vectors and GPU branches -- unreachable from a serial unit test. Expose the chain as public PW_Basis::init_serial and PW_Basis_K::init_serial (FFT-box + k-list variant) so heavily-used test setup references the source API instead of mirroring it; the DFPT serial fixture's SetupBases shrinks to the two init_serial calls plus its (k, q) data wiring. The parallel production path is untouched. All DFPT serial test binaries rebuilt from deleted binaries; full MODULE_DFPT ctest 10/10 (the local 11_PW_GPU integration failure is a pre-existing no-CUDA environment issue, identical on the unmodified baseline). --- source/source_basis/module_pw/pw_basis.h | 11 +++++++++++ source/source_basis/module_pw/pw_basis_k.cpp | 16 ++++++++++++++++ source/source_basis/module_pw/pw_basis_k.h | 16 ++++++++++++++++ source/source_basis/module_pw/pw_init.cpp | 15 ++++++++++++++- .../test_serial/dfpt_serial_fixture.cpp | 16 +++++----------- 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/source/source_basis/module_pw/pw_basis.h b/source/source_basis/module_pw/pw_basis.h index d476e59a542..cde31660195 100644 --- a/source/source_basis/module_pw/pw_basis.h +++ b/source/source_basis/module_pw/pw_basis.h @@ -97,6 +97,17 @@ class PW_Basis const bool xprime_in = true ); + //Serial basis assembly: the plain production sequence (initgrids -> + //initparameters -> default FFT mode -> setuptransform -> collect_local_pw) + //without any parallel/device context (no initmpi, default distribution). + //The reusable form of the setup chain for serial utilities and unit + //tests; the parallel production path stays in setup_pwrho. + void init_serial( + const double lat0_in, //unit length (unit in bohr) + const ModuleBase::Matrix3 latvec_in, // Unitcell lattice vectors (unit in lat0) + const double gridecut //unit in Ry, ecut to set up grids + ); + //Set parameters about full planewave, only used in OFDFT for now. void setfullpw( const bool inpt_full_pw = false, diff --git a/source/source_basis/module_pw/pw_basis_k.cpp b/source/source_basis/module_pw/pw_basis_k.cpp index 2c2d02bf927..3b15a0c16f2 100644 --- a/source/source_basis/module_pw/pw_basis_k.cpp +++ b/source/source_basis/module_pw/pw_basis_k.cpp @@ -529,4 +529,20 @@ double* PW_Basis_K::get_gk2_data() const return this->d_gk2; } +void PW_Basis_K::init_serial(const double lat0_in, + const ModuleBase::Matrix3 latvec_in, + const int nx_in, + const int ny_in, + const int nz_in, + const double ecut_in, + const int nk_in, + const ModuleBase::Vector3* kvec_d) +{ + initgrids(lat0_in, latvec_in, nx_in, ny_in, nz_in); + initparameters(false, ecut_in, nk_in, kvec_d); + this->fft_bundle.initfftmode(0); + setuptransform(); + collect_local_pw(); +} + } // namespace ModulePW \ No newline at end of file diff --git a/source/source_basis/module_pw/pw_basis_k.h b/source/source_basis/module_pw/pw_basis_k.h index 65e332b8a25..27cf40c0107 100644 --- a/source/source_basis/module_pw/pw_basis_k.h +++ b/source/source_basis/module_pw/pw_basis_k.h @@ -70,6 +70,22 @@ class PW_Basis_K : public PW_Basis const bool xprime_in = true ); + //Serial basis assembly on a given FFT box (usually the rho grid's + //nx/ny/nz so the two bases share the box): initgrids -> initparameters + //with the k list -> default FFT mode -> setuptransform -> + //collect_local_pw, without any parallel/device context. The reusable + //form of the setup chain for serial utilities and unit tests; the + //parallel production path stays in setup_pwwfc. + void init_serial( + const double lat0_in, + const ModuleBase::Matrix3 latvec_in, + const int nx_in, + const int ny_in, + const int nz_in, + const double ecut_in, + const int nk_in, + const ModuleBase::Vector3* kvec_d); + public: int nks=0;//number of k points in this pool ModuleBase::Vector3 *kvec_d=nullptr; // Direct coordinates of k points diff --git a/source/source_basis/module_pw/pw_init.cpp b/source/source_basis/module_pw/pw_init.cpp index 5240d35b12d..d534214c8f2 100644 --- a/source/source_basis/module_pw/pw_init.cpp +++ b/source/source_basis/module_pw/pw_init.cpp @@ -235,13 +235,26 @@ void PW_Basis:: initparameters( this->ggecut = pwecut_in / this->tpiba2; //ggecut should be no larger than gridecut - if(this->ggecut > this->gridecut_lat) + if(this->ggecut > this->gridecut_lat) { this->ggecut = this->gridecut_lat; } this->distribution_type = distribution_type_in; } +void PW_Basis:: init_serial( + const double lat0_in, + const ModuleBase::Matrix3 latvec_in, + const double gridecut +) +{ + initgrids(lat0_in, latvec_in, gridecut); + initparameters(false, gridecut); + this->fft_bundle.initfftmode(0); + setuptransform(); + collect_local_pw(); +} + // Set parameters about full planewave, used only in OFDFT for now. sunliang added 2022-08-30 void PW_Basis::setfullpw( const bool inpt_full_pw, diff --git a/source/source_pw/module_dfpt/test_serial/dfpt_serial_fixture.cpp b/source/source_pw/module_dfpt/test_serial/dfpt_serial_fixture.cpp index aa8ed639268..24db0e45338 100644 --- a/source/source_pw/module_dfpt/test_serial/dfpt_serial_fixture.cpp +++ b/source/source_pw/module_dfpt/test_serial/dfpt_serial_fixture.cpp @@ -38,18 +38,12 @@ void DFPTSerialBase::SetupBases(const ModuleBase::Vector3& k_d, int nbands) { G_ = ucell_.G; - pw_rho_.initgrids(lat0_, latvec_, rho_mult_ * ecutwfc_); - pw_rho_.initparameters(false, rho_mult_ * ecutwfc_); - pw_rho_.fft_bundle.initfftmode(0); - pw_rho_.setuptransform(); - pw_rho_.collect_local_pw(); - + // the serial assembly chains live in the PW_Basis / PW_Basis_K + // sources (init_serial); this fixture only supplies the geometry + // and the (k, q) data + pw_rho_.init_serial(lat0_, latvec_, rho_mult_ * ecutwfc_); const ModuleBase::Vector3 klist[1] = {k_d}; - pw_wfc_.initgrids(lat0_, latvec_, pw_rho_.nx, pw_rho_.ny, pw_rho_.nz); - pw_wfc_.initparameters(false, ecutwfc_, 1, klist); - pw_wfc_.fft_bundle.initfftmode(0); - pw_wfc_.setuptransform(); - pw_wfc_.collect_local_pw(); + pw_wfc_.init_serial(lat0_, latvec_, pw_rho_.nx, pw_rho_.ny, pw_rho_.nz, ecutwfc_, 1, klist); qlist_.nkstot = 1; qlist_.kvec_d.clear(); From 883b21de7c41aefd3c12a547c6c15ee709f4d44c Mon Sep 17 00:00:00 2001 From: Zanthoxylum <105619360+Zanthoxylum@users.noreply.github.com> Date: Tue, 3 Nov 2026 10:42:30 +0800 Subject: [PATCH 2/2] docs(pw): state the no-MPI compilation requirement of init_serial Per review: the no-initmpi use advertised by init_serial requires the PW sources compiled without __MPI -- with __MPI the initgrids overloads reduce over the object communicator, which is MPI_COMM_NULL on a fresh basis. Both init_serial declarations now state this; the DFPT fixture works because its test targets compile the PW sources with __MPI disabled. --- source/source_basis/module_pw/pw_basis.h | 9 +++++++-- source/source_basis/module_pw/pw_basis_k.h | 11 ++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/source/source_basis/module_pw/pw_basis.h b/source/source_basis/module_pw/pw_basis.h index cde31660195..4f30f5089dd 100644 --- a/source/source_basis/module_pw/pw_basis.h +++ b/source/source_basis/module_pw/pw_basis.h @@ -100,8 +100,13 @@ class PW_Basis //Serial basis assembly: the plain production sequence (initgrids -> //initparameters -> default FFT mode -> setuptransform -> collect_local_pw) //without any parallel/device context (no initmpi, default distribution). - //The reusable form of the setup chain for serial utilities and unit - //tests; the parallel production path stays in setup_pwrho. + //NOTE: this no-initmpi use requires the PW sources to be compiled + //without __MPI -- with __MPI the initgrids overloads reduce over this + //object's communicator, which is MPI_COMM_NULL on a fresh basis that + //never called initmpi. The reusable form of the setup chain for serial + //utilities and unit tests (compiled with __MPI disabled, like the DFPT + //serial test targets); the parallel production path stays in + //setup_pwrho. void init_serial( const double lat0_in, //unit length (unit in bohr) const ModuleBase::Matrix3 latvec_in, // Unitcell lattice vectors (unit in lat0) diff --git a/source/source_basis/module_pw/pw_basis_k.h b/source/source_basis/module_pw/pw_basis_k.h index 27cf40c0107..1a5e9cc8255 100644 --- a/source/source_basis/module_pw/pw_basis_k.h +++ b/source/source_basis/module_pw/pw_basis_k.h @@ -73,9 +73,14 @@ class PW_Basis_K : public PW_Basis //Serial basis assembly on a given FFT box (usually the rho grid's //nx/ny/nz so the two bases share the box): initgrids -> initparameters //with the k list -> default FFT mode -> setuptransform -> - //collect_local_pw, without any parallel/device context. The reusable - //form of the setup chain for serial utilities and unit tests; the - //parallel production path stays in setup_pwwfc. + //collect_local_pw, without any parallel/device context. NOTE: this + //no-initmpi use requires the PW sources to be compiled without __MPI + //-- with __MPI the initgrids overloads reduce over this object's + //communicator, which is MPI_COMM_NULL on a fresh basis that never + //called initmpi. The reusable form of the setup chain for serial + //utilities and unit tests (compiled with __MPI disabled, like the + //DFPT serial test targets); the parallel production path stays in + //setup_pwwfc. void init_serial( const double lat0_in, const ModuleBase::Matrix3 latvec_in,