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 <optional> 9 : #include <string> 10 : 11 : #include "ControlSystem/Component.hpp" 12 : #include "ControlSystem/ControlErrors/Rotation.hpp" 13 : #include "ControlSystem/Measurements/BNSCenterOfMass.hpp" 14 : #include "ControlSystem/Measurements/BothHorizons.hpp" 15 : #include "ControlSystem/Protocols/ControlError.hpp" 16 : #include "ControlSystem/Protocols/ControlSystem.hpp" 17 : #include "ControlSystem/Protocols/Measurement.hpp" 18 : #include "ControlSystem/Tags/QueueTags.hpp" 19 : #include "ControlSystem/Tags/SystemTags.hpp" 20 : #include "ControlSystem/UpdateControlSystem.hpp" 21 : #include "DataStructures/DataBox/DataBox.hpp" 22 : #include "DataStructures/DataBox/Tag.hpp" 23 : #include "DataStructures/LinkedMessageQueue.hpp" 24 : #include "Domain/Structure/ObjectLabel.hpp" 25 : #include "Parallel/GlobalCache.hpp" 26 : #include "Parallel/Printf/Printf.hpp" 27 : #include "ParallelAlgorithms/Actions/UpdateMessageQueue.hpp" 28 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/Tags.hpp" 29 : #include "Utilities/ErrorHandling/Assert.hpp" 30 : #include "Utilities/PrettyType.hpp" 31 : #include "Utilities/ProtocolHelpers.hpp" 32 : #include "Utilities/TMPL.hpp" 33 : 34 : /// \cond 35 : namespace Frame { 36 : struct Distorted; 37 : } // namespace Frame 38 : /// \endcond 39 : 40 : namespace control_system::Systems { 41 : /*! 42 : * \brief Controls the 3D \link domain::CoordinateMaps::TimeDependent::Rotation 43 : * Rotation \endlink map 44 : * 45 : * \details Controls the quaternion in the 3D \link 46 : * domain::CoordinateMaps::TimeDependent::Rotation Rotation \endlink map by 47 : * updating a \link domain::FunctionsOfTime::QuaternionFunctionOfTime 48 : * QuaternionFunctionOfTime \endlink. 49 : * 50 : * Requirements: 51 : * - The function of time this control system controls must be a 52 : * QuaternionFunctionOfTime. 53 : * - This control system requires that there be exactly two objects in the 54 : * simulation 55 : * - Currently both these objects must be black holes 56 : * - Currently this control system can only be used with the \link 57 : * control_system::measurements::BothHorizons BothHorizons \endlink 58 : * measurement 59 : * - Currently this control system can only be used with the \link 60 : * control_system::ControlErrors::Rotation Rotation \endlink control error 61 : * 62 : * \note Internally, QuaternionFunctionOfTime holds a PiecewisePolynomial 63 : * representing the angle about each axis that the system has rotated through. 64 : * The \link control_system::ControlErrors::Rotation rotation control error 65 : * \endlink is technically for this internal PiecewisePolynomial, not the 66 : * quaternion itself. However, the user doesn't need to know this. The 67 : * `QuaternionFunctionOfTime::update()` function takes care of everything 68 : * automatically. 69 : */ 70 : template <size_t DerivOrder, typename Measurement> 71 1 : struct Rotation : tt::ConformsTo<protocols::ControlSystem> { 72 0 : static constexpr size_t deriv_order = DerivOrder; 73 : 74 0 : static std::string name() { 75 : return pretty_type::short_name<Rotation<DerivOrder, Measurement>>(); 76 : } 77 : 78 0 : static std::optional<std::string> component_name( 79 : const size_t component, const size_t num_components) { 80 : ASSERT(num_components == 3, 81 : "Rotation control expects 3 components but there are " 82 : << num_components << " instead."); 83 : return component == 0 ? "x" : component == 1 ? "y" : "z"; 84 : } 85 : 86 0 : using measurement = Measurement; 87 : static_assert( 88 : tt::conforms_to_v<measurement, control_system::protocols::Measurement>); 89 : 90 0 : using control_error = ControlErrors::Rotation; 91 : static_assert(tt::conforms_to_v<control_error, 92 : control_system::protocols::ControlError>); 93 : 94 : // tag goes in control component 95 0 : struct MeasurementQueue : db::SimpleTag { 96 0 : using type = LinkedMessageQueue< 97 : double, tmpl::list<QueueTags::Center<::domain::ObjectLabel::A>, 98 : QueueTags::Center<::domain::ObjectLabel::B>>>; 99 : }; 100 : 101 0 : using simple_tags = tmpl::list<MeasurementQueue>; 102 : 103 0 : struct process_measurement { 104 : template <typename Submeasurement> 105 0 : using argument_tags = tmpl::conditional_t< 106 : std::is_same_v<Submeasurement, 107 : measurements::BothNSCenters::FindTwoCenters>, 108 : tmpl::list< 109 : measurements::Tags::NeutronStarCenter<::domain::ObjectLabel::A>, 110 : measurements::Tags::NeutronStarCenter<::domain::ObjectLabel::B>>, 111 : tmpl::list<ylm::Tags::Strahlkorper<Frame::Distorted>>>; 112 : 113 : template <::domain::ObjectLabel Horizon, typename Metavariables> 114 0 : static void apply( 115 : measurements::BothHorizons::FindHorizon<Horizon> submeasurement, 116 : const ylm::Strahlkorper<Frame::Distorted>& strahlkorper, 117 : Parallel::GlobalCache<Metavariables>& cache, 118 : const LinkedMessageId<double>& measurement_id) { 119 : auto& control_sys_proxy = Parallel::get_parallel_component< 120 : ControlComponent<Metavariables, Rotation<DerivOrder, Measurement>>>( 121 : cache); 122 : 123 : DataVector center(strahlkorper.physical_center()); 124 : 125 : Parallel::simple_action<::Actions::UpdateMessageQueue< 126 : QueueTags::Center<Horizon>, MeasurementQueue, 127 : UpdateControlSystem<Rotation>>>(control_sys_proxy, measurement_id, 128 : std::move(center)); 129 : 130 : if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Verbose) { 131 : Parallel::printf("%s, time = %.16f: Received measurement '%s'.\n", 132 : name(), measurement_id.id, 133 : pretty_type::name(submeasurement)); 134 : } 135 : } 136 : 137 : template <typename Metavariables> 138 0 : static void apply( 139 : measurements::BothNSCenters::FindTwoCenters submeasurement, 140 : const std::array<double, 3> center_a, 141 : const std::array<double, 3> center_b, 142 : Parallel::GlobalCache<Metavariables>& cache, 143 : const LinkedMessageId<double>& measurement_id) { 144 : auto& control_sys_proxy = Parallel::get_parallel_component< 145 : ControlComponent<Metavariables, Rotation<DerivOrder, Measurement>>>( 146 : cache); 147 : 148 : Parallel::simple_action<::Actions::UpdateMessageQueue< 149 : QueueTags::Center<::domain::ObjectLabel::A>, MeasurementQueue, 150 : UpdateControlSystem<Rotation>>>(control_sys_proxy, measurement_id, 151 : DataVector(center_a)); 152 : Parallel::simple_action<::Actions::UpdateMessageQueue< 153 : QueueTags::Center<::domain::ObjectLabel::B>, MeasurementQueue, 154 : UpdateControlSystem<Rotation>>>(control_sys_proxy, measurement_id, 155 : DataVector(center_b)); 156 : 157 : if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Verbose) { 158 : Parallel::printf("%s, time = %.16f: Received measurement '%s'.\n", 159 : name(), measurement_id.id, 160 : pretty_type::name(submeasurement)); 161 : } 162 : } 163 : }; 164 : }; 165 : } // namespace control_system::Systems