Skip to content

Commit 3dd275f

Browse files
sbryngelsonclaude
andcommitted
Fix 37 broken Fortran % accessors in docs and add lint check
Doxygen silently consumes %<word> (even inside backtick code spans), so `bc_y%beg` renders as `bc_ybeg`. Fixed all 37 instances in hand-written docs to use %% escape. Added check_doxygen_percent() lint check to catch this in CI going forward. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 91bdde2 commit 3dd275f

5 files changed

Lines changed: 76 additions & 34 deletions

File tree

docs/documentation/case.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ These physical parameters must be consistent with fluid material's parameters de
297297

298298
#### Elliptic Smoothing
299299

300-
Initial conditions in which not all patches support the `patch_icpp(j)%smoothen` parameter can still be smoothed by applying iterations of the heat equation to the initial condition.
300+
Initial conditions in which not all patches support the `patch_icpp(j)%%smoothen` parameter can still be smoothed by applying iterations of the heat equation to the initial condition.
301301
This is enabled by adding `'elliptic_smoothing': "T",` and `'elliptic_smoothing_iters': N,` to the case dictionary, where `N` is the number of smoothing iterations to apply.
302302

303303
### 4. Immersed Boundary Patches {#sec-immersed-boundary-patches}
@@ -620,8 +620,8 @@ To restart the simulation from $k$-th time step, see @ref running "Restarting Ca
620620
| `num_probes` | Integer | Number of probes |
621621
| `probe(i)%[x,y,z]` | Real | Coordinates of probe $i$ |
622622
| `output_partial_domain` | Logical | Output part of the domain |
623-
| `[x,y,z]_output%beg` | Real | Beginning of the output domain in the [x,y,z]-direction |
624-
| `[x,y,z]_output%end` | Real | End of the output domain in the [x,y,z]-direction |
623+
| `[x,y,z]_output%%beg` | Real | Beginning of the output domain in the [x,y,z]-direction |
624+
| `[x,y,z]_output%%end` | Real | End of the output domain in the [x,y,z]-direction |
625625
| `lag_txt_wrt` | Logical | Write Lagrangian bubble data to `.dat` files |
626626
| `lag_header` | Logical | Write header to Lagrangian bubble `.dat` files |
627627
| `lag_db_wrt` | Logical | Write Lagrangian bubble data to silo/hdf5 database files |
@@ -667,7 +667,7 @@ If `file_per_process` is true, then pre_process, simulation, and post_process mu
667667

668668
- `probe_wrt` activates the output of state variables at coordinates specified by `probe(i)%[x;y,z]`.
669669

670-
- `output_partial_domain` activates the output of part of the domain specified by `[x,y,z]_output%beg` and `[x,y,z]_output%end`.
670+
- `output_partial_domain` activates the output of part of the domain specified by `[x,y,z]_output%%beg` and `[x,y,z]_output%%end`.
671671
This is useful for large domains where only a portion of the domain is of interest.
672672
It is not supported when `precision = 1` and `format = 1`.
673673
It also cannot be enabled with `flux_wrt`, `heat_ratio_wrt`, `pres_inf_wrt`, `c_wrt`, `omega_wrt`, `ib`, `schlieren_wrt`, `qm_wrt`, or 'liutex_wrt'.
@@ -991,30 +991,30 @@ Note: For relativistic flow, the conservative and primitive densities are differ
991991

992992
When ``cyl_coord = 'T'`` is set in 3D the following constraints must be met:
993993

994-
- `bc_y%beg = -14` enables the axis boundary condition
994+
- `bc_y%%beg = -14` enables the axis boundary condition
995995

996-
- `bc_z%beg = bc_z%end = -1` enables periodic boundary conditions in the azimuthal direction
996+
- `bc_z%%beg = bc_z%%end = -1` enables periodic boundary conditions in the azimuthal direction
997997

