From f9316a4ecf19a134113fba215297b8b9192ef790 Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Sun, 10 May 2026 19:16:14 -0400 Subject: [PATCH 1/2] fix: inline Fortran constant defaults in _fc() to prevent Homebrew sync failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, _fc() raised if a constant was absent from _FALLBACK_CONSTANTS, a separate dict that could silently drift from definitions.py. This caused the v5.3.1 Homebrew build to fail: NIB = _fc('num_ib_patches_max') was added to definitions.py but _FALLBACK_CONSTANTS was never updated, so every Homebrew install hit a RuntimeError on startup. Fix: _fc(name, default) now requires an inline default — the default lives alongside the call, so they can't get out of sync. Remove _FALLBACK_CONSTANTS and simplify get_fortran_constants() to return {} when src/ is unavailable. --- toolchain/mfc/params/definitions.py | 21 ++++++++++----------- toolchain/mfc/params/namelist_parser.py | 17 +++-------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/toolchain/mfc/params/definitions.py b/toolchain/mfc/params/definitions.py index 18f107df74..bf26276a82 100644 --- a/toolchain/mfc/params/definitions.py +++ b/toolchain/mfc/params/definitions.py @@ -13,22 +13,21 @@ from .schema import ParamDef, ParamType # Index limits — sourced from Fortran compile-time constants (m_constants.fpp). -# These must stay in sync with Fortran; we error if the source can't be parsed. +# Falls back to the inline default when src/ is unavailable (e.g. Homebrew). +# Default must match src/common/m_constants.fpp — enforced by co-location. _FC = get_fortran_constants() -def _fc(name: str) -> int: - """Get a required Fortran constant, raising if unavailable.""" - if name not in _FC: - raise RuntimeError(f"Fortran constant '{name}' not found in m_constants.fpp. Toolchain is out of sync with Fortran source.") - return _FC[name] +def _fc(name: str, default: int) -> int: + """Get a Fortran constant, using the inline default when m_constants.fpp is unavailable.""" + return _FC.get(name, default) -NF = _fc("num_fluids_max") # fluid_pp -NPR = _fc("num_probes_max") # probe, acoustic, integral -NB = _fc("num_bc_patches_max") # patch_bc -NUM_PATCHES_MAX = _fc("num_patches_max") # patch_icpp (Fortran array bound) -NIB = _fc("num_ib_patches_max") # patch_ib (Fortran array bound) +NF = _fc("num_fluids_max", 10) # fluid_pp +NPR = _fc("num_probes_max", 10) # probe, acoustic, integral +NB = _fc("num_bc_patches_max", 10) # patch_bc +NUM_PATCHES_MAX = _fc("num_patches_max", 10) # patch_icpp (Fortran array bound) +NIB = _fc("num_ib_patches_max", 50000) # patch_ib (Fortran array bound) # Enumeration limits for families not yet converted to IndexedFamily. # These are smaller than the Fortran array bounds to keep the registry compact. # The CONSTRAINTS dict below uses the Fortran constants for validation. diff --git a/toolchain/mfc/params/namelist_parser.py b/toolchain/mfc/params/namelist_parser.py index fdcb21d38a..52385255d3 100644 --- a/toolchain/mfc/params/namelist_parser.py +++ b/toolchain/mfc/params/namelist_parser.py @@ -492,29 +492,18 @@ def get_fortran_constants() -> Dict[str, int]: """ Get Fortran compile-time constants from m_constants.fpp. - Cached after first call. Falls back to built-in defaults when the Fortran - source is unavailable (e.g. Homebrew installs where src/ is not shipped). + Cached after first call. Returns an empty dict when the Fortran source is + unavailable (e.g. Homebrew installs where src/ is not shipped); callers + supply their own inline defaults via _fc(name, default) in definitions.py. """ global _FORTRAN_CONSTANTS_CACHE # noqa: PLW0603 if _FORTRAN_CONSTANTS_CACHE is None: root = get_mfc_root() path = root / "src" / "common" / "m_constants.fpp" _FORTRAN_CONSTANTS_CACHE = parse_fortran_constants(path) - if not _FORTRAN_CONSTANTS_CACHE: - _FORTRAN_CONSTANTS_CACHE = _FALLBACK_CONSTANTS.copy() return _FORTRAN_CONSTANTS_CACHE -# Fallback values for when m_constants.fpp is not available at runtime. -# Keep in sync with src/common/m_constants.fpp. -_FALLBACK_CONSTANTS: Dict[str, int] = { - "num_fluids_max": 10, - "num_probes_max": 10, - "num_patches_max": 1000, - "num_bc_patches_max": 10, -} - - def get_mfc_root() -> Path: """Get the MFC root directory from this file's location.""" # This file is at toolchain/mfc/params/namelist_parser.py From 83f48186fcd076bd3ca6c28309351088c5834d8b Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Sun, 10 May 2026 21:05:16 -0400 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20restore=20drift=20detection=20in=20?= =?UTF-8?q?=5Ffc()=20=E2=80=94=20raise=20when=20src/=20is=20present=20but?= =?UTF-8?q?=20key=20is=20missing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- toolchain/mfc/params/definitions.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/toolchain/mfc/params/definitions.py b/toolchain/mfc/params/definitions.py index bf26276a82..e41acff235 100644 --- a/toolchain/mfc/params/definitions.py +++ b/toolchain/mfc/params/definitions.py @@ -20,7 +20,14 @@ def _fc(name: str, default: int) -> int: """Get a Fortran constant, using the inline default when m_constants.fpp is unavailable.""" - return _FC.get(name, default) + if _FC: + if name not in _FC: + raise RuntimeError( + f"Fortran constant '{name}' not found in m_constants.fpp. " + f"Toolchain is out of sync with Fortran source." + ) + return _FC[name] + return default NF = _fc("num_fluids_max", 10) # fluid_pp