CoolProp 7.2.0
An open-source fluid property and humid air property database
DataStructures.cpp
Go to the documentation of this file.
1
2
3#include "DataStructures.h"
4#include "Exceptions.h"
5#include "CoolPropTools.h"
6#include "CoolProp.h"
7#include <memory>
8
9namespace CoolProp {
10
12{
13 int key;
15 bool trivial;
16};
17
18const std::vector<parameter_info> parameter_info_list = {
20 {iT, "T", "IO", "K", "Temperature", false},
21 {iP, "P", "IO", "Pa", "Pressure", false},
22 {iDmolar, "Dmolar", "IO", "mol/m^3", "Molar density", false},
23 {iHmolar, "Hmolar", "IO", "J/mol", "Molar specific enthalpy", false},
24 {iSmolar, "Smolar", "IO", "J/mol/K", "Molar specific entropy", false},
25 {iUmolar, "Umolar", "IO", "J/mol", "Molar specific internal energy", false},
26 {iGmolar, "Gmolar", "O", "J/mol", "Molar specific Gibbs energy", false},
27 {iHelmholtzmolar, "Helmholtzmolar", "O", "J/mol", "Molar specific Helmholtz energy", false},
28 {iDmass, "Dmass", "IO", "kg/m^3", "Mass density", false},
29 {iHmass, "Hmass", "IO", "J/kg", "Mass specific enthalpy", false},
30 {iSmass, "Smass", "IO", "J/kg/K", "Mass specific entropy", false},
31 {iUmass, "Umass", "IO", "J/kg", "Mass specific internal energy", false},
32 {iGmass, "Gmass", "O", "J/kg", "Mass specific Gibbs energy", false},
33 {iHelmholtzmass, "Helmholtzmass", "O", "J/kg", "Mass specific Helmholtz energy", false},
34 {iQ, "Q", "IO", "mol/mol", "Molar vapor quality", false},
35 {iDelta, "Delta", "IO", "-", "Reduced density (rho/rhoc)", false},
36 {iTau, "Tau", "IO", "-", "Reciprocal reduced temperature (Tc/T)", false},
38 {iCpmolar, "Cpmolar", "O", "J/mol/K", "Molar specific constant pressure specific heat", false},
39 {iCpmass, "Cpmass", "O", "J/kg/K", "Mass specific constant pressure specific heat", false},
40 {iCvmolar, "Cvmolar", "O", "J/mol/K", "Molar specific constant volume specific heat", false},
41 {iCvmass, "Cvmass", "O", "J/kg/K", "Mass specific constant volume specific heat", false},
42 {iCp0molar, "Cp0molar", "O", "J/mol/K", "Ideal gas molar specific constant pressure specific heat", false},
43 {iCp0mass, "Cp0mass", "O", "J/kg/K", "Ideal gas mass specific constant pressure specific heat", false},
44 {iHmolar_residual, "Hmolar_residual", "O", "J/mol", "Residual molar enthalpy", false},
45 {iSmolar_residual, "Smolar_residual", "O", "J/mol/K", "Residual molar entropy (sr/R = s(T,rho) - s^0(T,rho))", false},
46 {iGmolar_residual, "Gmolar_residual", "O", "J/mol", "Residual molar Gibbs energy", false},
47 {iHmolar_idealgas, "Hmolar_idealgas", "O", "J/mol", "Ideal gas molar enthalpy", false},
48 {iSmolar_idealgas, "Smolar_idealgas", "O", "J/mol/K", "Ideal gas molar entropy", false},
49 {iUmolar_idealgas, "Umolar_idealgas", "O", "J/mol", "Ideal gas molar internal energy", false},
50 {iHmass_idealgas, "Hmass_idealgas", "O", "J/kg", "Ideal gas specific enthalpy", false},
51 {iSmass_idealgas, "Smass_idealgas", "O", "J/kg/K", "Ideal gas specific entropy", false},
52 {iUmass_idealgas, "Umass_idealgas", "O", "J/kg", "Ideal gas specific internal energy", false},
53 {iGWP20, "GWP20", "O", "-", "20-year global warming potential", true},
54 {iGWP100, "GWP100", "O", "-", "100-year global warming potential", true},
55 {iGWP500, "GWP500", "O", "-", "500-year global warming potential", true},
56 {iFH, "FH", "O", "-", "Flammability hazard", true},
57 {iHH, "HH", "O", "-", "Health hazard", true},
58 {iPH, "PH", "O", "-", "Physical hazard", true},
59 {iODP, "ODP", "O", "-", "Ozone depletion potential", true},
60 {iBvirial, "Bvirial", "O", "-", "Second virial coefficient", false},
61 {iCvirial, "Cvirial", "O", "-", "Third virial coefficient", false},
62 {idBvirial_dT, "dBvirial_dT", "O", "-", "Derivative of second virial coefficient with respect to T", false},
63 {idCvirial_dT, "dCvirial_dT", "O", "-", "Derivative of third virial coefficient with respect to T", false},
64 {igas_constant, "gas_constant", "O", "J/mol/K", "Molar gas constant", true},
65 {imolar_mass, "molar_mass", "O", "kg/mol", "Molar mass", true},
66 {iacentric_factor, "acentric", "O", "-", "Acentric factor", true},
67 {idipole_moment, "dipole_moment", "O", "C-m", "Dipole moment", true},
68 {irhomass_reducing, "rhomass_reducing", "O", "kg/m^3", "Mass density at reducing point", true},
69 {irhomolar_reducing, "rhomolar_reducing", "O", "mol/m^3", "Molar density at reducing point", true},
70 {irhomolar_critical, "rhomolar_critical", "O", "mol/m^3", "Molar density at critical point", true},
71 {irhomass_critical, "rhomass_critical", "O", "kg/m^3", "Mass density at critical point", true},
72 {iT_reducing, "T_reducing", "O", "K", "Temperature at the reducing point", true},
73 {iT_critical, "T_critical", "O", "K", "Temperature at the critical point", true},
74 {iT_triple, "T_triple", "O", "K", "Temperature at the triple point", true},
75 {iT_max, "T_max", "O", "K", "Maximum temperature limit", true},
76 {iT_min, "T_min", "O", "K", "Minimum temperature limit", true},
77 {iP_min, "P_min", "O", "Pa", "Minimum pressure limit", true},
78 {iP_max, "P_max", "O", "Pa", "Maximum pressure limit", true},
79 {iP_critical, "p_critical", "O", "Pa", "Pressure at the critical point", true},
80 {iP_reducing, "p_reducing", "O", "Pa", "Pressure at the reducing point", true},
81 {iP_triple, "p_triple", "O", "Pa", "Pressure at the triple point (pure only)", true},
82 {ifraction_min, "fraction_min", "O", "-", "Fraction (mole, mass, volume) minimum value for incompressible solutions", true},
83 {ifraction_max, "fraction_max", "O", "-", "Fraction (mole, mass, volume) maximum value for incompressible solutions", true},
84 {iT_freeze, "T_freeze", "O", "K", "Freezing temperature for incompressible solutions", true},
85
86 {ispeed_sound, "speed_of_sound", "O", "m/s", "Speed of sound", false},
87 {iviscosity, "viscosity", "O", "Pa-s", "Viscosity", false},
88 {iconductivity, "conductivity", "O", "W/m/K", "Thermal conductivity", false},
89 {isurface_tension, "surface_tension", "O", "N/m", "Surface tension", false},
90 {iPrandtl, "Prandtl", "O", "-", "Prandtl number", false},
91
92 {iisothermal_compressibility, "isothermal_compressibility", "O", "1/Pa", "Isothermal compressibility", false},
93 {iisobaric_expansion_coefficient, "isobaric_expansion_coefficient", "O", "1/K", "Isobaric expansion coefficient", false},
94 {iisentropic_expansion_coefficient, "isentropic_expansion_coefficient", "O", "-", "Isentropic expansion coefficient", false},
95 {iZ, "Z", "O", "-", "Compressibility factor", false},
96 {ifundamental_derivative_of_gas_dynamics, "fundamental_derivative_of_gas_dynamics", "O", "-", "Fundamental derivative of gas dynamics", false},
97 {iPIP, "PIP", "O", "-", "Phase identification parameter", false},
98
99 {ialphar, "alphar", "O", "-", "Residual Helmholtz energy", false},
100 {idalphar_dtau_constdelta, "dalphar_dtau_constdelta", "O", "-", "Derivative of residual Helmholtz energy with tau", false},
101 {idalphar_ddelta_consttau, "dalphar_ddelta_consttau", "O", "-", "Derivative of residual Helmholtz energy with delta", false},
102
103 {ialpha0, "alpha0", "O", "-", "Ideal Helmholtz energy", false},
104 {idalpha0_dtau_constdelta, "dalpha0_dtau_constdelta", "O", "-", "Derivative of ideal Helmholtz energy with tau", false},
105 {idalpha0_ddelta_consttau, "dalpha0_ddelta_consttau", "O", "-", "Derivative of ideal Helmholtz energy with delta", false},
106 {id2alpha0_ddelta2_consttau, "d2alpha0_ddelta2_consttau", "O", "-", "Second derivative of ideal Helmholtz energy with delta", false},
107 {id3alpha0_ddelta3_consttau, "d3alpha0_ddelta3_consttau", "O", "-", "Third derivative of ideal Helmholtz energy with delta", false},
108
109 {iPhase, "Phase", "O", "-", "Phase index as a float", false},
110
111};
112
114{
115 public:
116 std::map<int, bool> trivial_map;
117 std::map<int, std::string> short_desc_map, description_map, IO_map, units_map;
118 std::map<std::string, int> index_map;
120 for (auto& el : parameter_info_list) {
121 short_desc_map.insert(std::pair<int, std::string>(el.key, el.short_desc));
122 IO_map.insert(std::pair<int, std::string>(el.key, el.IO));
123 units_map.insert(std::pair<int, std::string>(el.key, el.units));
124 description_map.insert(std::pair<int, std::string>(el.key, el.description));
125 index_map_insert(el.short_desc, el.key);
126 trivial_map.insert(std::pair<int, bool>(el.key, el.trivial));
127 }
128 // Backward compatibility aliases
129 index_map_insert("D", iDmass);
130 index_map_insert("H", iHmass);
131 index_map_insert("M", imolar_mass);
132 index_map_insert("S", iSmass);
133 index_map_insert("U", iUmass);
134 index_map_insert("C", iCpmass);
135 index_map_insert("O", iCvmass);
136 index_map_insert("G", iGmass);
137 index_map_insert("V", iviscosity);
138 index_map_insert("L", iconductivity);
139 index_map_insert("pcrit", iP_critical);
140 index_map_insert("Pcrit", iP_critical);
141 index_map_insert("Tcrit", iT_critical);
142 index_map_insert("Ttriple", iT_triple);
143 index_map_insert("ptriple", iP_triple);
144 index_map_insert("rhocrit", irhomass_critical);
145 index_map_insert("Tmin", iT_min);
146 index_map_insert("Tmax", iT_max);
147 index_map_insert("pmax", iP_max);
148 index_map_insert("pmin", iP_min);
149 index_map_insert("molemass", imolar_mass);
150 index_map_insert("molarmass", imolar_mass);
151 index_map_insert("A", ispeed_sound);
152 index_map_insert("I", isurface_tension);
153 }
154
155 private:
156 void index_map_insert(const std::string& desc, int key) {
157 index_map.insert(std::pair<std::string, int>(desc, key));
158 index_map.insert(std::pair<std::string, int>(upper(desc), key));
159 }
160};
161
162std::unique_ptr<ParameterInformation> parameter_information_p;
165 parameter_information_p = std::make_unique<ParameterInformation>();
166 }
168}
169
170bool is_trivial_parameter(int key) {
171 auto& parameter_information = get_parameter_information();
172 auto it = parameter_information.trivial_map.find(key);
173 if (it != parameter_information.trivial_map.end()) {
174 return it->second;
175 }
176 throw ValueError(format("Unable to match the key [%d: %s] in is_trivial_parameter", key, get_parameter_information(key, "short").c_str()));
177}
178
179std::string get_parameter_information(int key, const std::string& info) {
180 const std::map<int, std::string>* M;
181 auto& parameter_information = get_parameter_information();
182 // Hook up the right map (since they are all of the same type)
183 if (info == "IO") {
184 M = &(parameter_information.IO_map);
185 } else if (info == "short") {
186 M = &(parameter_information.short_desc_map);
187 } else if (info == "long") {
188 M = &(parameter_information.description_map);
189 } else if (info == "units") {
190 M = &(parameter_information.units_map);
191 } else {
192 throw ValueError(format("Bad info string [%s] to get_parameter_information", info.c_str()));
193 }
194
195 auto it = M->find(key);
196 if (it != M->end()) {
197 return it->second;
198 }
199 throw ValueError(format("Unable to match the key [%d] in get_parameter_information for info [%s]", key, info.c_str()));
200}
201
204 auto& parameter_information = get_parameter_information();
205 std::vector<std::string> strings;
206 for (auto& it : parameter_information.index_map) {
207 strings.push_back(it.first);
208 }
209 return strjoin(strings, ",");
210}
211bool is_valid_parameter(const std::string& param_name, parameters& iOutput) {
212 auto& parameter_information = get_parameter_information();
213 // Try to find it
214 std::map<std::string, int>::const_iterator it = parameter_information.index_map.find(param_name);
215 // If equal to end, not found
216 if (it != parameter_information.index_map.end()) {
217 // Found, return it
218 iOutput = static_cast<parameters>(it->second);
219 return true;
220 } else {
221 return false;
222 }
223}
224
225bool is_valid_first_derivative(const std::string& name, parameters& iOf, parameters& iWrt, parameters& iConstant) {
226 if (get_debug_level() > 5) {
227 std::cout << format("is_valid_first_derivative(%s)", name.c_str());
228 }
229 // There should be exactly one /
230 // There should be exactly one |
231
232 // Suppose we start with "d(P)/d(T)|Dmolar"
233 std::vector<std::string> split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "Dmolar"
234 if (split_at_bar.size() != 2) {
235 return false;
236 }
237
238 std::vector<std::string> split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)"
239 if (split_at_slash.size() != 2) {
240 return false;
241 }
242
243 std::size_t i0 = split_at_slash[0].find("(");
244 std::size_t i1 = split_at_slash[0].find(")", i0);
245 if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) {
246 return false;
247 }
248 std::string num = split_at_slash[0].substr(i0 + 1, i1 - i0 - 1);
249
250 i0 = split_at_slash[1].find("(");
251 i1 = split_at_slash[1].find(")", i0);
252 if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) {
253 return false;
254 }
255 std::string den = split_at_slash[1].substr(i0 + 1, i1 - i0 - 1);
256
257 parameters Of, Wrt, Constant;
258 if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && is_valid_parameter(split_at_bar[1], Constant)) {
259 iOf = Of;
260 iWrt = Wrt;
261 iConstant = Constant;
262 return true;
263 } else {
264 return false;
265 }
266}
267
268bool is_valid_first_saturation_derivative(const std::string& name, parameters& iOf, parameters& iWrt) {
269 if (get_debug_level() > 5) {
270 std::cout << format("is_valid_first_saturation_derivative(%s)", name.c_str());
271 }
272 // There should be exactly one /
273 // There should be exactly one |
274
275 // Suppose we start with "d(P)/d(T)|sigma"
276 std::vector<std::string> split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "sigma"
277 if (split_at_bar.size() != 2) {
278 return false;
279 }
280
281 std::vector<std::string> split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)"
282 if (split_at_slash.size() != 2) {
283 return false;
284 }
285
286 std::size_t i0 = split_at_slash[0].find("(");
287 std::size_t i1 = split_at_slash[0].find(")", i0);
288 if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) {
289 return false;
290 }
291 std::string num = split_at_slash[0].substr(i0 + 1, i1 - i0 - 1);
292
293 i0 = split_at_slash[1].find("(");
294 i1 = split_at_slash[1].find(")", i0);
295 if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) {
296 return false;
297 }
298 std::string den = split_at_slash[1].substr(i0 + 1, i1 - i0 - 1);
299
300 parameters Of, Wrt;
301 if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && upper(split_at_bar[1]) == "SIGMA") {
302 iOf = Of;
303 iWrt = Wrt;
304 return true;
305 } else {
306 return false;
307 }
308}
309
310bool is_valid_second_derivative(const std::string& name, parameters& iOf1, parameters& iWrt1, parameters& iConstant1, parameters& iWrt2,
311 parameters& iConstant2) {
312 if (get_debug_level() > 5) {
313 std::cout << format("is_valid_second_derivative(%s)", name.c_str());
314 }
315
316 // Suppose we start with "d(d(P)/d(Dmolar)|T)/d(Dmolar)|T"
317 std::size_t i = name.rfind('|');
318 if ((i == 0) || (i == std::string::npos)) {
319 return false;
320 }
321 std::string constant2 = name.substr(i + 1); // "T"
322 if (!is_valid_parameter(constant2, iConstant2)) {
323 return false;
324 };
325 std::string left_of_bar = name.substr(0, i); // "d(d(P)/d(Dmolar)|T)/d(Dmolar)"
326
327 i = left_of_bar.rfind('/');
328 if ((i == 0) || (i == std::string::npos)) {
329 return false;
330 }
331 std::string left_of_slash = left_of_bar.substr(0, i); // "d(d(P)/d(Dmolar)|T)"
332 std::string right_of_slash = left_of_bar.substr(i + 1); // "d(Dmolar)"
333
334 i = left_of_slash.find("(");
335 std::size_t i1 = left_of_slash.rfind(")");
336 if (!((i > 0) && (i != std::string::npos) && (i1 > (i + 1)) && (i1 != std::string::npos))) {
337 return false;
338 }
339 std::string num = left_of_slash.substr(i + 1, i1 - i - 1); // "d(P)/d(Dmolar)|T"
340 if (!is_valid_first_derivative(num, iOf1, iWrt1, iConstant1)) {
341 return false;
342 }
343
344 i = right_of_slash.find("(");
345 i1 = right_of_slash.rfind(")");
346 if (!((i > 0) && (i != std::string::npos) && (i1 > (i + 1)) && (i1 != std::string::npos))) {
347 return false;
348 }
349 std::string den = right_of_slash.substr(i + 1, i1 - i - 1); // "Dmolar"
350 if (!is_valid_parameter(den, iWrt2)) {
351 return false;
352 }
353
354 // If we haven't quit yet, all is well
355 return true;
356}
357
359{
361 const char *short_desc, *long_desc;
362};
363
365 {iphase_liquid, "phase_liquid", ""},
366 {iphase_gas, "phase_gas", ""},
367 {iphase_twophase, "phase_twophase", ""},
368 {iphase_supercritical, "phase_supercritical", ""},
369 {iphase_supercritical_gas, "phase_supercritical_gas", "p < pc, T > Tc"},
370 {iphase_supercritical_liquid, "phase_supercritical_liquid", "p > pc, T < Tc"},
371 {iphase_critical_point, "phase_critical_point", "p = pc, T = Tc"},
372 {iphase_unknown, "phase_unknown", ""},
373 {iphase_not_imposed, "phase_not_imposed", ""},
374};
375
377{
378 public:
379 std::map<phases, std::string> short_desc_map, long_desc_map;
380 std::map<std::string, phases> index_map;
382 const phase_info* const end = phase_info_list + sizeof(phase_info_list) / sizeof(phase_info_list[0]);
383 for (const phase_info* el = phase_info_list; el != end; ++el) {
384 short_desc_map.insert(std::pair<phases, std::string>(el->key, el->short_desc));
385 long_desc_map.insert(std::pair<phases, std::string>(el->key, el->long_desc));
386 index_map.insert(std::pair<std::string, phases>(el->short_desc, el->key));
387 }
388 }
389};
390
391std::unique_ptr<PhaseInformation> phase_information_p;
393 if (!phase_information_p) {
394 phase_information_p = std::make_unique<PhaseInformation>();
395 }
396 return *phase_information_p;
397}
398
399const std::string& get_phase_short_desc(phases phase) {
400 auto& coolprop_information = get_phase_information();
401 auto iter = coolprop_information.short_desc_map.find(phase);
402 if (iter != coolprop_information.short_desc_map.end()) {
403 return iter->second;
404 }
405 throw ValueError("Cannot find the short phase description.");
406}
407bool is_valid_phase(const std::string& phase_name, phases& iOutput) {
408 auto& phase_information = get_phase_information();
409 // Try to find it
410 std::map<std::string, phases>::const_iterator it = phase_information.index_map.find(phase_name);
411 // If equal to end, not found
412 if (it != phase_information.index_map.end()) {
413 // Found, return it
414 iOutput = static_cast<phases>(it->second);
415 return true;
416 } else {
417 return false;
418 }
419}
420
421phases get_phase_index(const std::string& param_name) {
423 if (is_valid_phase(param_name, iPhase)) {
424 return iPhase;
425 } else {
426 throw ValueError(format("Your input name [%s] is not valid in get_phase_index (names are case sensitive)", param_name.c_str()));
427 }
428}
429
431{
433 std::string short_desc;
434};
435
437 {i1, "1"}, {i2a, "2A"}, {i2b, "2B"}, {i3a, "3A"}, {i3b, "3B"}, {i4a, "4A"}, {i4b, "4B"}, {i4c, "4C"},
438};
439
441{
442 public:
443 std::map<schemes, std::string> short_desc_map;
444 std::map<std::string, schemes> index_map;
446 const scheme_info* const end = scheme_info_list + sizeof(scheme_info_list) / sizeof(scheme_info_list[0]);
447 for (const scheme_info* el = scheme_info_list; el != end; ++el) {
448 short_desc_map.insert(std::pair<schemes, std::string>(el->key, el->short_desc));
449 index_map.insert(std::pair<std::string, schemes>(el->short_desc, el->key));
450 }
451 }
452};
453
454std::unique_ptr<SchemeInformation> scheme_information_p;
457 scheme_information_p = std::make_unique<SchemeInformation>();
458 }
459 return *scheme_information_p;
460}
461
462const std::string& get_scheme_short_desc(schemes scheme) {
463 auto& coolprop_information = get_scheme_information();
464 auto it = coolprop_information.short_desc_map.find(scheme);
465 if (it != coolprop_information.short_desc_map.end()) {
466 return it->second;
467 }
468 throw ValueError("Cannot find the short scheme description.");
469}
470
471bool is_valid_scheme(const std::string& scheme_name, schemes& iOutput) {
472 auto& scheme_information = get_scheme_information();
473 auto it = scheme_information.index_map.find(scheme_name);
474 // If equal to end, not found
475 if (it != scheme_information.index_map.end()) {
476 // Found, return it
477 iOutput = static_cast<schemes>(it->second);
478 return true;
479 } else {
480 return false;
481 }
482}
483
484schemes get_scheme_index(const std::string& scheme_name) {
485 schemes iScheme;
486 if (is_valid_scheme(scheme_name, iScheme)) {
487 return iScheme;
488 } else {
489 throw ValueError(format("Your input name [%s] is not valid in get_scheme_index (names are case sensitive)", scheme_name.c_str()));
490 }
491}
492
493parameters get_parameter_index(const std::string& param_name) {
494 parameters iOutput;
495 if (is_valid_parameter(param_name, iOutput)) {
496 return iOutput;
497 } else {
498 throw ValueError(format("Your input name [%s] is not valid in get_parameter_index (names are case sensitive)", param_name.c_str()));
499 }
500}
501
503{
505 const char *short_desc, *long_desc;
506};
507
509 {QT_INPUTS, "QT_INPUTS", "Molar quality, Temperature in K"},
510 {QSmolar_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/mol/K"},
511 {QSmass_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/kg/K"},
512 {HmolarQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/mol, Molar quality"},
513 {HmassQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/kg, Molar quality"},
514 {DmassQ_INPUTS, "DmassQ_INPUTS", "Molar density kg/m^3, Molar quality"},
515 {DmolarQ_INPUTS, "DmolarQ_INPUTS", "Molar density in mol/m^3, Molar quality"},
516
517 {PQ_INPUTS, "PQ_INPUTS", "Pressure in Pa, Molar quality"},
518
519 {PT_INPUTS, "PT_INPUTS", "Pressure in Pa, Temperature in K"},
520
521 {DmassT_INPUTS, "DmassT_INPUTS", "Mass density in kg/m^3, Temperature in K"},
522 {DmolarT_INPUTS, "DmolarT_INPUTS", "Molar density in mol/m^3, Temperature in K"},
523 {HmassT_INPUTS, "HmassT_INPUTS", "Enthalpy in J/kg, Temperature in K"},
524 {HmolarT_INPUTS, "HmolarT_INPUTS", "Enthalpy in J/mol, Temperature in K"},
525 {SmassT_INPUTS, "SmassT_INPUTS", "Entropy in J/kg/K, Temperature in K"},
526 {SmolarT_INPUTS, "SmolarT_INPUTS", "Entropy in J/mol/K, Temperature in K"},
527 {TUmass_INPUTS, "TUmass_INPUTS", "Temperature in K, Internal energy in J/kg"},
528 {TUmolar_INPUTS, "TUmolar_INPUTS", "Temperature in K, Internal energy in J/mol"},
529
530 {DmassP_INPUTS, "DmassP_INPUTS", "Mass density in kg/m^3, Pressure in Pa"},
531 {DmolarP_INPUTS, "DmolarP_INPUTS", "Molar density in mol/m^3, Pressure in Pa"},
532 {HmassP_INPUTS, "HmassP_INPUTS", "Enthalpy in J/kg, Pressure in Pa"},
533 {HmolarP_INPUTS, "HmolarP_INPUTS", "Enthalpy in J/mol, Pressure in Pa"},
534 {PSmass_INPUTS, "PSmass_INPUTS", "Pressure in Pa, Entropy in J/kg/K"},
535 {PSmolar_INPUTS, "PSmolar_INPUTS", "Pressure in Pa, Entropy in J/mol/K "},
536 {PUmass_INPUTS, "PUmass_INPUTS", "Pressure in Pa, Internal energy in J/kg"},
537 {PUmolar_INPUTS, "PUmolar_INPUTS", "Pressure in Pa, Internal energy in J/mol"},
538
539 {DmassHmass_INPUTS, "DmassHmass_INPUTS", "Mass density in kg/m^3, Enthalpy in J/kg"},
540 {DmolarHmolar_INPUTS, "DmolarHmolar_INPUTS", "Molar density in mol/m^3, Enthalpy in J/mol"},
541 {DmassSmass_INPUTS, "DmassSmass_INPUTS", "Mass density in kg/m^3, Entropy in J/kg/K"},
542 {DmolarSmolar_INPUTS, "DmolarSmolar_INPUTS", "Molar density in mol/m^3, Entropy in J/mol/K"},
543 {DmassUmass_INPUTS, "DmassUmass_INPUTS", "Mass density in kg/m^3, Internal energy in J/kg"},
544 {DmolarUmolar_INPUTS, "DmolarUmolar_INPUTS", "Molar density in mol/m^3, Internal energy in J/mol"},
545
546 {HmassSmass_INPUTS, "HmassSmass_INPUTS", "Enthalpy in J/kg, Entropy in J/kg/K"},
547 {HmolarSmolar_INPUTS, "HmolarSmolar_INPUTS", "Enthalpy in J/mol, Entropy in J/mol/K"},
548 {SmassUmass_INPUTS, "SmassUmass_INPUTS", "Entropy in J/kg/K, Internal energy in J/kg"},
549 {SmolarUmolar_INPUTS, "SmolarUmolar_INPUTS", "Entropy in J/mol/K, Internal energy in J/mol"},
550};
551
553{
554 public:
555 std::map<input_pairs, std::string> short_desc_map, long_desc_map;
556 std::map<std::string, input_pairs> index_map;
558 const input_pair_info* const end = input_pair_list + sizeof(input_pair_list) / sizeof(input_pair_list[0]);
559 for (const input_pair_info* el = input_pair_list; el != end; ++el) {
560 short_desc_map.insert(std::pair<input_pairs, std::string>(el->key, el->short_desc));
561 long_desc_map.insert(std::pair<input_pairs, std::string>(el->key, el->long_desc));
562 index_map.insert(std::pair<std::string, input_pairs>(el->short_desc, el->key));
563 }
564 }
565};
566
567std::unique_ptr<InputPairInformation> input_pair_information_p;
570 input_pair_information_p = std::make_unique<InputPairInformation>();
571 }
573}
574
575input_pairs get_input_pair_index(const std::string& input_pair_name) {
576 auto& coolprop_information = get_input_pair_information();
577 auto it = coolprop_information.index_map.find(input_pair_name);
578 if (it != coolprop_information.index_map.end()) {
579 return it->second;
580 }
581 throw ValueError(format("Your input name [%s] is not valid in get_input_pair_index (names are case sensitive)", input_pair_name.c_str()));
582}
583
584const std::string& get_input_pair_short_desc(input_pairs pair) {
585 auto& coolprop_information = get_input_pair_information();
586 auto it = coolprop_information.short_desc_map.find(pair);
587 if (it != coolprop_information.short_desc_map.end()) {
588 return it->second;
589 }
590 throw ValueError("Cannot find the short input pair description.");
591}
592const std::string& get_input_pair_long_desc(input_pairs pair) {
593 auto& coolprop_information = get_input_pair_information();
594 auto it = coolprop_information.long_desc_map.find(pair);
595 if (it != coolprop_information.long_desc_map.end()) {
596 return it->second;
597 }
598 throw ValueError("Cannot find the long input pair description.");
599}
601 switch (pair) {
602 case QT_INPUTS:
603 p1 = iQ;
604 p2 = iT;
605 break;
606 case QSmolar_INPUTS:
607 p1 = iQ;
608 p2 = iSmolar;
609 break;
610 case QSmass_INPUTS:
611 p1 = iQ;
612 p2 = iSmass;
613 break;
614 case HmolarQ_INPUTS:
615 p1 = iHmolar;
616 p2 = iQ;
617 break;
618 case HmassQ_INPUTS:
619 p1 = iHmass;
620 p2 = iQ;
621 break;
622 case PQ_INPUTS:
623 p1 = iP;
624 p2 = iQ;
625 break;
626 case PT_INPUTS:
627 p1 = iP;
628 p2 = iT;
629 break;
630 case DmassT_INPUTS:
631 p1 = iDmass;
632 p2 = iT;
633 break;
634 case DmolarT_INPUTS:
635 p1 = iDmolar;
636 p2 = iT;
637 break;
638 case HmassT_INPUTS:
639 p1 = iHmass;
640 p2 = iT;
641 break;
642 case HmolarT_INPUTS:
643 p1 = iHmolar;
644 p2 = iT;
645 break;
646 case SmassT_INPUTS:
647 p1 = iSmass;
648 p2 = iT;
649 break;
650 case SmolarT_INPUTS:
651 p1 = iSmolar;
652 p2 = iT;
653 break;
654 case TUmass_INPUTS:
655 p1 = iT;
656 p2 = iUmass;
657 break;
658 case TUmolar_INPUTS:
659 p1 = iT;
660 p2 = iUmolar;
661 break;
662 case DmassP_INPUTS:
663 p1 = iDmass;
664 p2 = iP;
665 break;
666 case DmolarP_INPUTS:
667 p1 = iDmolar;
668 p2 = iP;
669 break;
670 case DmassQ_INPUTS:
671 p1 = iDmass;
672 p2 = iQ;
673 break;
674 case DmolarQ_INPUTS:
675 p1 = iDmolar;
676 p2 = iQ;
677 break;
678 case HmassP_INPUTS:
679 p1 = iHmass;
680 p2 = iP;
681 break;
682 case HmolarP_INPUTS:
683 p1 = iHmolar;
684 p2 = iP;
685 break;
686 case PSmass_INPUTS:
687 p1 = iP;
688 p2 = iSmass;
689 break;
690 case PSmolar_INPUTS:
691 p1 = iP;
692 p2 = iSmolar;
693 break;
694 case PUmass_INPUTS:
695 p1 = iP;
696 p2 = iUmass;
697 break;
698 case PUmolar_INPUTS:
699 p1 = iP;
700 p2 = iUmolar;
701 break;
703 p1 = iDmass;
704 p2 = iHmass;
705 break;
707 p1 = iDmolar;
708 p2 = iHmolar;
709 break;
711 p1 = iDmass;
712 p2 = iSmass;
713 break;
715 p1 = iDmolar;
716 p2 = iSmolar;
717 break;
719 p1 = iDmass;
720 p2 = iUmass;
721 break;
723 p1 = iDmolar;
724 p2 = iUmolar;
725 break;
727 p1 = iHmass;
728 p2 = iSmass;
729 break;
731 p1 = iHmolar;
732 p2 = iSmolar;
733 break;
735 p1 = iSmass;
736 p2 = iUmass;
737 break;
739 p1 = iSmolar;
740 p2 = iUmolar;
741 break;
742 default:
743 throw ValueError(format("Invalid input pair"));
744 }
745}
746
748{
750 std::string name;
751};
752
754{
756 std::string name;
758};
759
760const std::vector<backend_family_info> backend_family_list = {
761 {HEOS_BACKEND_FAMILY, "HEOS"}, {REFPROP_BACKEND_FAMILY, "REFPROP"}, {INCOMP_BACKEND_FAMILY, "INCOMP"}, {IF97_BACKEND_FAMILY, "IF97"},
762 {TREND_BACKEND_FAMILY, "TREND"}, {TTSE_BACKEND_FAMILY, "TTSE"}, {BICUBIC_BACKEND_FAMILY, "BICUBIC"}, {SRK_BACKEND_FAMILY, "SRK"},
763 {PR_BACKEND_FAMILY, "PR"}, {VTPR_BACKEND_FAMILY, "VTPR"}, {PCSAFT_BACKEND_FAMILY, "PCSAFT"}};
764
765const std::vector<backend_info> backend_list = {{HEOS_BACKEND_PURE, "HelmholtzEOSBackend", HEOS_BACKEND_FAMILY},
766 {HEOS_BACKEND_MIX, "HelmholtzEOSMixtureBackend", HEOS_BACKEND_FAMILY},
767 {REFPROP_BACKEND_PURE, "REFPROPBackend", REFPROP_BACKEND_FAMILY},
768 {REFPROP_BACKEND_MIX, "REFPROPMixtureBackend", REFPROP_BACKEND_FAMILY},
769 {INCOMP_BACKEND, "IncompressibleBackend", INCOMP_BACKEND_FAMILY},
770 {IF97_BACKEND, "IF97Backend", IF97_BACKEND_FAMILY},
771 {TREND_BACKEND, "TRENDBackend", TREND_BACKEND_FAMILY},
772 {TTSE_BACKEND, "TTSEBackend", TTSE_BACKEND_FAMILY},
773 {BICUBIC_BACKEND, "BicubicBackend", BICUBIC_BACKEND_FAMILY},
774 {SRK_BACKEND, "SRKBackend", SRK_BACKEND_FAMILY},
775 {PR_BACKEND, "PengRobinsonBackend", PR_BACKEND_FAMILY},
776 {VTPR_BACKEND, "VTPRBackend", VTPR_BACKEND_FAMILY},
777 {PCSAFT_BACKEND, "PCSAFTBackend", PCSAFT_BACKEND_FAMILY}};
778
780{
781 public:
782 std::map<backend_families, std::string> family_name_map;
783 std::map<backends, backend_families> backend_family_map;
784 std::map<backends, std::string> backend_name_map;
785
786 std::map<std::string, backend_families> family_name_map_r;
787 std::map<std::string, backends> backend_name_map_r;
788
790 for (auto& el : backend_family_list) {
791 family_name_map.insert(std::pair<backend_families, std::string>(el.family, el.name));
792 family_name_map_r.insert(std::pair<std::string, backend_families>(el.name, el.family));
793 }
794 for (auto& el : backend_list) {
795 backend_family_map.insert(std::pair<backends, backend_families>(el.backend, el.family));
796 backend_name_map.insert(std::pair<backends, std::string>(el.backend, el.name));
797 backend_name_map_r.insert(std::pair<std::string, backends>(el.name, el.backend));
798 family_name_map_r.insert(std::pair<std::string, backend_families>(el.name, el.family));
799 }
800 }
801};
802
803std::unique_ptr<BackendInformation> backend_information_p;
806 backend_information_p = std::make_unique<BackendInformation>();
807 }
808 return *backend_information_p;
809}
810
812void extract_backend_families(std::string backend_string, backend_families& f1, backend_families& f2) {
813 auto& backend_information = get_backend_information();
816 std::size_t i = backend_string.find("&");
817 std::map<std::string, backend_families>::const_iterator it;
818 if (i != std::string::npos) {
819 it = backend_information.family_name_map_r.find(backend_string.substr(0, i)); // Before "&"
820 if (it != backend_information.family_name_map_r.end()) f1 = it->second;
821 it = backend_information.family_name_map_r.find(backend_string.substr(i + 1)); // After "&"
822 if (it != backend_information.family_name_map_r.end()) f2 = it->second;
823 } else {
824 it = backend_information.family_name_map_r.find(backend_string);
825 if (it != backend_information.family_name_map_r.end()) f1 = it->second;
826 }
827}
828
829void extract_backend_families_string(std::string backend_string, backend_families& f1, std::string& f2) {
830 auto& backend_information = get_backend_information();
831 backend_families f2_enum;
832 extract_backend_families(backend_string, f1, f2_enum);
833 std::map<backend_families, std::string>::const_iterator it;
834 it = backend_information.family_name_map.find(f2_enum);
835 if (it != backend_information.family_name_map.end())
836 f2 = it->second;
837 else
838 f2.clear();
839}
840
841std::string get_backend_string(backends backend) {
842 auto& backend_information = get_backend_information();
843 std::map<backends, std::string>::const_iterator it;
844 it = backend_information.backend_name_map.find(backend);
845 if (it != backend_information.backend_name_map.end())
846 return it->second;
847 else
848 return std::string("");
849}
850
851} /* namespace CoolProp */
852
853#ifdef ENABLE_CATCH
854# include <catch2/catch_all.hpp>
855# include <sstream>
856
857TEST_CASE("Check that csv list of parameters is possible", "[parameter_list]") {
858 CHECK_NOTHROW(CoolProp::get_csv_parameter_list());
859}
860
861TEST_CASE("Check that all parameters are described", "") {
862 for (int i = 1; i < CoolProp::iundefined_parameter; ++i) {
863 std::ostringstream ss;
864 ss << "Parameter index," << i << "last index:" << CoolProp::iundefined_parameter;
865 SECTION(ss.str(), "") {
866 std::string prior;
867 if (i > 1) {
868 CHECK_NOTHROW(prior = CoolProp::get_parameter_information(i - 1, "short"));
869 CAPTURE(prior);
870 }
871 CHECK_NOTHROW(CoolProp::get_parameter_information(i, "short"));
872 }
873 }
874}
875
876TEST_CASE("Check that all phases are described", "[phase_index]") {
877 for (int i = 0; i < CoolProp::iphase_not_imposed; ++i) {
878 std::ostringstream ss;
879 ss << "Parameter index," << i << "last index:" << CoolProp::iundefined_parameter;
880 SECTION(ss.str(), "") {
881 std::string stringrepr;
882 int key;
883 CHECK_NOTHROW(stringrepr = CoolProp::get_phase_short_desc(static_cast<CoolProp::phases>(i)));
884 CAPTURE(stringrepr);
885 CHECK_NOTHROW(key = CoolProp::get_phase_index(stringrepr));
886 CAPTURE(key);
887 CHECK(key == i);
888 }
889 }
890}
891
892#endif