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