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 : 10 : #include "DataStructures/DataBox/Tag.hpp" 11 : #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags/OptionsGroup.hpp" 12 : #include "Options/Auto.hpp" 13 : #include "Options/String.hpp" 14 : #include "Utilities/TMPL.hpp" 15 : 16 : /// \cond 17 : namespace PUP { 18 : class er; 19 : } // namespace PUP 20 : /// \endcond 21 : 22 : namespace grmhd::ValenciaDivClean::subcell { 23 : /*! 24 : * \brief Class holding options using by the GRMHD-specific parts of the 25 : * troubled-cell indicator. 26 : */ 27 1 : struct TciOptions { 28 : private: 29 0 : struct DoNotCheckMagneticField {}; 30 : 31 : public: 32 : /// \brief Minimum value of rest-mass density times Lorentz factor before we 33 : /// switch to subcell. Used to identify places where the density has suddenly 34 : /// become negative 35 1 : struct MinimumValueOfD { 36 0 : using type = double; 37 0 : static type lower_bound() { return 0.0; } 38 0 : static constexpr Options::String help = { 39 : "Minimum value of rest-mass density times Lorentz factor before we " 40 : "switch to subcell."}; 41 : }; 42 : /// \brief Minimum value of \f$Y_e\f$ before we switch to subcell. 43 : /// Used to identify places where the electron fraction has suddenly become 44 : // negative 45 1 : struct MinimumValueOfYe { 46 0 : using type = double; 47 0 : static type lower_bound() { return 0.0; } 48 0 : static constexpr Options::String help = { 49 : "Minimum value of Y_e before we switch to subcell."}; 50 : }; 51 : /// \brief Minimum value of \f$\tilde{\tau}\f$ before we switch to subcell. 52 : /// Used to identify places where the energy has suddenly become negative 53 1 : struct MinimumValueOfTildeTau { 54 0 : using type = double; 55 0 : static type lower_bound() { return 0.0; } 56 0 : static constexpr Options::String help = { 57 : "Minimum value of tilde tau before we switch to subcell."}; 58 : }; 59 : /// \brief The density cutoff where if the maximum value of the density in the 60 : /// DG element is below this value we skip primitive recovery and treat the 61 : /// cell as atmosphere. 62 1 : struct AtmosphereDensity { 63 0 : using type = double; 64 0 : static type lower_bound() { return 0.0; } 65 0 : static constexpr Options::String help = { 66 : "The density cutoff where if the maximum value of the density in the " 67 : "DG element is below this value we skip primitive recovery and treat " 68 : "the cell as atmosphere."}; 69 : }; 70 : /// \brief Safety factor \f$\epsilon_B\f$. 71 : /// 72 : /// See the documentation for TciOnDgGrid for details on what this parameter 73 : /// controls. 74 1 : struct SafetyFactorForB { 75 0 : using type = double; 76 0 : static type lower_bound() { return 0.0; } 77 0 : static constexpr Options::String help = { 78 : "Safety factor for magnetic field bound."}; 79 : }; 80 : /// \brief The cutoff where if the maximum of the magnetic field in an element 81 : /// is below this value we do not apply the Persson TCI to the magnetic field. 82 1 : struct MagneticFieldCutoff { 83 0 : using type = Options::Auto<double, DoNotCheckMagneticField>; 84 0 : static constexpr Options::String help = { 85 : "The cutoff where if the maximum of the magnetic field in an element " 86 : "is below this value we do not apply the Persson TCI to the magnetic " 87 : "field. This is to avoid switching to subcell in regions where there's " 88 : "no magnetic field.\n" 89 : "To disable the magnetic field check, set to " 90 : "'DoNotCheckMagneticField'."}; 91 : }; 92 : 93 0 : using options = 94 : tmpl::list<MinimumValueOfD, MinimumValueOfYe, MinimumValueOfTildeTau, 95 : AtmosphereDensity, SafetyFactorForB, MagneticFieldCutoff>; 96 0 : static constexpr Options::String help = { 97 : "Options for the troubled-cell indicator."}; 98 : 99 : // NOLINTNEXTLINE(google-runtime-references) 100 0 : void pup(PUP::er& p); 101 : 102 0 : double minimum_rest_mass_density_times_lorentz_factor{ 103 : std::numeric_limits<double>::signaling_NaN()}; 104 0 : double minimum_ye{std::numeric_limits<double>::signaling_NaN()}; 105 0 : double minimum_tilde_tau{std::numeric_limits<double>::signaling_NaN()}; 106 0 : double atmosphere_density{std::numeric_limits<double>::signaling_NaN()}; 107 0 : double safety_factor_for_magnetic_field{ 108 : std::numeric_limits<double>::signaling_NaN()}; 109 : // The signaling_NaN default is chosen so that users hit an error/FPE if the 110 : // cutoff is not specified, rather than silently defaulting to ignoring the 111 : // magnetic field. 112 0 : std::optional<double> magnetic_field_cutoff{ 113 : std::numeric_limits<double>::signaling_NaN()}; 114 : }; 115 : 116 0 : namespace OptionTags { 117 0 : struct TciOptions { 118 0 : using type = subcell::TciOptions; 119 0 : static constexpr Options::String help = "GRMHD-specific options for the TCI."; 120 0 : using group = ::dg::OptionTags::DiscontinuousGalerkinGroup; 121 : }; 122 : } // namespace OptionTags 123 : 124 0 : namespace Tags { 125 0 : struct TciOptions : db::SimpleTag { 126 0 : using type = subcell::TciOptions; 127 : 128 0 : using option_tags = tmpl::list<OptionTags::TciOptions>; 129 0 : static constexpr bool pass_metavariables = false; 130 0 : static type create_from_options(const type& tci_options) { 131 : return tci_options; 132 : } 133 : }; 134 : } // namespace Tags 135 : } // namespace grmhd::ValenciaDivClean::subcell