Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions .claude/rules/common-pitfalls.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,27 @@ covered in `docs/documentation/contributing.md`.
`toolchain/mfc/params/definitions.py`; `case_validator.py` only if physics-constrained
(with a `PHYSICS_DOCS` entry). Fortran declarations and namelist bindings are
auto-generated at CMake configure time — re-run cmake (or `./mfc.sh build`) after editing.
- Still manual: array variables and derived-type members (declare in
`src/*/m_global_parameters.fpp` / the relevant type), and case-optimization parameters
(`CASE_OPT_PARAMS` + the `#:else` block in `src/simulation/m_global_parameters.fpp`).
Gotcha: under `--case-optimization` those are baked into the binary and dropped from
the namelist, so changing one needs a *rebuild*, not a case edit.
- Still manual: derived-type `TYPE` member definitions in `src/common/m_derived_types.fpp`;
default-value assignments in `s_assign_default_values_to_user_inputs`; the
`CASE_OPT_EXTRA_LINES` literal in `toolchain/mfc/params/generators/fortran_gen.py` (covers `num_dims`,
`num_vels`, `weno_polyn`, `muscl_polyn`, `weno_num_stencils`, `wenojs`);
multi-variable declaration lines (`bc_x/y/z`, `x/y/z_domain`, `x/y/z_output`, post's
`G`); and MPI broadcast lists in `m_mpi_proxy`. Everything else — scalar declarations,
plain arrays (`FORTRAN_ARRAY_DIMS` table in `definitions.py`), derived-type namelist
declarations including `GPU_DECLARE` lines and Doxygen descs (`TYPED_DECLS` table in
`definitions.py`), and the simulation case-optimization declaration block — is
auto-generated at CMake configure time.
Gotcha: after editing a generator or table, force regen via `cmake_gen.py` into
`build/staging/*/` or simply reconfigure (`./mfc.sh build`) — cached builds compile
stale includes. Under `--case-optimization` the baked-in constants are dropped from the
namelist, so changing one needs a *rebuild*, not a case edit.
- Runtime checks (`@:PROHIBIT`) go where they run: shared →
`src/common/m_checker_common.fpp`; simulation-only → `src/simulation/m_checker.fpp`;
pre/post-only → `src/{pre,post}_process/m_checker.fpp` (their `s_check_inputs` are
currently empty — that IS the right place, not m_checker_common).
- Analytic ICs are compiled into the binary (syntax error = build failure, not runtime).
- Analytic ICs are compiled into the binary. Expressions are AST-validated at case load
(syntax errors and unknown variables are immediate, named errors; bare `e` is not a
variable — write `exp(1.0)`).
Each IC variable maps to an `eqn_idx%…` expression in `QPVF_IDX_VARS`
(`toolchain/mfc/case.py`); a new patch-settable conserved variable means updating that
map AND the Fortran `eqn_idx` builder to agree — a mismatch is a silent wrong index.
Expand Down
47 changes: 44 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,9 @@ macro(HANDLE_SOURCES target useCommon)

# Gather:
# * src/[<target>,common]/include/*.fpp
# * (if any) <build>/include/<target>/*.fpp
file(GLOB ${target}_incs CONFIGURE_DEPENDS "${${target}_DIR}/include/*.fpp"
"${CMAKE_BINARY_DIR}/include/${target}/*.fpp")
# * generated includes from build/include/<target>/ (explicit list, not a GLOB)
file(GLOB ${target}_incs CONFIGURE_DEPENDS "${${target}_DIR}/include/*.fpp")
list(APPEND ${target}_incs ${_mfc_gen_files_${target}})

if (${useCommon})
file(GLOB common_incs CONFIGURE_DEPENDS "${common_DIR}/include/*.fpp")
Expand Down Expand Up @@ -494,6 +494,47 @@ if(_mfc_needs_regen)
file(TOUCH "${_mfc_gen_stamp}")
endif()

