CoolProp
FluidLibrary.h
1 
2 #ifndef FLUIDLIBRARY_H
3 #define FLUIDLIBRARY_H
4 
5 #include "CoolPropFluid.h"
6 
7 #include "rapidjson_include.h"
8 #include "crossplatform_shared_ptr.h"
9 
10 #include <map>
11 #include <algorithm>
12 #include "Configuration.h"
13 #include "Backends/Cubics/CubicsLibrary.h"
14 #include "Helmholtz.h"
15 
16 namespace CoolProp {
17 
18 // Forward declaration of the necessary debug function to avoid including the whole header
19 extern int get_debug_level();
20 
22 
28 {
30  std::map<std::size_t, CoolPropFluid> fluid_map;
32  std::map<std::size_t, std::string> JSONstring_map;
33  std::vector<std::string> name_vector;
34  std::map<std::string, std::size_t> string_to_index_map;
35  bool _is_empty;
36 
37  public:
39  static ResidualHelmholtzContainer parse_alphar(rapidjson::Value& jsonalphar) {
41 
42  for (rapidjson::Value::ValueIterator itr = jsonalphar.Begin(); itr != jsonalphar.End(); ++itr) {
43  // A reference for code cleanness
44  rapidjson::Value& contribution = *itr;
45 
46  // Get the type (required!)
47  std::string type = contribution["type"].GetString();
48 
49  if (!type.compare("ResidualHelmholtzPower")) {
50  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
51  std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
52  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
53  std::vector<CoolPropDbl> l = cpjson::get_long_double_array(contribution["l"]);
54  assert(n.size() == d.size());
55  assert(n.size() == t.size());
56  assert(n.size() == l.size());
57 
58  alphar.GenExp.add_Power(n, d, t, l);
59  } else if (!type.compare("ResidualHelmholtzGaussian")) {
60  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
61  std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
62  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
63  std::vector<CoolPropDbl> eta = cpjson::get_long_double_array(contribution["eta"]);
64  std::vector<CoolPropDbl> epsilon = cpjson::get_long_double_array(contribution["epsilon"]);
65  std::vector<CoolPropDbl> beta = cpjson::get_long_double_array(contribution["beta"]);
66  std::vector<CoolPropDbl> gamma = cpjson::get_long_double_array(contribution["gamma"]);
67  assert(n.size() == d.size());
68  assert(n.size() == t.size());
69  assert(n.size() == eta.size());
70  assert(n.size() == epsilon.size());
71  assert(n.size() == beta.size());
72  assert(n.size() == gamma.size());
73  alphar.GenExp.add_Gaussian(n, d, t, eta, epsilon, beta, gamma);
74  } else if (!type.compare("ResidualHelmholtzGaoB")) {
75  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
76  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
77  std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
78  std::vector<CoolPropDbl> eta = cpjson::get_long_double_array(contribution["eta"]);
79  std::vector<CoolPropDbl> beta = cpjson::get_long_double_array(contribution["beta"]);
80  std::vector<CoolPropDbl> gamma = cpjson::get_long_double_array(contribution["gamma"]);
81  std::vector<CoolPropDbl> epsilon = cpjson::get_long_double_array(contribution["epsilon"]);
82  std::vector<CoolPropDbl> b = cpjson::get_long_double_array(contribution["b"]);
83  assert(n.size() == t.size());
84  assert(n.size() == d.size());
85  assert(n.size() == eta.size());
86  assert(n.size() == epsilon.size());
87  assert(n.size() == beta.size());
88  assert(n.size() == gamma.size());
89  assert(n.size() == b.size());
90  alphar.GaoB = ResidualHelmholtzGaoB(n, t, d, eta, beta, gamma, epsilon, b);
91  } else if (!type.compare("ResidualHelmholtzNonAnalytic")) {
92  if (alphar.NonAnalytic.N > 0) {
93  throw ValueError("Cannot add ");
94  }
95  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
96  std::vector<CoolPropDbl> a = cpjson::get_long_double_array(contribution["a"]);
97  std::vector<CoolPropDbl> b = cpjson::get_long_double_array(contribution["b"]);
98  std::vector<CoolPropDbl> beta = cpjson::get_long_double_array(contribution["beta"]);
99  std::vector<CoolPropDbl> A = cpjson::get_long_double_array(contribution["A"]);
100  std::vector<CoolPropDbl> B = cpjson::get_long_double_array(contribution["B"]);
101  std::vector<CoolPropDbl> C = cpjson::get_long_double_array(contribution["C"]);
102  std::vector<CoolPropDbl> D = cpjson::get_long_double_array(contribution["D"]);
103  assert(n.size() == a.size());
104  assert(n.size() == b.size());
105  assert(n.size() == beta.size());
106  assert(n.size() == A.size());
107  assert(n.size() == B.size());
108  assert(n.size() == C.size());
109  assert(n.size() == D.size());
110  alphar.NonAnalytic = ResidualHelmholtzNonAnalytic(n, a, b, beta, A, B, C, D);
111  } else if (!type.compare("ResidualHelmholtzLemmon2005")) {
112  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
113  std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
114  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
115  std::vector<CoolPropDbl> l = cpjson::get_long_double_array(contribution["l"]);
116  std::vector<CoolPropDbl> m = cpjson::get_long_double_array(contribution["m"]);
117  assert(n.size() == d.size());
118  assert(n.size() == t.size());
119  assert(n.size() == l.size());
120  assert(n.size() == m.size());
121  alphar.GenExp.add_Lemmon2005(n, d, t, l, m);
122  } else if (!type.compare("ResidualHelmholtzExponential")) {
123  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
124  std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
125  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
126  std::vector<CoolPropDbl> g = cpjson::get_long_double_array(contribution["g"]);
127  std::vector<CoolPropDbl> l = cpjson::get_long_double_array(contribution["l"]);
128  assert(n.size() == d.size());
129  assert(n.size() == t.size());
130  assert(n.size() == g.size());
131  assert(n.size() == l.size());
132  alphar.GenExp.add_Exponential(n, d, t, g, l);
133  } else if (!type.compare("ResidualHelmholtzAssociating")) {
134  if (alphar.SAFT.disabled == false) {
135  throw ValueError("Cannot add ");
136  }
137  CoolPropDbl a = cpjson::get_double(contribution, "a");
138  CoolPropDbl m = cpjson::get_double(contribution, "m");
139  CoolPropDbl epsilonbar = cpjson::get_double(contribution, "epsilonbar");
140  CoolPropDbl vbarn = cpjson::get_double(contribution, "vbarn");
141  CoolPropDbl kappabar = cpjson::get_double(contribution, "kappabar");
142  alphar.SAFT = ResidualHelmholtzSAFTAssociating(a, m, epsilonbar, vbarn, kappabar);
143  } else {
144  throw ValueError(format("Unsupported Residual helmholtz type: %s", type.c_str()));
145  }
146  }
147 
148  // Finish adding parts to the Generalized Exponential term, build other vectors
149  alphar.GenExp.finish();
150 
151  return alphar;
152  };
153 
155  static IdealHelmholtzContainer parse_alpha0(rapidjson::Value& jsonalpha0) {
156  if (!jsonalpha0.IsArray()) {
157  throw ValueError();
158  }
159 
161 
162  for (rapidjson::Value::ConstValueIterator itr = jsonalpha0.Begin(); itr != jsonalpha0.End(); ++itr) {
163  // A reference for code cleanness
164  const rapidjson::Value& contribution = *itr;
165 
166  // Get the type (required!)
167  std::string type = contribution["type"].GetString();
168 
169  if (!type.compare("IdealGasHelmholtzLead")) {
170  if (alpha0.Lead.is_enabled() == true) {
171  throw ValueError("Cannot add ");
172  }
173  CoolPropDbl a1 = cpjson::get_double(contribution, "a1");
174  CoolPropDbl a2 = cpjson::get_double(contribution, "a2");
175 
176  alpha0.Lead = IdealHelmholtzLead(a1, a2);
177  } else if (!type.compare("IdealGasHelmholtzPower")) {
178  if (alpha0.Power.is_enabled() == true) {
179  throw ValueError("Cannot add ");
180  }
181  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
182  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
183 
184  alpha0.Power = IdealHelmholtzPower(n, t);
185  } else if (!type.compare("IdealGasHelmholtzLogTau")) {
186  if (alpha0.LogTau.is_enabled() == true) {
187  throw ValueError("Cannot add ");
188  }
189  CoolPropDbl a = cpjson::get_double(contribution, "a");
190 
191  alpha0.LogTau = IdealHelmholtzLogTau(a);
192  } else if (!type.compare("IdealGasHelmholtzPlanckEinsteinGeneralized")) {
193  // Retrieve the values
194  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
195  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
196 
197  std::vector<CoolPropDbl> c = cpjson::get_long_double_array(contribution["c"]);
198  std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
199 
200  if (alpha0.PlanckEinstein.is_enabled() == true) {
201  alpha0.PlanckEinstein.extend(n, t, c, d);
202  } else {
203  alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d);
204  }
205  } else if (!type.compare("IdealGasHelmholtzPlanckEinstein")) {
206  // Retrieve the values
207  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
208  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
209  // Flip the sign of theta
210  for (std::size_t i = 0; i < t.size(); ++i) {
211  t[i] *= -1;
212  }
213  std::vector<CoolPropDbl> c(n.size(), 1);
214  std::vector<CoolPropDbl> d(c.size(), -1);
215 
216  if (alpha0.PlanckEinstein.is_enabled() == true) {
217  alpha0.PlanckEinstein.extend(n, t, c, d);
218  } else {
219  alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d);
220  }
221  } else if (!type.compare("IdealGasHelmholtzPlanckEinsteinFunctionT")) {
222  // Retrieve the values
223  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
224  std::vector<CoolPropDbl> v = cpjson::get_long_double_array(contribution["v"]), theta(n.size(), 0.0);
225  // Calculate theta
226  double Tc = cpjson::get_double(contribution, "Tcrit");
227  for (std::size_t i = 0; i < v.size(); ++i) {
228  theta[i] = -v[i] / Tc;
229  }
230  std::vector<CoolPropDbl> c(n.size(), 1);
231  std::vector<CoolPropDbl> d(c.size(), -1);
232 
233  if (alpha0.PlanckEinstein.is_enabled() == true) {
234  alpha0.PlanckEinstein.extend(n, theta, c, d);
235  } else {
236  alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, theta, c, d);
237  }
238  } else if (!type.compare("IdealGasHelmholtzGERG2004Cosh")) {
239  // Retrieve the values
240  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
241  std::vector<CoolPropDbl> theta = cpjson::get_long_double_array(contribution["theta"]);
242  double Tc = cpjson::get_double(contribution, "Tcrit");
243  if (alpha0.GERG2004Cosh.is_enabled() == true) {
244  alpha0.GERG2004Cosh.extend(n, theta);
245  } else {
246  alpha0.GERG2004Cosh = IdealHelmholtzGERG2004Cosh(n, theta, Tc);
247  }
248  } else if (!type.compare("IdealGasHelmholtzGERG2004Sinh")) {
249  // Retrieve the values
250  std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
251  std::vector<CoolPropDbl> theta = cpjson::get_long_double_array(contribution["theta"]);
252  double Tc = cpjson::get_double(contribution, "Tcrit");
253  if (alpha0.GERG2004Sinh.is_enabled() == true) {
254  alpha0.GERG2004Sinh.extend(n, theta);
255  } else {
256  alpha0.GERG2004Sinh = IdealHelmholtzGERG2004Sinh(n, theta, Tc);
257  }
258  } else if (!type.compare("IdealGasHelmholtzCP0Constant")) {
259  if (alpha0.CP0Constant.is_enabled() == true) {
260  throw ValueError("Cannot add another IdealGasHelmholtzCP0Constant term; join them together");
261  }
262  CoolPropDbl cp_over_R = cpjson::get_double(contribution, "cp_over_R");
263  CoolPropDbl Tc = cpjson::get_double(contribution, "Tc");
264  CoolPropDbl T0 = cpjson::get_double(contribution, "T0");
265  alpha0.CP0Constant = IdealHelmholtzCP0Constant(cp_over_R, Tc, T0);
266  } else if (!type.compare("IdealGasHelmholtzCP0PolyT")) {
267  if (alpha0.CP0PolyT.is_enabled() == true) {
268  throw ValueError("Cannot add another CP0PolyT term; join them together");
269  }
270  std::vector<CoolPropDbl> c = cpjson::get_long_double_array(contribution["c"]);
271  std::vector<CoolPropDbl> t = cpjson::get_long_double_array(contribution["t"]);
272  CoolPropDbl Tc = cpjson::get_double(contribution, "Tc");
273  CoolPropDbl T0 = cpjson::get_double(contribution, "T0");
274  alpha0.CP0PolyT = IdealHelmholtzCP0PolyT(c, t, Tc, T0);
275  } else if (!type.compare("IdealGasHelmholtzCP0AlyLee")) {
276 
277  std::vector<CoolPropDbl> constants = cpjson::get_long_double_array(contribution["c"]);
278  CoolPropDbl Tc = cpjson::get_double(contribution, "Tc");
279  CoolPropDbl T0 = cpjson::get_double(contribution, "T0");
280 
281  // Take the constant term if nonzero and set it as a polyT term
282  if (std::abs(constants[0]) > 1e-14) {
283  std::vector<CoolPropDbl> c(1, constants[0]), t(1, 0);
284  if (alpha0.CP0PolyT.is_enabled() == true) {
285  alpha0.CP0PolyT.extend(c, t);
286  } else {
287  alpha0.CP0PolyT = IdealHelmholtzCP0PolyT(c, t, Tc, T0);
288  }
289  }
290  std::vector<CoolPropDbl> n, c, d, t;
291  if (std::abs(constants[1]) > 1e-14) {
292  // sinh term can be converted by setting a_k = C, b_k = 2*D, c_k = -1, d_k = 1
293  n.push_back(constants[1]);
294  t.push_back(-2 * constants[2] / Tc);
295  c.push_back(1);
296  d.push_back(-1);
297  }
298  if (std::abs(constants[3]) > 1e-14) {
299  // cosh term can be converted by setting a_k = C, b_k = 2*D, c_k = 1, d_k = 1
300  n.push_back(-constants[3]);
301  t.push_back(-2 * constants[4] / Tc);
302  c.push_back(1);
303  d.push_back(1);
304  }
305  if (alpha0.PlanckEinstein.is_enabled() == true) {
306  alpha0.PlanckEinstein.extend(n, t, c, d);
307  } else {
308  alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d);
309  }
310  } else if (!type.compare("IdealGasHelmholtzEnthalpyEntropyOffset")) {
311  CoolPropDbl a1 = cpjson::get_double(contribution, "a1");
312  CoolPropDbl a2 = cpjson::get_double(contribution, "a2");
313  std::string reference = cpjson::get_string(contribution, "reference");
314  alpha0.EnthalpyEntropyOffsetCore = IdealHelmholtzEnthalpyEntropyOffset(a1, a2, reference);
315  } else {
316  std::cout << format("Unsupported ideal-gas Helmholtz type: %s\n", type.c_str());
317  //throw ValueError(format("Unsupported ideal-gas Helmholtz type: %s",type.c_str()));
318  }
319  }
320  return alpha0;
321  };
322 
323  protected:
325  void parse_environmental(rapidjson::Value& json, CoolPropFluid& fluid) {
326  fluid.environment.ASHRAE34 = cpjson::get_string(json, "ASHRAE34");
327  fluid.environment.GWP20 = cpjson::get_double(json, "GWP20");
328  fluid.environment.GWP100 = cpjson::get_double(json, "GWP100");
329  fluid.environment.GWP500 = cpjson::get_double(json, "GWP500");
330  fluid.environment.HH = cpjson::get_double(json, "HH");
331  fluid.environment.FH = cpjson::get_double(json, "FH");
332  fluid.environment.PH = cpjson::get_double(json, "PH");
333  fluid.environment.ODP = cpjson::get_double(json, "ODP");
334  }
335 
337  void parse_EOS(rapidjson::Value& EOS_json, CoolPropFluid& fluid) {
338  EquationOfState E;
339  fluid.EOSVector.push_back(E);
340 
341  EquationOfState& EOS = fluid.EOSVector.at(fluid.EOSVector.size() - 1);
342 
343  // Universal gas constant [J/mol/K]
344  EOS.R_u = cpjson::get_double(EOS_json, "gas_constant");
345  EOS.molar_mass = cpjson::get_double(EOS_json, "molar_mass");
346  EOS.acentric = cpjson::get_double(EOS_json, "acentric");
347 
348  EOS.pseudo_pure = cpjson::get_bool(EOS_json, "pseudo_pure");
349  EOS.limits.Tmax = cpjson::get_double(EOS_json, "T_max");
350  EOS.limits.pmax = cpjson::get_double(EOS_json, "p_max");
351 
352  rapidjson::Value& reducing_state = EOS_json["STATES"]["reducing"];
353  rapidjson::Value& satminL_state = EOS_json["STATES"]["sat_min_liquid"];
354  rapidjson::Value& satminV_state = EOS_json["STATES"]["sat_min_vapor"];
355 
356  // Reducing state
357  EOS.reduce.T = cpjson::get_double(reducing_state, "T");
358  EOS.reduce.rhomolar = cpjson::get_double(reducing_state, "rhomolar");
359  EOS.reduce.p = cpjson::get_double(reducing_state, "p");
360  EOS.reduce.hmolar = cpjson::get_double(reducing_state, "hmolar");
361  EOS.reduce.smolar = cpjson::get_double(reducing_state, "smolar");
362 
363  EOS.sat_min_liquid.T = cpjson::get_double(satminL_state, "T");
364  EOS.sat_min_liquid.p = cpjson::get_double(satminL_state, "p");
365  EOS.sat_min_liquid.rhomolar = cpjson::get_double(satminL_state, "rhomolar");
366  EOS.sat_min_vapor.T = cpjson::get_double(satminV_state, "T");
367  EOS.sat_min_vapor.p = cpjson::get_double(satminV_state, "p");
368  EOS.sat_min_vapor.rhomolar = cpjson::get_double(satminV_state, "rhomolar");
369 
371  EOS.limits.Tmin = cpjson::get_double(satminL_state, "T");
372  EOS.ptriple = cpjson::get_double(satminL_state, "p");
373  EOS.Ttriple = EOS.limits.Tmin;
374 
375  // BibTex keys
376  EOS.BibTeX_EOS = cpjson::get_string(EOS_json, "BibTeX_EOS");
377  EOS.BibTeX_CP0 = cpjson::get_string(EOS_json, "BibTeX_CP0");
378 
379  EOS.alphar = parse_alphar(EOS_json["alphar"]);
380  EOS.alpha0 = parse_alpha0(EOS_json["alpha0"]);
381 
382  // Store the prefactor multipliying alpha0 if present
383  if (EOS_json.HasMember("alpha0_prefactor")) {
384  EOS.alpha0.set_prefactor(cpjson::get_double(EOS_json, "alpha0_prefactor"));
385  }
386  if (EOS_json["STATES"].HasMember("hs_anchor")) {
387  rapidjson::Value& hs_anchor = EOS_json["STATES"]["hs_anchor"];
388  EOS.hs_anchor.T = cpjson::get_double(hs_anchor, "T");
389  EOS.hs_anchor.p = cpjson::get_double(hs_anchor, "p");
390  EOS.hs_anchor.rhomolar = cpjson::get_double(hs_anchor, "rhomolar");
391  EOS.hs_anchor.hmolar = cpjson::get_double(hs_anchor, "hmolar");
392  EOS.hs_anchor.smolar = cpjson::get_double(hs_anchor, "smolar");
393  }
394 
395  if (EOS_json["STATES"].HasMember("pressure_max_sat")) {
396  rapidjson::Value& s = EOS_json["STATES"]["pressure_max_sat"];
397  EOS.max_sat_p.T = cpjson::get_double(s, "T");
398  EOS.max_sat_p.p = cpjson::get_double(s, "p");
399  EOS.max_sat_p.rhomolar = cpjson::get_double(s, "rhomolar");
400  if (s.HasMember("hmolar")) {
401  EOS.max_sat_p.hmolar = cpjson::get_double(s, "hmolar");
402  EOS.max_sat_p.smolar = cpjson::get_double(s, "smolar");
403  }
404  }
405 
406  if (EOS_json["STATES"].HasMember("temperature_max_sat")) {
407  rapidjson::Value& s = EOS_json["STATES"]["temperature_max_sat"];
408  EOS.max_sat_T.T = cpjson::get_double(s, "T");
409  EOS.max_sat_T.p = cpjson::get_double(s, "p");
410  EOS.max_sat_T.rhomolar = cpjson::get_double(s, "rhomolar");
411  if (s.HasMember("hmolar")) {
412  EOS.max_sat_T.hmolar = cpjson::get_double(s, "hmolar");
413  EOS.max_sat_T.smolar = cpjson::get_double(s, "smolar");
414  }
415  }
416 
417  if (EOS_json.HasMember("critical_region_splines")) {
418  rapidjson::Value& spline = EOS_json["critical_region_splines"];
419  EOS.critical_region_splines.T_min = cpjson::get_double(spline, "T_min");
420  EOS.critical_region_splines.T_max = cpjson::get_double(spline, "T_max");
421  EOS.critical_region_splines.rhomolar_min = cpjson::get_double(spline, "rhomolar_min");
422  EOS.critical_region_splines.rhomolar_max = cpjson::get_double(spline, "rhomolar_max");
423  EOS.critical_region_splines.cL = cpjson::get_double_array(spline["cL"]);
424  EOS.critical_region_splines.cV = cpjson::get_double_array(spline["cV"]);
425  EOS.critical_region_splines.enabled = true;
426  }
427 
428  // Validate the equation of state that was just created
429  EOS.validate();
430  }
431 
433  void parse_EOS_listing(rapidjson::Value& EOS_array, CoolPropFluid& fluid) {
434  for (rapidjson::Value::ValueIterator itr = EOS_array.Begin(); itr != EOS_array.End(); ++itr) {
435  parse_EOS(*itr, fluid);
436  }
437  };
438 
440  void parse_dilute_viscosity(rapidjson::Value& dilute, CoolPropFluid& fluid) {
441  if (dilute.HasMember("hardcoded")) {
442  std::string target = cpjson::get_string(dilute, "hardcoded");
443  if (!target.compare("Ethane")) {
444  fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE;
445  return;
446  } else if (!target.compare("Cyclohexane")) {
447  fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_CYCLOHEXANE;
448  return;
449  } else if (!target.compare("CarbonDioxideLaeseckeJPCRD2017")) {
451  return;
452  } else {
453  throw ValueError(format("hardcoded dilute viscosity [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
454  }
455  }
456  std::string type = cpjson::get_string(dilute, "type");
457  if (!type.compare("collision_integral")) {
458  // Get a reference to the entry in the fluid instance
459  CoolProp::ViscosityDiluteGasCollisionIntegralData& CI = fluid.transport.viscosity_dilute.collision_integral;
460 
461  // Set the type flag
462  fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL;
463 
464  // Load up the values
465  CI.a = cpjson::get_long_double_array(dilute["a"]);
466  CI.t = cpjson::get_long_double_array(dilute["t"]);
467  CI.molar_mass = cpjson::get_double(dilute, "molar_mass");
468  CI.C = cpjson::get_double(dilute, "C");
469  } else if (!type.compare("kinetic_theory")) {
470  fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_KINETIC_THEORY;
471  } else if (!type.compare("powers_of_T")) {
472  // Get a reference to the entry in the fluid instance
473  CoolProp::ViscosityDiluteGasPowersOfT& CI = fluid.transport.viscosity_dilute.powers_of_T;
474 
475  // Load up the values
476  CI.a = cpjson::get_long_double_array(dilute["a"]);
477  CI.t = cpjson::get_long_double_array(dilute["t"]);
478 
479  fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_T;
480  } else if (!type.compare("powers_of_Tr")) {
481  // Get a reference to the entry in the fluid instance
482  CoolProp::ViscosityDiluteGasPowersOfTr& CI = fluid.transport.viscosity_dilute.powers_of_Tr;
483  // Load up the values
484  CI.a = cpjson::get_long_double_array(dilute["a"]);
485  CI.t = cpjson::get_long_double_array(dilute["t"]);
486  CI.T_reducing = cpjson::get_double(dilute, "T_reducing");
487  fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_TR;
488  } else if (!type.compare("collision_integral_powers_of_Tstar")) {
489  // Get a reference to the entry in the fluid instance
491 
492  // Load up the values
493  CI.a = cpjson::get_long_double_array(dilute["a"]);
494  CI.t = cpjson::get_long_double_array(dilute["t"]);
495  CI.T_reducing = cpjson::get_double(dilute, "T_reducing");
496  CI.C = cpjson::get_double(dilute, "C");
497 
499  } else {
500  throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
501  }
502  };
503 
505  void parse_initial_density_viscosity(rapidjson::Value& initial_density, CoolPropFluid& fluid) {
506  std::string type = cpjson::get_string(initial_density, "type");
507  if (!type.compare("Rainwater-Friend")) {
508  // Get a reference to the entry in the fluid instance
509  CoolProp::ViscosityRainWaterFriendData& RF = fluid.transport.viscosity_initial.rainwater_friend;
510 
511  // Load up the values
512  RF.b = cpjson::get_long_double_array(initial_density["b"]);
513  RF.t = cpjson::get_long_double_array(initial_density["t"]);
514 
515  // Set the type flag
517  } else if (!type.compare("empirical")) {
518  // Get a reference to the entry in the fluid instance
519  CoolProp::ViscosityInitialDensityEmpiricalData& EM = fluid.transport.viscosity_initial.empirical;
520 
521  // Load up the values
522  EM.n = cpjson::get_long_double_array(initial_density["n"]);
523  EM.d = cpjson::get_long_double_array(initial_density["d"]);
524  EM.t = cpjson::get_long_double_array(initial_density["t"]);
525  EM.T_reducing = cpjson::get_double(initial_density, "T_reducing");
526  EM.rhomolar_reducing = cpjson::get_double(initial_density, "rhomolar_reducing");
527 
528  // Set the type flag
530  } else {
531  throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
532  }
533  };
534 
536  void parse_higher_order_viscosity(rapidjson::Value& higher, CoolPropFluid& fluid) {
537  // First check for hardcoded higher-order term
538  if (higher.HasMember("hardcoded")) {
539  std::string target = cpjson::get_string(higher, "hardcoded");
540  if (!target.compare("Hydrogen")) {
541  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HYDROGEN;
542  return;
543  } else if (!target.compare("n-Hexane")) {
544  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEXANE;
545  return;
546  } else if (!target.compare("n-Heptane")) {
547  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEPTANE;
548  return;
549  } else if (!target.compare("Toluene")) {
550  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_TOLUENE;
551  return;
552  } else if (!target.compare("Ethane")) {
553  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_ETHANE;
554  return;
555  } else if (!target.compare("Benzene")) {
556  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BENZENE;
557  return;
558  } else if (!target.compare("CarbonDioxideLaeseckeJPCRD2017")) {
560  return;
561  } else {
562  throw ValueError(
563  format("hardcoded higher order viscosity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
564  }
565  }
566 
567  std::string type = cpjson::get_string(higher, "type");
568  if (!type.compare("modified_Batschinski_Hildebrand")) {
569  // Get a reference to the entry in the fluid instance to simplify the code that follows
571 
572  // Set the flag for the type of this model
574 
575  BH.T_reduce = cpjson::get_double(higher, "T_reduce");
576  BH.rhomolar_reduce = cpjson::get_double(higher, "rhomolar_reduce");
577  // Load up the values
578  BH.a = cpjson::get_long_double_array(higher["a"]);
579  BH.t1 = cpjson::get_long_double_array(higher["t1"]);
580  BH.d1 = cpjson::get_long_double_array(higher["d1"]);
581  BH.gamma = cpjson::get_long_double_array(higher["gamma"]);
582  BH.l = cpjson::get_long_double_array(higher["l"]);
583  assert(BH.a.size() == BH.t1.size());
584  assert(BH.a.size() == BH.d1.size());
585  assert(BH.a.size() == BH.gamma.size());
586  assert(BH.a.size() == BH.l.size());
587  BH.f = cpjson::get_long_double_array(higher["f"]);
588  BH.t2 = cpjson::get_long_double_array(higher["t2"]);
589  BH.d2 = cpjson::get_long_double_array(higher["d2"]);
590  assert(BH.f.size() == BH.t2.size());
591  assert(BH.f.size() == BH.d2.size());
592  BH.g = cpjson::get_long_double_array(higher["g"]);
593  BH.h = cpjson::get_long_double_array(higher["h"]);
594  assert(BH.g.size() == BH.h.size());
595  BH.p = cpjson::get_long_double_array(higher["p"]);
596  BH.q = cpjson::get_long_double_array(higher["q"]);
597  assert(BH.p.size() == BH.q.size());
598  } else if (!type.compare("friction_theory")) {
599  // Get a reference to the entry in the fluid instance to simplify the code that follows
600  CoolProp::ViscosityFrictionTheoryData& F = fluid.transport.viscosity_higher_order.friction_theory;
601 
602  // Set the flag for the type of this model
603  fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_FRICTION_THEORY;
604 
605  // Always need these terms
606  F.Ai = cpjson::get_long_double_array(higher["Ai"]);
607  F.Aa = cpjson::get_long_double_array(higher["Aa"]);
608  F.Aaa = cpjson::get_long_double_array(higher["Aaa"]);
609  F.Ar = cpjson::get_long_double_array(higher["Ar"]);
610 
611  F.Na = cpjson::get_integer(higher, "Na");
612  F.Naa = cpjson::get_integer(higher, "Naa");
613  F.Nr = cpjson::get_integer(higher, "Nr");
614  F.Nrr = cpjson::get_integer(higher, "Nrr");
615  F.c1 = cpjson::get_double(higher, "c1");
616  F.c2 = cpjson::get_double(higher, "c2");
617  assert(F.Aa.size() == 3);
618  assert(F.Aaa.size() == 3);
619  assert(F.Ar.size() == 3);
620 
621  F.T_reduce = cpjson::get_double(higher, "T_reduce");
622 
623  if (higher.HasMember("Arr") && !higher.HasMember("Adrdr")) {
624  F.Arr = cpjson::get_long_double_array(higher["Arr"]);
625  assert(F.Arr.size() == 3);
626  } else if (higher.HasMember("Adrdr") && !higher.HasMember("Arr")) {
627  F.Adrdr = cpjson::get_long_double_array(higher["Adrdr"]);
628  assert(F.Adrdr.size() == 3);
629  } else {
630  throw ValueError(format("can only provide one of Arr or Adrdr for fluid %s", fluid.name.c_str()));
631  }
632  if (higher.HasMember("Aii")) {
633  F.Aii = cpjson::get_long_double_array(higher["Aii"]);
634  F.Nii = cpjson::get_integer(higher, "Nii");
635  }
636  if (higher.HasMember("Aaaa") && higher.HasMember("Arrr")) {
637  F.Aaaa = cpjson::get_long_double_array(higher["Aaaa"]);
638  F.Arrr = cpjson::get_long_double_array(higher["Arrr"]);
639  F.Naaa = cpjson::get_integer(higher, "Naaa");
640  F.Nrrr = cpjson::get_integer(higher, "Nrrr");
641  }
642 
643  } else {
644  throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
645  }
646  };
647 
648  void parse_ECS_conductivity(rapidjson::Value& conductivity, CoolPropFluid& fluid) {
649  fluid.transport.conductivity_ecs.reference_fluid = cpjson::get_string(conductivity, "reference_fluid");
650 
651  // Parameters for correction polynomials
652  fluid.transport.conductivity_ecs.psi_a = cpjson::get_long_double_array(conductivity["psi"]["a"]);
653  fluid.transport.conductivity_ecs.psi_t = cpjson::get_long_double_array(conductivity["psi"]["t"]);
654  fluid.transport.conductivity_ecs.psi_rhomolar_reducing = cpjson::get_double(conductivity["psi"], "rhomolar_reducing");
655  fluid.transport.conductivity_ecs.f_int_a = cpjson::get_long_double_array(conductivity["f_int"]["a"]);
656  fluid.transport.conductivity_ecs.f_int_t = cpjson::get_long_double_array(conductivity["f_int"]["t"]);
657  fluid.transport.conductivity_ecs.f_int_T_reducing = cpjson::get_double(conductivity["f_int"], "T_reducing");
658 
659  fluid.transport.conductivity_using_ECS = true;
660  }
661 
662  void parse_ECS_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) {
663  fluid.transport.viscosity_ecs.reference_fluid = cpjson::get_string(viscosity, "reference_fluid");
664 
665  // Parameters for correction polynomial
666  fluid.transport.viscosity_ecs.psi_a = cpjson::get_long_double_array(viscosity["psi"]["a"]);
667  fluid.transport.viscosity_ecs.psi_t = cpjson::get_long_double_array(viscosity["psi"]["t"]);
668  fluid.transport.viscosity_ecs.psi_rhomolar_reducing = cpjson::get_double(viscosity["psi"], "rhomolar_reducing");
669 
670  fluid.transport.viscosity_using_ECS = true;
671  }
672 
673  void parse_Chung_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) {
674  // These in base SI units
675  fluid.transport.viscosity_Chung.rhomolar_critical = cpjson::get_double(viscosity, "rhomolar_critical");
676  fluid.transport.viscosity_Chung.T_critical = cpjson::get_double(viscosity, "T_critical");
677  fluid.transport.viscosity_Chung.molar_mass = cpjson::get_double(viscosity, "molar_mass");
678  fluid.transport.viscosity_Chung.dipole_moment_D = cpjson::get_double(viscosity, "dipole_moment_D");
679  fluid.transport.viscosity_Chung.acentric = cpjson::get_double(viscosity, "acentric");
680  fluid.transport.viscosity_using_Chung = true;
681  }
682 
683  void parse_rhosr_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) {
684  fluid.transport.viscosity_rhosr.C = cpjson::get_double(viscosity, "C");
685  fluid.transport.viscosity_rhosr.c_liq = cpjson::get_double_array(viscosity, "c_liq");
686  fluid.transport.viscosity_rhosr.c_vap = cpjson::get_double_array(viscosity, "c_vap");
687  fluid.transport.viscosity_rhosr.rhosr_critical = cpjson::get_double(viscosity, "rhosr_critical");
688  fluid.transport.viscosity_rhosr.x_crossover = cpjson::get_double(viscosity, "x_crossover");
689  fluid.transport.viscosity_using_rhosr = true;
690  }
691 
693  void parse_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) {
694  // If an array, use the first one, and then stop;
695  if (viscosity.IsArray()) {
696  rapidjson::Value::ValueIterator itr = viscosity.Begin();
697  parse_viscosity(*itr, fluid);
698  return;
699  }
700 
701  // Load the BibTeX key
702  fluid.transport.BibTeX_viscosity = cpjson::get_string(viscosity, "BibTeX");
703 
704  // Set the Lennard-Jones 12-6 potential variables, or approximate them from method of Chung
705  if (!viscosity.HasMember("sigma_eta") || !viscosity.HasMember("epsilon_over_k")) {
706  default_transport(fluid);
707  } else {
708  fluid.transport.sigma_eta = cpjson::get_double(viscosity, "sigma_eta");
709  fluid.transport.epsilon_over_k = cpjson::get_double(viscosity, "epsilon_over_k");
710  }
711 
712  // If it is using ECS, set ECS parameters and quit
713  if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("ECS")) {
714  parse_ECS_viscosity(viscosity, fluid);
715  return;
716  }
717 
718  // If it is using rho*sr CS, set parameters and quit
719  if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("rhosr-CS")) {
720  parse_rhosr_viscosity(viscosity, fluid);
721  return;
722  }
723 
724  // Use the method of Chung
725  // If it is using ECS, set ECS parameters and quit
726  if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("Chung")) {
727  parse_Chung_viscosity(viscosity, fluid);
728  return;
729  }
730 
731  if (viscosity.HasMember("hardcoded")) {
732  std::string target = cpjson::get_string(viscosity, "hardcoded");
733  if (!target.compare("Water")) {
735  return;
736  } else if (!target.compare("HeavyWater")) {
738  return;
739  } else if (!target.compare("Helium")) {
741  return;
742  } else if (!target.compare("R23")) {
744  return;
745  } else if (!target.compare("Methanol")) {
747  return;
748  } else if (!target.compare("m-Xylene")) {
750  return;
751  } else if (!target.compare("o-Xylene")) {
753  return;
754  } else if (!target.compare("p-Xylene")) {
756  return;
757  } else {
758  throw ValueError(format("hardcoded viscosity [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
759  }
760  }
761 
762  // Load dilute viscosity term
763  if (viscosity.HasMember("dilute")) {
764  parse_dilute_viscosity(viscosity["dilute"], fluid);
765  }
766  // Load initial density term
767  if (viscosity.HasMember("initial_density")) {
768  parse_initial_density_viscosity(viscosity["initial_density"], fluid);
769  }
770  // Load higher_order term
771  if (viscosity.HasMember("higher_order")) {
772  parse_higher_order_viscosity(viscosity["higher_order"], fluid);
773  }
774  };
775 
777  void parse_dilute_conductivity(rapidjson::Value& dilute, CoolPropFluid& fluid) {
778  if (dilute.HasMember("hardcoded")) {
779  std::string target = cpjson::get_string(dilute, "hardcoded");
780  if (!target.compare("CO2")) {
781  fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2;
782  return;
783  }
784  else if (!target.compare("CarbonDioxideHuberJPCRD2016")) {
785  fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2_HUBER_JPCRD_2016;
786  return;
787  } else if (!target.compare("Ethane")) {
788  fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETHANE;
789  return;
790  } else if (!target.compare("none")) {
791  fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_NONE;
792  return;
793  } else {
794  throw ValueError(
795  format("hardcoded dilute conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
796  }
797  }
798  std::string type = cpjson::get_string(dilute, "type");
799  if (!type.compare("ratio_of_polynomials")) {
800  // Get a reference to the entry in the fluid instance
801  CoolProp::ConductivityDiluteRatioPolynomialsData& data = fluid.transport.conductivity_dilute.ratio_polynomials;
802 
803  // Set the type flag
804  fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS;
805 
806  // Load up the values
807  data.A = cpjson::get_long_double_array(dilute["A"]);
808  data.B = cpjson::get_long_double_array(dilute["B"]);
809  data.n = cpjson::get_long_double_array(dilute["n"]);
810  data.m = cpjson::get_long_double_array(dilute["m"]);
811  data.T_reducing = cpjson::get_double(dilute, "T_reducing");
812  } else if (!type.compare("eta0_and_poly")) {
813  // Get a reference to the entry in the fluid instance
814  CoolProp::ConductivityDiluteEta0AndPolyData& data = fluid.transport.conductivity_dilute.eta0_and_poly;
815 
816  // Set the type flag
817  fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETA0_AND_POLY;
818 
819  // Load up the values
820  data.A = cpjson::get_long_double_array(dilute["A"]);
821  data.t = cpjson::get_long_double_array(dilute["t"]);
822  } else {
823  throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
824  }
825  };
826 
828  void parse_residual_conductivity(rapidjson::Value& dilute, CoolPropFluid& fluid) {
829  if (dilute.HasMember("hardcoded")) {
830  std::string target = cpjson::get_string(dilute, "hardcoded");
831  if (!target.compare("CO2")) {
832  fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_CO2;
833  return;
834  } else {
835  throw ValueError(
836  format("hardcoded residual conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
837  }
838  }
839  std::string type = cpjson::get_string(dilute, "type");
840  if (!type.compare("polynomial")) {
841  // Get a reference to the entry in the fluid instance
842  CoolProp::ConductivityResidualPolynomialData& data = fluid.transport.conductivity_residual.polynomials;
843 
844  // Set the type flag
845  fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL;
846 
847  // Load up the values
848  data.B = cpjson::get_long_double_array(dilute["B"]);
849  data.d = cpjson::get_long_double_array(dilute["d"]);
850  data.t = cpjson::get_long_double_array(dilute["t"]);
851  data.T_reducing = cpjson::get_double(dilute, "T_reducing");
852  data.rhomass_reducing = cpjson::get_double(dilute, "rhomass_reducing");
853  } else if (!type.compare("polynomial_and_exponential")) {
854  // Get a reference to the entry in the fluid instance
855  CoolProp::ConductivityResidualPolynomialAndExponentialData& data = fluid.transport.conductivity_residual.polynomial_and_exponential;
856 
857  // Set the type flag
858  fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL_AND_EXPONENTIAL;
859 
860  // Load up the values
861  data.A = cpjson::get_long_double_array(dilute["A"]);
862  data.d = cpjson::get_long_double_array(dilute["d"]);
863  data.t = cpjson::get_long_double_array(dilute["t"]);
864  data.gamma = cpjson::get_long_double_array(dilute["gamma"]);
865  data.l = cpjson::get_long_double_array(dilute["l"]);
866  } else {
867  throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
868  }
869  };
870 
871  void parse_critical_conductivity(rapidjson::Value& critical, CoolPropFluid& fluid) {
872  if (critical.HasMember("hardcoded")) {
873  std::string target = cpjson::get_string(critical, "hardcoded");
874  if (!target.compare("R123")) {
875  fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_R123;
876  return;
877  } else if (!target.compare("Ammonia")) {
878  fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_AMMONIA;
879  return;
880  } else if (!target.compare("CarbonDioxideScalabrinJPCRD2006")) {
881  fluid.transport.conductivity_critical.type =
882  CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_CARBONDIOXIDE_SCALABRIN_JPCRD_2006;
883  return;
884  } else if (!target.compare("None")) {
885  fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_NONE;
886  return;
887  } else {
888  throw ValueError(format("critical conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
889  }
890  }
891  std::string type = cpjson::get_string(critical, "type");
892  if (!type.compare("simplified_Olchowy_Sengers")) {
894  CoolProp::ConductivityCriticalSimplifiedOlchowySengersData& data = fluid.transport.conductivity_critical.Olchowy_Sengers;
895 
896  // Set the type flag
897  fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS;
898 
899  // Set values if they are found - otherwise fall back to default values
900  if (critical.HasMember("qD")) {
901  data.qD = cpjson::get_double(critical, "qD");
902  }
903  if (critical.HasMember("zeta0")) {
904  data.zeta0 = cpjson::get_double(critical, "zeta0");
905  }
906  if (critical.HasMember("GAMMA")) {
907  data.GAMMA = cpjson::get_double(critical, "GAMMA");
908  }
909  if (critical.HasMember("gamma")) {
910  data.gamma = cpjson::get_double(critical, "gamma");
911  }
912  if (critical.HasMember("R0")) {
913  data.R0 = cpjson::get_double(critical, "R0");
914  }
915  if (critical.HasMember("T_ref")) {
916  data.T_ref = cpjson::get_double(critical, "T_ref");
917  }
918  } else {
919  throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
920  }
921  };
922 
924  void parse_thermal_conductivity(rapidjson::Value& conductivity, CoolPropFluid& fluid) {
925  // Load the BibTeX key
926  fluid.transport.BibTeX_conductivity = cpjson::get_string(conductivity, "BibTeX");
927 
928  // If it is using ECS, set ECS parameters and quit
929  if (conductivity.HasMember("type") && !cpjson::get_string(conductivity, "type").compare("ECS")) {
930  parse_ECS_conductivity(conductivity, fluid);
931  return;
932  }
933 
934  if (conductivity.HasMember("hardcoded")) {
935  std::string target = cpjson::get_string(conductivity, "hardcoded");
936  if (!target.compare("Water")) {
938  return;
939  } else if (!target.compare("HeavyWater")) {
941  return;
942  } else if (!target.compare("Methane")) {
944  return;
945  } else if (!target.compare("R23")) {
947  return;
948  } else if (!target.compare("Helium")) {
950  return;
951  } else {
952  throw ValueError(
953  format("hardcoded residual conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str()));
954  }
955  }
956 
957  // Load dilute conductivity term
958  if (conductivity.HasMember("dilute")) {
959  parse_dilute_conductivity(conductivity["dilute"], fluid);
960  }
961  // Load residual conductivity term
962  if (conductivity.HasMember("residual")) {
963  parse_residual_conductivity(conductivity["residual"], fluid);
964  }
965  // Load critical conductivity term
966  if (conductivity.HasMember("critical")) {
967  parse_critical_conductivity(conductivity["critical"], fluid);
968  }
969  };
970 
972  void parse_transport(rapidjson::Value& transport, CoolPropFluid& fluid) {
973 
974  // Parse viscosity
975  if (transport.HasMember("viscosity")) {
976  parse_viscosity(transport["viscosity"], fluid);
977  fluid.transport.viscosity_model_provided = true;
978  }
979 
980  // Parse thermal conductivity
981  if (transport.HasMember("conductivity")) {
982  parse_thermal_conductivity(transport["conductivity"], fluid);
983  fluid.transport.conductivity_model_provided = true;
984  }
985  };
986 
987  void default_transport(CoolPropFluid& fluid) {
988  // Use the method of Chung to approximate the values for epsilon_over_k and sigma_eta
989  // Chung, T.-H.; Ajlan, M.; Lee, L. L.; Starling, K. E. Generalized Multiparameter Correlation for Nonpolar and Polar Fluid Transport Properties. Ind. Eng. Chem. Res. 1988, 27, 671-679.
990  // rhoc needs to be in mol/L to yield a sigma in nm,
991  CoolPropDbl rho_crit_molar = fluid.EOS().reduce.rhomolar / 1000.0; // [mol/m3 to mol/L]
992  CoolPropDbl Tc = fluid.EOS().reduce.T;
993  fluid.transport.sigma_eta = 0.809 / pow(rho_crit_molar, static_cast<CoolPropDbl>(1.0 / 3.0)) / 1e9; // 1e9 is to convert from nm to m
994  fluid.transport.epsilon_over_k = Tc / 1.2593; // [K]
995  }
996 
997  void parse_melting_line(rapidjson::Value& melting_line, CoolPropFluid& fluid) {
998  fluid.ancillaries.melting_line.T_m = cpjson::get_double(melting_line, "T_m");
999  fluid.ancillaries.melting_line.BibTeX = cpjson::get_string(melting_line, "BibTeX");
1000 
1001  if (melting_line.HasMember("type")) {
1002  std::string type = cpjson::get_string(melting_line, "type");
1003  if (!type.compare("Simon")) {
1004  rapidjson::Value& parts = melting_line["parts"];
1006  for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) {
1008  data.a = cpjson::get_double((*itr), "a");
1009  data.c = cpjson::get_double((*itr), "c");
1010  data.T_min = cpjson::get_double((*itr), "T_min");
1011  data.T_max = cpjson::get_double((*itr), "T_max");
1012  data.T_0 = cpjson::get_double((*itr), "T_0");
1013  data.p_0 = cpjson::get_double((*itr), "p_0");
1014  fluid.ancillaries.melting_line.simon.parts.push_back(data);
1015  }
1016  } else if (!type.compare("polynomial_in_Tr")) {
1017  rapidjson::Value& parts = melting_line["parts"];
1019  for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) {
1021  data.a = cpjson::get_long_double_array((*itr), "a");
1022  data.t = cpjson::get_long_double_array((*itr), "t");
1023  data.T_min = cpjson::get_double((*itr), "T_min");
1024  data.T_max = cpjson::get_double((*itr), "T_max");
1025  data.T_0 = cpjson::get_double((*itr), "T_0");
1026  data.p_0 = cpjson::get_double((*itr), "p_0");
1027  fluid.ancillaries.melting_line.polynomial_in_Tr.parts.push_back(data);
1028  }
1029  } else if (!type.compare("polynomial_in_Theta")) {
1030  rapidjson::Value& parts = melting_line["parts"];
1032  for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) {
1034  data.a = cpjson::get_long_double_array((*itr), "a");
1035  data.t = cpjson::get_long_double_array((*itr), "t");
1036  data.T_min = cpjson::get_double((*itr), "T_min");
1037  data.T_max = cpjson::get_double((*itr), "T_max");
1038  data.T_0 = cpjson::get_double((*itr), "T_0");
1039  data.p_0 = cpjson::get_double((*itr), "p_0");
1040  fluid.ancillaries.melting_line.polynomial_in_Theta.parts.push_back(data);
1041  }
1042  } else {
1043  throw ValueError(format("melting line type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str()));
1044  }
1045  // Set the limits for the melting line curve
1046  fluid.ancillaries.melting_line.set_limits();
1047  } else {
1048  throw ValueError(format("melting line does not have \"type\" for fluid %s", fluid.name.c_str()));
1049  }
1050  };
1051 
1053  void parse_states(rapidjson::Value& states, CoolPropFluid& fluid) {
1054  if (!states.HasMember("critical")) {
1055  throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"critical\" member", fluid.name.c_str()));
1056  }
1057  rapidjson::Value& crit = states["critical"];
1058  fluid.crit.T = cpjson::get_double(crit, "T");
1059  fluid.crit.p = cpjson::get_double(crit, "p");
1060  fluid.crit.rhomolar = cpjson::get_double(crit, "rhomolar");
1061  fluid.crit.hmolar = cpjson::get_double(crit, "hmolar");
1062  fluid.crit.smolar = cpjson::get_double(crit, "smolar");
1063 
1064  if (!states.HasMember("triple_liquid")) {
1065  throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"triple_liquid\" member", fluid.name.c_str()));
1066  }
1067  rapidjson::Value& triple_liquid = states["triple_liquid"];
1068  if (triple_liquid.ObjectEmpty()) {
1069  // State is empty - probably because the triple point temperature is below the minimum saturation temperature
1070  fluid.triple_liquid.T = -1;
1071  fluid.triple_liquid.p = -1;
1072  fluid.triple_liquid.rhomolar = -1;
1073  fluid.triple_liquid.hmolar = _HUGE;
1074  fluid.triple_liquid.smolar = _HUGE;
1075  } else {
1076  fluid.triple_liquid.T = cpjson::get_double(triple_liquid, "T");
1077  fluid.triple_liquid.p = cpjson::get_double(triple_liquid, "p");
1078  fluid.triple_liquid.rhomolar = cpjson::get_double(triple_liquid, "rhomolar");
1079  fluid.triple_liquid.hmolar = cpjson::get_double(triple_liquid, "hmolar");
1080  fluid.triple_liquid.smolar = cpjson::get_double(triple_liquid, "smolar");
1081  }
1082 
1083  if (!states.HasMember("triple_vapor")) {
1084  throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"triple_vapor\" member", fluid.name.c_str()));
1085  }
1086  rapidjson::Value& triple_vapor = states["triple_vapor"];
1087  if (triple_vapor.ObjectEmpty()) {
1088  // State is empty - probably because the triple point temperature is below the minimum saturation temperature
1089  fluid.triple_vapor.T = -1;
1090  fluid.triple_vapor.p = -1;
1091  fluid.triple_vapor.rhomolar = -1;
1092  fluid.triple_vapor.hmolar = _HUGE;
1093  fluid.triple_vapor.smolar = _HUGE;
1094  } else {
1095  fluid.triple_vapor.T = cpjson::get_double(triple_vapor, "T");
1096  fluid.triple_vapor.p = cpjson::get_double(triple_vapor, "p");
1097  fluid.triple_vapor.rhomolar = cpjson::get_double(triple_vapor, "rhomolar");
1098  fluid.triple_vapor.hmolar = cpjson::get_double(triple_vapor, "hmolar");
1099  fluid.triple_vapor.smolar = cpjson::get_double(triple_vapor, "smolar");
1100  }
1101  };
1102 
1104  void parse_ancillaries(rapidjson::Value& ancillaries, CoolPropFluid& fluid) {
1105  if (!ancillaries.HasMember("rhoL") || !ancillaries.HasMember("rhoV")) {
1106  throw ValueError("Ancillary curves for either rhoL or rhoV are missing");
1107  }
1108  fluid.ancillaries.rhoL = SaturationAncillaryFunction(ancillaries["rhoL"]);
1109  fluid.ancillaries.rhoV = SaturationAncillaryFunction(ancillaries["rhoV"]);
1110 
1111  // If a pseudo-pure fluid, has pL and pV curves
1112  if (ancillaries.HasMember("pL") && ancillaries.HasMember("pV")) {
1113  fluid.ancillaries.pL = SaturationAncillaryFunction(ancillaries["pL"]);
1114  fluid.ancillaries.pV = SaturationAncillaryFunction(ancillaries["pV"]);
1115  }
1116  // Otherwise has a single pS curve and not pL and not pV
1117  else if (!ancillaries.HasMember("pL") && !ancillaries.HasMember("pV") && ancillaries.HasMember("pS")) {
1118  fluid.ancillaries.pL = SaturationAncillaryFunction(ancillaries["pS"]);
1119  fluid.ancillaries.pV = SaturationAncillaryFunction(ancillaries["pS"]);
1120  } else {
1121  throw ValueError("Pressure ancillary curves are missing or invalid");
1122  }
1123 
1124  if (ancillaries.HasMember("hL")) {
1125  fluid.ancillaries.hL = SaturationAncillaryFunction(ancillaries["hL"]);
1126  } else {
1127  if (get_debug_level() > 0) {
1128  std::cout << "Missing hL ancillary for fluid " << fluid.name;
1129  }
1130  }
1131  if (ancillaries.HasMember("hLV")) {
1132  fluid.ancillaries.hLV = SaturationAncillaryFunction(ancillaries["hLV"]);
1133  } else {
1134  if (get_debug_level() > 0) {
1135  std::cout << "Missing hLV ancillary for fluid " << fluid.name;
1136  }
1137  }
1138 
1139  if (ancillaries.HasMember("sL")) {
1140  fluid.ancillaries.sL = SaturationAncillaryFunction(ancillaries["sL"]);
1141  } else {
1142  if (get_debug_level() > 0) {
1143  std::cout << "Missing sL ancillary for fluid " << fluid.name;
1144  }
1145  }
1146  if (ancillaries.HasMember("sLV")) {
1147  fluid.ancillaries.sLV = SaturationAncillaryFunction(ancillaries["sLV"]);
1148  } else {
1149  if (get_debug_level() > 0) {
1150  std::cout << "Missing sLV ancillary for fluid " << fluid.name;
1151  }
1152  }
1153  if (!ValidNumber(fluid.ancillaries.sL.get_Tmin()) && get_debug_level() > 0) {
1154  std::cout << "Tmin invalid for sL for " << fluid.name << std::endl;
1155  }
1156  };
1157 
1159  void parse_surface_tension(rapidjson::Value& surface_tension, CoolPropFluid& fluid) {
1160  fluid.ancillaries.surface_tension = SurfaceTensionCorrelation(surface_tension);
1161  };
1162 
1164  void validate(CoolPropFluid& fluid) {
1165  assert(fluid.EOSVector.size() > 0);
1166  assert(fluid.CAS.length() > 0);
1167  assert(fluid.name.length() > 0);
1168  }
1169 
1170  public:
1171  // Default constructor;
1172  JSONFluidLibrary() {
1173  _is_empty = true;
1174  };
1175  bool is_empty(void) {
1176  return _is_empty;
1177  };
1178 
1180  static void add_many(const std::string& JSON_string);
1181 
1183  void add_many(rapidjson::Value& listing);
1184 
1185  void add_one(rapidjson::Value& fluid_json);
1186 
1187  std::string get_JSONstring(const std::string& key) {
1188  // Try to find it
1189  std::map<std::string, std::size_t>::const_iterator it = string_to_index_map.find(key);
1190  if (it != string_to_index_map.end()) {
1191 
1192  std::map<std::size_t, std::string>::const_iterator it2 = JSONstring_map.find(it->second);
1193  if (it2 != JSONstring_map.end()) {
1194  // Then, load the fluids we would like to add
1195  rapidjson::Document doc;
1196  cpjson::JSON_string_to_rapidjson(it2->second, doc);
1197  rapidjson::Document doc2;
1198  doc2.SetArray();
1199  doc2.PushBack(doc, doc.GetAllocator());
1200  return cpjson::json2string(doc2);
1201  } else {
1202  throw ValueError(format("Unable to obtain JSON string for this identifier [%d]", it->second));
1203  }
1204  } else {
1205  throw ValueError(format("Unable to obtain index for this identifier [%s]", key.c_str()));
1206  }
1207  }
1208 
1210 
1213  CoolPropFluid get(const std::string& key) {
1214  // Try to find it
1215  std::map<std::string, std::size_t>::const_iterator it = string_to_index_map.find(key);
1216  // If it is found
1217  if (it != string_to_index_map.end()) {
1218  return get(it->second);
1219  } else {
1220  // Here we check for the use of a cubic Helmholtz energy transformation for a multi-fluid model
1221  std::vector<std::string> endings;
1222  endings.push_back("-SRK");
1223  endings.push_back("-PengRobinson");
1224  for (std::vector<std::string>::const_iterator end = endings.begin(); end != endings.end(); ++end) {
1225  if (endswith(key, *end)) {
1226  std::string used_name = key.substr(0, key.size() - (*end).size());
1227  it = string_to_index_map.find(used_name);
1228  if (it != string_to_index_map.end()) {
1229  // We found the name of the fluid within the library of multiparameter
1230  // Helmholtz-explicit models. We will load its parameters from the
1231  // multiparameter EOS
1232  //
1233  CoolPropFluid fluid = get(it->second);
1234  // Remove all the residual contributions to the Helmholtz energy
1235  fluid.EOSVector[0].alphar.empty_the_EOS();
1236  // Get the parameters for the cubic EOS
1237  CoolPropDbl Tc = fluid.EOSVector[0].reduce.T;
1238  CoolPropDbl pc = fluid.EOSVector[0].reduce.p;
1239  CoolPropDbl rhomolarc = fluid.EOSVector[0].reduce.rhomolar;
1240  CoolPropDbl acentric = fluid.EOSVector[0].acentric;
1241  CoolPropDbl R = 8.3144598; // fluid.EOSVector[0].R_u;
1242  // Set the cubic contribution to the residual Helmholtz energy
1243  shared_ptr<AbstractCubic> ac;
1244  if (*end == "-SRK") {
1245  ac.reset(new SRK(Tc, pc, acentric, R));
1246  } else if (*end == "-PengRobinson") {
1247  ac.reset(new PengRobinson(Tc, pc, acentric, R));
1248  } else {
1249  throw CoolProp::ValueError(format("Unable to match this ending [%s]", (*end).c_str()));
1250  }
1251  ac->set_Tr(Tc);
1252  ac->set_rhor(rhomolarc);
1253  fluid.EOSVector[0].alphar.cubic = ResidualHelmholtzGeneralizedCubic(ac);
1254  return fluid;
1255  } else {
1256  // Let's look in the library of cubic EOS
1257  CubicLibrary::CubicsValues vals = CubicLibrary::get_cubic_values(used_name);
1258  // Set the cubic contribution to the residual Helmholtz energy
1259  shared_ptr<AbstractCubic> ac;
1260  if (*end == "-SRK") {
1261  ac.reset(new SRK(vals.Tc, vals.pc, vals.acentric, get_config_double(R_U_CODATA)));
1262  } else if (*end == "-PengRobinson") {
1263  ac.reset(new PengRobinson(vals.Tc, vals.pc, vals.acentric, get_config_double(R_U_CODATA)));
1264  } else {
1265  throw CoolProp::ValueError(format("Unable to match this ending [%s]", (*end).c_str()));
1266  }
1267  ac->set_Tr(vals.Tc);
1268  if (vals.rhomolarc > 0) {
1269  ac->set_rhor(vals.rhomolarc);
1270  } else {
1271  // Curve fit from all the pure fluids in CoolProp (thanks to recommendation of A. Kazakov)
1272  double v_c_Lmol = 2.14107171795 * (vals.Tc / vals.pc * 1000) + 0.00773144012514; // [L/mol]
1273  ac->set_rhor(1 / (v_c_Lmol / 1000.0));
1274  }
1275  if (vals.alpha_type == "Twu") {
1276  std::vector<double>& c = vals.alpha_coeffs;
1277  ac->set_C_Twu(0, c[0], c[1], c[2]);
1278  }
1279  CoolPropFluid fluid;
1280  fluid.CAS = vals.CAS;
1281  EquationOfState E;
1282  E.acentric = vals.acentric;
1283  E.sat_min_liquid.T = _HUGE;
1284  E.sat_min_liquid.p = _HUGE;
1285  E.reduce.T = vals.Tc;
1286  E.reduce.p = vals.pc;
1287  E.reduce.rhomolar = ac->get_rhor();
1288  fluid.EOSVector.push_back(E);
1289  fluid.EOS().alphar.cubic = ResidualHelmholtzGeneralizedCubic(ac);
1290  fluid.EOS().alpha0 = vals.alpha0;
1291  fluid.crit.T = vals.Tc;
1292  fluid.crit.p = vals.pc;
1293  fluid.crit.rhomolar = ac->get_rhor();
1294 
1295  return fluid;
1296  }
1297  }
1298  }
1299  throw ValueError(format("key [%s] was not found in string_to_index_map in JSONFluidLibrary", key.c_str()));
1300  }
1301  };
1302 
1304 
1307  CoolPropFluid get(std::size_t key) {
1308  // Try to find it
1309  std::map<std::size_t, CoolPropFluid>::iterator it = fluid_map.find(key);
1310  // If it is found
1311  if (it != fluid_map.end()) {
1312  return it->second;
1313  } else {
1314  throw ValueError(format("key [%d] was not found in JSONFluidLibrary", key));
1315  }
1316  };
1317  void set_fluid_enthalpy_entropy_offset(const std::string& fluid, double delta_a1, double delta_a2, const std::string& ref);
1319  std::string get_fluid_list(void) {
1320  return strjoin(name_vector, get_config_string(LIST_STRING_DELIMITER));
1321  };
1322 };
1323 
1326 
1328 std::string get_fluid_list(void);
1329 
1331 CoolPropFluid get_fluid(const std::string& fluid_string);
1332 
1334 std::string get_fluid_as_JSONstring(const std::string& indentifier);
1335 
1337 void set_fluid_enthalpy_entropy_offset(const std::string& fluid, double delta_a1, double delta_a2, const std::string& ref);
1338 
1339 } /* namespace CoolProp */
1340 #endif
Use TransportRoutines::viscosity_o_xylene_hardcoded.
Definition: CoolPropFluid.h:353
Use TransportRoutines::viscosity_CO2_higher_order_hardcoded_LaeseckeJPCRD2017.
Definition: CoolPropFluid.h:313
The core class for an equation of state.
Definition: CoolPropFluid.h:418
Definition: Ancillaries.h:159
Definition: CoolPropFluid.h:235
bool viscosity_using_rhosr
A flag for whether to use rho*sr CS model of Bell. False for no.
Definition: CoolPropFluid.h:383
ViscosityInitialDensityEmpiricalData empirical
Data for TransportRoutines::viscosity_initial_density_dependence_empirical.
Definition: CoolPropFluid.h:285
SimpleState sat_min_vapor
The saturated vapor state at the minimum saturation temperature.
Definition: CoolPropFluid.h:422
Use TransportRoutines::viscosity_hexane_higher_order_hardcoded.
Definition: CoolPropFluid.h:308
Use TransportRoutines::viscosity_p_xylene_hardcoded.
Definition: CoolPropFluid.h:354
ConductivityHardcodedEnum hardcoded_conductivity
Hardcoded flags for the conductivity.
Definition: CoolPropFluid.h:389
void parse_EOS_listing(rapidjson::Value &EOS_array, CoolPropFluid &fluid)
Parse the list of possible equations of state.
Definition: FluidLibrary.h:433
Use TransportRoutines::viscosity_heptane_higher_order_hardcoded.
Definition: CoolPropFluid.h:309
Ancillaries ancillaries
The set of ancillary equations for dewpoint, bubblepoint, surface tension, etc.
Definition: CoolPropFluid.h:554
static ResidualHelmholtzContainer parse_alphar(rapidjson::Value &jsonalphar)
Parse the contributions to the residual Helmholtz energy.
Definition: FluidLibrary.h:39
void parse_states(rapidjson::Value &states, CoolPropFluid &fluid)
Parse the critical state for the given EOS.
Definition: FluidLibrary.h:1053
bool pseudo_pure
Is a pseudo-pure fluid (true) or pure fluid (false)
Definition: CoolPropFluid.h:435
Variables for the dilute gas part.
Definition: CoolPropFluid.h:220
Use TransportRoutines::viscosity_m_xylene_hardcoded.
Definition: CoolPropFluid.h:352
CoolPropDbl epsilon_over_k
The Lennard-Jones 12-6 parameter.
Definition: CoolPropFluid.h:386
a polynomial in is in use
Definition: Ancillaries.h:227
Use TransportRoutines::viscosity_water_hardcoded.
Definition: CoolPropFluid.h:347
void parse_ancillaries(rapidjson::Value &ancillaries, CoolPropFluid &fluid)
Parse the critical state for the given EOS.
Definition: FluidLibrary.h:1104
Use TransportRoutines::conductivity_hardcoded_heavywater.
Definition: CoolPropFluid.h:360
void parse_dilute_viscosity(rapidjson::Value &dilute, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:440
double get_config_double(configuration_keys key)
Return the value of a double configuration key.
Definition: Configuration.cpp:92
Use TransportRoutines::viscosity_benzene_higher_order_hardcoded.
Definition: CoolPropFluid.h:311
void parse_dilute_conductivity(rapidjson::Value &dilute, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:777
void add_Gaussian(const std::vector< CoolPropDbl > &n, const std::vector< CoolPropDbl > &d, const std::vector< CoolPropDbl > &t, const std::vector< CoolPropDbl > &eta, const std::vector< CoolPropDbl > &epsilon, const std::vector< CoolPropDbl > &beta, const std::vector< CoolPropDbl > &gamma)
Add and convert an old-style Gaussian term to generalized form.
Definition: Helmholtz.h:398
std::vector< double > alpha_coeffs
The vector of coefficients for the alpha function.
Definition: CubicsLibrary.h:26
Definition: CoolPropFluid.h:120
This is generalized class that can be used to manage an ancillary curve, here they are ancillary curv...
Definition: Ancillaries.h:84
ViscosityDiluteCollisionIntegralPowersOfTstarData collision_integral_powers_of_Tstar
Data for TransportRoutines::viscosity_dilute_collision_integral_powers_of_T.
Definition: CoolPropFluid.h:257
JSONFluidLibrary & get_library(void)
Get a reference to the library instance.
Definition: FluidLibrary.cpp:327
ViscosityModifiedBatschinskiHildebrandData modified_Batschinski_Hildebrand
Data for TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand.
Definition: CoolPropFluid.h:319
int get_debug_level()
Get the debug level.
Definition: CoolProp.cpp:64
EOSLimits limits
Limits on the EOS.
Definition: CoolPropFluid.h:429
Definition: CoolPropFluid.h:269
ViscosityRainWaterFriendData rainwater_friend
Data for TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend.
Definition: CoolPropFluid.h:284
std::string get_config_string(configuration_keys key)
Return the value of a string configuration key.
Definition: Configuration.cpp:95
The surface tension correlation class uses correlations for the surface tension that are all of the f...
Definition: Ancillaries.h:24
void parse_EOS(rapidjson::Value &EOS_json, CoolPropFluid &fluid)
Parse the Equation of state JSON entry.
Definition: FluidLibrary.h:337
Use TransportRoutines::viscosity_initial_density_dependence_empirical.
Definition: CoolPropFluid.h:280
std::vector< EquationOfState > EOSVector
The equations of state that could be used for this fluid.
Definition: CoolPropFluid.h:538
std::string BibTeX_CP0
The bibtex key for the ideal gas specific heat correlation.
Definition: CoolPropFluid.h:438
double acentric
Acentric factor (-)
Definition: CubicsLibrary.h:16
double ptriple
Triple point pressure (Pa)
Definition: CoolPropFluid.h:430
std::string BibTeX_conductivity
The BibTeX key for the conductivity model.
Definition: CoolPropFluid.h:378
int type
The data needed for a melting curve formed of segments that are polynomials in .
Definition: Ancillaries.h:241
SimpleState sat_min_liquid
The saturated liquid state at the minimum saturation temperature.
Definition: CoolPropFluid.h:422
SimpleState max_sat_T
The state at the maximum saturation temperature for pseudo-pure.
Definition: CoolPropFluid.h:422
double R_u
The universal gas constant used for this EOS (usually, but not always, 8.314472 J/mol/K) ...
Definition: CoolPropFluid.h:430
void parse_viscosity(rapidjson::Value &viscosity, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:693
Use TransportRoutines::conductivity_hardcoded_methane.
Definition: CoolPropFluid.h:363
bool conductivity_model_provided
A flag for whether thermal conductivity model is provided. False for no.
Definition: CoolPropFluid.h:385
Use TransportRoutines::viscosity_dilute_powers_of_T.
Definition: CoolPropFluid.h:250
void parse_environmental(rapidjson::Value &json, CoolPropFluid &fluid)
Parse the environmental parameters (ODP, GWP, etc.)
Definition: FluidLibrary.h:325
Use TransportRoutines::viscosity_dilute_CO2_LaeseckeJPCRD2017.
Definition: CoolPropFluid.h:249
A thermophysical property provider for critical and reducing values as well as derivatives of Helmhol...
Definition: CoolPropFluid.h:521
void add_Power(const std::vector< CoolPropDbl > &n, const std::vector< CoolPropDbl > &d, const std::vector< CoolPropDbl > &t, const std::vector< CoolPropDbl > &l)
Add and convert an old-style power (polynomial) term to generalized form.
Definition: Helmholtz.h:357
std::string BibTeX_EOS
The bibtex key for the equation of state.
Definition: CoolPropFluid.h:438
Definition: Helmholtz.h:1174
Term in the ideal-gas specific heat equation that is based on Aly-Lee formulation ** Specific heat is...
Definition: Helmholtz.h:1339
CriticalRegionSplines critical_region_splines
A cubic spline in the form T = f(rho) for saturated liquid and saturated vapor curves in the near-cri...
Definition: CoolPropFluid.h:441
Definition: Helmholtz.h:1109
Definition: Helmholtz.h:936
Definition: GeneralizedCubic.h:612
double Ttriple
Triple point temperature (K)
Definition: CoolPropFluid.h:430
Definition: CubicsLibrary.h:14
Definition: Helmholtz.h:573
static IdealHelmholtzContainer parse_alpha0(rapidjson::Value &jsonalpha0)
Parse the contributions to the ideal-gas Helmholtz energy.
Definition: FluidLibrary.h:155
Definition: CoolPropFluid.h:231
Definition: CoolPropFluid.h:157
double get_Tmin(void)
Get the minimum temperature in K.
Definition: Ancillaries.h:143
Definition: Helmholtz.h:515
The leading term in the EOS used to set the desired reference state.
Definition: Helmholtz.h:853
ViscosityFrictionTheoryData friction_theory
Data for TransportRoutines::viscosity_higher_order_friction_theory.
Definition: CoolPropFluid.h:320
Use TransportRoutines::viscosity_hydrogen_higher_order_hardcoded.
Definition: CoolPropFluid.h:307
const EquationOfState & EOS() const
Get a reference to the equation of state.
Definition: CoolPropFluid.h:532
Use TransportRoutines::viscosity_dilute_kinetic_theory.
Definition: CoolPropFluid.h:246
Definition: Exceptions.h:45
Definition: Helmholtz.h:965
Definition: CoolPropFluid.h:296
CoolPropDbl sigma_eta
The Lennard-Jones 12-6 parameter.
Definition: CoolPropFluid.h:386
double molar_mass
The molar mass in kg/mol (note NOT kg/kmol)
Definition: CoolPropFluid.h:430
Definition: CoolPropFluid.h:265
std::string BibTeX
BibTeX key for the melting curve in use.
Definition: Ancillaries.h:234
void add_Lemmon2005(const std::vector< CoolPropDbl > &n, const std::vector< CoolPropDbl > &d, const std::vector< CoolPropDbl > &t, const std::vector< CoolPropDbl > &l, const std::vector< CoolPropDbl > &m)
Add and convert a term from Lemmon and Jacobsen (2005) used for R125.
Definition: Helmholtz.h:442
Use TransportRoutines::viscosity_higher_order_friction_theory.
Definition: CoolPropFluid.h:314
std::string get_fluid_list(void)
Return a comma-separated list of fluid names.
Definition: FluidLibrary.h:1319
SimpleState reduce
Reducing state used for the EOS (usually, but not always, the critical point)
Definition: CoolPropFluid.h:422
Use TransportRoutines::viscosity_dilute_powers_of_Tr.
Definition: CoolPropFluid.h:251
The evaluator class for a melting curve formed of segments in the form.
Definition: Ancillaries.h:175
CoolPropDbl T_m
Melting temperature at 1 atmosphere.
Definition: Ancillaries.h:235
double acentric
The acentric factor .
Definition: CoolPropFluid.h:430
static void add_many(const std::string &JSON_string)
Add all the fluid entries in the JSON-encoded string passed in.
Definition: FluidLibrary.cpp:83
std::string CAS
The CAS number of the fluid.
Definition: CoolPropFluid.h:543
A simon-type curve is in use.
Definition: Ancillaries.h:225
std::string name
The name of the fluid.
Definition: CoolPropFluid.h:540
void parse_transport(rapidjson::Value &transport, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:972
MeltingLinePiecewisePolynomialInTrData polynomial_in_Tr
The data used for a Simon-style curve.
Definition: Ancillaries.h:238
SimpleState hs_anchor
A fixed anchor state at Tc*1.1 and rhoc*0.9 used as a reference state for enthalpy and entropy ancill...
Definition: CoolPropFluid.h:422
double pc
Critical pressure (Pa)
Definition: CubicsLibrary.h:16
std::string get_fluid_as_JSONstring(const std::string &identifier)
Get the fluid as a JSON string, suitable for modification and reloading.
Definition: FluidLibrary.cpp:341
SimpleState triple_vapor
The saturated vapor state at the triple point temperature.
Definition: CoolPropFluid.h:556
Use TransportRoutines::viscosity_ethane_higher_order_hardcoded.
Definition: CoolPropFluid.h:310
double rhomolarc
Critical density (mol/m3) (initialized to an invalid negative number)
Definition: CubicsLibrary.h:16
The evaluator class for a melting curve formed of segments in the form.
Definition: Ancillaries.h:200
void parse_surface_tension(rapidjson::Value &surface_tension, CoolPropFluid &fluid)
Parse the surface_tension.
Definition: FluidLibrary.h:1159
double Tc
Critical temperature (K)
Definition: CubicsLibrary.h:16
Definition: Helmholtz.h:796
Use TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand.
Definition: CoolPropFluid.h:306
SimpleState triple_liquid
The saturated liquid state at the triple point temperature.
Definition: CoolPropFluid.h:556
Use TransportRoutines::viscosity_dilute_ethane.
Definition: CoolPropFluid.h:247
Use TransportRoutines::conductivity_hardcoded_helium.
Definition: CoolPropFluid.h:362
void parse_higher_order_viscosity(rapidjson::Value &higher, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:536
Definition: GeneralizedCubic.h:632
Use TransportRoutines::viscosity_toluene_higher_order_hardcoded.
Definition: CoolPropFluid.h:312
std::string BibTeX_viscosity
The BibTeX key for the viscosity model.
Definition: CoolPropFluid.h:378
MeltingLinePiecewisePolynomialInThetaData polynomial_in_Theta
The data needed for a melting curve formed of segments that are polynomials in .
Definition: Ancillaries.h:240
CoolPropFluid get_fluid(const std::string &fluid_string)
Get the fluid structure.
Definition: FluidLibrary.cpp:334
Use TransportRoutines::viscosity_dilute_collision_integral.
Definition: CoolPropFluid.h:244
void set_limits()
Evaluate the melting line to calculate the limits of the curve (Tmin/Tmax and pmin/pmax) ...
Definition: Ancillaries.cpp:105
bool viscosity_model_provided
A flag for whether viscosity model is provided. False for no.
Definition: CoolPropFluid.h:384
SimpleState crit
The state at the critical point.
Definition: CoolPropFluid.h:556
ViscosityDiluteGasPowersOfTr powers_of_Tr
Data for TransportRoutines::viscosity_dilute_powers_of_Tr.
Definition: CoolPropFluid.h:259
The term in the EOS used to shift the reference state of the fluid.
Definition: Helmholtz.h:886
Use TransportRoutines::viscosity_R23_hardcoded.
Definition: CoolPropFluid.h:350
void validate(CoolPropFluid &fluid)
Validate the fluid file that was just constructed.
Definition: FluidLibrary.h:1164
Definition: Helmholtz.h:1142
bool viscosity_using_ECS
A flag for whether to use extended corresponding states for viscosity. False for no.
Definition: CoolPropFluid.h:380
EnvironmentalFactorsStruct environment
The environmental variables for global warming potential, ODP, etc.
Definition: CoolPropFluid.h:553
Use TransportRoutines::viscosity_helium_hardcoded.
Definition: CoolPropFluid.h:349
void parse_thermal_conductivity(rapidjson::Value &conductivity, CoolPropFluid &fluid)
Parse the thermal conductivity data.
Definition: FluidLibrary.h:924
void parse_initial_density_viscosity(rapidjson::Value &initial_density, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:505
CoolPropDbl T_reducing
Reducing temperature [K[.
Definition: CoolPropFluid.h:227
Use TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend.
Definition: CoolPropFluid.h:279
ViscosityDiluteGasPowersOfT powers_of_T
Data for TransportRoutines::viscosity_dilute_powers_of_T.
Definition: CoolPropFluid.h:258
IdealHelmholtzContainer alpha0
The ideal Helmholtz energy.
Definition: CoolPropFluid.h:437
Use TransportRoutines::conductivity_hardcoded_water.
Definition: CoolPropFluid.h:359
Use TransportRoutines::viscosity_heavywater_hardcoded.
Definition: CoolPropFluid.h:348
Use TransportRoutines::conductivity_hardcoded_R23.
Definition: CoolPropFluid.h:361
This file contains flash routines in which the state is unknown, and a solver of some kind must be us...
Definition: AbstractState.h:19
CoolPropDbl C
Leading constant.
Definition: CoolPropFluid.h:227
Use TransportRoutines::viscosity_dilute_collision_integral_powers_of_T.
Definition: CoolPropFluid.h:245
bool conductivity_using_ECS
A flag for whether to use extended corresponding states for conductivity. False for no...
Definition: CoolPropFluid.h:381
bool viscosity_using_Chung
A flag for whether to use Chung model. False for no.
Definition: CoolPropFluid.h:382
ViscosityHardcodedEnum hardcoded_viscosity
Hardcoded flags for the viscosity.
Definition: CoolPropFluid.h:388
SimpleState max_sat_p
The state at the maximum saturation pressure for pseudo-pure.
Definition: CoolPropFluid.h:422
A container for the fluid parameters for the CoolProp fluids.
Definition: FluidLibrary.h:27
void parse_residual_conductivity(rapidjson::Value &dilute, CoolPropFluid &fluid)
Parse the transport properties.
Definition: FluidLibrary.h:828
ResidualHelmholtzContainer alphar
The residual Helmholtz energy.
Definition: CoolPropFluid.h:436
a polynomial in is in use
Definition: Ancillaries.h:226
std::string alpha_type
The type of alpha function.
Definition: CubicsLibrary.h:25
Definition: Helmholtz.h:1073
void add_Exponential(const std::vector< CoolPropDbl > &n, const std::vector< CoolPropDbl > &d, const std::vector< CoolPropDbl > &t, const std::vector< CoolPropDbl > &g, const std::vector< CoolPropDbl > &l)
Add and convert an old-style exponential term to generalized form.
Definition: Helmholtz.h:379
Use TransportRoutines::viscosity_dilute_cyclohexane.
Definition: CoolPropFluid.h:248
IdealHelmholtzContainer alpha0
The ideal Helmholtz energy.
Definition: CubicsLibrary.h:27
void validate()
Validate the EOS that was just constructed.
Definition: CoolPropFluid.h:444
Use TransportRoutines::viscosity_methanol_hardcoded.
Definition: CoolPropFluid.h:351
ViscosityDiluteGasCollisionIntegralData collision_integral
Data for TransportRoutines::viscosity_dilute_collision_integral.
Definition: CoolPropFluid.h:255