VolumeDataReaderActions.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <iterator>
8 #include <unordered_map>
9 
12 #include "DataStructures/Index.hpp"
13 #include "DataStructures/Tensor/TensorData.hpp"
14 #include "ErrorHandling/Error.hpp"
15 #include "IO/H5/AccessType.hpp"
16 #include "IO/H5/File.hpp"
17 #include "IO/H5/VolumeData.hpp"
18 #include "IO/Importers/Tags.hpp"
19 #include "IO/Observer/ArrayComponentId.hpp"
21 #include "Parallel/Info.hpp"
22 #include "Parallel/Invoke.hpp"
23 #include "Utilities/Algorithm.hpp"
24 #include "Utilities/Requires.hpp"
26 
27 namespace importers {
28 /// Actions related to importers
29 namespace Actions {
30 
31 /*!
32  * \brief Invoked on the `importers::VolumeDataReader` component to store the
33  * registered data.
34  *
35  * The `importers::Actions::RegisterWithVolumeDataReader` action, which is
36  * performed on each element of an array parallel component, invokes this action
37  * on the `importers::VolumeDataReader` component.
38  */
40  template <
41  typename ParallelComponent, typename DbTagsList, typename Metavariables,
42  typename ArrayIndex, typename DataBox = db::DataBox<DbTagsList>,
44  nullptr>
45  static void apply(db::DataBox<DbTagsList>& box,
47  const ArrayIndex& /*array_index*/,
48  const observers::ArrayComponentId& array_component_id,
49  const std::string& grid_name) noexcept {
50  db::mutate<Tags::RegisteredElements>(
51  make_not_null(&box),
52  [&array_component_id, &grid_name](
54  registered_elements) noexcept {
55  (*registered_elements)[array_component_id] = grid_name;
56  });
57  }
58 };
59 
60 } // namespace Actions
61 
62 /// Threaded actions related to importers
63 namespace ThreadedActions {
64 
65 /*!
66  * \brief Read a volume data file and distribute the data to the registered
67  * elements.
68  *
69  * This action can be invoked on the `importers::VolumeDataReader` component
70  * once all elements have been registered with it. It opens the data file, reads
71  * the data for each registered element and calls the `CallbackAction` on each
72  * element providing the data.
73  *
74  * - The `ImporterOptionsGroup` parameter specifies the \ref OptionGroupsGroup
75  * "options group" in the input file that provides the following run-time
76  * options:
77  * - `importers::OptionTags::FileName`
78  * - `importers::OptionTags::Subgroup`
79  * - `importers::OptionTags::ObservationValue`
80  * - The `FieldTagsList` parameter specifies a typelist of tensor tags that
81  * are read from the file and provided to each element. It is assumed that the
82  * tensor data is stored in datasets named `db::tag_name<Tag>() + suffix`, where
83  * the `suffix` is empty for scalars or `"_"` followed by the
84  * `Tensor::component_name` for each independent tensor component.
85  * - The `CallbackAction` is invoked on each registered element of the
86  * `CallbackComponent` with a
87  * `tuples::tagged_tuple_from_typelist<FieldTagsList>` containing the
88  * tensor data for that element. Use `Actions::SetData` to write the data
89  * directly into their respective tags in the DataBox. The `CallbackComponent`
90  * must the the same that was encoded into the `observers::ArrayComponentId`
91  * used to register the elements.
92  */
93 template <typename ImporterOptionsGroup, typename FieldTagsList,
94  typename CallbackAction, typename CallbackComponent>
96  using const_global_cache_tags =
97  tmpl::list<Tags::FileName<ImporterOptionsGroup>,
100 
101  template <typename ParallelComponent, typename DataBox,
102  typename Metavariables, typename ArrayIndex,
104  DataBox>> = nullptr>
105  static void apply(DataBox& box,
107  const ArrayIndex& /*array_index*/,
108  const gsl::not_null<CmiNodeLock*> node_lock) noexcept {
109  Parallel::lock(node_lock);
110  {
111  // The scoping is to close the file before unlocking
114  constexpr size_t version_number = 0;
115  const auto& volume_file = h5file.get<h5::VolumeData>(
116  "/" + Parallel::get<Tags::Subgroup<ImporterOptionsGroup>>(cache),
117  version_number);
118  const auto observation_id = volume_file.find_observation_id(
119  Parallel::get<Tags::ObservationValue<ImporterOptionsGroup>>(cache));
120  // Read the tensor data for all elements at once, since that's how it's
121  // stored in the file
122  tuples::tagged_tuple_from_typelist<FieldTagsList> all_tensor_data{};
123  tmpl::for_each<FieldTagsList>([
124  &all_tensor_data, &volume_file, &observation_id
125  ](auto field_tag_v) noexcept {
126  using field_tag = tmpl::type_from<decltype(field_tag_v)>;
127  auto& tensor_data = get<field_tag>(all_tensor_data);
128  for (size_t i = 0; i < tensor_data.size(); i++) {
129  tensor_data[i] = volume_file.get_tensor_component(
130  observation_id,
131  db::tag_name<field_tag>() + tensor_data.component_suffix(
132  tensor_data.get_tensor_index(i)));
133  }
134  });
135  // Retrieve the information needed to reconstruct which element the data
136  // belongs to
137  const auto all_grid_names = volume_file.get_grid_names(observation_id);
138  const auto all_extents = volume_file.get_extents(observation_id);
139  // Distribute the tensor data to the registered elements
140  for (auto& element_and_name : get<Tags::RegisteredElements>(box)) {
141  const CkArrayIndex& raw_element_index =
142  element_and_name.first.array_index();
143  // Check if the parallel component of the registered element matches the
144  // callback, because it's possible that elements from other components
145  // with the same index are also registered.
146  // Since the way the component is encoded in `ArrayComponentId` is
147  // private to that class, we construct one and compare.
148  if (element_and_name.first !=
151  raw_element_index)) {
152  continue;
153  }
154  // Find the data offset that corresponds to this element
155  const auto element_data_offset_and_length =
156  h5::offset_and_length_for_grid(element_and_name.second,
157  all_grid_names, all_extents);
158  // Extract this element's data from the read-in dataset
159  tuples::tagged_tuple_from_typelist<FieldTagsList> element_data{};
160  tmpl::for_each<FieldTagsList>([
161  &element_data, &element_data_offset_and_length, &all_tensor_data
162  ](auto field_tag_v) noexcept {
163  using field_tag = tmpl::type_from<decltype(field_tag_v)>;
164  auto& element_tensor_data = get<field_tag>(element_data);
165  // Iterate independent components of the tensor
166  for (size_t i = 0; i < element_tensor_data.size(); i++) {
167  const DataVector& data_tensor_component =
168  get<field_tag>(all_tensor_data)[i];
169  DataVector element_tensor_component{
170  element_data_offset_and_length.second};
171  // Retrieve data from slice of the contigious dataset
172  for (size_t j = 0; j < element_tensor_component.size(); j++) {
173  element_tensor_component[j] =
174  data_tensor_component[element_data_offset_and_length.first +
175  j];
176  }
177  element_tensor_data[i] = element_tensor_component;
178  }
179  });
180  // Pass the data to the element in a simple action
181  const auto element_index =
183  raw_element_index)
184  .get_index();
185  Parallel::simple_action<CallbackAction>(
186  Parallel::get_parallel_component<CallbackComponent>(
187  cache)[element_index],
188  std::move(element_data));
189  }
190  }
191  Parallel::unlock(node_lock);
192  }
193 };
194 
195 } // namespace ThreadedActions
196 } // namespace importers
Defines class tuples::TaggedTuple.
Defines functions for interfacing with the parallelization framework.
Read a volume data file and distribute the data to the registered elements.
Definition: VolumeDataReaderActions.hpp:95
Defines class h5::H5File.
The file to read data from.
Definition: Tags.hpp:84
The elements that will receive data from the importer.
Definition: Tags.hpp:141
The observation value at which to read data from the file.
Definition: Tags.hpp:120
The subgroup within the file to read data from.
Definition: Tags.hpp:103
Defines the type alias Requires.
An ID type that identifies both the parallel component and the index in the parallel component...
Definition: ArrayComponentId.hpp:27
void unlock(const gsl::not_null< CmiNodeLock *> node_lock) noexcept
Unlock a converse CmiNodeLock.
Definition: NodeLock.hpp:62
Defines class template Index.
Defines enum for specifying whether the H5 file is ReadWrite or ReadOnly.
Defines classes and functions used for manipulating DataBox&#39;s.
A volume data subfile written inside an H5 file.
Definition: VolumeData.hpp:67
constexpr bool tag_is_retrievable_v
Equal to true if Tag can be retrieved from a DataBox of type DataBoxType.
Definition: DataBox.hpp:72
Definition: InterpolationTargetWedgeSectionTorus.hpp:24
A Charm++ chare that caches constant data once per Charm++ node.
Definition: ConstGlobalCache.hpp:135
std::pair< size_t, size_t > offset_and_length_for_grid(const std::string &grid_name, const std::vector< std::string > &all_grid_names, const std::vector< std::vector< size_t >> &all_extents) noexcept
Find the interval within the contiguous dataset stored in h5::VolumeData that holds data for a partic...
void lock(const gsl::not_null< CmiNodeLock *> node_lock) noexcept
Lock a converse CmiNodeLock.
Definition: NodeLock.hpp:34
Items related to loading data from files.
Definition: ElementActions.hpp:18
Stores a collection of function values.
Definition: DataVector.hpp:42
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:879
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
ObjectType & get(const std::string &path, Args &&... args)
Definition: File.hpp:192
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
Defines class template ConstGlobalCache.
Defines macro ERROR.
auto get(const ConstGlobalCache< Metavariables > &cache) noexcept -> const ConstGlobalCache_detail::type_for_get< ConstGlobalCacheTag, Metavariables > &
Access data in the cache.
Definition: ConstGlobalCache.hpp:253
Definition: ComputeTimeDerivative.hpp:28
Require a pointer to not be a nullptr
Definition: Gsl.hpp:182
The array index used for indexing Chare Arrays, mostly an implementation detail.
Definition: ArrayIndex.hpp:25
Invoked on the importers::VolumeDataReader component to store the registered data.
Definition: VolumeDataReaderActions.hpp:39