Observe.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <string>
8 #include <tuple>
9 
11 #include "Domain/Tags.hpp"
12 #include "Evolution/Systems/Burgers/Tags.hpp"
13 #include "IO/Observer/Actions.hpp"
14 #include "IO/Observer/ArrayComponentId.hpp"
15 #include "IO/Observer/Helpers.hpp"
16 #include "IO/Observer/ObservationId.hpp"
17 #include "IO/Observer/ObserverComponent.hpp"
18 #include "IO/Observer/ReductionActions.hpp"
19 #include "IO/Observer/VolumeActions.hpp"
20 #include "Options/Options.hpp"
22 #include "PointwiseFunctions/AnalyticSolutions/Tags.hpp"
23 #include "Time/Tags.hpp"
24 #include "Utilities/Functional.hpp"
25 #include "Utilities/MakeString.hpp"
26 #include "Utilities/Numeric.hpp"
27 #include "Utilities/TMPL.hpp"
29 
30 namespace Burgers {
31 namespace Actions {
32 
33 /*!
34  * \brief Temporary action for observing volume and reduction data
35  *
36  * A few notes:
37  * - Writes the solution and error in \f$U\f$ to disk.
38  * - The RMS error of \f$U\f$ is written to disk.
39  */
40 struct Observe {
41  private:
45  using reduction_data = Parallel::ReductionData<
48 
49  public:
50  struct ObserveNSlabs {
51  using type = size_t;
52  static constexpr OptionString help = {"Observe every Nth slab"};
53  };
54  struct ObserveAtT0 {
55  using type = bool;
56  static constexpr OptionString help = {"If true observe at t=0"};
57  };
58 
59  using const_global_cache_tags = tmpl::list<ObserveNSlabs, ObserveAtT0>;
60  using observed_reduction_data_tags =
61  observers::make_reduction_data_tags<tmpl::list<reduction_data>>;
62 
63  template <typename... DbTags, typename... InboxTags, typename Metavariables,
64  size_t Dim, typename ActionList, typename ParallelComponent>
65  static auto apply(db::DataBox<tmpl::list<DbTags...>>& box,
68  const ElementIndex<Dim>& array_index,
69  const ActionList /*meta*/,
70  const ParallelComponent* const /*meta*/) noexcept {
71  const auto& time_id = db::get<::Tags::TimeId>(box);
72  if (time_id.substep() != 0 or (time_id.slab_number() == 0 and
73  not Parallel::get<ObserveAtT0>(cache))) {
74  return std::forward_as_tuple(std::move(box));
75  }
76 
77  const auto& time = time_id.time();
78 
79  const std::string element_name = MakeString{} << ElementId<Dim>(array_index)
80  << '/';
81  if (time_id.slab_number() >= 0 and time_id.time().is_at_slab_start() and
82  static_cast<size_t>(time_id.slab_number()) %
83  Parallel::get<ObserveNSlabs>(cache) ==
84  0) {
85  const auto& extents = db::get<::Tags::Mesh<Dim>>(box).extents();
86  // Retrieve the tensors and compute the solution error.
87  const auto& u = db::get<Burgers::Tags::U>(box);
88  const auto& inertial_coordinates =
89  db::get<::Tags::Coordinates<Dim, Frame::Inertial>>(box);
90 
91  // Compute the error in the solution, and generate tensor component list.
92  using Vars = typename Metavariables::system::variables_tag::type;
93  using solution_tag = OptionTags::AnalyticSolutionBase;
94  const auto exact_solution = Parallel::get<solution_tag>(cache).variables(
95  inertial_coordinates, time.value(), typename Vars::tags_list{});
96 
97  // Remove tensor types, only storing individual components.
99  // U, UError, x
100  components.reserve(3);
101 
102  components.emplace_back(element_name + Burgers::Tags::U::name(), u.get());
104  DataVector error =
105  tuples::get<Burgers::Tags::U>(exact_solution).get() - u.get();
106  const double u_error = alg::accumulate(error, 0.0, PlusSquare{});
107  components.emplace_back(element_name + "Error" + Burgers::Tags::U::name(),
108  error);
109  components.emplace_back(
110  element_name + ::Tags::Coordinates<1, Frame::Inertial>::name() + "_x",
111  get<0>(inertial_coordinates));
112 
113  // Send data to volume observer
114  auto& local_observer =
115  *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
116  cache)
117  .ckLocalBranch();
118  Parallel::simple_action<observers::Actions::ContributeVolumeData>(
119  local_observer, observers::ObservationId(time),
120  std::string{"/element_data"},
124  std::move(components), extents);
125 
126  // Send data to reduction observer
127  Parallel::simple_action<observers::Actions::ContributeReductionData>(
128  local_observer, observers::ObservationId(time),
129  std::string{"/element_data"},
130  std::vector<std::string>{"Time", "NumberOfPoints", "UError"},
131  reduction_data{
132  time.value(),
133  db::get<::Tags::Mesh<Dim>>(box).number_of_grid_points(),
134  u_error});
135  }
136  return std::forward_as_tuple(std::move(box));
137  }
138 };
139 } // namespace Actions
140 } // namespace Burgers
Defines class tuples::TaggedTuple.
Defines classes and functions for making classes creatable from input files.
An ID type that identifies both the parallel component and the index in the parallel component...
Definition: ArrayComponentId.hpp:27
decltype(auto) accumulate(const Container &c, T init)
Convenience wrapper around std::accumulate, returns std::accumulate(begin(c), end(c), init).
Definition: Numeric.hpp:54
const char *const OptionString
The string used in option structs.
Definition: Options.hpp:27
Make a string by streaming into object.
Definition: MakeString.hpp:16
Temporary action for observing volume and reduction data.
Definition: Observe.hpp:40
Definition: Observe.hpp:54
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:272
Defines classes and functions used for manipulating DataBox&#39;s.
Functional for computing + of two objects.
Definition: Functional.hpp:234
Definition: InterpolationTargetWedgeSectionTorus.hpp:24
A Charm++ chare that caches constant data once per Charm++ node.
Definition: ConstGlobalCache.hpp:76
The coordinates in a given frame.
Definition: Tags.hpp:95
Can be used to retrieve the analytic solution from the cache without having to know the template para...
Definition: Tags.hpp:12
Stores a collection of function values.
Definition: DataVector.hpp:46
Functional for computing sqrt on an object.
Definition: Functional.hpp:269
Wraps the template metaprogramming library used (brigand)
Defines tags related to domain quantities.
Definition: SolvePoissonProblem.hpp:38
A class for indexing a Charm array by Element.
Definition: ElementIndex.hpp:53
A type-erased identifier that combines the identifier&#39;s type and hash used to uniquely identify an ob...
Definition: ObservationId.hpp:43
Defines class template ConstGlobalCache.
Items related to evolving the Burgers equation .
Definition: Equations.cpp:20
The data to be reduced, and invokables to be called whenever two reduction messages are combined and ...
Definition: Reduction.hpp:64
Defines tags related to Time quantities.
Definition: ComputeTimeDerivative.hpp:28
The array index used for indexing Chare Arrays, mostly an implementation detail.
Definition: ArrayIndex.hpp:20