Item.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <pup.h>
8 #include <utility>
9 
10 #include "DataStructures/DataBox/TagTraits.hpp"
11 #include "Utilities/Gsl.hpp"
12 #include "Utilities/Requires.hpp"
13 
14 /// \cond
15 namespace db::detail {
16 
17 // Used to label the different types of items in a DataBox (which are described
18 // in detail below for each specialization of Item).
19 enum class ItemType { Mutable, Compute, Reference, Invalid };
20 
21 // A unique item in a DataBox labeled by Tag
22 template <typename Tag, ItemType = db::is_mutable_item_tag_v<Tag>
23  ? ItemType::Mutable
24  : (db::is_compute_tag_v<Tag>
25  ? ItemType::Compute
26  : (db::is_reference_tag_v<Tag>
27  ? ItemType::Reference
28  : ItemType::Invalid))>
29 class Item {
30  static_assert(
31  db::is_non_base_tag_v<Tag>,
32  "The Tag of an Item in the Databox must be derived from db::SimpleTag");
33 };
34 
35 // A mutable item in a DataBox
36 //
37 // A mutable item is an item in a DataBox that is initialized when the DataBox
38 // is constructed using either db::create or db::create_from
39 //
40 // Its value may be fetched by calling db::get (which calls get)
41 //
42 // Its value may be changed by calling db::mutate (which calls mutate)
43 template <typename Tag>
44 class Item<Tag, ItemType::Mutable> {
45  public:
46  static constexpr ItemType item_type = ItemType::Mutable;
47 
48  using value_type = typename Tag::type;
49 
50  constexpr Item() = default;
51  constexpr Item(Item const&) = default;
52  constexpr Item(Item&&) = default;
53  constexpr Item& operator=(Item const&) = default;
54  constexpr Item& operator=(Item&&) = default;
55  ~Item() = default;
56 
57  explicit Item(value_type value) noexcept : value_(std::move(value)) {}
58 
59  const value_type& get() const noexcept { return value_; }
60 
61  value_type& mutate() noexcept { return value_; }
62 
63  private:
64  value_type value_{};
65 };
66 
67 // A compute item in a DataBox
68 //
69 // A compute item is an item in a DataBox whose value depends upon other items
70 // in the DataBox. It is lazily evaluated (i.e. not computed until it is
71 // retrieved) and will be reevaluated if any of the items upon which it depends
72 // is changed.
73 //
74 // A compute item is default constructed when the DataBox is constructed.
75 //
76 // When a compute item is fetched via db::get, db::get will check whether it has
77 // already been evaluated (by calling evaluated). If it has been evaluated,
78 // db::get fetches its value (via get). If it has not been evaluated (either
79 // initially or after reset has been called), db::get will call evaluate which
80 // will compute the value using tag::function.
81 //
82 // When db::mutate is called on a mutable item, all compute items that depend
83 // (directly or indirectly) on the mutated item will have their reset function
84 // called.
85 //
86 // A compute item may not be directly mutated (its value only changes after one
87 // of its dependencies changes and it is fetched again)
88 template <typename Tag>
89 class Item<Tag, ItemType::Compute> {
90  public:
91  static constexpr ItemType item_type = ItemType::Compute;
92 
93  using value_type = typename Tag::type;
94 
95  constexpr Item() = default;
96  constexpr Item(Item const&) = default;
97  constexpr Item(Item&&) = default;
98  constexpr Item& operator=(Item const&) = default;
99  constexpr Item& operator=(Item&&) = default;
100  ~Item() = default;
101 
102  const value_type& get() const noexcept { return value_; }
103 
104  bool evaluated() const noexcept { return evaluated_; }
105 
106  void reset() noexcept { evaluated_ = false; }
107 
108  template <typename... Args>
109  void evaluate(const Args&... args) const noexcept {
110  Tag::function(make_not_null(&value_), args...);
111  evaluated_ = true;
112  }
113 
114  // NOLINTNEXTLINE(google-runtime-references)
115  void pup(PUP::er& p) noexcept {
116  p | evaluated_;
117  if (evaluated_) {
118  p | value_;
119  }
120  }
121 
122  private:
123  mutable value_type value_{};
124  mutable bool evaluated_{false};
125 };
126 
127 // A reference item in the DataBox
128 //
129 // A reference item is an item in a DataBox used as a const reference to a
130 // subitem of another item (called the parent item) contained in the DataBox
131 //
132 // Its value may be fetched via db::get (by calling Tag::get directly)
133 //
134 // A reference item cannot be used to mutate its value.
135 template <typename Tag>
136 class Item<Tag, ItemType::Reference> {
137  public:
138  static constexpr ItemType item_type = ItemType::Reference;
139 
140  constexpr Item() = default;
141  constexpr Item(Item const&) = default;
142  constexpr Item(Item&&) = default;
143  constexpr Item& operator=(Item const&) = default;
144  constexpr Item& operator=(Item&&) = default;
145  ~Item() = default;
146 
147  // NOLINTNEXTLINE(google-runtime-references)
148  void pup(PUP::er& /*p*/) noexcept {}
149 };
150 } // namespace db::detail
151 /// \endcond
utility
db::get
const auto & get(const DataBox< TagList > &box) noexcept
Retrieve the item with tag Tag from the DataBox.
Definition: DataBox.hpp:791
TensorExpressions::evaluate
void evaluate(const gsl::not_null< Tensor< X, LhsSymmetry, LhsIndexList > * > lhs_tensor, const TensorExpression< Derived, X, RhsSymmetry, RhsIndexList, tmpl::list< RhsTensorIndices... >> &rhs_tensorexpression)
Evaluate a RHS tensor expression to a tensor with the LHS index order set in the template parameters.
Definition: Evaluate.hpp:153
db::mutate
decltype(auto) mutate(const gsl::not_null< DataBox< TagList > * > box, Invokable &&invokable, Args &&... args) noexcept
Allows changing the state of one or more non-computed elements in the DataBox.
Definition: DataBox.hpp:641
cstddef
Gsl.hpp
Requires.hpp
make_not_null
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,...
Definition: Gsl.hpp:880