option_registry.f90 Source File


Source Code

!> @file option_registry.f90
!> @brief Canonical string tokens for runtime-selectable solver options.
!!
!! Centralises the valid scheme, limiter, boundary-condition, and config-enum
!! names that are accepted throughout the solver. Modules that dispatch on a
!! string token should import the corresponding named constants from here
!! instead of duplicating string literals locally.
module option_registry
  implicit none
  private

  ! Flux schemes
  character(len=*), parameter, public :: flux_lax_friedrichs = 'lax_friedrichs'
  character(len=*), parameter, public :: flux_steger_warming = 'steger_warming'
  character(len=*), parameter, public :: flux_van_leer = 'van_leer'
  character(len=*), parameter, public :: flux_ausm_plus = 'ausm_plus'
  character(len=*), parameter, public :: flux_hll = 'hll'
  character(len=*), parameter, public :: flux_hllc = 'hllc'
  character(len=*), parameter, public :: flux_roe = 'roe'

  ! Reconstruction schemes
  character(len=*), parameter, public :: recon_weno5 = 'weno5'
  character(len=*), parameter, public :: recon_weno5z = 'weno5z'
  character(len=*), parameter, public :: recon_weno_cu6 = 'weno_cu6'
  character(len=*), parameter, public :: recon_weno7 = 'weno7'
  character(len=*), parameter, public :: recon_weno9 = 'weno9'
  character(len=*), parameter, public :: recon_weno11 = 'weno11'
  character(len=*), parameter, public :: recon_eno3 = 'eno3'
  character(len=*), parameter, public :: recon_muscl = 'muscl'
  character(len=*), parameter, public :: recon_mp5 = 'mp5'
  character(len=*), parameter, public :: recon_teno5 = 'teno5'
  character(len=*), parameter, public :: recon_upwind1 = 'upwind1'
  character(len=*), parameter, public :: recon_upwind2 = 'upwind2'
  character(len=*), parameter, public :: recon_central2 = 'central2'

  ! Time integrators
  character(len=*), parameter, public :: time_euler = 'euler'
  character(len=*), parameter, public :: time_ssprk22 = 'ssprk22'
  character(len=*), parameter, public :: time_rk3 = 'rk3'
  character(len=*), parameter, public :: time_rk4 = 'rk4'
  character(len=*), parameter, public :: time_ssprk54 = 'ssprk54'
  character(len=*), parameter, public :: time_beuler = 'beuler'
  character(len=*), parameter, public :: time_bdf2 = 'bdf2'

  ! MUSCL limiters
  character(len=*), parameter, public :: limiter_minmod = 'minmod'
  character(len=*), parameter, public :: limiter_superbee = 'superbee'
  character(len=*), parameter, public :: limiter_mc = 'mc'
  character(len=*), parameter, public :: limiter_van_leer = 'van_leer'
  character(len=*), parameter, public :: limiter_koren = 'koren'

  ! Problem types
  character(len=*), parameter, public :: problem_sod = 'sod'
  character(len=*), parameter, public :: problem_shu_osher = 'shu_osher'
  character(len=*), parameter, public :: problem_smooth_wave = 'smooth_wave'
  character(len=*), parameter, public :: problem_linear_advection = 'linear_advection'
  character(len=*), parameter, public :: problem_woodward_colella = 'woodward_colella'
  character(len=*), parameter, public :: problem_lax = 'lax'
  character(len=*), parameter, public :: problem_from_file = 'from_file'
  character(len=*), parameter, public :: problem_udf = 'udf'
  character(len=*), parameter, public :: problem_acoustic_pulse = 'acoustic_pulse'

  ! Boundary conditions
  character(len=*), parameter, public :: bc_dirichlet = 'dirichlet'
  character(len=*), parameter, public :: bc_inflow = 'inflow'
  character(len=*), parameter, public :: bc_outflow = 'outflow'
  character(len=*), parameter, public :: bc_reflecting = 'reflecting'
  character(len=*), parameter, public :: bc_periodic = 'periodic'
  character(len=*), parameter, public :: bc_nonreflecting = 'nonreflecting'
  character(len=*), parameter, public :: bc_supersonic_inlet = 'supersonic_inlet'
  character(len=*), parameter, public :: bc_subsonic_inlet = 'subsonic_inlet'
  character(len=*), parameter, public :: bc_supersonic_outlet = 'supersonic_outlet'
  character(len=*), parameter, public :: bc_subsonic_outlet = 'subsonic_outlet'
  character(len=*), parameter, public :: bc_neumann = 'neumann'
  character(len=*), parameter, public :: bc_neumann_gradient = 'neumann_gradient'
  character(len=*), parameter, public :: bc_farfield = 'farfield'

  ! Enum-like mode values
  character(len=*), parameter, public :: char_proj_auto = 'auto'
  character(len=*), parameter, public :: char_proj_yes = 'yes'
  character(len=*), parameter, public :: char_proj_no = 'no'

  character(len=*), parameter, public :: nrbc_mode_pressure = 'pressure'
  character(len=*), parameter, public :: nrbc_mode_characteristic = 'characteristic'

  character(len=*), parameter, public :: hybrid_sensor_jameson = 'jameson'
  character(len=*), parameter, public :: hybrid_sensor_density_gradient = 'density_gradient'
  character(len=*), parameter, public :: hybrid_sensor_weno_beta = 'weno_beta'

  character(len=32), parameter, public :: flux_scheme_names(7) = [character(len=32) :: &
                                                                  flux_lax_friedrichs, flux_steger_warming, flux_van_leer, &
                                                                  flux_ausm_plus, flux_hll, flux_hllc, flux_roe]
  character(len=32), parameter, public :: recon_scheme_names(13) = [character(len=32) :: &
                                                                    recon_weno5, recon_weno5z, recon_weno_cu6, recon_weno7, &
                                                                    recon_weno9, recon_weno11, recon_eno3, recon_muscl, &
                                                                    recon_mp5, recon_teno5, recon_upwind1, recon_upwind2, &
                                                                    recon_central2]
  character(len=16), parameter, public :: time_scheme_names(7) = [character(len=16) :: &
                                                                  time_euler, time_ssprk22, time_rk3, time_rk4, time_ssprk54, &
                                                                  time_beuler, time_bdf2]
  character(len=16), parameter, public :: limiter_names(5) = [character(len=16) :: &
                                                              limiter_minmod, limiter_superbee, limiter_mc, limiter_van_leer, &
                                                              limiter_koren]
  character(len=32), parameter, public :: problem_type_names(9) = [character(len=32) :: &
                                                                   problem_sod, problem_shu_osher, problem_smooth_wave, &
                                                                   problem_linear_advection, &
                                                                   problem_woodward_colella, problem_lax, problem_from_file, &
                                                                   problem_udf, problem_acoustic_pulse]
  character(len=32), parameter, public :: boundary_condition_names(12) = [character(len=32) :: &
                                                                          bc_dirichlet, bc_inflow, bc_outflow, bc_reflecting, &
                                                                          bc_periodic, bc_nonreflecting, &
                                                                          bc_supersonic_inlet, bc_subsonic_inlet, &
                                                                          bc_supersonic_outlet, bc_subsonic_outlet, &
                                                                          bc_neumann, bc_neumann_gradient]
  character(len=8), parameter, public :: char_proj_mode_names(3) = [character(len=8) :: &
                                                                    char_proj_auto, char_proj_yes, char_proj_no]
  character(len=16), parameter, public :: nrbc_mode_names(2) = [character(len=16) :: &
                                                                nrbc_mode_pressure, nrbc_mode_characteristic]
  character(len=32), parameter, public :: hybrid_sensor_names(3) = [character(len=32) :: &
                                                                    hybrid_sensor_jameson, hybrid_sensor_density_gradient, &
                                                                    hybrid_sensor_weno_beta]

  ! Discretization methods (1D)
  character(len=*), parameter, public :: method_fdm = 'fdm'
  character(len=*), parameter, public :: method_fvm = 'fvm'

  character(len=8), parameter, public :: method_names(2) = [character(len=8) :: &
                                                            method_fdm, method_fvm]

  ! --- 2D solver token sets (euler_2d) ---------------------------------------
  ! These are NARROWER, dimension-specific subsets/variants of the 1D sets
  ! above: euler_2d implements only a fraction of the 1D scheme/BC zoo, plus
  ! its own initial conditions. Each array MUST mirror the live 2D `select case`
  ! dispatch (schemes_2d.f90 / boundary_2d.f90 / euler_riemann_2d.f90 /
  ! time_integration_2d.f90); do not widen them to the 1D arrays.

  ! 2D-only scalar tokens (no 1D named equivalent):
  !> 2D-only Rusanov flux selector (euler_riemann_2d.f90 `face_flux_2d`).
  character(len=*), parameter, public :: flux_rusanov = 'rusanov'
  !> 2D-only initial-condition / problem-type selectors (disjoint from `problem_*`).
  character(len=*), parameter, public :: problem_2d_uniform = 'uniform'
  character(len=*), parameter, public :: problem_2d_isentropic_vortex = 'isentropic_vortex'
  character(len=*), parameter, public :: problem_2d_sedov = 'sedov'
  character(len=*), parameter, public :: problem_2d_toro_explosion = 'toro_explosion'
  character(len=*), parameter, public :: problem_2d_riemann2d_config3 = 'riemann2d_config3'
  character(len=*), parameter, public :: problem_2d_freestream = 'freestream'

  !> Valid 2D numerical-flux selectors. Mirrors `face_flux_2d`
  !! (euler_riemann_2d.f90): explicit `rusanov`, plus `hllc` (the `case default`
  !! target and documented default). `rusanov` is 2D-only (no 1D named token).
  !! FVS schemes (`lax_friedrichs`, `steger_warming`, `van_leer`) are FDM-only.
  character(len=32), parameter, public :: flux_scheme_2d_names(5) = [character(len=32) :: &
                                                                     flux_hllc, flux_rusanov, &
                                                                     flux_lax_friedrichs, flux_steger_warming, &
                                                                     flux_van_leer]
  !> Valid 2D reconstruction selectors. Mirrors the live `select case` in
  !! `init_recon_scheme_2d` (schemes_2d.f90); `weno5` is also the `case default`
  !! target and the config default. A strict subset of `recon_scheme_names`.
  character(len=32), parameter, public :: recon_scheme_2d_names(8) = [character(len=32) :: &
                                                                      recon_weno5, recon_weno7, recon_weno9, recon_mp5, &
                                                                      recon_teno5, recon_muscl, recon_upwind1, recon_upwind2]
  !> Valid 2D time-integration selectors. Mirrors `resolve_time_scheme_2d`
  !! (time_integration_2d.f90): explicit `euler`, `ssprk22`, `rk4`, and
  !! `ssprk54` (R2: shared stepper_kernels adapters), plus `rk3` — the
  !! user-facing name for the `case default` target and the config default.
  character(len=16), parameter, public :: time_scheme_2d_names(5) = [character(len=16) :: &
                                                                     time_rk3, time_euler, time_ssprk22, &
                                                                     time_rk4, time_ssprk54]
  !> Valid 2D initial-condition / problem-type selectors (extended as ICs are
  !! added). These are 2D-only and disjoint from the 1D `problem_type_names`.
  character(len=32), parameter, public :: problem_type_2d_names(6) = [character(len=32) :: &
                                                                      problem_2d_uniform, problem_2d_isentropic_vortex, &
                                                                      problem_2d_sedov, problem_2d_toro_explosion, &
                                                                      problem_2d_riemann2d_config3, problem_2d_freestream]
  !> Valid 2D per-edge boundary-condition selectors. Mirrors the live 2D BC
  !! dispatch (boundary_2d.f90). A strict subset of `boundary_condition_names`.
  character(len=32), parameter, public :: bc_2d_names(5) = [character(len=32) :: &
                                                            bc_periodic, bc_reflecting, bc_outflow, bc_supersonic_inlet, &
                                                            bc_farfield]

  public :: is_valid_flux_scheme, is_valid_recon_scheme, is_valid_time_scheme
  public :: is_valid_limiter, is_valid_problem_type, is_valid_boundary_condition
  public :: is_valid_char_proj_mode, is_valid_nrbc_mode, is_valid_hybrid_sensor
  public :: is_valid_method
  public :: join_token_list, token_in_list
  public :: recon_uses_char_proj_by_default, is_fds_flux_scheme

