SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Initialization - Evolution.hpp Hit Total Coverage
Commit: 9ddc33268b29014a4956c8f0c24ca90b397463e1 Lines: 14 40 35.0 %
Date: 2024-04-26 20:00:04
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 <array>
       7             : #include <cstddef>
       8             : #include <cstdint>
       9             : #include <optional>
      10             : #include <unordered_map>
      11             : #include <utility>
      12             : 
      13             : #include "DataStructures/ApplyMatrices.hpp"
      14             : #include "DataStructures/DataBox/DataBox.hpp"
      15             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      16             : #include "DataStructures/DataBox/Prefixes.hpp"
      17             : #include "Domain/Amr/Flag.hpp"
      18             : #include "Domain/Amr/Helpers.hpp"
      19             : #include "Domain/Amr/Info.hpp"
      20             : #include "Domain/Amr/Tags/Flags.hpp"
      21             : #include "Domain/Structure/ElementId.hpp"
      22             : #include "Domain/Tags.hpp"
      23             : #include "Evolution/Initialization/Tags.hpp"
      24             : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      25             : #include "NumericalAlgorithms/Spectral/Projection.hpp"
      26             : #include "Parallel/Tags/ArrayIndex.hpp"
      27             : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
      28             : #include "Time/AdaptiveSteppingDiagnostics.hpp"
      29             : #include "Time/ChooseLtsStepSize.hpp"
      30             : #include "Time/Slab.hpp"
      31             : #include "Time/StepChoosers/StepChooser.hpp"
      32             : #include "Time/Tags/AdaptiveSteppingDiagnostics.hpp"
      33             : #include "Time/Tags/HistoryEvolvedVariables.hpp"
      34             : #include "Time/Tags/StepChoosers.hpp"
      35             : #include "Time/Tags/Time.hpp"
      36             : #include "Time/Tags/TimeStep.hpp"
      37             : #include "Time/Tags/TimeStepId.hpp"
      38             : #include "Time/Tags/TimeStepper.hpp"
      39             : #include "Time/Time.hpp"
      40             : #include "Time/TimeStepId.hpp"
      41             : #include "Time/TimeSteppers/LtsTimeStepper.hpp"
      42             : #include "Time/TimeSteppers/TimeStepper.hpp"
      43             : #include "Utilities/Algorithm.hpp"
      44             : #include "Utilities/ErrorHandling/Error.hpp"
      45             : #include "Utilities/Gsl.hpp"
      46             : #include "Utilities/TMPL.hpp"
      47             : #include "Utilities/TaggedTuple.hpp"
      48             : 
      49             : namespace Initialization {
      50             : 
      51             : namespace detail {
      52             : inline Time initial_time(const bool time_runs_forward,
      53             :                          const double initial_time_value,
      54             :                          const double initial_slab_size) {
      55             :   const Slab initial_slab =
      56             :       time_runs_forward
      57             :           ? Slab::with_duration_from_start(initial_time_value,
      58             :                                            initial_slab_size)
      59             :           : Slab::with_duration_to_end(initial_time_value, initial_slab_size);
      60             :   return time_runs_forward ? initial_slab.start() : initial_slab.end();
      61             : }
      62             : 
      63             : template <typename TimeStepper>
      64             : void set_next_time_step_id(const gsl::not_null<TimeStepId*> next_time_step_id,
      65             :                            const Time& initial_time,
      66             :                            const bool time_runs_forward,
      67             :                            const TimeStepper& time_stepper) {
      68             :   *next_time_step_id = TimeStepId(
      69             :       time_runs_forward,
      70             :       -static_cast<int64_t>(time_stepper.number_of_past_steps()), initial_time);
      71             : }
      72             : }  // namespace detail
      73             : 
      74             : /// \ingroup InitializationGroup
      75             : /// \brief Initialize items related to time stepping
      76             : ///
      77             : /// \details See the type aliases defined below for what items are added to the
      78             : /// GlobalCache and DataBox and how they are initialized
      79             : ///
      80             : /// Since the evolution has not started yet, initialize the state
      81             : /// _before_ the initial time. So `Tags::TimeStepId` is undefined at this point,
      82             : /// and `Tags::Next<Tags::TimeStepId>` is the initial time.
      83             : template <typename Metavariables, typename TimeStepperBase>
      84           1 : struct TimeStepping {
      85             :   /// Tags for constant items added to the GlobalCache.  These items are
      86             :   /// initialized from input file options.
      87           1 :   using const_global_cache_tags = tmpl::conditional_t<
      88             :       TimeStepperBase::local_time_stepping,
      89             :       tmpl::list<::Tags::ConcreteTimeStepper<TimeStepperBase>,
      90             :                  ::Tags::StepChoosers>,
      91             :       tmpl::list<::Tags::ConcreteTimeStepper<TimeStepperBase>>>;
      92             : 
      93             :   /// Tags for mutable items added to the GlobalCache.  These items are
      94             :   /// initialized from input file options.
      95           1 :   using mutable_global_cache_tags = tmpl::list<>;
      96             : 
      97             :   /// Tags for items fetched by the DataBox and passed to the apply function
      98           1 :   using argument_tags =
      99             :       tmpl::list<::Tags::Time, Tags::InitialTimeDelta,
     100             :                  Tags::InitialSlabSize<TimeStepperBase::local_time_stepping>,
     101             :                  ::Tags::ConcreteTimeStepper<TimeStepperBase>>;
     102             : 
     103             :   /// Tags for simple DataBox items that are initialized from input file options
     104           1 :   using simple_tags_from_options =
     105             :       tmpl::list<::Tags::Time, Tags::InitialTimeDelta,
     106             :                  Tags::InitialSlabSize<TimeStepperBase::local_time_stepping>>;
     107             : 
     108             :   /// Tags for simple DataBox items that are default initialized.
     109           1 :   using default_initialized_simple_tags =
     110             :       tmpl::push_back<StepChoosers::step_chooser_simple_tags<
     111             :                           Metavariables, TimeStepperBase::local_time_stepping>,
     112             :                       ::Tags::TimeStepId, ::Tags::AdaptiveSteppingDiagnostics>;
     113             : 
     114             :   /// Tags for items in the DataBox that are mutated by the apply function
     115           1 :   using return_tags =
     116             :       tmpl::list<::Tags::Next<::Tags::TimeStepId>, ::Tags::TimeStep,
     117             :                  ::Tags::Next<::Tags::TimeStep>>;
     118             : 
     119             :   /// Tags for mutable DataBox items that are either default initialized or
     120             :   /// initialized by the apply function
     121           1 :   using simple_tags =
     122             :       tmpl::append<default_initialized_simple_tags, return_tags>;
     123             : 
     124             :   /// Tags for immutable DataBox items (compute items or reference items) added
     125             :   /// to the DataBox.
     126           1 :   using compute_tags = time_stepper_ref_tags<TimeStepperBase>;
     127             : 
     128             :   /// Given the items fetched from a DataBox by the argument_tags when using
     129             :   /// LTS, mutate the items in the DataBox corresponding to return_tags
     130           1 :   static void apply(const gsl::not_null<TimeStepId*> next_time_step_id,
     131             :                     const gsl::not_null<TimeDelta*> time_step,
     132             :                     const gsl::not_null<TimeDelta*> next_time_step,
     133             :                     const double initial_time_value,
     134             :                     const double initial_dt_value,
     135             :                     const double initial_slab_size,
     136             :                     const LtsTimeStepper& time_stepper) {
     137             :     const bool time_runs_forward = initial_dt_value > 0.0;
     138             :     const Time initial_time = detail::initial_time(
     139             :         time_runs_forward, initial_time_value, initial_slab_size);
     140             :     detail::set_next_time_step_id(next_time_step_id, initial_time,
     141             :                                   time_runs_forward, time_stepper);
     142             :     *time_step = choose_lts_step_size(initial_time, initial_dt_value);
     143             :     *next_time_step = *time_step;
     144             :   }
     145             : 
     146             :   /// Given the items fetched from a DataBox by the argument_tags, when not
     147             :   /// using LTS, mutate the items in the DataBox corresponding to return_tags
     148           1 :   static void apply(const gsl::not_null<TimeStepId*> next_time_step_id,
     149             :                     const gsl::not_null<TimeDelta*> time_step,
     150             :                     const gsl::not_null<TimeDelta*> next_time_step,
     151             :                     const double initial_time_value,
     152             :                     const double initial_dt_value,
     153             :                     const double initial_slab_size,
     154             :                     const TimeStepper& time_stepper) {
     155             :     const bool time_runs_forward = initial_dt_value > 0.0;
     156             :     const Time initial_time = detail::initial_time(
     157             :         time_runs_forward, initial_time_value, initial_slab_size);
     158             :     detail::set_next_time_step_id(next_time_step_id, initial_time,
     159             :                                   time_runs_forward, time_stepper);
     160             :     *time_step = (time_runs_forward ? 1 : -1) * initial_time.slab().duration();
     161             :     *next_time_step = *time_step;
     162             :   }
     163             : };
     164             : 
     165             : /// \brief Initialize/update items related to time stepping after an AMR change
     166             : template <size_t Dim>
     167           1 : struct ProjectTimeStepping : tt::ConformsTo<amr::protocols::Projector> {
     168           0 :   using return_tags =
     169             :       tmpl::list<::Tags::TimeStepId, ::Tags::Next<::Tags::TimeStepId>,
     170             :                  ::Tags::TimeStep, ::Tags::Next<::Tags::TimeStep>, ::Tags::Time,
     171             :                  ::Tags::AdaptiveSteppingDiagnostics>;
     172           0 :   using argument_tags = tmpl::list<Parallel::Tags::ArrayIndex>;
     173             : 
     174           0 :   static void apply(
     175             :       const gsl::not_null<TimeStepId*> /*time_step_id*/,
     176             :       const gsl::not_null<TimeStepId*> /*next_time_step_id*/,
     177             :       const gsl::not_null<TimeDelta*> /*time_step*/,
     178             :       const gsl::not_null<TimeDelta*> /*next_time_step*/,
     179             :       const gsl::not_null<double*> /*time*/,
     180             :       const gsl::not_null<AdaptiveSteppingDiagnostics*>
     181             :       /*adaptive_stepping_diagnostics*/,
     182             :       const ElementId<Dim>& /*element_id*/,
     183             :       const std::pair<Mesh<Dim>, Element<Dim>>& /*old_mesh_and_element*/) {
     184             :     // Do not change anything for p-refinement
     185             :   }
     186             : 
     187             :   template <typename... Tags>
     188           0 :   static void apply(const gsl::not_null<TimeStepId*> time_step_id,
     189             :                     const gsl::not_null<TimeStepId*> next_time_step_id,
     190             :                     const gsl::not_null<TimeDelta*> time_step,
     191             :                     const gsl::not_null<TimeDelta*> next_time_step,
     192             :                     const gsl::not_null<double*> time,
     193             :                     const gsl::not_null<AdaptiveSteppingDiagnostics*>
     194             :                         adaptive_stepping_diagnostics,
     195             :                     const ElementId<Dim>& element_id,
     196             :                     const tuples::TaggedTuple<Tags...>& parent_items) {
     197             :     *time_step_id = get<::Tags::TimeStepId>(parent_items);
     198             :     *next_time_step_id = get<::Tags::Next<::Tags::TimeStepId>>(parent_items);
     199             :     *time_step = get<::Tags::TimeStep>(parent_items);
     200             :     *next_time_step = get<::Tags::Next<::Tags::TimeStep>>(parent_items);
     201             :     *time = get<::Tags::Time>(parent_items);
     202             : 
     203             :     // Since AdaptiveSteppingDiagnostics are reduced over all elements, we
     204             :     // set the slab quantities to the same value over all children, and the
     205             :     // step quantities to belong to the first child
     206             :     const auto& parent_diagnostics =
     207             :         get<::Tags::AdaptiveSteppingDiagnostics>(parent_items);
     208             :     const auto& parent_amr_flags =
     209             :         get<amr::Tags::Info<Dim>>(parent_items).flags;
     210             :     const auto& parent_id =
     211             :         get<Parallel::Tags::ArrayIndexImpl<ElementId<Dim>>>(parent_items);
     212             :     auto children_ids = amr::ids_of_children(parent_id, parent_amr_flags);
     213             :     if (element_id == children_ids.front()) {
     214             :       *adaptive_stepping_diagnostics = parent_diagnostics;
     215             :     } else {
     216             :       adaptive_stepping_diagnostics->number_of_slabs =
     217             :           parent_diagnostics.number_of_slabs;
     218             :       adaptive_stepping_diagnostics->number_of_slab_size_changes =
     219             :           parent_diagnostics.number_of_slab_size_changes;
     220             :     }
     221             :   }
     222             : 
     223             :   template <typename... Tags>
     224           0 :   static void apply(
     225             :       const gsl::not_null<TimeStepId*> time_step_id,
     226             :       const gsl::not_null<TimeStepId*> next_time_step_id,
     227             :       const gsl::not_null<TimeDelta*> time_step,
     228             :       const gsl::not_null<TimeDelta*> next_time_step,
     229             :       const gsl::not_null<double*> time,
     230             :       const gsl::not_null<AdaptiveSteppingDiagnostics*>
     231             :           adaptive_stepping_diagnostics,
     232             :       const ElementId<Dim>& /*element_id*/,
     233             :       const std::unordered_map<ElementId<Dim>, tuples::TaggedTuple<Tags...>>&
     234             :           children_items) {
     235             :     const auto slowest_child =
     236             :         alg::min_element(children_items, [](const auto& a, const auto& b) {
     237             :           const auto& time_step_a = get<::Tags::TimeStep>(a.second);
     238             :           const auto& time_step_b = get<::Tags::TimeStep>(b.second);
     239             :           ASSERT(time_step_a.is_positive() == time_step_b.is_positive(),
     240             :                  "Elements are not taking time steps in the same direction!");
     241             :           return time_step_a.is_positive() ? (time_step_a < time_step_b)
     242             :                                            : (time_step_a > time_step_b);
     243             :         });
     244             :     const auto& slowest_child_items = (*slowest_child).second;
     245             :     *time_step_id = get<::Tags::TimeStepId>(slowest_child_items);
     246             :     *next_time_step_id =
     247             :         get<::Tags::Next<::Tags::TimeStepId>>(slowest_child_items);
     248             :     *time_step = get<::Tags::TimeStep>(slowest_child_items);
     249             :     *next_time_step = get<::Tags::Next<::Tags::TimeStep>>(slowest_child_items);
     250             :     *time = get<::Tags::Time>(slowest_child_items);
     251             :     const auto& slowest_child_diagnostics =
     252             :         get<::Tags::AdaptiveSteppingDiagnostics>(slowest_child_items);
     253             : 
     254             :     adaptive_stepping_diagnostics->number_of_slabs =
     255             :         slowest_child_diagnostics.number_of_slabs;
     256             :     adaptive_stepping_diagnostics->number_of_slab_size_changes =
     257             :         slowest_child_diagnostics.number_of_slab_size_changes;
     258             :     for (const auto& [_, child_items] : children_items) {
     259             :       *adaptive_stepping_diagnostics +=
     260             :           get<::Tags::AdaptiveSteppingDiagnostics>(child_items);
     261             :     }
     262             :   }
     263             : };
     264             : 
     265             : /// \ingroup InitializationGroup
     266             : /// \brief Initialize time-stepper items
     267             : ///
     268             : /// DataBox changes:
     269             : /// - Adds:
     270             : ///   * `db::add_tag_prefix<Tags::dt, variables_tag>`
     271             : ///   * `Tags::HistoryEvolvedVariables<variables_tag, dt_variables_tag>`
     272             : /// - Removes: nothing
     273             : /// - Modifies: nothing
     274             : ///
     275             : /// \note HistoryEvolvedVariables is allocated, but needs to be initialized
     276             : template <typename Metavariables>
     277           1 : struct TimeStepperHistory {
     278           0 :   static constexpr size_t dim = Metavariables::volume_dim;
     279           0 :   using variables_tag = typename Metavariables::system::variables_tag;
     280           0 :   using dt_variables_tag = db::add_tag_prefix<::Tags::dt, variables_tag>;
     281             : 
     282           0 :   using const_global_cache_tags = tmpl::list<>;
     283           0 :   using mutable_global_cache_tags = tmpl::list<>;
     284           0 :   using simple_tags_from_options = tmpl::list<>;
     285           0 :   using simple_tags =
     286             :       tmpl::list<dt_variables_tag,
     287             :                  ::Tags::HistoryEvolvedVariables<variables_tag>>;
     288           0 :   using compute_tags = tmpl::list<>;
     289             : 
     290           0 :   using argument_tags =
     291             :       tmpl::list<::Tags::TimeStepper<TimeStepper>, domain::Tags::Mesh<dim>>;
     292           0 :   using return_tags = simple_tags;
     293             : 
     294           0 :   static void apply(
     295             :       const gsl::not_null<typename dt_variables_tag::type*> dt_vars,
     296             :       const gsl::not_null<TimeSteppers::History<typename variables_tag::type>*>
     297             :           history,
     298             :       const TimeStepper& time_stepper, const Mesh<dim>& mesh) {
     299             :     // Will be overwritten before use
     300             :     dt_vars->initialize(mesh.number_of_grid_points());
     301             : 
     302             :     // All steppers we have that need to start at low order require
     303             :     // one additional point per order, so this is the order that
     304             :     // requires no initial past steps.
     305             :     const size_t starting_order =
     306             :         time_stepper.order() - time_stepper.number_of_past_steps();
     307             :     history->integration_order(starting_order);
     308             :   }
     309             : };
     310             : 
     311             : /// \brief Initialize/update items related to time stepper history after an AMR
     312             : /// change
     313             : template <typename Metavariables>
     314           1 : struct ProjectTimeStepperHistory : tt::ConformsTo<amr::protocols::Projector> {
     315           0 :   static constexpr size_t dim = Metavariables::volume_dim;
     316           0 :   using variables_tag = typename Metavariables::system::variables_tag;
     317           0 :   using dt_variables_tag = db::add_tag_prefix<::Tags::dt, variables_tag>;
     318           0 :   using history_tag = ::Tags::HistoryEvolvedVariables<variables_tag>;
     319             : 
     320           0 :   using return_tags = tmpl::list<dt_variables_tag, history_tag>;
     321           0 :   using argument_tags =
     322             :       tmpl::list<domain::Tags::Mesh<dim>, Parallel::Tags::ArrayIndex>;
     323             : 
     324           0 :   static void apply(
     325             :       const gsl::not_null<typename dt_variables_tag::type*> dt_vars,
     326             :       const gsl::not_null<typename history_tag::type*> history,
     327             :       const Mesh<dim>& new_mesh, const ElementId<dim>& /*element_id*/,
     328             :       const std::pair<Mesh<dim>, Element<dim>>& old_mesh_and_element) {
     329             :     const auto& old_mesh = old_mesh_and_element.first;
     330             :     if (old_mesh == new_mesh) {
     331             :       return;  // mesh was not refined, so no projection needed
     332             :     }
     333             :     const auto projection_matrices =
     334             :         Spectral::p_projection_matrices(old_mesh, new_mesh);
     335             :     const auto& old_extents = old_mesh.extents();
     336             :     history->map_entries(
     337             :         [&projection_matrices, &old_extents](const auto entry) {
     338             :           *entry = apply_matrices(projection_matrices, *entry, old_extents);
     339             :         });
     340             :     dt_vars->initialize(new_mesh.number_of_grid_points());
     341             :   }
     342             : 
     343             :   template <typename... Tags>
     344           0 :   static void apply(
     345             :       const gsl::not_null<typename dt_variables_tag::type*> /*dt_vars*/,
     346             :       const gsl::not_null<typename history_tag::type*> /*history*/,
     347             :       const Mesh<dim>& /*new_mesh*/, const ElementId<dim>& /*element_id*/,
     348             :       const tuples::TaggedTuple<Tags...>& /*parent_items*/) {
     349             :     ERROR("h-refinement not implemented yet");
     350             :   }
     351             : 
     352             :   template <typename... Tags>
     353           0 :   static void apply(
     354             :       const gsl::not_null<typename dt_variables_tag::type*> /*dt_vars*/,
     355             :       const gsl::not_null<typename history_tag::type*> /*history*/,
     356             :       const Mesh<dim>& /*new_mesh*/, const ElementId<dim>& /*element_id*/,
     357             :       const std::unordered_map<ElementId<dim>, tuples::TaggedTuple<Tags...>>&
     358             :       /*children_items*/) {
     359             :     ERROR("h-refinement not implemented yet");
     360             :   }
     361             : };
     362             : }  // namespace Initialization

Generated by: LCOV version 1.14