SpECTRE Documentation Coverage Report
Current view: top level - Evolution/DgSubcell - SubcellOptions.hpp Hit Total Coverage
Commit: 1e29a35ad8559408f21493dc5db8a49a237bb2f0 Lines: 22 127 17.3 %
Date: 2026-03-31 22:27:51
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : #pragma once
       5             : 
       6             : #include <cstddef>
       7             : #include <limits>
       8             : #include <optional>
       9             : #include <string>
      10             : #include <vector>
      11             : 
      12             : #include "Evolution/DgSubcell/ReconstructionMethod.hpp"
      13             : #include "NumericalAlgorithms/FiniteDifference/DerivativeOrder.hpp"
      14             : #include "Options/Auto.hpp"
      15             : #include "Options/Context.hpp"
      16             : #include "Options/String.hpp"
      17             : #include "Utilities/ErrorHandling/Assert.hpp"
      18             : #include "Utilities/Literals.hpp"
      19             : #include "Utilities/TMPL.hpp"
      20             : 
      21             : /// \cond
      22             : template <size_t VolumeDim>
      23             : class DomainCreator;
      24             : namespace PUP {
      25             : class er;
      26             : }  // namespace PUP
      27             : /// \endcond
      28             : 
      29             : namespace evolution::dg::subcell {
      30             : /*!
      31             :  * \brief Holds the system-agnostic subcell parameters, such as numbers
      32             :  * controlling when to switch between DG and subcell.
      33             :  */
      34           1 : class SubcellOptions {
      35             :  public:
      36             :   /// Parameters related to the troubled cell indicator (TCI) that determines
      37             :   /// when to switch between DG and FD.
      38           1 :   struct TroubledCellIndicator {
      39           0 :     static constexpr Options::String help =
      40             :         "Parameters related to the troubled cell indicator (TCI) that "
      41             :         "determines when to switch between DG and FD.";
      42             :   };
      43             : 
      44           0 :   struct PerssonTci {
      45           0 :     static constexpr Options::String help =
      46             :         "Parameters related to the Persson TCI";
      47           0 :     using group = TroubledCellIndicator;
      48             :   };
      49             :   /// The exponent \f$\alpha\f$ passed to the Persson troubled-cell indicator
      50           1 :   struct PerssonExponent {
      51           0 :     static std::string name() { return "Exponent"; }
      52           0 :     static constexpr Options::String help{
      53             :         "The exponent at which the error should decrease with (N+1-M)"};
      54           0 :     using type = double;
      55           0 :     static constexpr type lower_bound() { return 1.0; }
      56           0 :     static constexpr type upper_bound() { return 10.0; }
      57           0 :     using group = PerssonTci;
      58             :   };
      59             :   /// The number of highest modes the Persson troubled-cell indicator monitors
      60           1 :   struct PerssonNumHighestModes {
      61           0 :     static std::string name() { return "NumHighestModes"; }
      62           0 :     static constexpr Options::String help{
      63             :         "The number of highest modes M the Persson TCI monitors."};
      64           0 :     using type = size_t;
      65           0 :     static constexpr type lower_bound() { return 1_st; }
      66           0 :     static constexpr type upper_bound() { return 10_st; }
      67           0 :     using group = PerssonTci;
      68             :   };
      69             : 
      70           0 :   struct RdmpTci {
      71           0 :     static constexpr Options::String help =
      72             :         "Parameters related to the relaxed discrete maximum principle TCI";
      73           0 :     using group = TroubledCellIndicator;
      74             :   };
      75             :   /// The \f$\delta_0\f$ parameter in the relaxed discrete maximum principle
      76             :   /// troubled-cell indicator
      77           1 :   struct RdmpDelta0 {
      78           0 :     static std::string name() { return "Delta0"; }
      79           0 :     static constexpr Options::String help{"Absolute jump tolerance parameter."};
      80           0 :     using type = double;
      81           0 :     static type lower_bound() { return 0.0; }
      82           0 :     using group = RdmpTci;
      83             :   };
      84             :   /// The \f$\epsilon\f$ parameter in the relaxed discrete maximum principle
      85             :   /// troubled-cell indicator
      86           1 :   struct RdmpEpsilon {
      87           0 :     static std::string name() { return "Epsilon"; }
      88           0 :     static constexpr Options::String help{
      89             :         "The jump-dependent relaxation constant."};
      90           0 :     using type = double;
      91           0 :     static type lower_bound() { return 0.0; }
      92           0 :     static type upper_bound() { return 1.0; }
      93           0 :     using group = RdmpTci;
      94             :   };
      95             :   /// If true, then we always use the subcell method, not DG.
      96           1 :   struct AlwaysUseSubcells {
      97           0 :     static constexpr Options::String help{
      98             :         "If true, then always use the subcell method (e.g. finite-difference) "
      99             :         "instead of DG."};
     100           0 :     using type = bool;
     101           0 :     using group = TroubledCellIndicator;
     102             :   };
     103             :   /// If true, then we allow extension directions to be used for
     104             :   /// computing the ghost points in the FD subcell method to avoid
     105             :   /// extrapolation.
     106           1 :   struct EnableExtensionDirections {
     107           0 :     static constexpr Options::String help{
     108             :         "If true, then we allow extension directions to be used for "
     109             :         "computing the ghost points in the FD subcell method to avoid "
     110             :         "extrapolation."};
     111           0 :     using type = bool;
     112           0 :     using group = TroubledCellIndicator;
     113             :   };
     114             :   /// Method to use for reconstructing the DG solution from the subcell
     115             :   /// solution.
     116           1 :   struct SubcellToDgReconstructionMethod {
     117           0 :     static constexpr Options::String help{
     118             :         "Method to use for reconstructing the DG solution from the subcell "
     119             :         "solution."};
     120           0 :     using type = fd::ReconstructionMethod;
     121             :   };
     122             :   /// \brief Use a width-one halo of FD elements around any troubled element.
     123             :   ///
     124             :   /// This provides a buffer of FD subcells so that as a discontinuity moves
     125             :   /// from one element to another we do not get any Gibbs phenomenon. In the
     126             :   /// case where we evolve the spacetime metric (e.g. GH+GRMHD) a halo region
     127             :   /// provides a buffer in case the stellar surface is near an element
     128             :   /// boundary. Since the GH variables are interpolated using high-order
     129             :   /// unlimited reconstruction, they can run into issues with Gibbs phenomenon.
     130           1 :   struct UseHalo {
     131           0 :     using type = bool;
     132           0 :     static constexpr Options::String help = {
     133             :         "Use a width-one halo of FD elements around any troubled element."
     134             :         "\n"
     135             :         "This provides a buffer of FD subcells so that as a discontinuity "
     136             :         "moves from one element to another we do not get any Gibbs "
     137             :         "phenomenon."};
     138           0 :     using group = TroubledCellIndicator;
     139             :   };
     140             : 
     141             :   /// \brief A list of block names on which to never do subcell.
     142             :   ///
     143             :   /// Set to `None` to allow subcell in all blocks.
     144           1 :   struct OnlyDgBlocksAndGroups {
     145           0 :     using type =
     146             :         Options::Auto<std::vector<std::string>, Options::AutoLabel::None>;
     147           0 :     static constexpr Options::String help = {
     148             :         "A list of block and group names on which to never do subcell.\n"
     149             :         "Set to 'None' to not restrict where FD can be used."};
     150           0 :     using group = TroubledCellIndicator;
     151             :   };
     152             : 
     153             :   /// \brief The order of the FD derivative used.
     154             :   ///
     155             :   /// Must be one of 2, 4, 6, 8, or 10. If `Auto` then the derivative order is
     156             :   /// determined for you, typically the next-lowest even order compared with
     157             :   /// the reconstruction scheme order. E.g. for a 5th-order reconstruction we
     158             :   /// would use 4th order derivatives.
     159           1 :   struct FiniteDifferenceDerivativeOrder {
     160           0 :     using type = ::fd::DerivativeOrder;
     161           0 :     static constexpr Options::String help = {
     162             :         "The finite difference derivative order to use. If computed from the "
     163             :         "reconstruction, then the reconstruction method must support returning "
     164             :         "its reconstruction order."};
     165             :   };
     166             : 
     167           0 :   struct FdToDgTci {
     168           0 :     static constexpr Options::String help =
     169             :         "Options related to how quickly we switch from FD to DG.";
     170           0 :     using group = TroubledCellIndicator;
     171             :   };
     172             :   /// The number of time steps taken between calls to the TCI to check if we
     173             :   /// can go back to the DG grid. A value of `1` means every time step, while
     174             :   /// `2` means every other time step.
     175           1 :   struct NumberOfStepsBetweenTciCalls {
     176           0 :     static constexpr Options::String help{
     177             :         "The number of time steps taken between calls to the TCI to check if "
     178             :         "we can go back to the DG grid. A value of `1` means every time step, "
     179             :         "while `2` means every other time step."};
     180           0 :     using type = size_t;
     181           0 :     static constexpr type lower_bound() { return 1; }
     182           0 :     using group = FdToDgTci;
     183             :   };
     184             :   /// The number of time steps/TCI calls after a switch from DG to FD before we
     185             :   /// allow switching back to DG.
     186           1 :   struct MinTciCallsAfterRollback {
     187           0 :     static constexpr Options::String help{
     188             :         "The number of time steps/TCI calls after a switch from DG to FD "
     189             :         "before we allow switching back to DG."};
     190           0 :     using type = size_t;
     191           0 :     static constexpr type lower_bound() { return 1; }
     192           0 :     using group = FdToDgTci;
     193             :   };
     194             :   /// The number of time steps/TCI calls that the TCI needs to have decided
     195             :   /// switching to DG is fine before we actually do the switch.
     196           1 :   struct MinimumClearTcis {
     197           0 :     static constexpr Options::String help{
     198             :         "The number of time steps/TCI calls that the TCI needs to have decided "
     199             :         "switching to DG is fine before we actually do the switch."};
     200           0 :     using type = size_t;
     201           0 :     static constexpr type lower_bound() { return 1; }
     202           0 :     using group = FdToDgTci;
     203             :   };
     204             : 
     205             :   /// \brief FD to FD interpolation order.
     206             :   ///
     207           1 :   struct FdInterpolationOrder {
     208           0 :     using type = size_t;
     209           0 :     static constexpr Options::String help = {
     210             :         "The interpolation order to use when interpolating from FD block to FD "
     211             :         "block."};
     212           0 :     static constexpr type lower_bound() { return 1; }
     213           0 :     static constexpr type upper_bound() { return 3; }
     214             :   };
     215             : 
     216             :   /// \brief Subcell steps per slab in regions allowed to do subcell
     217             :   /// in LTS mode.  Must be a power of 2.
     218           1 :   struct LtsStepsPerSlab {
     219           0 :     using type = size_t;
     220           0 :     static constexpr Options::String help = {
     221             :         "Steps per slab in regions allowed to do subcell.  Must be a power of "
     222             :         "2."};
     223           0 :     static constexpr type lower_bound() { return 1; }
     224           0 :     static constexpr type upper_bound() { return 1_st << 31; }
     225             :   };
     226             : 
     227           0 :   using gts_options =
     228             :       tmpl::list<PerssonExponent, PerssonNumHighestModes, RdmpDelta0,
     229             :                  RdmpEpsilon, AlwaysUseSubcells, EnableExtensionDirections,
     230             :                  SubcellToDgReconstructionMethod, UseHalo,
     231             :                  OnlyDgBlocksAndGroups, FiniteDifferenceDerivativeOrder,
     232             :                  NumberOfStepsBetweenTciCalls, MinTciCallsAfterRollback,
     233             :                  MinimumClearTcis, FdInterpolationOrder>;
     234             : 
     235             :   template <typename Metavars>
     236           0 :   using options =
     237             :       tmpl::conditional_t<Metavars::local_time_stepping,
     238             :                           tmpl::push_back<gts_options, LtsStepsPerSlab>,
     239             :                           gts_options>;
     240             : 
     241           0 :   static constexpr Options::String help{
     242             :       "System-agnostic options for the DG-subcell method."};
     243             : 
     244           0 :   SubcellOptions() = default;
     245           0 :   SubcellOptions(
     246             :       double persson_exponent, size_t persson_num_highest_modes,
     247             :       double rdmp_delta0, double rdmp_epsilon, bool always_use_subcells,
     248             :       bool enable_extension_directions, fd::ReconstructionMethod recons_method,
     249             :       bool use_halo,
     250             :       std::optional<std::vector<std::string>> only_dg_block_and_group_names,
     251             :       ::fd::DerivativeOrder finite_difference_derivative_order,
     252             :       size_t number_of_steps_between_tci_calls,
     253             :       size_t min_tci_calls_after_rollback, size_t min_clear_tci_before_dg,
     254             :       size_t fd_to_fd_interp_order = 1_st,
     255             :       const std::optional<size_t>& lts_steps_per_slab = std::nullopt,
     256             :       const Options::Context& context = {});
     257             : 
     258             :   /// \brief Given an existing SubcellOptions that was created from block and
     259             :   /// group names, create one that stores block IDs.
     260             :   ///
     261             :   /// The `DomainCreator` is used to convert block and group names into IDs
     262             :   /// and also to check that all listed block names and groups are in the
     263             :   /// domain.
     264             :   ///
     265             :   /// \note This is a workaround since our option parser does not allow us to
     266             :   /// retrieve options specified somewhere completely different in the input
     267             :   /// file.
     268             :   template <size_t Dim>
     269           1 :   SubcellOptions(const SubcellOptions& subcell_options_with_block_names,
     270             :                  const DomainCreator<Dim>& domain_creator);
     271             : 
     272           0 :   void pup(PUP::er& p);
     273             : 
     274           0 :   double persson_exponent() const { return persson_exponent_; }
     275             : 
     276           0 :   size_t persson_num_highest_modes() const {
     277             :     return persson_num_highest_modes_;
     278             :   }
     279             : 
     280           0 :   double rdmp_delta0() const { return rdmp_delta0_; }
     281             : 
     282           0 :   double rdmp_epsilon() const { return rdmp_epsilon_; }
     283             : 
     284           0 :   bool always_use_subcells() const { return always_use_subcells_; }
     285             : 
     286           0 :   bool enable_extension_directions() const {
     287             :     return enable_extension_directions_;
     288             :   }
     289             : 
     290           0 :   fd::ReconstructionMethod reconstruction_method() const {
     291             :     return reconstruction_method_;
     292             :   }
     293             : 
     294           0 :   bool use_halo() const { return use_halo_; }
     295             : 
     296           0 :   const std::vector<size_t>& only_dg_block_ids() const {
     297             :     ASSERT(only_dg_block_ids_.has_value(),
     298             :            "The block IDs on which we are only allowed to do DG have not been "
     299             :            "set.");
     300             :     return only_dg_block_ids_.value();
     301             :   }
     302             : 
     303           0 :   size_t get_fd_to_fd_interp_order() const { return fd_to_fd_interp_order_; }
     304             : 
     305           0 :   ::fd::DerivativeOrder finite_difference_derivative_order() const {
     306             :     return finite_difference_derivative_order_;
     307             :   }
     308             : 
     309             :   /// The number of time steps between when we check the TCI to see if we can
     310             :   /// switch from FD back to DG.
     311           1 :   size_t number_of_steps_between_tci_calls() const {
     312             :     return number_of_steps_between_tci_calls_;
     313             :   }
     314             : 
     315             :   /// The number of time steps after a rollback before we check the TCI to see
     316             :   /// if we can switch from FD back to DG.
     317           1 :   size_t min_tci_calls_after_rollback() const {
     318             :     return min_tci_calls_after_rollback_;
     319             :   }
     320             : 
     321             :   /// The number of times the TCI must have flagged that we can switch back to
     322             :   /// DG before doing so.
     323             :   ///
     324             :   /// Note that if we only check the TCI every
     325             :   /// `number_of_steps_between_tci_calls()` then it takes
     326             :   /// `number_of_steps_between_tci_calls * min_clear_tci_before_dg` time steps
     327             :   /// before switching from FD back to DG.
     328             :   ///
     329             :   /// `0 means
     330           1 :   size_t min_clear_tci_before_dg() const { return min_clear_tci_before_dg_; }
     331             : 
     332             :   /// The number of steps per slab in regions allowed to do subcell.
     333             :   /// Only valid in LTS-subcell evolutions.
     334           1 :   size_t lts_steps_per_slab() const {
     335             :     ASSERT(lts_steps_per_slab_.has_value(),
     336             :            "Attempted to access lts_steps_per_slab in GTS evolution.");
     337             :     return lts_steps_per_slab_.value();
     338             :   }
     339             : 
     340             :  private:
     341           0 :   friend bool operator==(const SubcellOptions& lhs, const SubcellOptions& rhs);
     342             : 
     343           0 :   double persson_exponent_ = std::numeric_limits<double>::signaling_NaN();
     344           0 :   size_t persson_num_highest_modes_ =
     345             :       std::numeric_limits<size_t>::signaling_NaN();
     346           0 :   double rdmp_delta0_ = std::numeric_limits<double>::signaling_NaN();
     347           0 :   double rdmp_epsilon_ = std::numeric_limits<double>::signaling_NaN();
     348           0 :   bool always_use_subcells_ = false;
     349           0 :   bool enable_extension_directions_ = false;
     350           0 :   fd::ReconstructionMethod reconstruction_method_ =
     351             :       fd::ReconstructionMethod::AllDimsAtOnce;
     352           0 :   bool use_halo_{false};
     353           0 :   std::optional<std::vector<std::string>> only_dg_block_and_group_names_{};
     354           0 :   std::optional<std::vector<size_t>> only_dg_block_ids_{};
     355           0 :   ::fd::DerivativeOrder finite_difference_derivative_order_{};
     356           0 :   size_t number_of_steps_between_tci_calls_{1};
     357           0 :   size_t min_tci_calls_after_rollback_{1};
     358           0 :   size_t min_clear_tci_before_dg_{0};
     359           0 :   size_t fd_to_fd_interp_order_{};
     360           0 :   std::optional<size_t> lts_steps_per_slab_{};
     361             : };
     362             : 
     363           0 : bool operator!=(const SubcellOptions& lhs, const SubcellOptions& rhs);
     364             : }  // namespace evolution::dg::subcell

Generated by: LCOV version 1.14