Skip to content

source_basis/module_ao: remove the last #define private public in the module - #7965

Merged
mohanchen merged 1 commit into
deepmodeling:developfrom
Critsium-xy:refactor/orb-nonlocal-lm-friend
Sep 14, 2026
Merged

mohanchen merged 1 commit into
deepmodeling:developfrom
Critsium-xy:refactor/orb-nonlocal-lm-friend

Conversation

@Critsium-xy

Copy link
Copy Markdown
Collaborator

source_basis/module_ao: last access hack in the module, via accessors plus one friend

orb_nonlocal_lm_test.cpp is the last file in module_ao carrying
#define private public. It reaches 78 times into Numerical_Nonlocal_Lm from
its TEST_F bodies. Most of that needs nothing from the class: ten of the members
already have public accessors, so nnl[ip].nr becomes nnl[ip].getNr(),
.r_radial[ir] becomes .getRadial(ir), .beta_k[ik] becomes
.getBeta_k(ik), and so on.

Six things have no public route and get friend class NumericalNonlocalLmTest;
plus thin read-only forwarders on the fixture: the members label, kcut,
index_proj and rab, and the private methods freemem() and renew(), which
the FreeAndRenew test exists to exercise. Friendship is not inherited and a
TEST_F body lives in a derived class, hence the forwarders -- the arrangement
established in #7949.

Nothing that mutates state is exposed. The r->k->r round-trip check does reach
deep -- it swaps the r-space and k-space arrays of a projector, reallocates
rab, and calls the private get_kradial() -- but that code lives in
NumericalNonlocalLmTest::err_r2k2r, a member of the fixture itself, so the
friend declaration covers it and it is unchanged. 28 of the 106 total accesses
are inside fixture helpers like that one and needed no edit.

No test expectation changed; every substitution reads the same member through
the accessor that returns it. With this, module_ao has no
#define private public left. Occurrences tree-wide 84 -> 83.

Production change is four lines: a forward declaration and one friend.

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

Verification

Linux, cmake -B build -G Ninja -DBUILD_TESTING=ON -DENABLE_LCAO=ON -DENABLE_MPI=ON -DENABLE_OPENMP=ON, then cmake --install build (the module_ao tests take their orbital data from install(DIRECTORY lcao_H2O ...)):

  • Build: the only failing target is source_lcao/module_lr/.../lr_io_krlist.cpp.o, on ri_util.h: RI/global/Array_Operator.h: No such file or directory. That is pre-existing on develop in an environment without LibRI headers (from Refactor LR_IO function and add test case 58_KP_LR_BSE #7849); this PR touches neither file.
  • All four module_ao tests pass: MODULE_AO_ORB_nonlocal_test, MODULE_AO_ORB_nonlocal_lm_test, MODULE_AO_ORB_atomic_lm_test, MODULE_AO_ORB_read_test.
  • agent_governance_check.py --base upstream/develop --head HEAD: 0 errors. The access-hack ratchet reports nothing (1 removed, 0 added), and no PARAM/GlobalV/GlobalC reference is added or removed.

No INPUT parameter and no user-visible behaviour changed, so docs/parameters.yaml and docs/advanced/input_files/input-main.md need no update.

🤖 Generated with Claude Code

… plus one friend

`orb_nonlocal_lm_test.cpp` is the last file in `module_ao` carrying
`#define private public`. It reaches 78 times into `Numerical_Nonlocal_Lm` from
its TEST_F bodies. Most of that needs nothing from the class: ten of the members
already have public accessors, so `nnl[ip].nr` becomes `nnl[ip].getNr()`,
`.r_radial[ir]` becomes `.getRadial(ir)`, `.beta_k[ik]` becomes
`.getBeta_k(ik)`, and so on.

Six things have no public route and get `friend class NumericalNonlocalLmTest;`
plus thin read-only forwarders on the fixture: the members `label`, `kcut`,
`index_proj` and `rab`, and the private methods `freemem()` and `renew()`, which
the FreeAndRenew test exists to exercise. Friendship is not inherited and a
TEST_F body lives in a derived class, hence the forwarders -- the arrangement
established in deepmodeling#7949.

Nothing that mutates state is exposed. The r->k->r round-trip check does reach
deep -- it swaps the r-space and k-space arrays of a projector, reallocates
`rab`, and calls the private `get_kradial()` -- but that code lives in
`NumericalNonlocalLmTest::err_r2k2r`, a member of the fixture itself, so the
friend declaration covers it and it is unchanged. 28 of the 106 total accesses
are inside fixture helpers like that one and needed no edit.

No test expectation changed; every substitution reads the same member through
the accessor that returns it. With this, `module_ao` has no
`#define private public` left. Occurrences tree-wide 84 -> 83.

Production change is four lines: a forward declaration and one friend.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mohanchen mohanchen added Refactor Refactor ABACUS codes The Absolute Zero Reduce the "entropy" of the code to 0 labels Sep 14, 2026
@mohanchen
mohanchen merged commit 9e47c03 into deepmodeling:develop Sep 14, 2026
17 checks passed
mohanchen pushed a commit that referenced this pull request Sep 14, 2026
…public (#7966)

Continues the cleanup (#7940, #7949, #7952, #7953, and open #7963/#7964/#7965).
Two class families this time, handled by the same triage: use the accessor that
exists, and grant friendship only for what genuinely has no public route.

Measured against the TEST_F bodies -- accesses inside fixture members need
nothing, since the fixture is the friend -- the four files touch far less than
their size suggests: 10, 6, 5 and 1 sites respectively.

- **`pw_basis_k_test.cpp` needs nothing granted.** Its only non-public reads are
  `device` and `precision`, and `PW_Basis` already has `get_device()` /
  `get_precision()`.

- **`pw_basis_test.cpp`** reads the same two through those accessors, and calls
  three protected routines -- `distribute_g()`, `distribute_r()` and
  `getstartgr()` -- which set 7, 28 and 33 members of their object and have no
  stateless form. Those get `friend class ::PWBasisTEST;` and three forwarders.

- **`test_hsolver_pw.cpp`** has exactly one live call into protected territory,
  `hamiltSolvePsiK` (30 `this->`), in the NpwxLessThanNbandsDeath test; the
  other references to it and to `update_precondition` are commented out. It gets
  `friend class ::TestHSolverPW;` and one forwarder.

- **`test_hsolver_sdft.cpp`** is vestigial: every `TEST_F` in it is commented
  out, and the `nbands` it appeared to touch is `stowf.nbands_diag`, a member of
  a different class. The directives are simply deleted, as with `cal_test.cpp`
  and `test_hsolver.cpp` in #7921.

`FFT_Bundle` gains `get_device()` and `get_precision()`. The pw tests check that
`PW_Basis`'s constructor propagates device and precision into its `fft_bundle`,
which is a real behavioural check and not redundant, but `FFT_Bundle`'s copies
were private with no accessor. `PW_Basis` already exposes exactly this pair, so
this completes a parallel that was half-present rather than inventing an
accessor for a test.

Both friended classes live in a namespace (`ModulePW`, `hsolver`) while the
fixtures are at global scope, so each needs a global forward declaration and
`friend class ::Fixture;` -- an unqualified `friend class Fixture;` would name a
nonexistent class inside the namespace and silently grant nothing.

Occurrences tree-wide 88 -> 84. Production change is three friend declarations
with their forward declarations, plus the two `FFT_Bundle` accessors.

Co-authored-by: Claude Opus 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

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.

2 participants