# Enumerate the 10 generated .fpp files explicitly so ninja can track them as
# build-time outputs and so HANDLE_SOURCES does not need a configure-time GLOB
# of ${CMAKE_BINARY_DIR}/include/<target>/ (which fails when the dir is empty).
set(_mfc_gen_inc "${CMAKE_BINARY_DIR}/include")
set(_mfc_gen_files_pre_process
"${_mfc_gen_inc}/pre_process/generated_namelist.fpp"
"${_mfc_gen_inc}/pre_process/generated_decls.fpp"
"${_mfc_gen_inc}/pre_process/generated_constants.fpp"
)
set(_mfc_gen_files_simulation
"${_mfc_gen_inc}/simulation/generated_namelist.fpp"
"${_mfc_gen_inc}/simulation/generated_decls.fpp"
"${_mfc_gen_inc}/simulation/generated_constants.fpp"
"${_mfc_gen_inc}/simulation/generated_case_opt_decls.fpp"
)
set(_mfc_gen_files_post_process
"${_mfc_gen_inc}/post_process/generated_namelist.fpp"
"${_mfc_gen_inc}/post_process/generated_decls.fpp"
"${_mfc_gen_inc}/post_process/generated_constants.fpp"
)
set(_mfc_gen_files_syscheck)
set(_mfc_all_gen_files
${_mfc_gen_files_pre_process}
${_mfc_gen_files_simulation}
${_mfc_gen_files_post_process}
)

# Build-time regeneration: ninja re-runs cmake_gen.py and re-preprocesses
# any .fpp that includes a generated file whenever a params .py changes.
add_custom_command(
OUTPUT ${_mfc_all_gen_files}
COMMAND "${Python3_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/generators/cmake_gen.py"
"${CMAKE_BINARY_DIR}"
DEPENDS ${_mfc_gen_inputs}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Regenerating Fortran parameter includes"
VERBATIM
)
add_custom_target(mfc_params_gen DEPENDS ${_mfc_all_gen_files})

HANDLE_SOURCES(pre_process ON)
HANDLE_SOURCES(simulation ON)
HANDLE_SOURCES(post_process ON)
Expand Down
40 changes: 16 additions & 24 deletions docs/documentation/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,35 +276,27 @@ def check_my_feature(self):