998-
- `z_domain%beg = 0` sets the azimuthal starting point to 0
998+
- `z_domain%%beg = 0` sets the azimuthal starting point to 0
999999

1000-
- `z_domain%end = 2*math.pi` to set the azimuthal ending point to \f$2\pi\f$ (note, requires `import math` in the case file)
1000+
- `z_domain%%end = 2*math.pi` to set the azimuthal ending point to \f$2\pi\f$ (note, requires `import math` in the case file)
10011001

10021002
When ``cyl_coord = 'T'`` is set in 2D the following constraints must be met:
10031003

1004-
- `bc_y%beg = -2` to enable reflective boundary conditions
1004+
- `bc_y%%beg = -2` to enable reflective boundary conditions
10051005

10061006
### 17. Chemistry
10071007

10081008
| Parameter | Type | Description |
10091009
| ---: | :---: | :--- |
10101010
| `chemistry` | Logical | Enable chemistry simulation |
1011-
| `chem_params%diffusion` | Logical | Enable multispecies diffusion |
1012-
| `chem_params%reactions` | Logical | Enable chemical reactions |
1013-
| `chem_params%gamma_method` | Integer | Methodology for calculating the heat capacity ratio |
1014-
| `chem_params%transport_model` | Integer | Methodology for calculating the diffusion coefficients |
1011+
| `chem_params%%diffusion` | Logical | Enable multispecies diffusion |
1012+
| `chem_params%%reactions` | Logical | Enable chemical reactions |
1013+
| `chem_params%%gamma_method` | Integer | Methodology for calculating the heat capacity ratio |
1014+
| `chem_params%%transport_model` | Integer | Methodology for calculating the diffusion coefficients |
10151015
| `cantera_file` | String | Cantera-format mechanism file (e.g., .yaml) |
10161016

1017-
- `chem_params%transport_model` specifies the methodology for calculating diffusion coefficients and other transport properties, `1` for mixture-average, `2` for Unity-Lewis
1017+
- `chem_params%%transport_model` specifies the methodology for calculating diffusion coefficients and other transport properties, `1` for mixture-average, `2` for Unity-Lewis
10181018

10191019
- `cantera_file` specifies the chemical mechanism file. If the file is part of the standard Cantera library, only the filename is required. Otherwise, the file must be located in the same directory as your `case.py` file
10201020

@@ -1051,15 +1051,15 @@ The entries labeled "Characteristic." are characteristic boundary conditions bas
10511051

10521052
| Parameter | Type | Description |
10531053
| ---: | :----: | :--- |
1054-
| `bc_[x,y,z]%grcbc_in` | Logical | Enable grcbc for subsonic inflow |
1055-
| `bc_[x,y,z]%grcbc_out` | Logical | Enable grcbc for subsonic outflow (pressure)|
1056-
| `bc_[x,y,z]%grcbc_vel_out` | Logical | Enable grcbc for subsonic outflow (pressure + normal velocity) |
1057-
| `bc_[x,y,z]%vel_in` | Real Array | Inflow velocities in x, y and z directions |
1058-
| `bc_[x,y,z]%vel_out` | Real Array | Outflow velocities in x, y and z directions |
1059-
| `bc_[x,y,z]%pres_in` | Real | Inflow pressure |
1060-
| `bc_[x,y,z]%pres_out` | Real | Outflow pressure |
1061-
| `bc_[x,y,z]%alpha_rho_in` | Real Array | Inflow density |
1062-
| `bc_[x,y,z]%alpha_in` | Real Array | Inflow void fraction |
1054+
| `bc_[x,y,z]%%grcbc_in` | Logical | Enable grcbc for subsonic inflow |
1055+
| `bc_[x,y,z]%%grcbc_out` | Logical | Enable grcbc for subsonic outflow (pressure)|
1056+
| `bc_[x,y,z]%%grcbc_vel_out` | Logical | Enable grcbc for subsonic outflow (pressure + normal velocity) |
1057+
| `bc_[x,y,z]%%vel_in` | Real Array | Inflow velocities in x, y and z directions |
1058+
| `bc_[x,y,z]%%vel_out` | Real Array | Outflow velocities in x, y and z directions |
1059+
| `bc_[x,y,z]%%pres_in` | Real | Inflow pressure |
1060+
| `bc_[x,y,z]%%pres_out` | Real | Outflow pressure |
1061+
| `bc_[x,y,z]%%alpha_rho_in` | Real Array | Inflow density |
1062+
| `bc_[x,y,z]%%alpha_in` | Real Array | Inflow void fraction |
10631063

