Skip to content

Commit a21bfbf

Browse files
authored
refactor(params): auto-generate Fortran namelists from Python, eliminate toolchain duplication (#1456)
1 parent 4b633d5 commit a21bfbf

37 files changed

Lines changed: 1089 additions & 1698 deletions

.claude/rules/common-pitfalls.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Before submitting a PR:
5959
- [ ] `./mfc.sh precheck -j 8` (5 CI lint checks)
6060
- [ ] `./mfc.sh build -j 8` (compiles)
6161
- [ ] `./mfc.sh test --only <relevant> -j 8` (tests pass)
62-
- [ ] If adding parameters: all 4 locations updated
62+
- [ ] If adding parameters: definitions.py (_r + _nv) updated; cmake reconfigured; case_validator.py if constraints
6363
- [ ] If modifying `src/common/`: all three targets tested
6464
- [ ] If changing output: golden files regenerated for affected tests
6565
- [ ] One logical change per commit

.claude/rules/parameter-system.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,22 @@ MFC has ~3,400 simulation parameters defined in Python and read by Fortran via n
2323
- Reads `&user_inputs` namelist
2424
- Each parameter must be declared in the namelist statement
2525

26-
## Adding a New Parameter (4-location checklist)
26+
## Adding a New Parameter (2-location checklist)
2727

28-
YOU MUST update the first 3 locations. Missing any causes silent failures or compile errors.
29-
Location 4 is required only if the parameter has physics constraints.
28+
Fortran declarations and namelist bindings are now auto-generated from definitions.py
29+
at CMake configure time — no manual Fortran edits needed for simple scalar parameters.
3030

31-
1. **`toolchain/mfc/params/definitions.py`**: Add parameter with type, default, constraints
32-
2. **`src/*/m_global_parameters.fpp`**: Declare the Fortran variable in the relevant
33-
target(s). If the param is used by simulation only, add it there. If shared, add to
34-
all three targets' m_global_parameters.fpp.
35-
3. **`src/*/m_start_up.fpp`**: Add to the Fortran `namelist` declaration in the relevant
36-
target(s).
37-
4. **`toolchain/mfc/case_validator.py`**: Add validation rules if the parameter has
31+
1. **`toolchain/mfc/params/definitions.py`**: Add parameter with `_r()` (type, default,
32+
constraints) AND add it to `NAMELIST_VARS` via `_nv()` for the relevant target(s).
33+
After editing, re-run cmake (or `./mfc.sh build`) to regenerate the Fortran includes.
34+
2. **`toolchain/mfc/case_validator.py`**: Add validation rules if the parameter has
3835
physics constraints. Include `PHYSICS_DOCS` entry with title, category, explanation.
3936

37+
**Exceptions — still require manual Fortran edits:**
38+
- Array variables (e.g. `logical, dimension(num_fluids_max)`) → declare in `src/*/m_global_parameters.fpp`
39+
- Derived-type members (`fluid_pp%attr`, `patch_icpp(i)%attr`) → declare in the relevant derived type
40+
- Case-optimization parameters → add to `CASE_OPT_PARAMS` and the `#:else` block in `src/simulation/m_global_parameters.fpp`
41+
4042
## Case Files
4143
- Case files are Python scripts (`.py`) that define a dict of parameters
4244
- Validated with `./mfc.sh validate case.py`

CLAUDE.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,12 @@ NEVER use `stop` or `error stop`. Use `call s_mpi_abort()` or `@:PROHIBIT()`/`@:
139139
NEVER use `goto`, `COMMON` blocks, or global `save` variables.
140140

141141
Every `@:ALLOCATE(...)` MUST have a matching `@:DEALLOCATE(...)`.
142-
Every new parameter MUST be added in at least 3 places (4 if it has constraints):
143-
1. `toolchain/mfc/params/definitions.py` (parameter definition)
144-
2. Fortran variable declaration in `src/*/m_global_parameters.fpp`
145-
3. Fortran namelist in `src/*/m_start_up.fpp` (namelist binding)
146-
4. `toolchain/mfc/case_validator.py` (only if parameter has physics constraints)
142+
Every new parameter MUST be added in at least 2 places (3 if it has constraints):
143+
1. `toolchain/mfc/params/definitions.py` (parameter definition + NAMELIST_VARS target set)
144+
2. `toolchain/mfc/case_validator.py` (only if parameter has physics constraints)
145+
Note: Fortran declarations and namelist bindings are auto-generated from definitions.py
146+
at CMake configure time. Simple scalars need no manual Fortran edits. Array/derived-type
147+
variables still require a manual declaration in `src/*/m_global_parameters.fpp`.
147148

148149
Changes to `src/common/` affect ALL three executables. Test comprehensively.
149150

CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,39 @@ macro(HANDLE_SOURCES target useCommon)
461461
endmacro()
462462

463463

464+
# Generate Fortran parameter namelist/decl includes into the per-target build
465+
# include directories before HANDLE_SOURCES globs them for Fypp.
466+
find_package(Python3 REQUIRED COMPONENTS Interpreter)
467+
set(_mfc_gen_stamp "${CMAKE_BINARY_DIR}/mfc_params_gen.stamp")
468+
file(GLOB_RECURSE _mfc_gen_inputs
469+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/*.py"
470+
)
471+
set(_mfc_needs_regen FALSE)
472+
if(NOT EXISTS "${_mfc_gen_stamp}")
473+
set(_mfc_needs_regen TRUE)
474+
else()
475+
foreach(_input IN LISTS _mfc_gen_inputs)
476+
if("${_input}" IS_NEWER_THAN "${_mfc_gen_stamp}")
477+
set(_mfc_needs_regen TRUE)
478+
break()
479+
endif()
480+
endforeach()
481+
endif()
482+
if(_mfc_needs_regen)
483+
execute_process(
484+
COMMAND "${Python3_EXECUTABLE}"
485+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/generators/cmake_gen.py"
486+
"${CMAKE_BINARY_DIR}"
487+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
488+
RESULT_VARIABLE _mfc_gen_result
489+
ERROR_VARIABLE _mfc_gen_error
490+
)
491+
if(NOT _mfc_gen_result EQUAL 0)
492+
message(FATAL_ERROR "Fortran param generation failed:\n${_mfc_gen_error}")
493+
endif()
494+
file(TOUCH "${_mfc_gen_stamp}")
495+
endif()
496+
464497
HANDLE_SOURCES(pre_process ON)
465498
HANDLE_SOURCES(simulation ON)
466499
HANDLE_SOURCES(post_process ON)

src/post_process/m_global_parameters.fpp

Lines changed: 12 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,19 @@ module m_global_parameters
1717

1818
implicit none
1919

20+
#:include 'generated_decls.fpp'
21+
2022
!> @name Logistics
2123
!> @{
22-
integer :: num_procs !< Number of processors
23-
character(LEN=path_len) :: case_dir !< Case folder location
24+
integer :: num_procs !< Number of processors
2425
!> @}
2526

2627
! Computational Domain Parameters
2728

2829
integer :: proc_rank !< Rank of the local processor
2930
!> @name Number of cells in the x-, y- and z-coordinate directions
3031
!> @{
31-
integer :: m, m_root
32-
integer :: n
33-
integer :: p
32+
integer :: m_root
3433
!> @}
3534

3635
!> @name Max and min number of cells in a direction of each combination of x-,y-, and z-
@@ -39,7 +38,6 @@ module m_global_parameters
3938

4039
!> @name Cylindrical coordinates (either axisymmetric or full 3D)
4140
!> @{
42-
logical :: cyl_coord
4341
integer :: grid_geometry
4442
!> @}
4543

@@ -66,50 +64,24 @@ module m_global_parameters
6664
real(wp), allocatable, dimension(:) :: dx, dy, dz
6765
!> @}
6866

69-
integer :: buff_size !< Number of ghost cells for boundary condition storage
70-
integer :: t_step_start !< First time-step directory
71-
integer :: t_step_stop !< Last time-step directory
72-
integer :: t_step_save !< Interval between consecutive time-step directory
67+
integer :: buff_size !< Number of ghost cells for boundary condition storage
7368
!> @name IO options for adaptive time-stepping
7469
!> @{
75-
logical :: cfl_adap_dt, cfl_const_dt, cfl_dt
76-
real(wp) :: t_save
77-
real(wp) :: t_stop
78-
real(wp) :: cfl_target
79-
integer :: n_save
80-
integer :: n_start
70+
logical :: cfl_dt
71+
integer :: n_save
8172
!> @}
8273

8374
! NOTE: m_root, x_root_cb, x_root_cc = defragmented grid (1D only; equals m, x_cb, x_cc in serial)
8475

8576
!> @name Simulation Algorithm Parameters
8677
!> @{
87-
integer :: model_eqns !< Multicomponent flow model
88-
integer :: num_fluids !< Number of different fluids present in the flow
89-
logical :: relax !< phase change
90-
integer :: relax_model !< Phase change relaxation model
91-
logical :: mpp_lim !< Maximum volume fraction limiter
9278
integer :: sys_size !< Number of unknowns in the system of equations
93-
integer :: recon_type !< Which type of reconstruction to use
94-
integer :: weno_order !< Order of accuracy for the WENO reconstruction
95-
integer :: muscl_order !< Order of accuracy for the MUSCL reconstruction
96-
logical :: mixture_err !< Mixture error limiter
97-
logical :: alt_soundspeed !< Alternate sound speed
98-
logical :: mhd !< Magnetohydrodynamics
99-
logical :: relativity !< Relativity for RMHD
100-
logical :: hypoelasticity !< Turn hypoelasticity on
101-
logical :: hyperelasticity !< Turn hyperelasticity on
10279
logical :: elasticity !< elasticity modeling, true for hyper or hypo
10380
integer :: b_size !< Number of components in the b tensor
10481
integer :: tensor_size !< Number of components in the nonsymmetric tensor
105-
logical :: cont_damage !< Continuum damage modeling
106-
logical :: hyper_cleaning !< Hyperbolic cleaning for MHD
107-
logical :: igr !< enable IGR
108-
integer :: igr_order !< IGR reconstruction order
10982
logical, parameter :: chemistry = .${chemistry}$. !< Chemistry modeling
11083
!> @}
11184

112-
integer :: avg_state !< Average state evaluation method
11385
!> @name Annotations of the structure, i.e. the organization, of the state vectors
11486
!> @{
11587
type(eqn_idx_info) :: eqn_idx !< All conserved-variable equation index ranges and scalars.
@@ -122,7 +94,6 @@ module m_global_parameters
12294

12395
! Cell indices (InDices With BUFFer): includes buffer in simulation only
12496
type(int_bounds_info) :: idwbuff(1:3)
125-
integer :: num_bc_patches
12697
logical :: bc_io
12798
!> @name Boundary conditions in the x-, y- and z-coordinate directions
12899
!> @{
@@ -133,12 +104,8 @@ module m_global_parameters
133104
integer, dimension(3) :: shear_indices !< Indices of the stress components that represent shear stress
134105
integer :: shear_BC_flip_num !< Number of shear stress components to reflect for boundary conditions
135106
integer, dimension(3, 2) :: shear_BC_flip_indices !< Shear stress BC reflection indices (1:3, 1:shear_BC_flip_num)
136-
logical :: parallel_io !< Format of the data files
137-
logical :: sim_data
138-
logical :: file_per_process !< output format
139107
integer, allocatable, dimension(:) :: proc_coords !< Processor coordinates in MPI_CART_COMM
140108
integer, allocatable, dimension(:) :: start_idx !< Starting cell-center index of local processor in global grid
141-
integer :: num_ibs !< Number of immersed boundaries
142109
#ifdef MFC_MPI
143110
type(mpi_io_var), public :: MPI_IO_DATA
144111
type(mpi_io_ib_var), public :: MPI_IO_IB_DATA
@@ -159,10 +126,6 @@ module m_global_parameters
159126
real(wp), allocatable, dimension(:) :: adv !< Advection variables
160127
! Formatted Database File(s) Structure Parameters
161128

162-
integer :: format !< Format of the database file(s)
163-
integer :: precision !< Floating point precision of the database file(s)
164-
logical :: down_sample !< down sampling of the database file(s)
165-
logical :: output_partial_domain !< Specify portion of domain to output for post-processing
166129
type(bounds_info) :: x_output, y_output, z_output !< Portion of domain to output for post-processing
167130
type(int_bounds_info) :: x_output_idx, y_output_idx, z_output_idx !< Indices of domain to output for post-processing
168131
!> @name Size of the ghost zone layer in the x-, y- and z-coordinate directions. The definition of the ghost zone layers is only
@@ -172,101 +135,23 @@ module m_global_parameters
172135
type(int_bounds_info) :: offset_x, offset_y, offset_z
173136
!> @}
174137

175-
!> @name The list of all possible flow variables that may be written to a database file. It includes partial densities, density,
176-
!! momentum, velocity, energy, pressure, volume fraction(s), specific heat ratio function, specific heat ratio, liquid stiffness
177-
!! function, liquid stiffness, primitive variables, conservative variables, speed of sound, the vorticity, and the numerical
178-
!! Schlieren function.
179-
!> @{
180-
logical, dimension(num_fluids_max) :: alpha_rho_wrt
181-
logical :: rho_wrt
182-
logical, dimension(3) :: mom_wrt
183-
logical, dimension(3) :: vel_wrt
184-
integer :: flux_lim
185-
logical, dimension(3) :: flux_wrt
186-
logical :: E_wrt
187-
logical, dimension(num_fluids_max) :: alpha_rho_e_wrt
188-
logical :: fft_wrt
189-
logical :: pres_wrt
190-
logical, dimension(num_fluids_max) :: alpha_wrt
191-
logical :: gamma_wrt
192-
logical :: heat_ratio_wrt
193-
logical :: pi_inf_wrt
194-
logical :: pres_inf_wrt
195-
logical :: prim_vars_wrt
196-
logical :: cons_vars_wrt
197-
logical :: c_wrt
198-
logical, dimension(3) :: omega_wrt
199-
logical :: qm_wrt
200-
logical :: liutex_wrt
201-
logical :: schlieren_wrt
202-
logical :: cf_wrt
203-
logical :: ib
204-
logical :: ib_state_wrt
205-
logical :: chem_wrt_Y(1:num_species)
206-
logical :: chem_wrt_T
207-
logical :: lag_header
208-
logical :: lag_txt_wrt
209-
logical :: lag_db_wrt
210-
logical :: lag_id_wrt
211-
logical :: lag_pos_wrt
212-
logical :: lag_pos_prev_wrt
213-
logical :: lag_vel_wrt
214-
logical :: lag_rad_wrt
215-
logical :: lag_rvel_wrt
216-
logical :: lag_r0_wrt
217-
logical :: lag_rmax_wrt
218-
logical :: lag_rmin_wrt
219-
logical :: lag_dphidt_wrt
220-
logical :: lag_pres_wrt
221-
logical :: lag_mv_wrt
222-
logical :: lag_mg_wrt
223-
logical :: lag_betaT_wrt
224-
logical :: lag_betaC_wrt
225-
!> @}
226-
227-
real(wp), dimension(num_fluids_max) :: schlieren_alpha !< Per-fluid Schlieren intensity amplitude coefficients
228-
integer :: fd_order !< Finite-difference order for vorticity and Schlieren derivatives
229-
integer :: fd_number !< Finite-difference half-stencil size: MAX(1, fd_order/2)
230-
!> @name Reference parameters for Tait EOS
231-
!> @{
232-
real(wp) :: rhoref, pref
233-
!> @}
234-
138+
! alpha_rho_wrt, mom_wrt, vel_wrt, flux_wrt, alpha_rho_e_wrt, alpha_wrt,
139+
! omega_wrt, chem_wrt_Y, schlieren_alpha: auto-generated in generated_decls.fpp
140+
integer :: fd_number !< Finite-difference half-stencil size: MAX(1, fd_order/2)
235141
type(chemistry_parameters) :: chem_params
236142
!> @name Bubble modeling variables and parameters
237143
!> @{
238-
integer :: nb
239-
real(wp) :: Eu, Ca, Web, Re_inv
144+
real(wp) :: Eu
240145
real(wp), dimension(:), allocatable :: weight, R0
241-
logical :: bubbles_euler
242-
logical :: qbmm
243-
logical :: polytropic
244-
logical :: polydisperse
245-
logical :: adv_n
246-
integer :: thermal !< 1 = adiabatic, 2 = isotherm, 3 = transfer
247146
real(wp) :: phi_vg, phi_gv, Pe_c, Tw, k_vl, k_gl
248147
real(wp) :: gam_m
249148
real(wp), dimension(:), allocatable :: pb0, mass_g0, mass_v0, Pe_T, k_v, k_g
250149
real(wp), dimension(:), allocatable :: Re_trans_T, Re_trans_c, Im_trans_T, Im_trans_c, omegaN
251-
real(wp) :: R0ref, p0ref, rho0ref, T0ref, ss, pv, vd, mu_l, mu_v, mu_g, gam_v, gam_g, M_v, M_g, cp_v, cp_g, R_v, R_g
150+
real(wp) :: p0ref, rho0ref, T0ref, ss, pv, vd, mu_l, mu_v, mu_g, gam_v, gam_g, M_v, M_g, cp_v, cp_g, R_v, R_g
252151
real(wp) :: G
253-
real(wp) :: poly_sigma
254-
real(wp) :: sigR
255152
integer :: nmom
256153
!> @}
257154

258-
!> @name surface tension coefficient
259-
!> @{
260-
real(wp) :: sigma
261-
logical :: surface_tension
262-
!> @}
263-
264-
!> @name Lagrangian bubbles
265-
!> @{
266-
logical :: bubbles_lagrange
267-
!> @}
268-
269-
real(wp) :: Bx0 !< Constant magnetic field in the x-direction (1D)
270155
real(wp) :: wall_time, wall_time_avg !< Wall time measurements
271156

272157
contains

src/post_process/m_start_up.fpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,7 @@ contains
5959
integer :: iostatus
6060
character(len=1000) :: line
6161

62-
namelist /user_inputs/ case_dir, m, n, p, t_step_start, t_step_stop, t_step_save, model_eqns, num_fluids, mpp_lim, &
63-
& weno_order, bc_x, bc_y, bc_z, fluid_pp, bub_pp, format, precision, output_partial_domain, x_output, y_output, &
64-
& z_output, hypoelasticity, G, mhd, chem_wrt_Y, chem_wrt_T, avg_state, alpha_rho_wrt, rho_wrt, mom_wrt, vel_wrt, &
65-
& E_wrt, fft_wrt, pres_wrt, alpha_wrt, gamma_wrt, heat_ratio_wrt, pi_inf_wrt, pres_inf_wrt, cons_vars_wrt, &
66-
& prim_vars_wrt, c_wrt, omega_wrt, qm_wrt, liutex_wrt, schlieren_wrt, schlieren_alpha, fd_order, mixture_err, &
67-
& alt_soundspeed, flux_lim, flux_wrt, cyl_coord, parallel_io, rhoref, pref, bubbles_euler, qbmm, sigR, R0ref, nb, &
68-
& polytropic, thermal, Ca, Web, Re_inv, polydisperse, poly_sigma, file_per_process, relax, relax_model, cf_wrt, &
69-
& sigma, adv_n, ib, num_ibs, cfl_adap_dt, cfl_const_dt, t_save, t_stop, n_start, cfl_target, surface_tension, &
70-
& bubbles_lagrange, sim_data, hyperelasticity, Bx0, relativity, cont_damage, hyper_cleaning, num_bc_patches, igr, &
71-
& igr_order, down_sample, recon_type, muscl_order, lag_header, lag_txt_wrt, lag_db_wrt, lag_id_wrt, lag_pos_wrt, &
72-
& lag_pos_prev_wrt, lag_vel_wrt, lag_rad_wrt, lag_rvel_wrt, lag_r0_wrt, lag_rmax_wrt, lag_rmin_wrt, lag_dphidt_wrt, &
73-
& lag_pres_wrt, lag_mv_wrt, lag_mg_wrt, lag_betaT_wrt, lag_betaC_wrt, alpha_rho_e_wrt, ib_state_wrt
62+
#:include 'generated_namelist.fpp'
7463

7564
file_loc = 'post_process.inp'
7665
inquire (FILE=trim(file_loc), EXIST=file_check)

0 commit comments

Comments
 (0)