If your check enforces a physics constraint, also add a `PHYSICS_DOCS` entry (see [How to Document Physics Constraints](#how-to-document-physics-constraints) below).

**Step 5: Declare in Fortran** (`src/<target>/m_global_parameters.fpp`)
**Step 5: Fortran declaration and namelist binding (auto-generated)**

Add the variable declaration in the appropriate target's global parameters module. Choose the target(s) where the parameter is used:
Scalar declarations, GPU declare lines, Doxygen descriptions, and namelist bindings are
auto-generated at CMake configure time from the `TYPED_DECLS` and `FORTRAN_ARRAY_DIMS`
tables in `toolchain/mfc/params/definitions.py`. For a plain scalar registered with
`_r()` / `_nv()` above, no manual Fortran edit is needed — reconfigure (`./mfc.sh build`)
and the generated include in each target's `m_global_parameters.fpp` is updated
automatically.

- `src/pre_process/m_global_parameters.fpp`
- `src/simulation/m_global_parameters.fpp`
- `src/post_process/m_global_parameters.fpp`
Still manual (not auto-generated):

```fortran
real(wp) :: my_param !< Description of the parameter
```

If the parameter is used in GPU kernels, add a GPU declaration:

```fortran
$:GPU_DECLARE(create='[my_param]')
```

**Step 6: Add to Fortran namelist** (`src/<target>/m_start_up.fpp`)

Add the parameter name to the `namelist /user_inputs/` declaration:

```fortran
namelist /user_inputs/ ... , my_param, ...
```
- `TYPE` member definitions inside derived types in `src/common/m_derived_types.fpp`
- Default-value assignments in `s_assign_default_values_to_user_inputs`
- Multi-variable declaration lines (`bc_x/y/z`, `x/y/z_domain`, `x/y/z_output`)
- MPI broadcast lists in `src/*/m_mpi_proxy.fpp`
- `CASE_OPT_EXTRA_LINES` in `toolchain/mfc/params/generators/fortran_gen.py` for case-optimization constants

The toolchain writes the parameter to the input file and Fortran reads it via this namelist. No other I/O code is needed.
After editing any generator or table, force regen by reconfiguring (`./mfc.sh build`) —
cached builds compile stale includes.

**Step 7: Use in Fortran code**
**Step 6: Use in Fortran code**

Reference `my_param` anywhere in the target's modules. It is available as a global after the namelist is read at startup.

Expand Down
5 changes: 1 addition & 4 deletions src/common/m_constants.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ module m_constants
real(wp), parameter :: broadband_spectral_level_constant = 20._wp
!> The spectral level constant to correct the magnitude at each frequency to ensure the source is overall broadband
real(wp), parameter :: broadband_spectral_level_growth_rate = 10._wp
! Reconstruction Types
integer, parameter :: WENO_TYPE = 1 !< Using WENO for reconstruction type
integer, parameter :: MUSCL_TYPE = 2 !< Using MUSCL for reconstruction type
! Interface Compression
! Reconstruction Types Interface Compression
real(wp), parameter :: dflt_ic_eps = 1e-4_wp !< Ensure compression is only applied to surface cells in THINC
real(wp), parameter :: dflt_ic_beta = 1.6_wp !< Sharpness parameter's default value used in THINC
real(wp), parameter :: moncon_cutoff = 1e-8_wp !< Monotonicity constraint's limiter to prevent extremas in THINC
Expand Down
5 changes: 3 additions & 2 deletions src/common/m_helper_basic.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module m_helper_basic

use m_derived_types
use m_precision_select
use m_constants, only: recon_type_weno, recon_type_muscl

implicit none

Expand Down Expand Up @@ -125,13 +126,13 @@ contains

if (igr) then
buff_size = (igr_order - 1)/2 + 2
else if (recon_type == WENO_TYPE) then
else if (recon_type == recon_type_weno) then
if (viscous) then
buff_size = 2*weno_polyn + 2
else
buff_size = weno_polyn + 2
end if
else if (recon_type == MUSCL_TYPE) then
else if (recon_type == recon_type_muscl) then
buff_size = muscl_polyn + 2
end if

Expand Down
15 changes: 8 additions & 7 deletions src/common/m_mpi_common.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module m_mpi_common
use m_helper
use ieee_arithmetic
use m_nvtx
use m_constants, only: recon_type_weno, format_silo

implicit none

Expand Down Expand Up @@ -1031,7 +1032,7 @@ contains
integer :: i, j !< Generic loop iterators
integer :: ierr !< Generic flag used to identify and report MPI errors

if (recon_type == WENO_TYPE) then
if (recon_type == recon_type_weno) then
recon_order = weno_order
else
recon_order = muscl_order
Expand Down Expand Up @@ -1194,14 +1195,14 @@ contains

#ifdef MFC_POST_PROCESS
! Ghost zone at the beginning
if (proc_coords(3) > 0 .and. format == 1) then
if (proc_coords(3) > 0 .and. format == format_silo) then
offset_z%beg = 2
else
offset_z%beg = 0
end if

! Ghost zone at the end
if (proc_coords(3) < num_procs_z - 1 .and. format == 1) then
if (proc_coords(3) < num_procs_z - 1 .and. format == format_silo) then
offset_z%end = 2
else
offset_z%end = 0
Expand Down Expand Up @@ -1306,14 +1307,14 @@ contains

#ifdef MFC_POST_PROCESS
! Ghost zone at the beginning
if (proc_coords(2) > 0 .and. format == 1) then
if (proc_coords(2) > 0 .and. format == format_silo) then
offset_y%beg = 2
else
offset_y%beg = 0
end if

! Ghost zone at the end
if (proc_coords(2) < num_procs_y - 1 .and. format == 1) then
if (proc_coords(2) < num_procs_y - 1 .and. format == format_silo) then
offset_y%end = 2
else
offset_y%end = 0
Expand Down Expand Up @@ -1389,14 +1390,14 @@ contains

#ifdef MFC_POST_PROCESS
! Ghost zone at the beginning
if (proc_coords(1) > 0 .and. format == 1) then
if (proc_coords(1) > 0 .and. format == format_silo) then
offset_x%beg = 2
else
offset_x%beg = 0
end if

! Ghost zone at the end
if (proc_coords(1) < num_procs_x - 1 .and. format == 1) then
if (proc_coords(1) < num_procs_x - 1 .and. format == format_silo) then
offset_x%end = 2
else
offset_x%end = 0
Expand Down
4 changes: 2 additions & 2 deletions src/common/m_variables_conversion.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module m_variables_conversion
use m_helper_basic
use m_helper
use m_constants, only: riemann_solver_hll, riemann_solver_hlld, model_eqns_gamma_law, model_eqns_5eq, model_eqns_6eq, &
& model_eqns_4eq
& model_eqns_4eq, avg_state_roe
use m_thermochem, only: num_species, get_temperature, get_pressure, gas_constant, get_mixture_molecular_weight, &
& get_mixture_energy_mass

Expand Down Expand Up @@ -1267,7 +1267,7 @@ contains
integer :: q

if (chemistry) then ! Reacting mixture sound speed
if (avg_state == 1 .and. abs(c_c) > verysmall) then
if (avg_state == avg_state_roe .and. abs(c_c) > verysmall) then
c = sqrt(c_c - (gamma - 1.0_wp)*(vel_sum - H))
else
c = sqrt((1.0_wp + 1.0_wp/gamma)*pres/rho)
Expand Down
Loading
Loading