1 /** 2 * @file ValueCache.h 3 */ 4 5 // This file is part of Cantera. See License.txt in the top-level directory or 6 // at https://cantera.org/license.txt for license and copyright information. 7 8 #ifndef CT_VALUECACHE_H 9 #define CT_VALUECACHE_H 10 11 #include "ct_defs.h" 12 #include <limits> 13 14 namespace Cantera 15 { 16 17 /*! A cached property value and the state at which it was evaluated 18 * 19 * This struct stores the value of some property evaluated at a particular 20 * thermodynamic state. The #value can be either a real scalar or an array, 21 * depending on the template parameter `T`. The exact meaning of #state1, 22 * #state2, and #stateNum is determined by the function using the cached value, 23 * which can check any combination of these variables before deciding whether 24 * to recompute the cached values. 25 * 26 * References to CachedValue objects are returned by the "get" methods of 27 * ValueCache, e.g. ValueCache::getScalar. Functions accessing cached values 28 * should use the typedefs CachedScalar and CachedArray. See ValueCache for 29 * details on how these classes should be used together. 30 */ 31 template <class T> 32 struct CachedValue { CachedValueCachedValue33 CachedValue() : 34 state1(std::numeric_limits<double>::quiet_NaN()), 35 state2(std::numeric_limits<double>::quiet_NaN()), 36 stateNum(std::numeric_limits<int>::min()), 37 value(T()) 38 { 39 } 40 41 //! Check whether the currently cached value is valid based on 42 //! a single state variable. If it is not valid it updates the stored 43 //! state to the new state in addition to returning false. validateCachedValue44 bool validate(double state1New) { 45 if(state1 == state1New) { 46 return true; 47 } else { 48 state1 = state1New; 49 } 50 return false; 51 } 52 53 //! Check whether the currently cached value is valid based on 54 //! state1 and state2. If it is not valid it updates the stored 55 //! state to the new state in addition to returning false. validateCachedValue56 bool validate(double state1New, double state2New) { 57 if(state1 == state1New && state2 == state2New) { 58 return true; 59 } else { 60 state1 = state1New; 61 state2 = state2New; 62 } 63 return false; 64 } 65 66 //! Check whether the currently cached value is valid based on 67 //! state1 and stateNum. If it is not valid it updates the stored 68 //! state to the new state in addition to returning false. validateCachedValue69 bool validate(double state1New, int stateNumNew) { 70 if(state1 == state1New && stateNum == stateNumNew) { 71 return true; 72 } else { 73 state1 = state1New; 74 stateNum = stateNumNew; 75 } 76 return false; 77 } 78 79 //! Check whether the currently cached value is valid based on 80 //! stateNum. If it is not valid it updates the stored 81 //! state to the new state in addition to returning false. validateCachedValue82 bool validate(int stateNumNew) { 83 if(stateNum == stateNumNew) { 84 return true; 85 } else { 86 stateNum = stateNumNew; 87 } 88 return false; 89 } 90 91 //! Check whether the currently cached value is valid based on 92 //! state1, state2, and stateNum. If it is not valid it updates the stored 93 //! state to the new state in addition to returning false. validateCachedValue94 bool validate(double state1New, double state2New, int stateNumNew) { 95 if(state1 == state1New && state2 == state2New && stateNum == stateNumNew) { 96 return true; 97 } else { 98 state1 = state1New; 99 state2 = state2New; 100 stateNum = stateNumNew; 101 } 102 return false; 103 } 104 105 //! Value of the first state variable for the state at which #value was 106 //! evaluated, e.g. temperature. 107 double state1; 108 109 //! Value of the second state variable for the state at which #value was 110 //! evaluated, e.g. density or pressure. 111 double state2; 112 113 //! A surrogate for the composition. For cached properties of Phase, 114 //! this should be set to Phase::stateMFNumber() 115 int stateNum; 116 117 //! The value of the cached property 118 T value; 119 }; 120 121 typedef CachedValue<double>& CachedScalar; 122 typedef CachedValue<vector_fp>& CachedArray; 123 124 /*! Storage for cached values 125 * 126 * Stores cached values of properties evaluated at a particular thermodynamic 127 * state. A class that needs cached values can have a ValueCache as a 128 * member variable. 129 * 130 * Each method in the class that implements caching behavior needs a unique id 131 * for its cached value. This id should be obtained by using the getId() 132 * function to initialize a static variable within the function. 133 * 134 * For cases where the property is a scalar or vector, the cached value can be 135 * stored in the CachedValue object. If the data type of the cached value is 136 * more complex, then it can be stored in the calling class, and the value 137 * attribute of the CachedScalar object can be ignored. 138 * 139 * An example use of class ValueCache: 140 * @code 141 * class Example { 142 * ValueCache m_cache; 143 * doublereal get_property(doublereal T, doublereal P) { 144 * const static int cacheId = m_cache.getId(); 145 * CachedScalar cached = m_cache.getScalar(cacheId); 146 * if (T != cached.state1 || P != cached.state2) { 147 * cached.value = some_expensive_function(T,P); 148 * cached.state1 = T; 149 * cached.state2 = P; 150 * } 151 * return cached.value; 152 * } 153 * }; 154 * @endcode 155 */ 156 class ValueCache 157 { 158 public: 159 //! Get a unique id for a cached value. Must be called exactly once for each 160 //! method that implements caching behavior. 161 int getId(); 162 163 //! Get a reference to a CachedValue object representing a scalar 164 //! (doublereal) with the given id. getScalar(int id)165 CachedScalar getScalar(int id) { 166 return m_scalarCache[id]; 167 } 168 169 //! Get a reference to a CachedValue object representing an array (vector_fp) 170 //! with the given id. getArray(int id)171 CachedArray getArray(int id) { 172 return m_arrayCache[id]; 173 } 174 175 //! Clear all cached values. This method should be called if the cached 176 //! values may be invalidated in a way that is not represented by the state 177 //! variables alone, such as a change to the constants defining a species 178 //! thermodynamics as a function of temperature. 179 void clear(); 180 181 protected: 182 //! Cached scalar values 183 std::map<int, CachedValue<double> > m_scalarCache; 184 185 //! Cached array values 186 std::map<int, CachedValue<vector_fp> > m_arrayCache; 187 188 //! The last assigned id. Automatically incremented by the getId() method. 189 static int m_last_id; 190 }; 191 192 } 193 194 #endif 195