Skip to content

Fix part of 6608: Make IO output self-describing: running-log messages, cube data_desc, and ofs_running parameterization - #8068

Merged
mohanchen merged 51 commits into
deepmodeling:developfrom
mohanchen:2026-10-02-6
Oct 10, 2026
Merged

mohanchen merged 51 commits into
deepmodeling:developfrom
mohanchen:2026-10-02-6

Conversation

@mohanchen

@mohanchen mohanchen commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

fix part of #6608 fix #8096

Summary

This PR improves the readability and consistency of ABACUS IO output (running log and .cube files) and removes a class of default-argument debt (Rule 5) from the IO layer. The work is split into three themes that build on each other.

1. Running-log messages: label what is being written

The running log previously contained many bare Write data to file: ... lines that did not say what data was written. This PR adds descriptive labels and spin tags so each line is self-describing:

  • Sparse matrix outputs (out_mat_h, out_mat_dh, out_mat_*) now report Write H matrix ..., Write dH matrix ..., etc., with per-spin/channel tags where applicable.
  • Cube outputs now carry a data_desc string at every call site (charge density, partial charge, effective/electrostatic potential, kinetic energy density, electron localization function, local DOS, wave function norm/real/imag, exciton density). The spin tag is owned by the caller through make_data_desc (cube_io.h) instead of being inferred from is inside write_vdata_palgrid, so spin-summed (is = -1) and 1-based-index callers are labeled correctly. nspin=4 magnetic channels are labeled magnetization density m{x,y,z} (rho[1..3]) and effective magnetic field b{x,y,z} (the B_xc components of the potential) instead of bare "charge density" / "effective potential" for all four channels.
  • All (spin up ) / (spin down) log tags come from one header-only helper, ModuleIO::make_spin_tag (module_output/spin_tag.h). make_data_desc and the DM(k), DM(R), H(R), H(R)-term, Vxc(R), dH/dR, dS/dR, band and PW/LCAO wave-function writers all use it, so nspin=2 runs label both spin channels consistently.
  • Removed the pre-write Writing cube file <name> log lines in get_pchg_lcao.cpp / get_wf_lcao.cpp that duplicated the Write ... to file: line now emitted by write_vdata_palgrid.
  • H(R) CSR header uses an explicit has_efermi flag instead of string-matching the label, and the running-log banner for Fermi energy is emitted through a single path. The CSR header example in docs/advanced/elec_properties/hs_matrix.md is updated for the , E_Fermi = <value> eV annotation.

Tests:

  • test_hsr_writer.cpp gains a text-CSR case covering per-spin Fermi sourced from Efermi; fixed under single-rank __MPI (the Parallel_Orbitals source must call set_atomic_trace before gatherParallels, otherwise get_nnrow_atom throws on nat==0).
  • Refreshed hrs*.csr.ref for scf_out_hsr_spin2 to carry the E_Fermi header.
  • Fixed Fermi-energy assertions in hsr_writer and output_log unittests.
  • write_bands_test.cpp adds RunningLogNamesSpinChannels, which checks the nspin=2 Write eigenvalues (spin up / spin down) log lines.
  • New test_spin_tag.cpp (MODULE_IO_spin_tag) covers make_spin_tag.

2. Cube filename normalization

.cube filenames are now lowercase, short, and consistent with the chg.cube / chgs1.cube / pot.cube / wfi1s1k1re.cube family. Indices start from 1 and carry a short suffix indicating their meaning (s = spin, k = k-point, g = geometry step, st = state, i = band index).

  • SPIN<n>_CHG.cube → chg.cube (nspin=1) / chgs<n>.cube (nspin=2, 4) in esolver_dm2rho, the same naming as ctrl_output_fp. For nspin=4 all four density channels are now written, because the init_chg=file reader reads chgs1..4.cube once chgs1.cube exists and aborts if one is missing.
  • LDOS_<en>eV.cube → ldos_<en>ev.cube (cal_ldos; updated stm.py, catch_properties.sh, result.ref, README; git mv LDOS.cube.ref → ldos.cube.ref).
  • Exciton_avg_<type>_state<n>_spin<s>.cube → exc_<type>_st<n+1>_s<s+1>.cube (exciton_plotter; indices now start from 1). The matching .dat slice filename is renamed the same way, and the conditional-slice .dat becomes exc_cond_<type>_slice_st<n+1>.dat so one run no longer mixes Exciton_cond_..._state<N> (0-based) with exc_..._st<N+1> names for the same state.
  • chg_init.cpp reads tau from tau.cube / taus<n>.cube, aligning with the charge read path; the probe distinguishes nspin==1 vs nspin>1. If neither exists, it falls back to the legacy SPIN<n>_TAU.cube names (3.10-LTS and earlier) with a warning, and it warns before the Thomas-Fermi fallback when no tau cube is found.
  • Removed dead std::remove("./support/OLD2_SPIN1_CHG.cube") in test_chg_extra.cpp (no code path generates that file).
  • Help text and docs that describe the historical 3.10-LTS filenames (SPIN1_CHG.cube etc.) are intentionally left in place.