10641064
This boundary condition can be used for subsonic inflow (`bc_[x,y,z]%[beg,end]` = -7) and subsonic outflow (`bc_[x,y,z]%[beg,end]` = -8) characteristic boundary conditions. These are based on \cite Pirozzoli13. This enables to provide inflow and outflow conditions outside the computational domain.
10651065

docs/documentation/contributing.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ q_cons_vf (conservative variables: density, momentum, energy, volume fractions)
6464
```
6565

6666
Key data structures (defined in `src/common/m_derived_types.fpp`):
67-
- `scalar_field` — wraps a 3D `real(stp)` array (`%sf(i,j,k)`)
68-
- `vector_field` — array of `scalar_field` (`%vf(1:sys_size)`)
67+
- `scalar_field` — wraps a 3D `real(stp)` array (`%%sf(i,j,k)`)
68+
- `vector_field` — array of `scalar_field` (`%%vf(1:sys_size)`)
6969
- `q_cons_vf` / `q_prim_vf` — conservative and primitive state vectors
7070

7171
### Build Toolchain
@@ -136,7 +136,7 @@ Both human reviewers and AI code reviewers reference this section.
136136

137137
### Array Bounds and Indexing
138138

139-
- MFC uses **non-unity lower bounds** (e.g., `idwbuff(1)%beg:idwbuff(1)%end` with negative ghost-cell indices). Always verify loop bounds match array declarations.
139+
- MFC uses **non-unity lower bounds** (e.g., `idwbuff(1)%%beg:idwbuff(1)%%end` with negative ghost-cell indices). Always verify loop bounds match array declarations.
140140
- **Riemann solver indexing:** Left states at `j`, right states at `j+1`. Off-by-one here corrupts fluxes.
141141

142142
### Precision and Type Safety
@@ -164,7 +164,7 @@ Both human reviewers and AI code reviewers reference this section.
164164
- **Pressure formula** must match `model_eqns` value. Model 2/3 (multi-fluid), model 4 (bubbles), MHD, and hypoelastic each use different EOS formulations. Wrong formula = wrong physics.
165165
- **Conservative-primitive conversion:** Density recovery, kinetic energy, and pressure each have model-specific paths. Verify the correct branch is taken.
166166
- **Volume fractions** must sum to 1. `alpha_rho_K` must be non-negative. Species mass fractions should be clipped to [0,1].
167-
- **Boundary conditions:** Periodic BCs must match at both ends (`bc_x%beg` and `bc_x%end`). Cylindrical coordinates have special requirements (`bc_y%beg = -14` for axis in 3D).
167+
- **Boundary conditions:** Periodic BCs must match at both ends (`bc_x%%beg` and `bc_x%%end`). Cylindrical coordinates have special requirements (`bc_y%%beg = -14` for axis in 3D).
168168
- **Parameter constraints:** New parameters or physics features must be validated in `toolchain/mfc/case_validator.py`. New features should add corresponding validation.
169169

170170
### Python Toolchain

docs/documentation/equations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ Used for viscous fluxes and velocity gradients.
777777
| `-15` | Slip wall |
778778
| `-16` | No-slip wall |
779779

780-
### 16.2 Characteristic BCs (\cite Thompson87, \cite Thompson90; `bc_x%beg = -5` to `-12`)
780+
### 16.2 Characteristic BCs (\cite Thompson87, \cite Thompson90; `bc_x%%beg = -5` to `-12`)
781781

782782
**Characteristic decomposition:**
783783

docs/documentation/running.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,8 @@ If you want to restart a simulation,
309309
1. For the Computational Domain Parameters
310310
- Have the following removed __except__ `m`, `n`, and `p`:
311311
- All domain/mesh information
312-
- `(xyz)_domain%beg`
313-
- `(xyz)_domain%end`
312+
- `(xyz)_domain%%beg`
313+
- `(xyz)_domain%%end`
314314
- `stretch_(xyz)`
315315
- `a_(xyz)`
316316
- `(xyz)_a`
@@ -334,11 +334,11 @@ If you want to restart a simulation,
334334

335335
3. For Patches
336336
- Have all information about old patches (used in the `case.py` file) removed.
337-
- `patch_icpp(1)%all variables`
338-
- `patch_icpp(2)%all variables`
339-
- `patch_icpp(num_patches)%all variables`
337+
- `patch_icpp(1)%%all variables`
338+
- `patch_icpp(2)%%all variables`
339+
- `patch_icpp(num_patches)%%all variables`
340340
- Add information about new patches that will be introduced, if any. The parameter num_patches should reflect this addition.
341-
- e.g. `patch_icpp(1)%some variables of interest`
341+
- e.g. `patch_icpp(1)%%some variables of interest`
342342

343343
4. For Fluid properties
344344
- Keep information about the fluid properties

toolchain/mfc/lint_docs.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,47 @@ def check_section_anchors(repo_root: Path) -> list[str]:
315315
return errors
316316

317317

318+
def check_doxygen_percent(repo_root: Path) -> list[str]:
319+
"""Check that Fortran % accessors inside backtick code spans use %% (Doxygen escape).
320+
321+
Doxygen treats %<word> as "suppress auto-link" and silently eats the %
322+
character, even inside backtick code spans. Writing %% produces a
323+
literal %. Only flag % followed by [a-zA-Z_] (the pattern Doxygen
324+
consumes); %[, %(, etc. are safe.
325+
"""
326+
doc_dir = repo_root / "docs" / "documentation"
327+
if not doc_dir.exists():
328+
return []
329+
330+
ignored = _gitignored_docs(repo_root)
331+
code_span_re = re.compile(r"`([^`\n]+)`")
332+
bad_pct_re = re.compile(r"(?<!%)%(?=[a-zA-Z_])")
333+
334+
errors = []
335+
for md_file in sorted(doc_dir.glob("*.md")):
336+
if md_file.name in ignored:
337+
continue
338+
text = md_file.read_text(encoding="utf-8")
339+
rel = md_file.relative_to(repo_root)
340+
in_code = False
341+
for i, line in enumerate(text.split("\n"), 1):
342+
if line.strip().startswith("```"):
343+
in_code = not in_code
344+
continue
345+
if in_code:
346+
continue
347+
for m in code_span_re.finditer(line):
348+
span = m.group(1)
349+
if bad_pct_re.search(span):
350+
fixed = bad_pct_re.sub("%%", span)
351+
errors.append(
352+
f" {rel}:{i} Doxygen will eat the % in `{span}`."
353+
f" Fix: `{fixed}`"
354+
)
355+
356+
return errors
357+
358+
318359
def check_page_refs(repo_root: Path) -> list[str]:
319360
"""Check that @ref targets in docs reference existing page identifiers."""
320361
doc_dir = repo_root / "docs" / "documentation"
@@ -354,6 +395,7 @@ def main():
354395
all_errors.extend(check_param_refs(repo_root))
355396
all_errors.extend(check_page_refs(repo_root))
356397
all_errors.extend(check_math_syntax(repo_root))
398+
all_errors.extend(check_doxygen_percent(repo_root))
357399
all_errors.extend(check_section_anchors(repo_root))
358400

359401
if all_errors:

0 commit comments

Comments
 (0)