CachedTempBuffer.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <utility> // IWYU pragma: keep // for std::move
8 
9 #include "DataStructures/TempBuffer.hpp"
10 #include "Utilities/Gsl.hpp"
11 #include "Utilities/TMPL.hpp"
12 #include "Utilities/TaggedTuple.hpp"
13 
14 /*!
15  * \ingroup DataStructuresGroup
16  * A temporary buffer with contents computed on demand.
17  *
18  * When an entry in the buffer is first requested, it is computed by
19  * the `Computer` class. Subsequent requests just return the cached
20  * value. The computer can itself request data from the cache to use
21  * in its computations.
22  *
23  * For the cache
24  * \snippet Test_CachedTempBuffer.cpp alias
25  * the function used to compute `Tags::Scalar2<DataType>` is
26  * \snippet Test_CachedTempBuffer.cpp compute_func
27  */
28 template <typename Computer, typename... Tags>
30  public:
31  using tags_list = tmpl::list<Tags...>;
32 
33  /// Construct the buffer with the given computer. `size` is passed
34  /// to the underlying `TempBuffer` constructor.
35  CachedTempBuffer(const size_t size, Computer computer) noexcept
36  : data_(size), computer_(std::move(computer)) {}
37 
38  /// Obtain a value from the buffer, computing it if necessary.
39  template <typename Tag>
40  const typename Tag::type& get_var(Tag /*meta*/) noexcept {
41  static_assert(tmpl::list_contains_v<tmpl::list<Tags...>, Tag>,
42  "The requested tag is not available. See the template "
43  "parameters of 'CachedTempBuffer' for the computer type and "
44  "the available tags, and the template parameter of the "
45  "'get_var' function for the requested tag.");
46  // This function can't be called "get" because that interferes
47  // with the ADL needed to access data_.
48  if (not get<Computed<Tag>>(computed_flags_)) {
49  computer_(make_not_null(&get<Tag>(data_)), make_not_null(this), Tag{});
50  get<Computed<Tag>>(computed_flags_) = true;
51  }
52  return get<Tag>(data_);
53  }
54 
55  private:
56  template <typename Tag>
57  struct Computed {
58  using type = bool;
59  };
60 
61  TempBuffer<tmpl::list<Tags...>> data_;
62  tuples::TaggedTuple<Computed<Tags>...> computed_flags_{
63  ((void)Tags{}, false)...};
64  Computer computer_;
65 };
66 
67 namespace CachedTempBuffer_detail {
68 template <typename Computer, typename Tags>
69 struct CachedTempBufferFromTypelistImpl;
70 template <typename Computer, typename... Tags>
71 struct CachedTempBufferFromTypelistImpl<Computer, tmpl::list<Tags...>> {
72  using type = CachedTempBuffer<Computer, Tags...>;
73 };
74 } // namespace CachedTempBuffer_detail
75 
76 /// Instantiate a `CachedTempBuffer` from a typelist instead of a parameter pack
77 template <typename Computer, typename Tags>
78 using cached_temp_buffer_from_typelist =
79  typename CachedTempBuffer_detail::CachedTempBufferFromTypelistImpl<
80  Computer, Tags>::type;
utility
db::get
const auto & get(const DataBox< TagList > &box) noexcept
Retrieve the item with tag Tag from the DataBox.
Definition: DataBox.hpp:791
CachedTempBuffer::get_var
const Tag::type & get_var(Tag) noexcept
Obtain a value from the buffer, computing it if necessary.
Definition: CachedTempBuffer.hpp:40
cstddef
CachedTempBuffer
Definition: CachedTempBuffer.hpp:29
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
Gsl.hpp
CachedTempBuffer::CachedTempBuffer
CachedTempBuffer(const size_t size, Computer computer) noexcept
Construct the buffer with the given computer. size is passed to the underlying TempBuffer constructor...
Definition: CachedTempBuffer.hpp:35
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
TempBuffer
A TempBuffer holds a set of Tensor<DataType>s, where DataType is either a DataVector (or similar type...
Definition: TempBuffer.hpp:30
TMPL.hpp