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