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 <unordered_map> 10 : #include <utility> 11 : #include <vector> 12 : 13 : #include "DataStructures/FloatingPointType.hpp" 14 : #include "Domain/Structure/ElementId.hpp" 15 : #include "IO/H5/TensorData.hpp" 16 : #include "IO/Observer/ObservationId.hpp" 17 : #include "IO/Observer/VolumeActions.hpp" 18 : #include "NumericalAlgorithms/Spectral/Basis.hpp" 19 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 20 : #include "NumericalAlgorithms/Spectral/Quadrature.hpp" 21 : #include "Options/String.hpp" 22 : #include "Parallel/ArrayComponentId.hpp" 23 : #include "Parallel/ArrayIndex.hpp" 24 : #include "Parallel/TypeTraits.hpp" 25 : #include "ParallelAlgorithms/Actions/FunctionsOfTimeAreReady.hpp" 26 : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp" 27 : #include "Utilities/TMPL.hpp" 28 : 29 : /// \cond 30 : template <size_t VolumeDim> 31 : class Domain; 32 : namespace domain::FunctionsOfTime { 33 : class FunctionOfTime; 34 : } // namespace domain::FunctionsOfTime 35 : namespace domain::Tags { 36 : struct FunctionsOfTime; 37 : } // namespace domain::Tags 38 : namespace observers { 39 : class ObservationKey; 40 : enum class TypeOfObservation; 41 : } // namespace observers 42 : namespace Parallel { 43 : template <typename Metavariables> 44 : class GlobalCache; 45 : } // namespace Parallel 46 : namespace PUP { 47 : class er; 48 : } // namespace PUP 49 : namespace Tags { 50 : struct Time; 51 : } // namespace Tags 52 : /// \endcond 53 : 54 : namespace dg::Events { 55 : /// \brief Base class for Observers that write data that is constant within an 56 : /// Element 57 : template <size_t VolumeDim> 58 1 : class ObserveConstantsPerElement : public Event { 59 : public: 60 : /// The name of the subfile inside the HDF5 file 61 1 : struct SubfileName { 62 0 : using type = std::string; 63 0 : static constexpr Options::String help = { 64 : "The name of the subfile inside the HDF5 file without an extension and " 65 : "without a preceding '/'."}; 66 : }; 67 : 68 : /// The floating point type/precision with which to write the data to disk. 69 1 : struct FloatingPointType { 70 0 : static constexpr Options::String help = 71 : "The floating point type/precision with which to write the data to " 72 : "disk."; 73 0 : using type = ::FloatingPointType; 74 : }; 75 : 76 : /// The floating point type/precision with which to write the coordinates to 77 : /// disk. 78 1 : struct CoordinatesFloatingPointType { 79 0 : static constexpr Options::String help = 80 : "The floating point type/precision with which to write the coordinates " 81 : "to disk."; 82 0 : using type = ::FloatingPointType; 83 : }; 84 : 85 0 : using options = 86 : tmpl::list<SubfileName, CoordinatesFloatingPointType, FloatingPointType>; 87 : 88 0 : ObserveConstantsPerElement() = default; 89 : 90 0 : ObserveConstantsPerElement( 91 : const std::string& subfile_name, 92 : ::FloatingPointType coordinates_floating_point_type, 93 : ::FloatingPointType floating_point_type); 94 : 95 : /// \cond 96 : explicit ObserveConstantsPerElement(CkMigrateMessage* /*unused*/); 97 : /// \endcond 98 : 99 0 : using observation_registration_tags = tmpl::list<>; 100 : 101 : std::optional< 102 : std::pair<observers::TypeOfObservation, observers::ObservationKey>> 103 0 : get_observation_type_and_key_for_registration() const; 104 : 105 0 : using is_ready_argument_tags = tmpl::list<::Tags::Time>; 106 : 107 : template <typename Metavariables, typename ArrayIndex, typename Component> 108 0 : bool is_ready(const double time, Parallel::GlobalCache<Metavariables>& cache, 109 : const ArrayIndex& array_index, 110 : const Component* const component) const { 111 : return ::domain::functions_of_time_are_ready_algorithm_callback< 112 : ::domain::Tags::FunctionsOfTime, VolumeDim>(cache, array_index, 113 : component, time); 114 : } 115 : 116 0 : void pup(PUP::er& p) override; 117 : 118 : protected: 119 : /// \brief Creates the vector of tensor components that will be observed 120 : /// and starts to fill it with the inertial coordinates 121 : /// 122 : /// \details number_of_constants is the number of additional tensor components 123 : /// that will be observed. These are added by calling add_constant 124 1 : std::vector<TensorComponent> allocate_and_insert_coords( 125 : size_t number_of_constants, double time, 126 : const std::unordered_map< 127 : std::string, 128 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>& 129 : functions_of_time, 130 : const Domain<VolumeDim>& domain, 131 : const ElementId<VolumeDim>& element_id) const; 132 : 133 : /// \brief Adds a TensorComponent to components with the given name and the 134 : /// given value. 135 : /// 136 : /// \details Should be called after allocate_and_insert_coords 137 1 : void add_constant(gsl::not_null<std::vector<TensorComponent>*> components, 138 : std::string name, double value) const; 139 : 140 : /// Observes the components as volume data 141 : template <typename Metavariables, typename ParallelComponent> 142 1 : void observe(std::vector<TensorComponent> components, 143 : Parallel::GlobalCache<Metavariables>& cache, 144 : const ElementId<VolumeDim>& element_id, 145 : const ParallelComponent* /*component*/, 146 : const ObservationValue& observation_value) const; 147 : private: 148 0 : std::string subfile_path_; 149 0 : ::FloatingPointType coordinates_floating_point_type_ = 150 : ::FloatingPointType::Double; 151 0 : ::FloatingPointType floating_point_type_ = ::FloatingPointType::Double; 152 : }; 153 : 154 : template <size_t VolumeDim> 155 : template <typename Metavariables, typename ParallelComponent> 156 : void ObserveConstantsPerElement<VolumeDim>::observe( 157 : std::vector<TensorComponent> components, 158 : Parallel::GlobalCache<Metavariables>& cache, 159 : const ElementId<VolumeDim>& element_id, 160 : const ParallelComponent* const /*component*/, 161 : const ObservationValue& observation_value) const { 162 : const Mesh<VolumeDim> single_cell_mesh(2, Spectral::Basis::Legendre, 163 : Spectral::Quadrature::GaussLobatto); 164 : const Parallel::ArrayComponentId array_component_id{ 165 : std::add_pointer_t<ParallelComponent>{nullptr}, 166 : Parallel::ArrayIndex<ElementId<VolumeDim>>{element_id}}; 167 : ElementVolumeData element_volume_data{element_id, std::move(components), 168 : single_cell_mesh}; 169 : observers::ObservationId observation_id{observation_value.value, 170 : subfile_path_ + ".vol"}; 171 : 172 : observers::contribute_volume_data< 173 : not Parallel::is_nodegroup_v<ParallelComponent>>( 174 : cache, std::move(observation_id), subfile_path_, array_component_id, 175 : std::move(element_volume_data)); 176 : } 177 : 178 : } // namespace dg::Events