Documents the top globals still in use in legacy code + their FS struct equivalents.
Refreshed 2026-07-03 post-v2.0.1 (paths reflect the runtime/ + legacy/ layout).
🇧🇷 Versao em portugues:
docs/auditoria-de-globais.md
The global declarations in legacy/ferncodes/** cannot be removed piecemeal
without breaking the runtime — each global in a callee is paired with an
implicit expectation that the same global was populated by some caller (usually
runtime/preproc/preprocessormod at startup). Killing them requires
coordinated caller + callee migration in tandem, which is a per-file
mechanical task better done as its own campaign.
This document is the migration map: for each global still in use, the FS struct field that replaces it and the migration pattern.
- ~183
.mfiles still declare at least oneglobal(counted viagrep -rl "^\s*global\s" --include='*.m' .) - Almost all live under
legacy/ferncodes/**(67 files) +runtime/**+ a few remaining underbenchmarks/,factories/,simulacoes/
| Global | Files | Kind | FS struct equivalent | Notes |
|---|---|---|---|---|
bedge |
107 | mesh face table | FS.mesh.bedge |
boundary faces |
inedge |
~100 | mesh face table | FS.mesh.inedge |
interior faces |
coord |
~100 | mesh coords | FS.mesh.coord |
node coordinates |
elem |
~85 | mesh conn | FS.mesh.elem |
element vertex tables |
centelem |
~85 | derived geom | FS.geom.centElem |
element centroids |
numcase |
58 | physics tag | FS.cfg.numcase |
benchmark selector |
bcflag |
~35 | BC map | FS.bc.bcflag |
flag→value dispatch |
normals |
~29 | derived geom | FS.geom.normalBnd / .normalInt |
face normals |
esurn2 |
~25 | CSR ptr | FS.mesh.esurn2 (alias FS.csr.nodePtr) |
elements-around-node row-pointer |
nsurn2 |
~22 | CSR ptr | FS.mesh.nsurn2 |
nodes-around-node row-pointer |
phasekey |
22 | physics tag | FS.cfg.phasekey |
1/4/5/6 dispatch |
elemarea |
~19 | derived geom | FS.geom.elemArea |
per-element areas |
bcflagc |
~19 | BC map (conc) | FS.bc.bcflagc |
concentration BCs |
(Counts are approximate — bedge is exact. See grep -rl "^\s*global.*<name>" --include='*.m' . to refresh.)
For each legacy ferncodes_*.m file to be migrated:
Before:
function [out] = ferncodes_foo(other, args)
global bedge inedge coord elem numcase bcflag;
% ... uses bedge(:,5), inedge(:,3), etc.
endAfter:
function [out] = ferncodes_foo(FS, other, args) % FS added as first arg
bedge = FS.mesh.bedge;
inedge = FS.mesh.inedge;
coord = FS.mesh.coord;
elem = FS.mesh.elem;
numcase = FS.cfg.numcase;
bcflag = FS.bc.bcflag;
% ... unchanged body
endEvery caller then passes FS as an extra arg. That's the tandem-migration
constraint: caller AND callee change together per PR.
+fs/+mesh/build.m— readsenv.geometry.*+env.config.*, packs into FS+fs/+csr/**— builds CSR corners + shifts, all FS-based+fs/+lpew/**— readsFS.mesh.*,FS.geom.*,FS.csr.*,FS.perm.*+fs/+assembly/+mpfad/build.m— reads env-style directly (no globals)+fs/+assembly/+tpfa/build.m— same+fs/+iter/{picard,anderson,lscheme}— env-based wrappers over legacy iterators+fs/+lpew/dmpWeights— env-based wrapper overferncodes_weightnlfvDMP+fs/+flow/{mpfad,tpfa}— env-based
The modern OOP layer (Metodo* / Sim* / Caso* classes under solvers/,
simulacoes/, benchmarks/) is already env-based — they don't touch globals
directly. MetodoBase provides env as method context.
- All
legacy/ferncodes/**files (~67.mfiles) — pending per-file migration runtime/time/hydraulic.m— the big steady driver, still using globalsruntime/time/hydraulic_RE.m— Richards transient driverruntime/time/IMPES.m/IMPEC.m/IMHEC.m— time-loop driversruntime/plug/PLUG_*.m— some readnumcase/phasekeyfor benchmark dispatchruntime/util/solver.m/solvePressure*.m— solver wrappersbenchmarks/Caso439.m— readscentelem,elemfrom globals
- Files on the Richards runtime path (highest value):
runtime/time/hydraulic_RE,ferncodes_iterpicard,ferncodes_calflag,ferncodes_Kde_Ded_Kt_Kn - Assembly variants when full-vectorization lands:
ferncodes_assemblematrix{MPFAH,NLFVPP,MPFAQL,DMP,NLFVH}— already scaffolded under+fs/+assembly/, but their internal ferncodes callees still use globals - Post-processing:
ferncodes_flowrate*,ferncodes_pressureinterp* - PLUG_ callbacks — smallest surface, could be batched
- Everything else — lowest priority, code path frequency unknown
legacy/transm/**— 8 files, all dead. Delete if desired.legacy/preprocessor/— 2 files, dead. Superseded byruntime/preproc/preprocessormod.legacy/ferncodes-con/— 7 dead concentration-coupled variants.legacy/solvers/— 2 dead solver variants.legacy/unknown/**— 32 files pending owner triage; no migration until known-live status.
To verify a migrated file, run its unit test (tests/unit/unit_<name>.m) which
diffs the new signature against the legacy signature on M8 mesh. Expected diff:
- Matrices —
< 1e-12relative Frobenius - Vectors —
< 1e-10relative L2 norm - The oracle —
unit_baseline_reproducesmust still hit rel diff0.000e+00on the committed golden (M8/num439/mpfad and M8/num439/tpfa).
A single-file migration is 15-30 min of mechanical work (declare param, substitute globals, update all callers). But because migrations must be tandem (caller + callee), each cascade can pull in 3-10 files. Realistic estimate for killing 90% of globals in the reachable set: 40-60 hours as a dedicated follow-up campaign, likely best sequenced right after the remaining 5-method vectorization work (which itself already touches the reachable assembly path).