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
|