contains

  pure logical function is_valid_flux_scheme(scheme)
    character(len=*), intent(in) :: scheme

    is_valid_flux_scheme = token_in_list(scheme, flux_scheme_names)
  end function is_valid_flux_scheme

  pure logical function is_valid_recon_scheme(scheme)
    character(len=*), intent(in) :: scheme

    is_valid_recon_scheme = token_in_list(scheme, recon_scheme_names)
  end function is_valid_recon_scheme

  pure logical function is_valid_time_scheme(scheme)
    character(len=*), intent(in) :: scheme

    is_valid_time_scheme = token_in_list(scheme, time_scheme_names)
  end function is_valid_time_scheme

  pure logical function is_valid_limiter(limiter)
    character(len=*), intent(in) :: limiter

    is_valid_limiter = token_in_list(limiter, limiter_names)
  end function is_valid_limiter

  pure logical function is_valid_problem_type(problem_type)
    character(len=*), intent(in) :: problem_type

    is_valid_problem_type = token_in_list(problem_type, problem_type_names)
  end function is_valid_problem_type

  pure logical function is_valid_boundary_condition(bc_type)
    character(len=*), intent(in) :: bc_type

    is_valid_boundary_condition = token_in_list(bc_type, boundary_condition_names)
  end function is_valid_boundary_condition

  pure logical function is_valid_char_proj_mode(mode)
    character(len=*), intent(in) :: mode

    is_valid_char_proj_mode = token_in_list(mode, char_proj_mode_names)
  end function is_valid_char_proj_mode

  pure logical function is_valid_nrbc_mode(mode)
    character(len=*), intent(in) :: mode

    is_valid_nrbc_mode = token_in_list(mode, nrbc_mode_names)
  end function is_valid_nrbc_mode

  pure logical function is_valid_hybrid_sensor(sensor_name)
    character(len=*), intent(in) :: sensor_name

    is_valid_hybrid_sensor = token_in_list(sensor_name, hybrid_sensor_names)
  end function is_valid_hybrid_sensor

  pure logical function is_valid_method(method)
    character(len=*), intent(in) :: method

    is_valid_method = token_in_list(method, method_names)
  end function is_valid_method

  pure logical function recon_uses_char_proj_by_default(scheme)
    character(len=*), intent(in) :: scheme

    select case (trim(scheme))
    case (recon_weno5, recon_weno5z, recon_weno_cu6, recon_weno7, recon_weno9, &
          recon_weno11, recon_eno3, recon_mp5, recon_teno5)
      recon_uses_char_proj_by_default = .true.
    case default
      recon_uses_char_proj_by_default = .false.
    end select
  end function recon_uses_char_proj_by_default

  pure logical function is_fds_flux_scheme(scheme)
    character(len=*), intent(in) :: scheme

    select case (trim(scheme))
    case (flux_ausm_plus, flux_hll, flux_hllc, flux_roe, flux_rusanov)
      is_fds_flux_scheme = .true.
    case default
      is_fds_flux_scheme = .false.
    end select
  end function is_fds_flux_scheme

  function join_token_list(valid_values) result(joined)
    character(len=*), intent(in) :: valid_values(:)
    character(len=512) :: joined

    integer :: i

    joined = ''
    do i = 1, size(valid_values)
      if (i > 1) then
        joined = trim(joined)//' '//trim(valid_values(i))
      else
        joined = trim(valid_values(i))
      end if
    end do
  end function join_token_list

  pure logical function token_in_list(token, valid_values)
    character(len=*), intent(in) :: token
    character(len=*), intent(in) :: valid_values(:)

    integer :: i

    token_in_list = .false.
    do i = 1, size(valid_values)
      if (trim(token) == trim(valid_values(i))) then
        token_in_list = .true.
        return
      end if
    end do
  end function token_in_list

end module option_registry