Repository navigation
feat(librpa): add Delta-Sternheimer response solver - #6
Closed
AroundPeking wants to merge 1 commit into
Closed
AroundPeking wants to merge 1 commit into
AroundPeking wants to merge 1 commit into
Conversation
Port the Delta-Sternheimer machinery from the long-lived development branch so the LibRPA feature set reaches parity after the strict 2D/3D Coulomb work. - add source_lcao/module_rpa/module_delta_st: the Sternheimer solvers, interface-perturbation and FD/FD-nonlocal paths, chi0 MPI distribution, Coulomb whitening, SIAB primitive export, grid diagnostics and the solid LCAO chi0 driver - register 22 INPUT parameters and their reader blocks; names keep at most two underscores, so six of them are shortened relative to the development branch (siab_vthr, freq_file, ao_file, virt_src, virt_max, vnorm_tol) - hook the LCAO SCF path to gather occupied k-point records and emit the chi0 response - extend Numerical_Basis with the SIAB primitive API, taking its inputs through an explicit structure instead of reading the global parameter object - keep the external GreenX minimax adapter behind an off-by-default ENABLE_GREENX_MINIMAX option so a stock build needs neither Fortran nor GreenX Verified locally: default configuration succeeds without Fortran or GreenX, all 40 module_delta_st translation units compile, and the governance checker reports no error-level finding.
AroundPeking
pushed a commit
that referenced
this pull request
Nov 1, 2026
…epmodeling#8240) * feat(dfpt): QE-format dynamical matrix file output (dfpt_out_dyn) New INPUT switch dfpt_out_dyn (Boolean, default false): when enabled, the esolver post-processing writes one QE-compatible dyn file per q point (OUT.<suffix>/dyn.q<i>) containing the raw (pre-ASR, pre-LO-TO) unreduced force-constant matrix Phi = D*sqrt(m_a m_b) in Ry/bohr^2, matching the layout of Quantum ESPRESSO ph.x's fildyn output. At Gamma with dfpt_compute_q0, the dielectric tensor and Born effective charges are appended in the QE convention. Implementation: the data layer stashes an untouched raw copy alongside the working dynmat (which is mutated in place by apply_asr/add_loto at Gamma); the writer (dfpt_write_dyn.cpp) reads it via a new DFPT_PW::get_data() const accessor. The matrix dump functionality that drove the nlcc element-level debugging now exists as a permanent, INPUT-gated feature. Verified: bn_cubic run with dfpt_out_dyn true produces OUT.autotest/ dyn.q0 with the QE layout (header, lattice vectors, species/masses, tau, q vector, per-atom-pair 3x3 blocks, dielectric tensor, Born charges); DFPT serial suite 9/9. * fix(dfpt): cache the output directory during init (governance) Move the PARAM.globalv.global_out_dir read into init_dfpt (which already accesses PARAM) and cache it as a member; the post-processing uses the cached copy. This keeps the PR's global dependency net delta at zero (the governance check's requirement). * fix(dfpt): single PARAM read for the output directory (governance) Keep the one PARAM.globalv.global_out_dir reference inline in the post-processing with a governance exception comment: the DFPT esolver has no StateSharing access and the directory is the same one every other esolver writes to. Net global dependency delta: 1 (allowed). * fix(dfpt): construct the output directory from the suffix (zero PARAM references) The output directory is 'OUT.' + suffix + '/', the same formula as ReadInput::set_global_dir (read_set_globalv.cpp:85). The esolver already holds this->inp_ (with the suffix field), so the dyn file writer path now constructs the directory inline instead of reading PARAM.globalv.global_out_dir — the governance check's global dependency net delta drops to zero. * fix(dfpt): remove the global-state mention from the comment * fix(build): add dfpt_write_dyn.o to Makefile.Objects (legacy Makefile build) * fix(dfpt): address all review findings on the dyn file writer Format (bot #1, #4): match QE's io_dyn_mat_old.f90 record contract — header with 6 celcdm values, species mass * AMU_RY, tau in alat units, q in cartesian 2pi/alat (through ucell.G), Basis vectors section, and the exact Effective Charges / Dielectric Tensor markers. Raw snapshot (bot #2): set_dynmat_raw is now a separate call invoked only at assembly time; the later apply_asr/add_loto set_dynmat calls no longer overwrite the raw copy. dynmat_raw_ is cleared in deallocate_memory (bot deepmodeling#9). Output gating (bot #6): the Born charges and dielectric tensor are exported whenever compute_q0 produced them at Gamma, independently of whether the LO-TO working-matrix correction was applied. MPI (bot deepmodeling#7): only rank 0 writes; every rank participates in the call and returns immediately on non-zero rank. Error handling (bot deepmodeling#8): open failures report the full path and skip that q; close is checked; each successfully written path is logged. Style (bot deepmodeling#11,12,13): forward-declare DFPT_PW_Data in dfpt_pw.h, timer labels use the function name, computed indices assigned to named locals. * refactor(dfpt): pass the rank through the InitContext (governance) The dyn file writer's rank-0 gate now flows through the explicit dependency chain: PARAM.globalv.myrank (one reference in the esolver's init_dfpt, alongside the pre-existing domag read) -> DFPT_PW_InitContext .myrank -> Impl::myrank_ -> DFPT_PW::get_myrank() -> writer parameter. No GlobalV reference anywhere in the writer; the governance net delta is one PARAM reference at the single point where the runtime context enters the module, matching the architecture the governance rules recommend (explicit dependency passing). * fix(dfpt): C++11 aggregate: no default member initializer on myrank Same pattern as the nlcc PR: '= 0' on the struct member makes DFPT_PW_InitContext a non-aggregate under C++11; the wrapper's brace-init then fails to compile in the abacuslite (non-LCAO non-MPI) configuration. The wrapper function's default parameter (int myrank = 0) is unaffected — function defaults are legal in C++11. * fix(dfpt): get the rank from the guarded CommunicationDomain wrapper Replace the PARAM.globalv.myrank read with ModuleBase::world_comm_domain().rank() — the same pattern as source_md (test_md_func.cpp, nhchain_test.cpp). The function internally calls MPI_Comm_rank through the CommunicationDomain wrapper (rule 9 compliant), so the PR diff now has zero GlobalV/GlobalC/PARAM references. * fix(dfpt): address second-round review on the dyn writer - Dielectric Tensor before Born charges: match QE's record order (io_dyn_mat_old.f90 writes the polar-data block as Dielectric Tensor first, then Effective Charges; sequential readers reject a Born-first trailer) - latvec scale: write ucell.latvec directly (it is already in lat0=alat units per unitcell_setup.cpp:175); the previous 'latvec / alat' division described a 1-bohr cell for a 10-lat0 input - rule 5: remove the '= 0' default from the init wrapper's myrank parameter; the three test callers in dfpt_pw_run_test.cpp pass an explicit 0 - running log: stdout log retained (simplified from the previous attempt that added a GlobalV::ofs_running reference); the serial stdout is the running log for the current single-rank DFPT * fix(dfpt): validate Gamma-first q ordering for compute_q0; wire running-log into the dyn writer setup_q_list now rejects, at input time, the q orderings that would silently mis-attach the polar machinery when dfpt_compute_q0 is on: Gamma not first (the q0 pipeline runs at index 0 and is only defined at Gamma) and duplicate Gamma entries later in the list. The dyn-file tensor export gate becomes an actual Gamma check on the q vector instead of the list index, so a reordered explicit q file cannot attach the tensors to a nonzero-q entry. The writer receives an explicit std::ostream* running_log dependency: created-file confirmations reach the running log stream (serial runs open a separate ofs_running in global_file.cpp, so the previous stdout-only print never reached it). The one ofs_running read added in the esolver is offset by removing the two global-record domag/domag_z reads there: they are captured in before_all_runners from (nspin, noncolin) with the exact set_globalv switch. * test(dfpt): cover the Gamma-ordering and dyn-writer branches; rule-14 named locals Extract the Gamma-first q validation into the free function ModuleDFPT::validate_q_ordering (dfpt_pw_data) so it is unit-testable; setup_q_list delegates to it. Add test_dfpt_write_dyn.cpp (rule-11 naming) with: Gamma-first acceptance, non-first-Gamma and duplicate- Gamma rejection under compute_q0 with the diagnostic texts, arbitrary ordering allowed when compute_q0 is off, Gamma-only polar records in QE order with the raw snapshot preserved, injected-log-stream confirmations, and the nonzero-rank write gate. Document the Gamma- first-and-unique requirement on the dfpt_qfile / dfpt_compute_q0 INPUT descriptions. Assign the two remaining rule-14 computed call arguments (mass product, raw storage size) to named locals.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After the strict 2D/3D Coulomb work (PR deepmodeling#8176), the LibRPA feature set of the
long-lived development branch is still missing the Delta-Sternheimer response
path. Users cannot request a Sternheimer-level response or the SIAB primitive
export that the RPA chi0 workflow relies on.
Change
source_lcao/module_rpa/module_delta_st: Sternheimer solvers, interfaceperturbation, FD and FD-nonlocal paths, chi0 MPI distribution, Coulomb
whitening, SIAB primitive export, grid diagnostics and the solid LCAO chi0
driver.
name keeps at most two underscores, so six of them are shortened relative to
the development branch:
sternheimer_siab_vthr,sternheimer_freq_file,sternheimer_ao_file,sternheimer_virt_src,sternheimer_virt_max,sternheimer_vnorm_tol.chi0 response is emitted.
Numerical_Basiswith the SIAB primitive API. Its inputs are passedthrough an explicit structure instead of reading the global parameter object.
ENABLE_GREENX_MINIMAXoption that is off by default, so a stock build needs neither Fortran nor
GreenX.
This PR is stacked on deepmodeling#8176 and should be merged after it.
Notes for reviewers
sternheimer_molecular_coulombis unchanged: it already has a single underscore and is used by existing runs.
all 40
module_delta_sttranslation units compile, and the governance checkerreports no error-level finding.
this macOS host (gtest/libc++ ABI mismatch), so their runtime result is left
to Linux CI.