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 <optional> 8 : #include <string> 9 : #include <type_traits> 10 : #include <unordered_map> 11 : #include <utility> 12 : #include <vector> 13 : 14 : #include "DataStructures/FloatingPointType.hpp" 15 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp" 16 : #include "Domain/Structure/ElementId.hpp" 17 : #include "Domain/Tags.hpp" 18 : #include "IO/H5/TensorData.hpp" 19 : #include "IO/Observer/ObservationId.hpp" 20 : #include "IO/Observer/ObserverComponent.hpp" 21 : #include "IO/Observer/TypeOfObservation.hpp" 22 : #include "IO/Observer/VolumeActions.hpp" 23 : #include "NumericalAlgorithms/Spectral/Basis.hpp" 24 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 25 : #include "NumericalAlgorithms/Spectral/Quadrature.hpp" 26 : #include "Options/String.hpp" 27 : #include "Parallel/ArrayComponentId.hpp" 28 : #include "Parallel/ArrayIndex.hpp" 29 : #include "Parallel/GlobalCache.hpp" 30 : #include "Parallel/Invoke.hpp" 31 : #include "Parallel/Local.hpp" 32 : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp" 33 : #include "Utilities/Serialization/CharmPupable.hpp" 34 : #include "Utilities/TMPL.hpp" 35 : 36 : /// \cond 37 : class DataVector; 38 : template <size_t VolumeDim> 39 : class Domain; 40 : class TimeDelta; 41 : namespace PUP { 42 : class er; 43 : } // namespace PUP 44 : namespace Tags { 45 : struct Time; 46 : struct TimeStep; 47 : } // namespace Tags 48 : namespace domain::Tags { 49 : template <size_t VolumeDim> 50 : struct Domain; 51 : struct FunctionsOfTime; 52 : } // namespace domain::Tags 53 : /// \endcond 54 : 55 : namespace dg::Events { 56 : /*! 57 : * \brief %Observe the time step in the volume. 58 : * 59 : * Observe the time step size in each element. Each element is output 60 : * as a single cell with two points per dimension and the observation 61 : * constant on all those points. 62 : * 63 : * Writes volume quantities: 64 : * - InertialCoordinates (only element corners) 65 : * - Time step 66 : * - Slab fraction 67 : */ 68 : template <size_t VolumeDim> 69 1 : class ObserveTimeStepVolume : public Event { 70 : public: 71 : /// The name of the subfile inside the HDF5 file 72 1 : struct SubfileName { 73 0 : using type = std::string; 74 0 : static constexpr Options::String help = { 75 : "The name of the subfile inside the HDF5 file without an extension and " 76 : "without a preceding '/'."}; 77 : }; 78 : 79 : /// \cond 80 : explicit ObserveTimeStepVolume(CkMigrateMessage* /*unused*/) {} 81 : using PUP::able::register_constructor; 82 : WRAPPED_PUPable_decl_template(ObserveTimeStepVolume); // NOLINT 83 : /// \endcond 84 : 85 : /// The floating point type/precision with which to write the data to disk. 86 1 : struct FloatingPointType { 87 0 : static constexpr Options::String help = 88 : "The floating point type/precision with which to write the data to " 89 : "disk."; 90 0 : using type = ::FloatingPointType; 91 : }; 92 : 93 : /// The floating point type/precision with which to write the coordinates to 94 : /// disk. 95 1 : struct CoordinatesFloatingPointType { 96 0 : static constexpr Options::String help = 97 : "The floating point type/precision with which to write the coordinates " 98 : "to disk."; 99 0 : using type = ::FloatingPointType; 100 : }; 101 : 102 0 : using options = 103 : tmpl::list<SubfileName, CoordinatesFloatingPointType, FloatingPointType>; 104 : 105 0 : static constexpr Options::String help = 106 : "Observe the time step in the volume."; 107 : 108 0 : ObserveTimeStepVolume() = default; 109 : 110 0 : ObserveTimeStepVolume(const std::string& subfile_name, 111 : ::FloatingPointType coordinates_floating_point_type, 112 : ::FloatingPointType floating_point_type); 113 : 114 0 : using compute_tags_for_observation_box = tmpl::list<>; 115 : 116 0 : using return_tags = tmpl::list<>; 117 0 : using argument_tags = 118 : tmpl::list<::Tags::Time, ::domain::Tags::FunctionsOfTime, 119 : ::domain::Tags::Domain<VolumeDim>, ::Tags::TimeStep>; 120 : 121 : template <typename Metavariables, typename ParallelComponent> 122 0 : void operator()(const double time, 123 : const domain::FunctionsOfTimeMap& functions_of_time, 124 : const Domain<VolumeDim>& domain, const TimeDelta& time_step, 125 : Parallel::GlobalCache<Metavariables>& cache, 126 : const ElementId<VolumeDim>& element_id, 127 : const ParallelComponent* const /*component*/, 128 : const ObservationValue& observation_value) const { 129 : std::vector<TensorComponent> components = 130 : assemble_data(time, functions_of_time, domain, element_id, time_step); 131 : 132 : const Mesh<VolumeDim> single_cell_mesh(2, Spectral::Basis::Legendre, 133 : Spectral::Quadrature::GaussLobatto); 134 : const Parallel::ArrayComponentId array_component_id{ 135 : std::add_pointer_t<ParallelComponent>{nullptr}, 136 : Parallel::ArrayIndex<ElementId<VolumeDim>>{element_id}}; 137 : ElementVolumeData element_volume_data{element_id, std::move(components), 138 : single_cell_mesh}; 139 : observers::ObservationId observation_id{observation_value.value, 140 : subfile_path_ + ".vol"}; 141 : 142 : auto& local_observer = *Parallel::local_branch( 143 : Parallel::get_parallel_component< 144 : tmpl::conditional_t<Parallel::is_nodegroup_v<ParallelComponent>, 145 : observers::ObserverWriter<Metavariables>, 146 : observers::Observer<Metavariables>>>(cache)); 147 : 148 : if constexpr (Parallel::is_nodegroup_v<ParallelComponent>) { 149 : // Send data to reduction observer writer (nodegroup) 150 : std::unordered_map<Parallel::ArrayComponentId, 151 : std::vector<ElementVolumeData>> 152 : data_to_send{}; 153 : data_to_send[array_component_id] = 154 : std::vector{std::move(element_volume_data)}; 155 : Parallel::threaded_action< 156 : observers::ThreadedActions::ContributeVolumeDataToWriter>( 157 : local_observer, std::move(observation_id), array_component_id, 158 : subfile_path_, std::move(data_to_send)); 159 : } else { 160 : // Send data to volume observer 161 : Parallel::simple_action<observers::Actions::ContributeVolumeData>( 162 : local_observer, std::move(observation_id), subfile_path_, 163 : array_component_id, std::move(element_volume_data)); 164 : } 165 : } 166 : 167 0 : using observation_registration_tags = tmpl::list<>; 168 : 169 : std::optional< 170 : std::pair<observers::TypeOfObservation, observers::ObservationKey>> 171 0 : get_observation_type_and_key_for_registration() const; 172 : 173 0 : using is_ready_argument_tags = tmpl::list<>; 174 : 175 : template <typename Metavariables, typename ArrayIndex, typename Component> 176 0 : bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/, 177 : const ArrayIndex& /*array_index*/, 178 : const Component* const /*meta*/) const { 179 : return true; 180 : } 181 : 182 1 : bool needs_evolved_variables() const override; 183 : 184 0 : void pup(PUP::er& p) override; 185 : 186 : private: 187 0 : std::vector<TensorComponent> assemble_data( 188 : double time, const domain::FunctionsOfTimeMap& functions_of_time, 189 : const Domain<VolumeDim>& domain, const ElementId<VolumeDim>& element_id, 190 : const TimeDelta& time_step) const; 191 : 192 0 : std::string subfile_path_; 193 0 : ::FloatingPointType coordinates_floating_point_type_ = 194 : ::FloatingPointType::Double; 195 0 : ::FloatingPointType floating_point_type_ = ::FloatingPointType::Double; 196 : }; 197 : } // namespace dg::Events