3. Parameterize ofs_running through IO output chains (Rule 5)

The IO output layer used to read GlobalV::ofs_running directly in many leaf and mid-level functions. This PR threads std::ofstream& ofs_running explicitly through:

  • write_vdata_palgrid (cube_io.h), write_bands, save_dH_sparse / output_dHR / output_dSR / output_TR / output_SR / output_mat_sparse, cal_ldos_lcao / cal_ldos_pw / stm_mode_pw / ldos_mode_pw, write_elf, write_chg_init / write_pot_init, Get_pchg_pw / Get_wf_pw begin + write_cube helpers, Get_pchg_lcao / Get_wf_lcao begin, ctrl_iter_pw / ctrl_scf_pw / ctrl_runner_pw / ctrl_runner_lcao / ctrl_scf_lcao / ctrl_output_fp, write_elecstat_pot, plus their explicit template instantiations (CPU/GPU, double/complex).
  • All esolver / non-IO boundary call sites pass GlobalV::ofs_running once at the boundary; the IO layer itself no longer reads the global.

Additionally, two historical default arguments are removed (Rule 5) and every caller now passes the value explicitly:

  • cube_io.h: removed data_desc = "data"; all 22 call sites pass a descriptive string (see theme 1).
  • write_bands.h: removed the nspin0 = 1 default on nscf_bands. The Write eigenvalues log line moved into write_bands, which owns nspin0, so nscf_bands keeps its upstream signature with no nspin0 parameter.

Governance notes

  • GlobalV dependency: net non-increasing at the PR level. The IO layer no longer reads GlobalV::ofs_running; reads are now concentrated at the esolver/control boundary (ctrl_scf_lcao takes ofs_running as a parameter and esolver_ks_lcao passes GlobalV::ofs_running at the boundary).
  • Rule 5: two default arguments removed; all call sites updated. write_cube's ndata_line = 6 remains as pre-existing debt (out of scope here).
  • Header includes: the <fstream> additions are in headers that now carry std::ofstream& parameters, and each is required by the new signature. cube_io.h includes the new header-only spin_tag.h, which depends only on <string>.

Test plan

  • make -j 30 passes.
  • ctest --test-dir build -V -R "rho_io|write_bands|hsr_writer|dhs_sparse|output_mat_sparse|CHARGE_extra" — 8/8 pass (MODULE_CHARGE_extra, MODULE_IO_rho_io, MODULE_IO_write_bands, MODULE_IO_write_bands_parallel, MODULE_IO_hsr_writer_test, MODULE_IO_hsr_writer_test_parallel, MODULE_IO_dhs_sparse_writer_test, MODULE_IO_output_mat_sparse_test).
  • python3 tools/03_code_analysis/code_quality_score.py on the 66 changed C++ files at head 2427fe3afe: average 73.5 (pass line 60), 52/66 pass. 14 files below 60 are pre-existing debt (tab_indentation, global_dependency, too_many_parameters) not introduced by this PR: ctrl_scf_lcao.cpp 0, esolver_ks_lcao.cpp 31, ctrl_output_pw.cpp 32, cal_ldos.cpp 33, dhs_sparse_writer.cpp 41, ctrl_output_fp.cpp 43, ctrl_runner_lcao.cpp 50, esolver_ks_pw.cpp 55, cal_ldos.h 55, exciton_plotter.cpp 56, test_chg_extra.cpp 57, esolver_fp.cpp 58, esolver_gets.cpp 58, pos_op_writer.cpp 59.
  • CASES_CPU.txt / CASES_GPU.txt (03_NAO_multik): newly enable scf_out_hsr_spin2 — it was previously in neither CI list, and its hrs{1,2}_nao.csr.ref were refreshed in this PR for the E_Fermi header, so CI now covers the new format.
  • props_mat.sh (compare_hr_csr): H(R) CSR bodies compare at 1e-8 with the , E_Fermi = ... eV annotation stripped, because it is printed with setprecision(6). The E_Fermi values are then compared separately at 1e-3 eV, so the refreshed .ref annotations are actually checked. A missing output or reference file now fails explicitly instead of passing through an empty process-substitution stream. S(R) carries no E_Fermi and is compared directly.
  • Full integrate/regression suite (tests/integrate) — to be run on the CI side; catch_properties.sh updated for the new ldos_<en>ev.cube filename.
  • Manual dispatch run required for workflow_dispatch-only workflows (e.g. interface.yml).

Review follow-up commits

