SpECTRE Documentation Coverage Report
Current view: top level - ControlSystem/Actions - GridCenters.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 12 36 33.3 %
Date: 2025-12-05 05:03:31
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 <cmath>
       7             : #include <limits>
       8             : #include <memory>
       9             : 
      10             : #include "ControlSystem/Tags/IsActiveMap.hpp"
      11             : #include "ControlSystem/Tags/OptionTags.hpp"
      12             : #include "DataStructures/DataBox/DataBox.hpp"
      13             : #include "DataStructures/DataBox/Tag.hpp"
      14             : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      15             : #include "Domain/FunctionsOfTime/SettleToConstantQuaternion.hpp"
      16             : #include "Domain/FunctionsOfTime/Tags.hpp"
      17             : #include "Domain/Structure/ElementId.hpp"
      18             : #include "Domain/Tags.hpp"
      19             : #include "Parallel/AlgorithmExecution.hpp"
      20             : #include "Parallel/GlobalCache.hpp"
      21             : #include "ParallelAlgorithms/EventsAndTriggers/EventsAndTriggers.hpp"
      22             : #include "ParallelAlgorithms/EventsAndTriggers/Tags.hpp"
      23             : #include "ParallelAlgorithms/EventsAndTriggers/WhenToCheck.hpp"
      24             : #include "Time/Tags/Time.hpp"
      25             : #include "Time/Tags/TimeStepId.hpp"
      26             : #include "Utilities/ConstantExpressions.hpp"
      27             : #include "Utilities/ErrorHandling/Error.hpp"
      28             : 
      29             : /// \cond
      30             : namespace Parallel {
      31             : template <typename Metavariables>
      32             : class GlobalCache;
      33             : }  // namespace Parallel
      34             : namespace Tags {
      35             : struct TimeStep;
      36             : struct TimeStepId;
      37             : template <typename StepperInterface>
      38             : struct TimeStepper;
      39             : }  // namespace Tags
      40             : namespace tuples {
      41             : template <class... Tags>
      42             : class TaggedTuple;
      43             : }  // namespace tuples
      44             : /// \endcond
      45             : 
      46           1 : namespace control_system {
      47             : /*!
      48             :  * \brief Holds options used to control when to start disabling the rotation
      49             :  * control system in a BNS simulation.
      50             :  */
      51           1 : struct DisableRotationWhen {
      52             :   /// The separation at which we start turning off rotation.
      53           1 :   struct DisableAtSeparation {
      54           0 :     using type = double;
      55           0 :     static type lower_bound() { return 2.0; }
      56           0 :     static constexpr Options::String help{
      57             :         "The separation at which we start turning off rotation."};
      58             :   };
      59             : 
      60             :   /// The timescale in code units over which grid rotation is disabled. A
      61             :   /// reasonable value is 30M-60M.
      62           1 :   struct RotationDecayTimescale {
      63           0 :     using type = double;
      64           0 :     static type lower_bound() { return 30.0; }
      65           0 :     static type upper_bound() { return 200.0; }
      66           0 :     static constexpr Options::String help{
      67             :         "The timescale in code units over which grid rotation is disabled. A "
      68             :         "reasonable value is 40M-60M."};
      69             :   };
      70             : 
      71           0 :   using options = tmpl::list<DisableAtSeparation, RotationDecayTimescale>;
      72             : 
      73           0 :   static constexpr Options::String help{
      74             :       "Constrols the separation at which the rotation control system is "
      75             :       "disabled and the rotation function of time starts settling to a "
      76             :       "constant."};
      77             : 
      78           0 :   void pup(PUP::er& p);
      79             : 
      80           0 :   double disable_at_separation{std::numeric_limits<double>::signaling_NaN()};
      81           0 :   double rotation_decay_timescale{std::numeric_limits<double>::signaling_NaN()};
      82             : };
      83             : 
      84           1 : namespace OptionTags {
      85             : /// Option tag for controlling when and how the rotation map is disabled.
      86           1 : struct DisableRotationWhen {
      87           0 :   static constexpr Options::String help =
      88             :       "Options for controlling how the rotation control system stops as the "
      89             :       "two neutron stars merge.";
      90           0 :   using type = control_system::DisableRotationWhen;
      91           0 :   using group = control_system::OptionTags::ControlSystemGroup;
      92             : };
      93             : }  // namespace OptionTags
      94             : 
      95           1 : namespace Tags {
      96             : /// Tag for controlling when and how the rotation map is disabled.
      97           1 : struct DisableRotationWhen : db::SimpleTag {
      98           0 :   using type = control_system::DisableRotationWhen;
      99           0 :   using option_tags = tmpl::list<OptionTags::DisableRotationWhen>;
     100             : 
     101           0 :   static constexpr bool pass_metavariables = false;
     102           0 :   static control_system::DisableRotationWhen create_from_options(
     103             :       const control_system::DisableRotationWhen& disable_rotation_when);
     104             : };
     105             : }  // namespace Tags
     106             : 
     107           1 : namespace Actions {
     108             : /*!
     109             :  * \brief Checks if the Rotation function of time has been updated because the
     110             :  * separation between the neutron star grid centers is small enough.
     111             :  *
     112             :  * \note This is an iterable action that is to be run on the elements. It is
     113             :  * only run on the element that satisfies `is_zeroth_element()`.
     114             :  *
     115             :  * \warning This action should only ever be run in the
     116             :  * `Parallel::Phase::DisableRotationControl` phase.
     117             :  *
     118             :  * The desired separation is controlled via the
     119             :  * control_systems::Tags::DisableRotationWhen tag. The main use for this
     120             :  * functionality is to disable the rotation control system in binary neutron
     121             :  * star mergers when the stars are sufficiently close because as the stars
     122             :  * merge, the dual control system starts to lose anything to lock on to and can
     123             :  * even start counter rotating.
     124             :  *
     125             :  * Tags used and modified:
     126             :  * - DataBox:
     127             :  *   - `domain::Tags::Element<3>`
     128             :  *   - `::Tags::TimeStepId`
     129             :  *   - `::Tags::Time`
     130             :  * - MutableGlobalCache:
     131             :  *  - Uses:
     132             :  *   - `domain::Tags::FunctionsOfTime` ("GridCenters" and "Rotation")
     133             :  *  - Modifies:
     134             :  *    - `domain::Tags::FunctionsOfTime` ("Rotation")
     135             :  *    - `control_system::Tags::IsActiveMap` ("Rotation")
     136             :  */
     137           1 : struct SwitchGridRotationToSettle {
     138             :   /// Invokable that changes the rotation function of time to a
     139             :   /// QuaternionSettleToConstant matching the current function of time values
     140             :   /// and derivatives for the rotation and decaying over a specified timescale.
     141             :   ///
     142             :   /// Note that the final orientation of the domain is arbitrary. If we want
     143             :   /// to rotate to a specific angle (e.g. aligning logical and inertial
     144             :   /// coordinate axes), we need a (new) QuaternionSettleToSpecifiedValue
     145             :   /// function of time.
     146           1 :   struct UpdateRotationToSettle {
     147           0 :     static void apply(
     148             :         gsl::not_null<std::unordered_map<
     149             :             std::string,
     150             :             std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>*>
     151             :             f_of_t_list,
     152             :         const std::string& function_of_time_name,
     153             :         const std::array<DataVector, 3>& initial_func_and_derivs,
     154             :         double match_time, double decay_time);
     155             :   };
     156             : 
     157             :   /// Invokable used to disable the rotation control system via a call to
     158             :   /// Parallel::mutate.
     159           1 :   struct DisableControlSystem {
     160           0 :     static void apply(
     161             :         gsl::not_null<std::unordered_map<std::string, bool>*> is_active_map,
     162             :         const std::string& control_system_name);
     163             :   };
     164             : 
     165           0 :   using const_global_cache_tags =
     166             :       tmpl::list<control_system::Tags::DisableRotationWhen>;
     167             : 
     168             :   template <typename DbTags, typename... InboxTags, typename Metavariables,
     169             :             typename ActionList, typename ParallelComponent>
     170           0 :   static Parallel::iterable_action_return_t apply(
     171             :       db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     172             :       Parallel::GlobalCache<Metavariables>& cache,
     173             :       const ElementId<3>& element_id, const ActionList /*meta*/,
     174             :       const ParallelComponent* const /*meta*/) {
     175             :     if (not is_zeroth_element(element_id)) {
     176             :       // Only one element needs to modify the control system and function of
     177             :       // time.
     178             :       return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     179             :     }
     180             :     const auto& time_step_id = db::get<::Tags::TimeStepId>(box);
     181             :     if (not time_step_id.is_at_slab_boundary()) {
     182             :       ERROR(
     183             :           "Expected to be at a Slab boundary when changing the Rotation "
     184             :           "function of time to a SettleToConstant. Current TimeStepId is "
     185             :           << time_step_id);
     186             :     }
     187             : 
     188             :     const auto& bns_rotation_control =
     189             :         db::get<control_system::Tags::DisableRotationWhen>(box);
     190             : 
     191             :     const double time = db::get<::Tags::Time>(box);
     192             :     if (not get<domain::Tags::FunctionsOfTime>(cache).contains("GridCenters")) {
     193             :       ERROR(
     194             :           "There is no function of time named 'GridCenters', which is required "
     195             :           "when disabling the rotation control system since in a binary "
     196             :           "neutron star simulation we need to track the grid centers of the "
     197             :           "stars to decide when to disable rotation control.");
     198             :     }
     199             :     const domain::FunctionsOfTime::FunctionOfTime& grid_centers_fot =
     200             :         *get<domain::Tags::FunctionsOfTime>(cache).at("GridCenters");
     201             :     const DataVector grid_centers = grid_centers_fot.func(time)[0];
     202             :     const double separation = sqrt(square(grid_centers[0] - grid_centers[3]) +
     203             :                                    square(grid_centers[1] - grid_centers[4]) +
     204             :                                    square(grid_centers[2] - grid_centers[5]));
     205             :     if (separation > bns_rotation_control.disable_at_separation) {
     206             :       ERROR(
     207             :           "Disabling the rotation control system should happen when the "
     208             :           "separation is less than or equal to "
     209             :           << bns_rotation_control.disable_at_separation
     210             :           << " but the separation at time " << time << " is calculated to be "
     211             :           << separation);
     212             :     }
     213             : 
     214             :     if (not get<domain::Tags::FunctionsOfTime>(cache).contains("Rotation")) {
     215             :       ERROR(
     216             :           "There is no function of time named 'Rotation', which means that it "
     217             :           "cannot be disabled.");
     218             :     }
     219             :     const domain::FunctionsOfTime::FunctionOfTime& rotation_fot =
     220             :         *get<domain::Tags::FunctionsOfTime>(cache).at("Rotation");
     221             :     const std::array<DataVector, 3> current_func_and_derivs =
     222             :         rotation_fot.func_and_2_derivs(time);
     223             :     Parallel::mutate<domain::Tags::FunctionsOfTime, UpdateRotationToSettle>(
     224             :         cache, std::string{"Rotation"}, current_func_and_derivs, time,
     225             :         bns_rotation_control.rotation_decay_timescale);
     226             :     Parallel::mutate<control_system::Tags::IsActiveMap, DisableControlSystem>(
     227             :         cache, std::string{"Rotation"});
     228             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     229             :   }
     230             : };
     231             : }  // namespace Actions
     232             : }  // namespace control_system

Generated by: LCOV version 1.14