source_basis/module_ao: use the getters that already exist instead of #define private public - #7952
Merged
mohanchen merged 1 commit intoSep 12, 2026
Conversation
…no production change `orb_nonlocal_test.cpp` and `orb_read_test.cpp` switched off access control for their whole translation unit to reach members of `Numerical_Nonlocal` and `LCAO_Orbitals` that mostly already have public getters. Neither file touches PARAM, and neither needs anything added to a production header: the macro is removed by using the accessors that exist, plus one fixture built through the public API instead of by assignment. Three distinct cases, and the second is the interesting one: 1. The member is used as a plain value. Read it through its getter -- `lcao_.kmesh` -> `lcao_.get_kmesh()` (4 sites), and the five assertions in `SetTypeInfo` now read `nn.getLabel()`, `getType()`, `getLmax()`, `get_rcut_max()`, `get_nproj()`. Those already compared against the fixture's inputs, so they stay real checks. 2. The assertion *is* `EXPECT_EQ(obj.get_x(), obj.x)`. Substituting the getter would turn it into `EXPECT_EQ(get_x(), get_x())` -- it cannot fail, and the test would be silently gutted. These are re-anchored to the value the object was given instead, which is what `orb_nonlocal_test` already did on one line (`EXPECT_EQ(nn.get_rcut_max(), rcut_max_)`); the rest now match it. In `LCAO_Orbitals::Getters`, seven of the twelve assertions covered private members. `ntype` and `lmax` are passed straight into `Read_Orbitals`, so they anchor to `ntype_` / `lmax_`. The other four are derived, and the production formula is deliberately *not* restated in the test -- a test that recomputes what it is checking passes even when the formula is wrong. They are asserted as the concrete values this fixture implies, each with its provenance: `kmesh` 1113 = int(sqrt(123)/0.01) + 4, `nchimax` 2 (H is 2s1p, O is 2s2p1d), `lmax_d`/`nchimax_d` 2 from jle.orb, `rcutmax_Phi` 8 au (H 8 au, O 7 au). Measured against the built test to confirm, and kmesh cross-checked by hand against Read_Orbitals. 3. The test *wrote* a private member to build a fixture: `nnl[i].rcut = 1.0` in `NumericalNonlocalTest::SetUp`. `Numerical_Nonlocal_Lm` derives rcut from the last point of its radial mesh, so each projector is now built through the public `set_NL_proj()` with a minimal three-point mesh whose endpoint is the wanted rcut. That removes the write and additionally exercises `set_NL_proj`, which no assertion in this file reached before. `ecutwfc`, `dk`, `dR`, `Rmax` and `dr_uniform` are public members of `LCAO_Orbitals` and never needed the macro; the four that compare against a fixture input are anchored to it for consistency, and `dr_uniform` is left alone. Macro occurrences in these two files go 2 -> 0. No `#undef private` is added, and no file whose macro survives is touched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Third tranche of the
#define private publiccleanup, after #7940 (testsdriving global
PARAM) and #7949 (tests calling private methods). This onecovers the case where the member the test reaches for already has a public
getter — so the macro comes off with no production change at all.
Three cases, and the middle one is a trap
orb_nonlocal_test.cppandorb_read_test.cppreach intoNumerical_Nonlocaland
LCAO_Orbitals. Neither file touchesPARAM; nothing is added to aproduction header. The entire diff is in the two test files.
1. The member is used as a plain value — read it through its getter.
lcao_.kmeshbecomeslcao_.get_kmesh()(4 sites); the fiveSetTypeInfoassertions become
nn.getLabel(),getType(),getLmax(),get_rcut_max(),get_nproj(). Those already compared against the fixture's inputs, so they stayreal checks.
2. The assertion is
EXPECT_EQ(obj.get_x(), obj.x). Substituting thegetter here would produce
EXPECT_EQ(get_x(), get_x())— an assertion thatcannot fail. Mechanically removing the macro this way would leave the test
green and empty, which is worse than the macro. These are re-anchored to the
value the object was actually given.
orb_nonlocal_testalready had one line in the right form(
EXPECT_EQ(nn.get_rcut_max(), rcut_max_)); the other four now match it.In
LCAO_Orbitals::Getters, seven of the twelve assertions covered privatemembers.
ntypeandlmaxare passed straight intoRead_Orbitals, so theyanchor to
ntype_/lmax_. The remaining four are derived, and theproduction formula is deliberately not restated in the test — a test that
recomputes the thing it is checking passes even when the formula is wrong. They
are asserted as the concrete values this fixture implies, each with its
provenance in a comment:
kmeshint(sqrt(ecutwfc)/dk) + 4=int(sqrt(123)/0.01) + 4nchimaxlmax_d,nchimax_djle.orbrcutmax_PhiEach was measured against the built test, and
kmeshadditionally cross-checkedby hand against
Read_Orbitalsso the assertion records the correct value ratherthan merely the observed one.
3. The test wrote a private member to build a fixture —
nnl[i].rcut = 1.0inNumericalNonlocalTest::SetUp.Numerical_Nonlocal_Lmderivesrcutfrom the last point of its radial mesh(
rcut = r_radial_in[nr-1]), so each projector is now built through the publicset_NL_proj()with a minimal three-point mesh whose endpoint is the wantedrcut. This removes the write and exercises
set_NL_proj, which no assertion inthis file reached before.
ecutwfc,dk,dR,Rmaxanddr_uniformare public members ofLCAO_Orbitalsand never needed the macro. The four that have a correspondingfixture input are anchored to it for consistency;
dr_uniformis left as it was.Result
Macro occurrences in these two files: 2 -> 0. No
#undef privateis added,and no file whose macro survives is touched.
Verification
Linux,
cmake -B build -G Ninja -DBUILD_TESTING=ON -DENABLE_LCAO=ON -DENABLE_MPI=ON -DENABLE_OPENMP=ON,followed by
cmake --install build— which matters here: themodule_aotestsget their orbital data from
install(DIRECTORY lcao_H2O ...), so without theinstall step
ORB_read_testfails andORB_atomic_lm_test/ORB_nonlocal_lm_testsegfault on missing input, both before and after thischange.
BUILD_EXIT=0).MODULE_AO_ORB_nonlocal_test,MODULE_AO_ORB_read_test,MODULE_AO_ORB_atomic_lm_test,MODULE_AO_ORB_nonlocal_lm_test: all pass.commit (
9cbcc0b55) built, installed and run in a parallel worktree in thesame environment; both
commdirections are empty. The two areMODULE_HSOLVER_diago_hs_parallelandMODULE_HSOLVER_LCAO, bothmpirun-based and pre-existing.agent_governance_check.py: 0 errors. The access-hack ratchet reportsnothing (2 removed, 0 added) and no
PARAM/GlobalV/GlobalCreference isadded or removed, so the global-dependency budget is untouched.
No INPUT parameter and no user-visible behaviour changed, so
docs/parameters.yamlanddocs/advanced/input_files/input-main.mdneed noupdate.
What is not here
The other two
module_aotests,orb_atomic_lm_test.cpp(887 lines) andorb_nonlocal_lm_test.cpp(755 lines), hold the bulk of this category — roughly190 further sites where a member with an existing getter is read directly. They
are left for a separate PR because they cannot be finished the same way: each
also calls private methods (
cal_kradial,cal_rradial_sbpool,plot,freemem,renew,get_kradial) andorb_atomic_lm_testreadspsir, whichhas no getter. Those need a
friendgrant in a production header — the #7949pattern — which is a different review question from "use the accessor that
already exists", and mixing the two would obscure both.
Their getter-vs-member block has the same shape as the one fixed here but over
arrays (
get_psi()vspsi), where there is no scalar input to re-anchor to;that block is better routed through the fixture once the
friendis in place.🤖 Generated with Claude Code