CoolProp 6.8.0
An open-source fluid property and humid air property database
Configuration.h
Go to the documentation of this file.
1#ifndef COOLPROP_CONFIGURATION
2#define COOLPROP_CONFIGURATION
3
4#include "Exceptions.h"
5#include "CoolPropTools.h"
6#include <cstdlib>
7
8#if !defined(SWIG) // Hide this for swig - Swig gets confused
9# include "rapidjson_include.h"
10#endif
11
12/* See http://stackoverflow.com/a/148610
13 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511
14 * This will be used to generate an enum like:
15 * enum configuration_keys {NORMALIZE_GAS_CONSTANTS, CRITICAL_SPLINES_ENABLED};
16 *
17 * The values in this list are given by:
18 * enum, string representation of enum, default value, description
19 *
20 * The type of the default value specifies the only type that will be accepted for this parameter
21 */
22#define CONFIGURATION_KEYS_ENUM \
23 X(NORMALIZE_GAS_CONSTANTS, "NORMALIZE_GAS_CONSTANTS", true, "If true, for mixtures, the molar gas constant (R) will be set to the CODATA value") \
24 X(CRITICAL_WITHIN_1UK, "CRITICAL_WITHIN_1UK", true, \
25 "If true, any temperature within 1 uK of the critical temperature will be considered to be AT the critical point") \
26 X(CRITICAL_SPLINES_ENABLED, "CRITICAL_SPLINES_ENABLED", true, \
27 "If true, the critical splines will be used in the near-vicinity of the critical point") \
28 X(SAVE_RAW_TABLES, "SAVE_RAW_TABLES", false, "If true, the raw, uncompressed tables will also be written to file") \
29 X(ALTERNATIVE_TABLES_DIRECTORY, "ALTERNATIVE_TABLES_DIRECTORY", "", \
30 "If provided, this path will be the root directory for the tabular data. Otherwise, ${HOME}/.CoolProp/Tables is used") \
31 X(ALTERNATIVE_REFPROP_PATH, "ALTERNATIVE_REFPROP_PATH", "", \
32 "An alternative path to be provided to the directory that contains REFPROP's fluids and mixtures directories. If provided, the SETPATH " \
33 "function will be called with this directory prior to calling any REFPROP functions.") \
34 X(ALTERNATIVE_REFPROP_HMX_BNC_PATH, "ALTERNATIVE_REFPROP_HMX_BNC_PATH", "", \
35 "An alternative path to the HMX.BNC file. If provided, it will be passed into REFPROP's SETUP or SETMIX routines") \
36 X(ALTERNATIVE_REFPROP_LIBRARY_PATH, "ALTERNATIVE_REFPROP_LIBRARY_PATH", "", \
37 "An alternative path to the shared library file. If provided, it will be used to load REFPROP") \
38 X(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS, "REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS", false, \
39 "If true, if the binary interaction parameters in REFPROP are estimated, throw an error rather than silently continuing") \
40 X(REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS, "REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS", false, \
41 "If true, if the binary interaction parameters in REFPROP are unable to be estimated, silently continue rather than failing") \
42 X(REFPROP_USE_GERG, "REFPROP_USE_GERG", false, \
43 "If true, rather than using the highly-accurate pure fluid equations of state, use the pure-fluid EOS from GERG-2008") \
44 X(REFPROP_ERROR_THRESHOLD, "REFPROP_ERROR_THRESHOLD", static_cast<int>(0), "The highest acceptable error code without throwing an exception") \
45 X(REFPROP_USE_PENGROBINSON, "REFPROP_USE_PENGROBINSON", false, \
46 "If true, rather than using the highly-accurate pure fluid equations of state, use the Peng-Robinson EOS") \
47 X(MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB, "MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB", 1.0, \
48 "The maximum allowed size of the directory that is used to store tabular data") \
49 X(DONT_CHECK_PROPERTY_LIMITS, "DONT_CHECK_PROPERTY_LIMITS", false, \
50 "If true, when possible, CoolProp will skip checking whether values are inside the property limits") \
51 X(HENRYS_LAW_TO_GENERATE_VLE_GUESSES, "HENRYS_LAW_TO_GENERATE_VLE_GUESSES", false, \
52 "If true, when doing water-based mixture dewpoint calculations, use Henry's Law to generate guesses for liquid-phase composition") \
53 X(PHASE_ENVELOPE_STARTING_PRESSURE_PA, "PHASE_ENVELOPE_STARTING_PRESSURE_PA", 100.0, "Starting pressure [Pa] for phase envelope construction") \
54 X(R_U_CODATA, "R_U_CODATA", 8.3144598, \
55 "The value for the ideal gas constant in J/mol/K according to CODATA 2014. This value is used to harmonize all the ideal gas constants. " \
56 "This is especially important in the critical region.") \
57 X(VTPR_UNIFAC_PATH, "VTPR_UNIFAC_PATH", "", "The path to the directory containing the UNIFAC JSON files. Should be slash terminated") \
58 X(SPINODAL_MINIMUM_DELTA, "SPINODAL_MINIMUM_DELTA", 0.5, \
59 "The minimal delta to be used in tracing out the spinodal; make sure that the EOS has a spinodal at this value of delta=rho/rho_r") \
60 X(OVERWRITE_FLUIDS, "OVERWRITE_FLUIDS", false, \
61 "If true, and a fluid is added to the fluids library that is already there, rather than not adding the fluid (and probably throwing an " \
62 "exception), overwrite it") \
63 X(OVERWRITE_DEPARTURE_FUNCTION, "OVERWRITE_DEPARTURE_FUNCTION", false, \
64 "If true, and a departure function to be added is already there, rather than not adding the departure function (and probably throwing an " \
65 "exception), overwrite it") \
66 X(OVERWRITE_BINARY_INTERACTION, "OVERWRITE_BINARY_INTERACTION", false, \
67 "If true, and a pair of binary interaction pairs to be added is already there, rather than not adding the binary interaction pair (and " \
68 "probably throwing an exception), overwrite it") \
69 X(USE_GUESSES_IN_PROPSSI, "USE_GUESSES_IN_PROPSSI", false, \
70 "If true, calls to the vectorized versions of PropsSI use the previous state as guess value while looping over the input vectors, only makes " \
71 "sense when working with a single fluid and with points that are not too far from each other.") \
72 X(ASSUME_CRITICAL_POINT_STABLE, "ASSUME_CRITICAL_POINT_STABLE", false, \
73 "If true, evaluation of the stability of critical point will be skipped and point will be assumed to be stable") \
74 X(VTPR_ALWAYS_RELOAD_LIBRARY, "VTPR_ALWAYS_RELOAD_LIBRARY", false, \
75 "If true, the library will always be reloaded, no matter what is currently loaded") \
76 X(FLOAT_PUNCTUATION, "FLOAT_PUNCTUATION", ".", "The first character of this string will be used as the separator between the number fraction.") \
77 X(LIST_STRING_DELIMITER, "LIST_STRING_DELIMITER", ",", "The delimiter to be used when converting a list of strings to a string")
78
79// Use preprocessor to create the Enum
81{
82#define X(Enum, String, Default, Desc) Enum,
84#undef X
85};
86
87// Evidently SWIG+MATLAB cannot properly wrap enums within classes
89{
96};
97
98namespace CoolProp {
99
102
104configuration_keys config_string_to_key(const std::string& s);
105
108
110std::string config_key_description(const std::string& key);
111
115{
116 public:
117 ConfigurationDataTypes get_type() const { return type; }
118
120 operator bool() const {
121 check_data_type(CONFIGURATION_BOOL_TYPE);
122 return v_bool;
123 };
125 operator double() const {
126 check_data_type(CONFIGURATION_DOUBLE_TYPE);
127 return v_double;
128 };
130 operator std::string() const {
131 check_data_type(CONFIGURATION_STRING_TYPE);
132 return v_string;
133 };
135 operator int() const {
136 check_data_type(CONFIGURATION_INTEGER_TYPE);
137 return v_integer;
138 };
139 // Initializer for bool
141 this->key = key;
143 v_bool = val;
144 };
145 // Initializer for integer
147 this->key = key;
149 v_integer = val;
150 };
151 // Initializer for double
153 this->key = key;
155 v_double = val;
156 };
157 // Initializer for const char *
158 ConfigurationItem(configuration_keys key, const char* val) {
159 this->key = key;
161 v_string = val;
162 };
163 // Initializer for string
164 ConfigurationItem(configuration_keys key, const std::string& val) {
165 this->key = key;
167 v_string = val;
168 };
169 void set_bool(bool val) {
170 check_data_type(CONFIGURATION_BOOL_TYPE);
171 v_bool = val;
172 }
173 void set_integer(int val) {
174 check_data_type(CONFIGURATION_INTEGER_TYPE);
175 v_integer = val;
176 }
177 void set_double(double val) {
178 check_data_type(CONFIGURATION_DOUBLE_TYPE);
179 v_double = val;
180 }
181 void set_string(const std::string& val) {
182 check_data_type(CONFIGURATION_STRING_TYPE);
183 v_string = val;
184 }
185
187 return this->key;
188 }
189#if !defined(SWIG)
191 void add_to_json(rapidjson::Value& val, rapidjson::Document& d) const {
192 std::string name_string = config_key_to_string(key);
193 rapidjson::Value name(name_string.c_str(), d.GetAllocator());
194 switch (type) {
196 rapidjson::Value v(v_bool);
197 val.AddMember(name, v, d.GetAllocator());
198 break;
199 }
201 rapidjson::Value v(v_integer);
202 val.AddMember(name, v, d.GetAllocator());
203 break;
204 }
206 rapidjson::Value v(v_double); // Try to upcast
207 val.AddMember(name, v, d.GetAllocator());
208 break;
209 }
211 rapidjson::Value v(v_string.c_str(), d.GetAllocator());
212 val.AddMember(name, v, d.GetAllocator());
213 break;
214 }
217 throw ValueError();
218 }
219 }
220 void set_from_json(rapidjson::Value& val) {
221 switch (type) {
223 if (!val.IsBool()) {
224 throw ValueError(format("Input is not boolean"));
225 };
226 v_bool = val.GetBool();
227 break;
229 if (!val.IsInt()) {
230 throw ValueError(format("Input is not integer"));
231 };
232 v_integer = val.GetInt();
233 break;
235 if (!val.IsDouble() && !val.IsInt()) {
236 throw ValueError(format("Input [%s] is not double (or something that can be cast to double)", cpjson::to_string(val).c_str()));
237 };
238 if (val.IsDouble()) {
239 v_double = val.GetDouble();
240 } else {
241 v_double = static_cast<double>(val.GetInt());
242 }
243 break;
244 }
246 if (!val.IsString()) {
247 throw ValueError(format("Input is not string"));
248 };
249 v_string = val.GetString();
250 break;
253 throw ValueError();
254 }
255 }
256#endif // !defined(SWIG)
257
258 private:
259 void check_data_type(ConfigurationDataTypes type) const {
260 if (type != this->type) {
261 throw ValueError(format("type does not match"));
262 }
263 };
265 union
266 {
267 double v_double;
268 bool v_bool;
270 };
271 std::string v_string;
273};
274
276{
277 protected:
278 std::map<configuration_keys, ConfigurationItem> items;
279
280 public:
282 set_defaults();
283 };
285
288 // Try to find it
289 std::map<configuration_keys, ConfigurationItem>::iterator it = items.find(key);
290 // If equal to end, not found
291 if (it != items.end()) {
292 // Found, return it
293 return it->second;
294 } else {
295 throw ValueError(format("invalid item"));
296 }
297 }
300 std::pair<configuration_keys, ConfigurationItem> pair(item.get_key(), item);
301 items.insert(pair);
302 };
303
305 std::map<configuration_keys, ConfigurationItem>& get_items(void) {
306 return items;
307 };
308
311 std::string envkey = "COOLPROP_" + config_key_to_string(key);
312 const char *envval = std::getenv(envkey.c_str());
313 if (envval){
314 auto tobool = [](const std::string x){
315 if (x == "True" || x == "true"){ return true;}
316 if (x == "False" || x == "false"){ return false;}
317 throw ValueError(x);
318 };
319 switch (get_item(key).get_type()){
321 items.erase(key); items.emplace(key, ConfigurationItem(key, std::string(envval)));
322 break;
324 int i;
325 try{
326 i = std::stoi(envval);
327 }
328 catch(...){
329 auto skey = config_key_to_string(key);
330 std::string msg = "Unable to convert \""+std::string(envval)+"\" to int for key ["+skey+"]";
331 std::cerr << msg << std::endl;
332 throw ValueError(msg);
333 }
334 items.erase(key); items.emplace(key, ConfigurationItem(key, i));
335 break;
337 int d;
338 try{
339 d = std::stod(envval);
340 }
341 catch(...){
342 auto skey = config_key_to_string(key);
343 std::string msg = "Unable to convert \""+std::string(envval)+"\" to double for key ["+skey+"]";
344 std::cerr << msg << std::endl;
345 throw ValueError(msg);
346 }
347 items.erase(key); items.emplace(key, ConfigurationItem(key, d));
348 break;
350 int b;
351 try{
352 b = tobool(envval);
353 }
354 catch(...){
355 auto skey = config_key_to_string(key);
356 std::string msg = "Unable to convert \""+std::string(envval)+"\" to bool for key ["+skey+"]";
357 std::cerr << msg << std::endl;
358 throw ValueError(msg);
359 }
360 items.erase(key); items.emplace(key, ConfigurationItem(key, b));
361 break;
362 default:
363 auto skey = config_key_to_string(key);
364 throw ValueError("This key ["+skey+"] has the wrong type; value was "+std::string(envval)+" ");
365 }
366 return true;
367 }
368 return false;
369 }
370
372 void set_defaults(void) {
373/* ***MAGIC WARNING**!!
374 * See http://stackoverflow.com/a/148610
375 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511
376 */
377#define X(Enum, String, Default, Desc) add_item(ConfigurationItem(Enum, Default));
379#undef X
380
381 // See if the variable is already present as environment variable
382#define X(Enum, String, Default, Desc) possibly_set_from_env(Enum);
384#undef X
385
386 };
387};
388
392
401#if !defined(SWIG) // Hide this for swig - Swig gets confused
402void get_config_as_json(rapidjson::Document& doc);
403#endif
405std::string get_config_as_json_string();
406
410
412void set_config_bool(configuration_keys key, bool val);
414void set_config_int(configuration_keys key, int val);
416void set_config_double(configuration_keys key, double val);
418void set_config_string(configuration_keys key, const std::string& val);
420#if !defined(SWIG) // Hide this for swig - Swig gets confused
421void set_config_json(rapidjson::Document& doc);
422#endif
424void set_config_as_json_string(const std::string& s);
425} // namespace CoolProp
426
427#endif // COOLPROP_CONFIGURATION