Commits 1287175cb..3f5ac3b2a were pushed by @Critsium-xy during review. They address the review findings described above: the H(R) check silently passing, dm2rho naming (nspin=1 and nspin=4), legacy tau cube fallback, threading ofs_running through ctrl_iter_pw, ctrl_runner_pw, ctrl_scf_lcao, write_dipole and write_elecstat_pot, the shared spin-tag helper, and spin tags in the PW/dH logs. These commits were checked with agent_governance_check.py (no errors, net GlobalV/PARAM references -6 across these commits) and a local shell test of compare_hr_csr covering 5 cases (identical, E_Fermi off by 3e-4 eV, E_Fermi off by 0.1 eV, missing annotation, missing file). They were not built locally; build and test verification relies on the PR CI. The make -j 30 / ctest results listed above were run by the author on an earlier head.

The TB2J interface (issue deepmodeling#6608) reads the Fermi energy from ABACUS output
to set the upper bound of the Green's-function integral, but the
"EFERMI = ... eV" line was removed from output_efermi on 2025-06-22 and
the CSR header of H(R) carried no Fermi information either.

- output_log: output_efermi now takes elecstate::Efermi and prints
  " E_Fermi = <ef> eV" or " E_Fermi = <up> <down> eV    # two fermi
  energies (up, down)" when two_efermi is set.
- hsr_writer: write_hcontainer_csr accepts an extra efermi_eV argument
  and appends ", E_Fermi = <value> eV" to the "# spin index" header line
  only when label == "H". write_hsr threads elecstate::Efermi through
  and converts each spin channel via Efermi::get_efval(ispin).
- esolver_fp / ctrl_scf_lcao: pass pelec->eferm down to the writers.
- write_dh / hterm_writer: pass 0.0 for the Fermi argument since dH/dR
  and other derived terms are not Hamiltonians and must not carry the
  Fermi annotation.
- unit tests: migrate OutputEfermiTest to the Efermi signature, add
  TestSingleFermi / TestTwoFermi content checks; extend hsr_writer
  unittests with per-channel Fermi header coverage and an "S(R) has no
  E_Fermi" assertion; link fp_energy.cpp into MODULE_IO_hsr_writer_test.
- integration reference: refresh scf_out_hsr/hrs1_nao.csr.ref with the
  new header line; remaining hrs*.csr.ref files will follow after their
  reference Fermi values are confirmed.
@mohanchen
mohanchen requested a review from Critsium-xy October 2, 2026 09:21
@mohanchen mohanchen added Input&Output Suitable for coders without knowing too many DFT details Refactor Refactor ABACUS codes The Absolute Zero Reduce the "entropy" of the code to 0 labels Oct 2, 2026
@mohanchen mohanchen changed the title Fix 6608: Fix(TB2J): restore Fermi energy in H(R) CSR header and running log Fix #6608: Fix(TB2J): restore Fermi energy in H(R) CSR header and running log Oct 2, 2026
@mohanchen mohanchen changed the title Fix #6608: Fix(TB2J): restore Fermi energy in H(R) CSR header and running log Fix(TB2J): restore Fermi energy in H(R) CSR header and running log Oct 2, 2026
@mohanchen mohanchen changed the title Fix(TB2J): restore Fermi energy in H(R) CSR header and running log Fix part of 6608: (TB2J) restore Fermi energy in H(R) CSR header and running log Oct 2, 2026
abacus_fixer added 5 commits October 2, 2026 21:44
- test_hsr_writer: expect setprecision(6) significant-digit output
  (5.4321 / 3.2109) instead of fixed 6-decimal strings; write the two
  spin channels to separate files since istep=0 opens in truncate mode
  and the second write was overwriting the first.
- outputlog_test: recompute expected E_Fermi values with the actual
  ModuleBase::Ry_to_eV = 13.605698 constant instead of 13.605693122994.

Verified: ctest -R "MODULE_IO_hsr_writer_test|MODULE_IO_output_log_test"
passes 3/3.
@mohanchen mohanchen added Machine Learning & AI Issues related to AI Interfaces Interfaces with other packages labels Oct 2, 2026
Report each matrix file with a consistent "Write <X> matrix in NAO
basis to file:" line in running log so users can see the write action:
H(R), S(R), T(R), r(R), and dH/dR components now all follow the
eig/occ message style. Drop the redundant "#Print out dH/dR
components#" banner. Pass ofs_running into write_hsr, out_lat_r, and
out_rR instead of reading GlobalV inside the IO layer.
@mohanchen mohanchen changed the title Fix part of 6608: (TB2J) restore Fermi energy in H(R) CSR header and running log Fix part of 6608: (TB2J) restore Fermi energy in H(R) CSR header and running log, adding output information for most out_* commands Oct 2, 2026
@mohanchen mohanchen changed the title Fix part of 6608: (TB2J) restore Fermi energy in H(R) CSR header and running log, adding output information for most out_* commands Fix part of 6608: (TB2J) restore Fermi energy in H(R) CSR header and running log, adding output information for most out_* input keywords Oct 2, 2026
abacus_fixer and others added 9 commits October 3, 2026 07:14
Print "Write H(R) (<term> term) matrix in NAO basis to file: <fname>"
for the individual Hamiltonian terms (kinetic/nonlocal/local/hartree/
xc/exx) when out_mat_h_t/vnl/vl/vh/vxc/exx writes their H(R) CSR
files. Thread ofs_running through WriteHParams and gather_and_write
instead of reading GlobalV inside the IO layer.
Print "Write dH/dR (<term> term) matrix in NAO basis to file: <fname>"
for each dH/dR component CSR file written by out_mat_dh and
out_mat_dh_t/vnl/vl/vh/vxc/exx (including the Pulay variants and the
total dH sum). Thread ofs_running through WriteDHParams and pass a
term name into write_dh_perI instead of reading GlobalV in the IO
layer.
Add "Write <X> matrix in NAO basis to file" running-log lines for the
matrix outputs that previously stayed silent: DM(R) (out_dmr), DM(k)
(out_dmk, replacing a commented-out cout), dS/dR (out_mat_ds, and fix
the label that hardcoded "dH/dR" for dS files), T(k) (out_mat_tk),
L(R) (out_mat_l, replacing the large banner), and Vxc(R) (out_mat_xc2).

Mark spin-polarized channels as "(spin up  )"/"(spin down)" padded to
equal width before the word "matrix" so consecutive lines stay aligned.
Thread ofs_running through the IO functions (write_dmr, write_dmk,
write_Vxc_R) instead of reading GlobalV inside the IO layer.
…sages

Move the generic "Write data to file" message out of the low-level
ModuleIO::write_cube (shared by all volumetric outputs) up into
write_vdata_palgrid, which knows the spin component. Add a data_desc
parameter (default "data") so the charge/potential call sites can pass
"charge density" and "potential", and annotate spin-polarized files
with "(spin up  )"/"(spin down)".

Do the same for out_band: thread nspin0 into nscf_bands so bands1/bands2
are labeled by spin channel. eig_occ.txt holds all spins in one file and
stays unlabeled.
Cache the global running-log stream in a local std::ofstream& at the
top of ctrl_scf_lcao and pass that reference onward, instead of naming
GlobalV::ofs_running at each call site. This drops the repeated global
references (13 -> 1) and brings the PR's global-dependency budget back
below zero.
# Conflicts:
#	source/source_io/module_dhs/write_dh.h
#	source/source_io/module_dhs/write_dh_terms.cpp
Comment thread source/source_io/module_output/output_log.cpp
Comment thread source/source_io/module_output/output_log.cpp
Comment thread tests/03_NAO_multik/scf_out_hsr/hrs1_nao.csr.ref
Comment thread source/source_io/module_hs/unittests/test_hsr_writer.cpp
Comment thread source/source_io/module_hs/hsr_writer.cpp Outdated
Comment thread source/source_io/module_ctrl/ctrl_scf_lcao.cpp Outdated
Comment thread source/source_io/module_dm/write_dmk.cpp
Comment thread source/source_io/module_hs/hterm_writer.cpp Outdated
Comment thread tests/03_NAO_multik/scf_deltaspin4/README Outdated
abacus_fixer added 2 commits October 6, 2026 16:50
Add the ', E_Fermi = 10.3798 eV' annotation to the '# spin index' line
of hrs1_nao.csr.ref and hrs2_nao.csr.ref so the reference matches the
output of write_hcontainer_csr. The Fermi value (10.3798 eV) is taken
from the last E_Fermi row of the energy table in running_scf.log.
… write_hcontainer_csr

The previous implementation keyed the Fermi-energy annotation on the
string label == "H" and used 0.0 as a sentinel for 'no Fermi value'.
That silently emitted 'E_Fermi = 0 eV' when a caller wrote an H(R)
file without a Fermi value available (e.g. the gamma-folded test),
which looks like a real value.

Add an explicit 'const bool has_efermi' parameter to write_hcontainer_csr.
The spin-index header line now appends ', E_Fermi = <value> eV' iff
has_efermi is true, independent of label. Update all call sites:

  - write_hsr: H(R) -> true, S(R) -> false
  - write_h_term (T/V^NL/V^L/V^H/V^XC): false
  - write_dh_perI (dH/dR components): false
  - unittests: pass true/false explicitly

Add a Not(HasSubstr("E_Fermi")) assertion to GammaFoldedHeaderKeepsCsrReadable
to lock in that label="H" + has_efermi=false produces no Fermi line.
abacus_fixer added 2 commits October 8, 2026 15:57
- cube_io.h: remove `data_desc = "data"` default; pass explicit
  descriptive strings at all 22 call sites (charge density, partial
  charge, effective/electrostatic potential, kinetic energy density,
  electron localization function, local DOS, wave function norm/real/imag,
  exciton density).
- write_bands.h: remove `nspin0 = 1` default; pass nspin0=1 explicitly
  at 4 test call sites in write_bands_test.cpp.
- Normalize cube filenames to lowercase with consistent short prefixes:
  SPIN1_CHG.cube -> chgs1.cube (esolver_dm2rho)
  LDOS_<en>eV.cube -> ldos_<en>ev.cube (cal_ldos + stm.py + catch_properties.sh)
  Exciton_avg_<type>_state<n>_spin<s>.cube -> exc_<type>_st<n+1>_s<s+1>.cube
  (exciton_plotter; indices now start from 1)
- Rename test reference: LDOS.cube.ref -> ldos.cube.ref (git mv).
- Update result.ref and README to match new filenames.

Verification: make -j 30 passed; ctest 7/7 passed (rho_io, write_bands,
write_bands_parallel, hsr_writer_test, hsr_writer_test_parallel,
dhs_sparse_writer_test, output_mat_sparse_test); code_quality_score
average 74.9 (pass line 60), 3 files below 60 are pre-existing debt
(tab_indentation, global_dependency, too_many_parameters in
cal_ldos/ctrl_output_fp/exciton_plotter).
- chg_init.cpp: read_kin_file now probes and reads tau.cube (nspin==1)
  / taus1.cube (nspin>1) instead of the legacy SPIN1_TAU.cube /
  SPIN<n>_TAU.cube. Aligns with the charge read path (chg.cube /
  chgs1.cube) in the same file.
- test_chg_extra.cpp: remove dead `std::remove("./support/OLD2_SPIN1_CHG.cube")`
  in ExtrapolateChargeCase4; no code path generates that file.

Verification: make -j 30 passed; ctest 8/8 passed (MODULE_CHARGE_extra +
  the 7 IO tests from the prior commit); code_quality_score chg_init.cpp
  64 (pass), test_chg_extra.cpp 57 (pre-existing debt: tab_indentation,
  uppercase_constant, global_dependency).
@mohanchen mohanchen changed the title Fix part of 6608: (TB2J) restore Fermi energy in H(R) CSR header and running log, adding output information for most out_* input keywords Fix part of 6608: Make IO output self-describing: running-log messages, cube data_desc, and ofs_running parameterization Oct 8, 2026

@Critsium-xy Critsium-xy left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up review on fa75532.

Verification: ran agent_governance_check.py --base 4c69130 --head fa75532 (0 errors, 46 warnings, GlobalV net delta -5) and code_quality_score.py on the 66 changed C++ files; static cross-check of every write_vdata_palgrid call site, every hrs*.csr.ref, and renamed-filename references across tests/, tools/ and docs/. Not compiled and no tests executed locally, so the make -j 30 / ctest results in the body are unverified here.

Comment thread source/source_io/module_output/write_cube.cpp Outdated
Comment thread source/source_io/module_chgpot/get_pchg_lcao.cpp Outdated
Comment thread source/source_io/module_hs/hsr_writer.cpp
Comment thread source/source_lcao/module_lr/utils/exciton_plotter.cpp
Comment thread source/source_io/module_ctrl/ctrl_scf_lcao.cpp
Comment thread tests/03_NAO_multik/CASES_CPU.txt
Comment thread tests/03_NAO_multik/scf_out_hsr/hrs1_nao.csr.ref
Comment thread source/source_io/module_ctrl/ctrl_output_fp.cpp Outdated
abacus_fixer and others added 16 commits October 9, 2026 20:02
Address remaining review comments on PR deepmodeling#8068:

- Let callers own the spin tag via make_data_desc() in cube_io.h; the
  removed write_cube.cpp inference mislabeled is=-1/1-based/summed calls
  as "(spin down)" or "(spin up)". nspin=4 magnetic channels now log
  magnetization density mx/my/mz (chgs), effective magnetic field
  bx/by/bz (pots, holding B_xc) instead of bare "charge density" /
  "effective potential" for all four channels.
- Drop the 5 pre-write cube log lines duplicated by write_vdata_palgrid.
- Sync hs_matrix.md CSR header example with the E_Fermi annotation.
- Rename the conditional-slice .dat to the 1-based exc_cond_ style so
  one run no longer mixes Exciton_cond_..._state<N> (0-based) with
  exc_..._st<N+1> names for the same state.
- Strip the 6-digit E_Fermi header annotation before the 1e-8 CSR
  comparison in catch_properties.sh to avoid platform-dependent
  rounding failures; matrix tokens still compare at 1e-8.
# Conflicts:
#	source/source_io/module_ctrl/ctrl_output_fp.cpp
ReadFile() pre-checked inputs with os.path.isfile(), which returns False
for the /dev/fd/<n> pipes produced by bash process substitution <(...),
so the CSR comparisons in catch_properties.sh (added in 23d0ee4 to
strip the E_Fermi header annotation) aborted with "can not find file".
Open the path directly and catch OSError instead; missing files still
report the same error and exit code.
# Conflicts:
#	tests/integrate/tools/catch_properties.sh
- Add compare_hr_csr helper: a missing hrs*/ref file now fails explicitly
  instead of passing via an empty process-substitution stream.
- Compare the E_Fermi header values separately at 1e-3 eV so the updated
  .ref annotations are actually verified.
- Compare sr_nao.csr directly; S(R) carries no E_Fermi annotation.
- Drop unrelated commented-out npz entries from CASES_CPU/GPU.txt.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- dm2rho now writes chg.cube for nspin=1 (chgs<n>.cube otherwise), matching
  ctrl_output_fp and the init_chg=file reader.
- read_kin_file falls back to legacy SPIN<n>_TAU.cube names with a warning,
  and warns when no tau cube is found before the Thomas-Fermi fallback.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
plot_istate is documented as 0-based and write_slice_data prints the
0-based index in the .dat header, so the st<n> tag in exc_* file names
now uses the same index instead of istate+1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…l outputs

- ctrl_iter_pw / ctrl_runner_pw: pass the ofs_running parameter to
  write_wfc_pw, DONE and the ML-KEDF set_para instead of GlobalV.
- ctrl_output_fp: write_dipole uses the ofs_running parameter.
- ctrl_scf_lcao: take ofs_running as an explicit parameter instead of
  re-binding GlobalV::ofs_running locally; the caller passes the stream.
- Realign the ofs_running parameter in ctrl_output_pw instantiations.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…_bands

- Add ModuleIO::make_spin_tag (module_output/spin_tag.h) and use it in
  make_data_desc and the DM(k), DM(R), H(R), H(R)-term and Vxc(R) writers
  instead of seven copies of the same nested ternary.
- Move the "Write eigenvalues" log line into write_bands, which owns nspin0,
  so nscf_bands keeps its upstream signature (no extra nspin0 parameter).
- Test the nspin=2 running-log labels in write_bands_test and add
  test_spin_tag.cpp for the helper.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
For nspin=2 the PW wavefunction cubes, dS/dR and dH/dR sparse files, and
dH/dR term files now log "(spin up  )"/"(spin down)" like the LCAO
wavefunction and H(R) writers, using ModuleIO::make_spin_tag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…bels

make_spin_tag already returns an empty suffix for nspin=1 and nspin=4, so
get_wf_lcao builds the labels directly instead of duplicating defaults
behind if (nspin_ == 2) and passing an unused "magnetization" base.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r read

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This reverts commit aa26f65. The PR intentionally makes exciton file-name
indices 1-based (st<n+1>), matching the other normalized cube names, so
restore the author's naming.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dm2rho wrote only chgs1.cube for nspin=4. The init_chg=file reader treats
chgs1.cube as "cube files present" and then reads chgs2..4.cube, so a
restart from a dm2rho directory aborted in read_vdata_palgrid. Write every
channel, matching ctrl_output_fp.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The caller ctrl_output_fp already receives the running-log stream, so pass
it through instead of adding two GlobalV::ofs_running reads.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Critsium-xy

Copy link
Copy Markdown
Collaborator

@mohanchen I edited the PR description so it matches the review follow-up commits I pushed to this branch (1287175cb..3f5ac3b2a). The original text is kept in the description's edit history.

What changed in the description:

  • Theme 1: added a note on the shared ModuleIO::make_spin_tag helper (module_output/spin_tag.h).
  • Theme 2, dm2rho: it now writes chg.cube for nspin=1 and chgs<n>.cube for nspin=2/4. For nspin=4 it writes all four channels, so an init_chg=file restart no longer aborts on a missing chgs2.cube.
  • Theme 2, tau reader: it falls back to the legacy SPIN<n>_TAU.cube names with a warning instead of silently dropping them.
  • Theme 3: ctrl_scf_lcao and write_elecstat_pot were added to the threaded ofs_running list, and the local GlobalV alias note was removed. nscf_bands keeps its upstream signature, because the eigenvalue log line moved into write_bands.
  • Test plan:
    • New tests: RunningLogNamesSpinChannels and test_spin_tag.cpp.
    • props_mat.sh now checks E_Fermi at 1e-3 eV and fails on missing files.
    • The commented-out npz placeholders were removed from CASES_*.txt.
  • New section "Review follow-up commits": says exactly how these commits were verified. They were checked with the governance checker and a shell test of compare_hr_csr, and were not built locally; build and test verification relies on CI.

The exciton file names keep your 1-based st<n+1> convention. I reverted my earlier change to that.

@mohanchen
mohanchen merged commit 53a0386 into deepmodeling:develop Oct 10, 2026
18 checks passed
Critsium-xy added a commit to mohanchen/abacus-mc that referenced this pull request Oct 10, 2026
…d::vector

deepmodeling#8068 added a test that assigned `new int[1]` to ucell.iat2it, which no
longer compiles now that UnitCell owns iat2it as std::vector<int>. Use
resize() as the other test in this file already does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
mohanchen added a commit that referenced this pull request Oct 10, 2026
…ing reference members (#8080)

* Refactor: remove the UnitCell Statistics layer and flattening reference members

UnitCell stored its atom-count and index-map data in a nested `Statistics`
struct and re-exported every field as a reference member (`int& nat = st.nat`,
`int*& iat2it = st.iat2it`, ...). This created dual-view aliasing, an
invisible raw-pointer ownership rule (fixtures had to `new[]` but never
`delete[]`, and several unit tests double-freed as a result), and a latent
shallow-copy double-free since the implicit copy constructor remained
available while copy assignment was silently deleted by the reference members.

Changes:
- Repoint the only consumers of the `Statistics` type: module_symmetry and
  module_exx_symmetry interfaces now take `const UnitCell&` instead of
  `const Statistics&`; all call sites pass `ucell` (or `*ucell`).
- Move the nine fields into UnitCell as direct members under the existing
  top-level names, so `ucell.nat`-style call sites are unchanged. Delete the
  `st` member, the reference members, and the `Statistics` struct.
- Convert iat2it/iat2ia/iwt2iat/iwt2iw from raw int* to std::vector<int>;
  migrate the ~100 test/support allocation sites from `new int[]` to
  resize()/assign(). Production sites (unitcell.cpp, cal_wfc.cpp) and the
  two force_pw.cpp device-upload call sites use .data().
- Delete UnitCell copy constructor/assignment and default the move
  operations, so accidental copies fail at compile time.
- Update AGENTS.md: replace the obsolete fixture note with the new
  ownership/vector rule.

Verification:
- Full build succeeds (no compile errors).
- ctest -R "unitcell|CELL_SYMMETRY|symmetry|hcontainer|dftu|operator_lcao|
  module_dm|pdos|hsr|restart_exx|gint|relax|esolver": 33/33 passed.
- agent_governance_check: no issues.

No INPUT parameter or user-facing behavior change; docs/parameters.yaml
unaffected. The Lattice lat reference-member block is intentionally out of
scope and can follow the same recipe in a later PR.

* Fix GPU build: use .data() for iat2it cudaMemcpy in gint_gpu_vars

The Statistics refactor converted UnitCell::iat2it from int* to
std::vector<int>. The CUDA-only translation unit gint_gpu_vars.cpp was not
compiled by the local CPU build, so this call site was missed: cudaMemcpy
expects a const void* source but received the vector object. Pass
ucell.iat2it.data() instead, matching the force_pw.cpp device-upload sites.

* Delete UnitCell move operations to avoid double free

The defaulted move constructor shallow-copied the owning raw pointer
'atoms' together with 'set_atom_flag' without resetting the source, so
both the moved-to and moved-from objects ran delete[] on the same Atom
array. The defaulted move assignment was implicitly deleted because the
reference aliases into 'lat' (Coordinate, a1, latvec, ...) cannot be
re-bound, triggering -Wdefaulted-function-deleted. Explicitly delete
both move operations so any accidental move fails at compile time;
correct move semantics require an owning container for 'atoms' and
removal of the reference aliases in later refactoring steps.

* Add compile-time guard for UnitCell non-copyable/non-movable contract

Add static_asserts on std::is_copy/move_constructible/assignable so that
re-enabling either operation during future UnitCell refactoring fails the
translation unit at compile time instead of reintroducing the double
free and dangling 'lat' reference aliases.

* update AGENTS.md

* Decouple Symmetry::analy_sys from UnitCell

Replace the const UnitCell& parameter of analy_sys (and its three private
helpers is_all_movable, analyze_magnetic_group,
analyze_magnetic_group_nspin4) with only the index data they actually
read: nat, ntype, iat2it, iat2ia, itia2iat. This breaks the
UnitCell <-> Symmetry type-level dependency cycle: symmetry.h no longer
names UnitCell at all, and the three implementation files drop their
unitcell.h includes. The two other classes in the module that still need
UnitCell (Irreducible_Sector, Symmetry_rotation_k) carry their own
forward declaration now. All production and test call sites pass the
five data members explicitly; behavior is unchanged.

* Decouple Irred_Sector and Symmetry_rotation_k from UnitCell

Replace the const UnitCell& parameters of find_irred_sector,
cal_return_lattice_all, gen_symm_bvk (Irred_Sector) and cal_Ms /
contruct_2d_rot_mat_ao (Symmetry_rotation_k) with the data they
actually read: nat, ntype, the iat2it/iat2ia maps, and explicit
symm/atoms/lat/latvec/lmax arguments. This removes the possibility of
passing mismatched atoms/lat alongside one cell's index maps and makes
both headers free of any UnitCell name; the three implementation files
drop their unitcell.h includes. Drop the unused get_aRb_direct helpers
(no callers anywhere in the tree).

Rename for brevity: Irreducible_Sector -> Irred_Sector,
irreducible_sector.{h,cpp} -> irred_sec.{h,cpp} (matching the existing
irred_sec_bvk.cpp and the irs_ member),
find/get_irreducible_sector -> find/get_irred_sector, and
gen_symmetry_BvK -> gen_symm_bvk. Comments, log strings and the output
file name keep the standard "BvK" spelling. All three production call
sites (DFTU x2, RDMFT) and the EXX info printer are updated; behavior
is unchanged.

* Decouple EXX Symmetry_rotation from UnitCell and drop dead test helpers

The EXX/RPA/RDMFT rotation templates only consume the atom index maps,
so pass iat2it/iat2ia explicitly instead of const UnitCell&, and remove
the unitcell.h include from symm_rotation.h (forward-declare UnitCell
for the non-template print_symrot_info_k). TUs that dereference UnitCell
now include unitcell.h directly.

Delete unreachable helpers: test_HR_rotation (both overloads),
test_Cs_rotation, get_Rs_from_adjacent_list, get_Rs_from_BvK.

Also fix the three missed .hpp call sites of the Irred_Sector rename
(exx_lri_interface.hpp, exx_lri.hpp, rpa_lri.hpp).

Verified: make -j 30 builds abacus_max_para with 0 warnings;
MODULE_RI_EXX_SYMMETRY_rotation test target also builds.

* Point integration tests to local build path

Set the ABACUS executable in Autotest.sh and general_info to the local
build_max_para_test/abacus_max_para binary for local test runs.

* Fix Intel Makefile build after irred_sec rename

Makefile.Objects still listed irreducible_sector.o, which no longer
exists after renaming irreducible_sector.{h,cpp} to irred_sec.{h,cpp};
update it to irred_sec.o so the mpiicpx Makefile build links again.

* Fix iat2it/iat2ia allocation in relax_sync unit test

The upstream merge brought in a test that assigned new int[nat] to
ucell.iat2it/iat2ia, but these are std::vector<int> members on this
branch. Use resize() instead, matching the other fixtures in this file
and removing the leaked allocation.

Verified: MODULE_RELAX_relax_sync_test target builds with 0 errors.

* Revert general_info EXEC to 'abacus'

The local absolute build path broke CUDA CI jobs that do not have
this directory; restore the upstream default of resolving abacus
from PATH.

* Revert Autotest.sh executable to 'abacus'

Complete the partial revert in b6be72d: the hardcoded local path
build_max_para_test/abacus_max_para was still set in Autotest.sh, so
CUDA CI jobs (which lack that local CPU build) failed to launch every
integration test case. Restore the upstream default and resolve the
executable via PATH, ABACUS_EXE, or the -a option for local runs.

* Fix stale Statistics/Irreducible_Sector uses after merging #8099

The previous merge of upstream/develop brought in #8099, whose code still
used the pre-refactor API and broke every CI build:

- symm_rotation_k.cpp: reset_symmetry() assigned Irreducible_Sector(),
  renamed to Irred_Sector on this branch.
- symm_test_analysis.cpp and test_symm_rotation.cpp: replace ucell.st,
  find_irreducible_sector() and cal_Ms(kv, cell, ...) with the new
  explicit nat/ntype/iat2it/iat2ia/itia2iat signatures, and assign the
  index maps as std::vector instead of new int[].

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Fix test_hsr_writer after merging #8068: iat2it is now std::vector

#8068 added a test that assigned `new int[1]` to ucell.iat2it, which no
longer compiles now that UnitCell owns iat2it as std::vector<int>. Use
resize() as the other test in this file already does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: abacus_fixer <mohanchen@pku.eud.cn>
Co-authored-by: Critsium <tsfxwbbzxy@163.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Input&Output Suitable for coders without knowing too many DFT details Interfaces Interfaces with other packages Machine Learning & AI Issues related to AI Refactor Refactor ABACUS codes The Absolute Zero Reduce the "entropy" of the code to 0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IO layer cleanup: remove Rule 5 default arguments and normalize cube filenames

2 participants