Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <boost/functional/hash.hpp>
7 : #include <cstddef>
8 : #include <functional>
9 : #include <iosfwd>
10 : #include <limits>
11 : #include <string>
12 : #include <type_traits>
13 :
14 : #include "Utilities/PrettyType.hpp"
15 :
16 : /// \cond
17 : namespace PUP {
18 : class er;
19 : } // namespace PUP
20 : /// \endcond
21 :
22 : namespace observers {
23 : /// \cond
24 : class ObservationId;
25 : /// \endcond
26 :
27 : /// Used as a key in maps to keep track of how many elements have registered.
28 1 : class ObservationKey {
29 : public:
30 0 : ObservationKey() = default;
31 :
32 0 : explicit ObservationKey(std::string tag);
33 :
34 : // NOLINTNEXTLINE(google-runtime-references)
35 0 : void pup(PUP::er& p);
36 :
37 0 : size_t key() const { return key_; }
38 :
39 0 : const std::string& tag() const;
40 :
41 : private:
42 0 : size_t key_{0};
43 0 : std::string tag_{};
44 : };
45 :
46 0 : bool operator==(const ObservationKey& lhs, const ObservationKey& rhs);
47 0 : bool operator!=(const ObservationKey& lhs, const ObservationKey& rhs);
48 :
49 0 : std::ostream& operator<<(std::ostream& os, const ObservationKey& t);
50 :
51 : /*!
52 : * \ingroup ObserversGroup
53 : * \brief A unique identifier for an observation representing the type of
54 : * observation and the instance (e.g. time) at which the observation occurs.
55 : *
56 : * The ObservationId is used to uniquely identify an observation inside our H5
57 : * subfiles that can be agreed upon across the system. That is, it does not
58 : * depend on hardware rounding of floating points because it is an integral. One
59 : * example would be a `Time` for output observed every `N` steps in a global
60 : * time stepping evolution. Another example could be having a counter class for
61 : * dense output observations that increments the counter for each observation
62 : * but has a value equal to the physical time.
63 : *
64 : * The constructor takes a `double` representing the current "time" at which we
65 : * are observing. For an evolution this could be the physical time, while for an
66 : * elliptic solve this could be a combination of nonlinear and linear iteration.
67 : *
68 : * A specialization of `std::hash` is provided to allow using `ObservationId`
69 : * as a key in associative containers.
70 : */
71 1 : class ObservationId {
72 : public:
73 0 : ObservationId() = default;
74 : /*!
75 : * \brief Construct from a value and a string tagging the observation
76 : *
77 : * The tag is a unique string used to identify the particular observation.
78 : */
79 1 : ObservationId(double t, std::string tag);
80 :
81 0 : ObservationId(double t, ObservationKey key);
82 :
83 : /// Hash used to distinguish between ObservationIds of different
84 : /// types and subtypes. This hash does not contain any information about the
85 : /// `Id` or its value.
86 1 : const ObservationKey& observation_key() const { return observation_key_; }
87 :
88 : /// Hash distinguishing different ObservationIds, including
89 : /// the value of the `Id`.
90 1 : size_t hash() const { return combined_hash_; }
91 :
92 : /// The simulation "time".
93 1 : double value() const { return value_; }
94 :
95 : // NOLINTNEXTLINE(google-runtime-references)
96 0 : void pup(PUP::er& p);
97 :
98 : private:
99 0 : ObservationKey observation_key_{};
100 0 : size_t combined_hash_{0};
101 0 : double value_{std::numeric_limits<double>::signaling_NaN()};
102 : };
103 :
104 0 : bool operator==(const ObservationId& lhs, const ObservationId& rhs);
105 0 : bool operator!=(const ObservationId& lhs, const ObservationId& rhs);
106 :
107 0 : std::ostream& operator<<(std::ostream& os, const ObservationId& t);
108 : } // namespace observers
109 :
110 : namespace std {
111 : template <>
112 : struct hash<observers::ObservationId> {
113 : size_t operator()(const observers::ObservationId& t) const {
114 : return t.hash();
115 : }
116 : };
117 :
118 : template <>
119 : struct hash<observers::ObservationKey> {
120 : size_t operator()(const observers::ObservationKey& t) const {
121 : return t.key();
122 : }
123 : };
124 : } // namespace std
|