Validates all parsed parameters against physical and algorithmic limits.
Triggers fatal_error for non-physical values (e.g., negative density,
zero timestep) or unsupported configurations.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(case_params_t), | intent(in) | :: | params |
subroutine validate_params(params) type(case_params_t), intent(in) :: params if (params%nsteps < 0) call fatal_error('input', 'nsteps must be non-negative') if (params%dt <= zero) call fatal_error('input', 'dt must be positive') if (params%max_dt <= zero) call fatal_error('input', 'max_dt must be positive') if (params%min_dt <= zero) call fatal_error('input', 'min_dt must be positive') if (params%min_dt > params%max_dt) call fatal_error('input', 'min_dt must be <= max_dt') if (params%dt_growth_limit < one) call fatal_error('input', 'dt_growth_limit must be >= 1') if (params%max_step_retries < 0) call fatal_error('input', 'max_step_retries must be non-negative') if (params%step_reject_cut_factor <= zero .or. params%step_reject_cut_factor >= one) then call fatal_error('input', 'step_reject_cut_factor must be in (0,1)') end if if (params%step_reject_min_dt <= zero) call fatal_error('input', 'step_reject_min_dt must be positive') if (params%max_KE_growth_per_step < zero) call fatal_error('input', 'max_KE_growth_per_step must be non-negative') if (params%ke_reject_floor < zero) call fatal_error('input', 'ke_reject_floor must be non-negative') if (params%max_cfl_overshoot_factor < zero) call fatal_error('input', 'max_cfl_overshoot_factor must be non-negative') if (params%output_interval <= 0) call fatal_error('input', 'output_interval must be positive') if (params%terminal_interval <= 0) call fatal_error('input', 'terminal_interval must be positive') select case (trim(params%terminal_detail)) case ('brief', 'health', 'full') continue case default call fatal_error('input', 'terminal_detail must be one of: brief, health, full') end select if (params%rho <= zero) call fatal_error('input', 'rho must be positive') if (params%nu < zero) call fatal_error('input', 'nu must be non-negative') if (params%enable_variable_nu .and. .not. params%enable_cantera_fluid) then call fatal_error('input', 'enable_variable_nu=.true. requires fluid_input enable_cantera=.true.; otherwise use constant nu') end if if (params%transport_update_interval <= 0) call fatal_error('input', 'transport_update_interval must be positive') if (params%pressure_max_iter <= 0) call fatal_error('input', 'pressure_max_iter must be positive') call validate_advection_scheme_local(params%momentum_convection_scheme, 'momentum_convection_scheme', .false.) call validate_advection_scheme_local(params%convection_scheme, 'convection_scheme', .false.) call validate_advection_scheme_local(params%species_convection_scheme, 'species_convection_scheme', .true.) call validate_advection_scheme_local(params%energy_convection_scheme, 'energy_convection_scheme', .true.) call validate_limiter_name_local(params%scalar_limiter) call validate_time_scheme_local(params%species_time_scheme, 'species_time_scheme') call validate_time_scheme_local(params%energy_time_scheme, 'energy_time_scheme') if (params%initial_T <= zero) call fatal_error('input', 'initial_T must be positive') if (params%energy_reference_T <= zero) call fatal_error('input', 'energy_reference_T must be positive') if (params%energy_cp <= zero) call fatal_error('input', 'energy_cp must be positive') if (params%energy_lambda < zero) call fatal_error('input', 'energy_lambda must be non-negative') if (params%thermo_update_interval <= 0) call fatal_error('input', 'thermo_update_interval must be positive') if (params%enable_cantera_thermo .and. params%thermo_update_interval /= 1) then call fatal_error('input', 'thermo_update_interval values other than 1 are reserved; Cantera thermo is currently updated every energy step') end if if (params%enable_cantera_thermo .and. len_trim(params%thermo_default_species) == 0) & call fatal_error('input', 'thermo_default_species must not be empty when enable_cantera_thermo is true') if (params%enable_species_enthalpy_diffusion) then if (.not. params%enable_energy) then call fatal_error('input', 'enable_species_enthalpy_diffusion requires enable_energy=.true.') end if if (.not. params%enable_species) then call fatal_error('input', 'enable_species_enthalpy_diffusion requires transported species') end if if (params%nspecies <= 0 .and. .not. params%enable_reactions .and. & .not. (params%enable_species .and. params%enable_cantera_species)) then call fatal_error('input', 'enable_species_enthalpy_diffusion requires nspecies > 0 unless Cantera auto-discovers mechanism species') end if if (.not. params%enable_cantera_thermo) then call fatal_error('input', 'enable_species_enthalpy_diffusion currently requires enable_cantera_thermo=.true. for species sensible enthalpies') end if end if if (params%n_patches < 0 .or. params%n_patches > max_patches) then call fatal_error('input', 'n_patches is outside supported range') end if if (len_trim(params%mesh_dir) == 0) then call fatal_error('input', 'mesh_dir cannot be empty') end if if (len_trim(params%output_dir) == 0) then call fatal_error('input', 'output_dir cannot be empty') end if if (params%vtu_format /= "ascii" .and. params%vtu_format /= "binary") then call fatal_error('input', 'vtu_format must be either "ascii" or "binary"') end if if (params%nspecies < 0 .or. params%nspecies > max_species) then call fatal_error('input', 'nspecies is outside supported range') end if if (params%enable_reactions) then if (.not. params%enable_species) call fatal_error('input', 'enable_reactions requires enable_species=.true.') if (.not. params%enable_energy) call fatal_error('input', 'enable_reactions requires enable_energy=.true.') if (.not. params%enable_cantera_thermo) call fatal_error('input', 'enable_reactions requires enable_cantera_thermo=.true.') if (params%chemistry_update_interval <= 0) call fatal_error('input', 'chemistry_update_interval must be positive') if (params%chemistry_rtol <= zero) call fatal_error('input', 'chemistry_rtol must be positive') if (params%chemistry_atol <= zero) call fatal_error('input', 'chemistry_atol must be positive') if (params%chemistry_max_steps <= 0) call fatal_error('input', 'chemistry_max_steps must be positive') if (params%chemistry_temperature_cutoff < zero) call fatal_error('input', 'chemistry_temperature_cutoff must be non-negative') if (params%chemistry_min_reactive_mass_fraction < zero) call fatal_error('input', 'chemistry_min_reactive_mass_fraction must be non-negative') if (params%chemistry_active_species_threshold < zero) call fatal_error('input', 'chemistry_active_species_threshold must be non-negative') if (params%chemistry_max_dT_per_step < zero) call fatal_error('input', 'chemistry_max_dT_per_step must be non-negative') if (params%chemistry_max_rel_rho_change_per_step < zero) call fatal_error('input', 'chemistry_max_rel_rho_change_per_step must be non-negative') if (params%chemistry_max_dY_per_step < zero) call fatal_error('input', 'chemistry_max_dY_per_step must be non-negative') if (params%chemistry_dt_safety <= zero .or. params%chemistry_dt_safety > one) call fatal_error('input', 'chemistry_dt_safety must be in (0,1]') if (params%chemistry_dt_min_factor <= zero .or. params%chemistry_dt_min_factor > one) call fatal_error('input', 'chemistry_dt_min_factor must be in (0,1]') if (params%chemistry_source_relaxation <= zero .or. params%chemistry_source_relaxation > one) call fatal_error('input', 'chemistry_source_relaxation must be in (0,1]') if (params%chemistry_n_active_species < 0 .or. params%chemistry_n_active_species > max_species) then call fatal_error('input', 'chemistry_n_active_species must be between 0 and max_species') end if end if if (params%variable_density_debug_interval <= 0) then call fatal_error('input', 'variable_density_debug_interval must be positive') end if if (params%enable_ignition_kernel) then if (.not. params%enable_energy) call fatal_error('input', 'enable_ignition_kernel requires enable_energy=.true.') select case (trim(lowercase(params%ignition_kernel_shape))) case ('sphere') continue case default call fatal_error('input', 'ignition_kernel_shape currently supports only sphere') end select select case (trim(lowercase(params%ignition_kernel_blend))) case ('overwrite') continue case default call fatal_error('input', 'ignition_kernel_blend currently supports only overwrite') end select if (params%ignition_kernel_radius <= zero) call fatal_error('input', 'ignition_kernel_radius must be positive') if (params%ignition_kernel_T <= zero) call fatal_error('input', 'ignition_kernel_T must be positive') if (len_trim(params%ignition_kernel_composition) > 0 .and. .not. params%enable_species) then call fatal_error('input', 'ignition_kernel_composition requires enable_species=.true.') end if end if if (params%restart_from_file .and. len_trim(params%restart_file) == 0) then call fatal_error('input', 'restart_from_file=.true. requires restart_file') end if if (params%write_restart) then if (params%restart_interval <= 0) call fatal_error('input', 'write_restart=.true. requires restart_interval > 0') if (len_trim(params%restart_output_dir) == 0) call fatal_error('input', 'restart_output_dir cannot be empty') if (params%restart_keep < 0) call fatal_error('input', 'restart_keep must be non-negative') end if if (params%enable_radiation) then if (.not. params%enable_energy) call fatal_error('input', 'enable_radiation requires enable_energy=.true.') if (params%radiation_update_interval <= 0) call fatal_error('input', 'radiation_update_interval must be positive') if (params%radiation_n_wavenumbers <= 0) call fatal_error('input', 'radiation_n_wavenumbers must be positive when radiation is enabled') if (params%radiation_n_species < 0 .or. params%radiation_n_species > max_species) then call fatal_error('input', 'radiation_n_species is outside supported range') end if if (params%radiation_n_species > 0 .and. .not. params%enable_species) then call fatal_error('input', 'radiation species selection requires enable_species=.true.') end if select case (trim(lowercase(params%radiation_source_model))) case ('none', 'spectral_test', 'external', 'p1', 'dom') continue case default call fatal_error('input', 'radiation_source_model must be one of: none, spectral_test, external, p1, dom') end select if (trim(lowercase(params%radiation_source_model)) == 'dom') then if (trim(lowercase(params%radiation_dom_quadrature)) /= 's2' .and. & trim(lowercase(params%radiation_dom_quadrature)) /= 's4' .and. & trim(lowercase(params%radiation_dom_quadrature)) /= 's6' .and. & trim(lowercase(params%radiation_dom_quadrature)) /= 's8') then call fatal_error('input', 'radiation_dom_quadrature must be s2, s4, s6, or s8') end if end if if (params%radiation_n_scalars < 0 .or. params%radiation_n_scalars > max_species) then call fatal_error('input', 'radiation_n_scalars is outside supported range') end if if (trim(lowercase(params%radiation_pressure_source)) /= 'background' .and. & trim(lowercase(params%radiation_pressure_source)) /= 'system') then call fatal_error('input', 'radiation_pressure_source must be one of: background, system') end if end if call validate_boundary_arrays(params) end subroutine validate_params