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