SpECTRE Documentation Coverage Report
Current view: top level - ControlSystem - WriteData.hpp Coverage Total Hit
Commit: a37d7b3c1803b88b537d2aef1c27ca5e6b499398 Lines: 50.0 % 2 1
Test Date: 2026-11-12 04:47:19
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 <memory>
       9              : #include <optional>
      10              : #include <string>
      11              : #include <vector>
      12              : 
      13              : #include "ControlSystem/Component.hpp"
      14              : #include "DataStructures/DataVector.hpp"
      15              : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      16              : #include "Domain/FunctionsOfTime/QuaternionFunctionOfTime.hpp"
      17              : #include "IO/Observer/ReductionActions.hpp"
      18              : #include "Parallel/GlobalCache.hpp"
      19              : #include "Parallel/Info.hpp"
      20              : #include "Parallel/Invoke.hpp"
      21              : 
      22              : namespace control_system {
      23              : /*!
      24              :  * \ingroup ControlSystemGroup
      25              :  * \brief Writes all components of a function of time to disk at a specific time
      26              :  * from a control system after it updates the functions of time.
      27              :  *
      28              :  * \details The columns of data written are:
      29              :  * - %Time
      30              :  * - FunctionOfTime
      31              :  * - dtFunctionOfTime
      32              :  * - d2tFunctionOfTime
      33              :  * - ControlError
      34              :  * - dtControlError
      35              :  * - DampingTimescale
      36              :  *
      37              :  * Data will be stored in the reduction file. All components are sent to the
      38              :  * `observers::ObserverWriter` in a single
      39              :  * `observers::ThreadedActions::WriteMultipleReductionDataRows` call so the
      40              :  * reduction file is opened only once per control system and measurement. All
      41              :  * subfiles for the control system within the H5 file will be under the group
      42              :  * "/ControlSystems".
      43              :  * Within this group, there will be one group for each control system. The name
      44              :  * of each group will be the result of the `name()` function from each control
      45              :  * system. An example would look like
      46              :  *
      47              :  * - /ControlSystems/SystemA
      48              :  * - /ControlSystems/SystemB
      49              :  * - /ControlSystems/SystemC
      50              :  *
      51              :  * Then, within each system group, there will be one subfile for each component
      52              :  * of the function of time that is being controlled. The name of this subfile is
      53              :  * the name of the component. The name of each component will be the result of
      54              :  * the `component_name(i)` function from the control system, where `i` is the
      55              :  * index of the component. For example, if "SystemA" has 3 components with names
      56              :  * "X", "Y", and "Z", then the subfiles would look like
      57              :  *
      58              :  * - /ControlSystems/SystemA/X.dat
      59              :  * - /ControlSystems/SystemA/Y.dat
      60              :  * - /ControlSystems/SystemA/Z.dat
      61              :  */
      62              : template <typename ControlSystem, typename Metavariables>
      63            1 : void write_components_to_disk(
      64              :     const double time, Parallel::GlobalCache<Metavariables>& cache,
      65              :     const std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>&
      66              :         function_of_time,
      67              :     const std::array<DataVector, 2>& q_and_dtq, const DataVector& timescales) {
      68              :   auto& observer_writer_proxy = Parallel::get_parallel_component<
      69              :       observers::ObserverWriter<Metavariables>>(cache);
      70              : 
      71              :   constexpr size_t deriv_order = ControlSystem::deriv_order;
      72              :   std::array<DataVector, 3> function_at_current_time{};
      73              :   const auto* const quat_func_of_time = dynamic_cast<
      74              :       const domain::FunctionsOfTime::QuaternionFunctionOfTime<deriv_order>*>(
      75              :       function_of_time.get());
      76              :   if (quat_func_of_time == nullptr) {
      77              :     // Just call the usual `func_and_2_derivs` member.
      78              :     function_at_current_time = function_of_time->func_and_2_derivs(time);
      79              :   } else {
      80              :     // If we are working with a QuaternionFunctionOfTime, we aren't actually
      81              :     // controlling a quaternion. We are controlling a small change in angle
      82              :     // associated with the angular velocity in each direction. Because of this,
      83              :     // we want to write the component data of the thing we are actually
      84              :     // controlling. This is accessed by the `angle_func_and_2_derivs` member of
      85              :     // a QuaternionFunctionOfTime. Since `angle_func_and_2_derivs` is not a
      86              :     // virtual function of the FunctionOfTime base class, we need to down cast
      87              :     // the original function to a QuaternionFunctionOfTime.
      88              :     function_at_current_time = quat_func_of_time->angle_func_and_2_derivs(time);
      89              :   }
      90              : 
      91              :   // Each control system is its own group under the overarching `ControlSystems`
      92              :   // group. There is a different subfile for each component, so loop over them.
      93              :   // Eg. translation files will look like
      94              :   //
      95              :   // ControlSystems/Translation/X.dat
      96              :   // ControlSystems/Translation/Y.dat
      97              :   // ControlSystems/Translation/Z.dat
      98              :   //
      99              :   // All components are collected and written with a single call so the
     100              :   // reduction file is opened only once rather than once per component.
     101              :   const std::vector<std::string> legend{
     102              :       "Time",         "FunctionOfTime", "dtFunctionOfTime", "d2tFunctionOfTime",
     103              :       "ControlError", "dtControlError", "DampingTimescale"};
     104              :   const size_t num_components = function_at_current_time[0].size();
     105              :   std::vector<observers::DatRows> rows_to_write{};
     106              :   rows_to_write.reserve(num_components);
     107              :   for (size_t i = 0; i < num_components; ++i) {
     108              :     const std::optional<std::string> component_name_opt =
     109              :         ControlSystem::component_name(i, num_components);
     110              :     if (not component_name_opt) {
     111              :       continue;
     112              :     }
     113              :     // Currently all reduction data is written to the reduction file so preface
     114              :     // everything with ControlSystems/
     115              :     rows_to_write.push_back(observers::DatRows{
     116              :         "/ControlSystems/" + ControlSystem::name() + "/" + *component_name_opt,
     117              :         legend,
     118              :         {{
     119              :             // clang-format off
     120              :             time,
     121              :             function_at_current_time[0][i],
     122              :             function_at_current_time[1][i],
     123              :             function_at_current_time[2][i],
     124              :             q_and_dtq[0][i],
     125              :             q_and_dtq[1][i],
     126              :             timescales[i]
     127              :             // clang-format on
     128              :         }}});
     129              :   }
     130              :   if (rows_to_write.empty()) {
     131              :     return;
     132              :   }
     133              : 
     134              :   Parallel::threaded_action<
     135              :       observers::ThreadedActions::WriteMultipleReductionDataRows>(
     136              :       // Node 0 is always the writer
     137              :       observer_writer_proxy[0], std::move(rows_to_write));
     138              : }
     139              : }  // namespace control_system
        

Generated by: LCOV version 2.0-1