teqp 0.22.0
Loading...
Searching...
No Matches
GERG.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4#include <unordered_map>
5#include <map>
6#include <string>
7#include <optional>
8#include <utility>
9#include <set>
10#include <unordered_set>
11
13#include "teqp/types.hpp"
14#include "teqp/exceptions.hpp"
15
16#include "Eigen/Dense"
17#include <boost/functional/hash.hpp>
18
19namespace teqp{
20
21namespace GERGGeneral{
22struct PureInfo{
24};
26 std::vector<double> n, t, d, c, l;
27 std::set<std::size_t> sizes(){ return {n.size(), t.size(), d.size(), c.size(), l.size()}; }
28};
31};
33 std::vector<double> n, t, d, eta, beta, gamma, epsilon;
34 std::set<std::size_t> sizes(){ return {n.size(), t.size(), d.size(), eta.size(), beta.size(), gamma.size(), epsilon.size()}; }
35};
37 std::vector<double> n0, theta0;
38 std::set<std::size_t> sizes(){ return {n0.size(), theta0.size()}; }
39
49 auto recalc_integration_constants(double T, double Tci, double rho, double rhoci, double Rstar_R){
50
51 // terms multiplying first two multiplicative constants, then the constant term that does not depend on the integration constants
52 std::vector<double> Aig00 = {Rstar_R, Rstar_R*Tci/T, log(rho/rhoci) + Rstar_R*(n0[3]*log(Tci/T)
53 + ((n0[4] != 0) ? n0[4]*log(std::abs(sinh(theta0[4]*Tci/T))) : 0)
54 + ((n0[6] != 0) ? n0[6]*log(std::abs(sinh(theta0[6]*Tci/T))) : 0)
55 - ((n0[5] != 0) ? n0[5]*log(std::abs(cosh(theta0[5]*Tci/T))) : 0)
56 - ((n0[7] != 0) ? n0[7]*log(std::abs(cosh(theta0[7]*Tci/T))) : 0))
57 };
58 std::vector<double> Aig10 = {0, Rstar_R*Tci/T, Rstar_R*(n0[3]
59 + ((n0[4] != 0) ? n0[4]*theta0[4]*Tci/T/tanh(theta0[4]*Tci/T) : 0)
60 + ((n0[6] != 0) ? n0[6]*theta0[6]*Tci/T/tanh(theta0[6]*Tci/T) : 0)
61 - n0[5]*theta0[5]*Tci/T*tanh(theta0[5]*Tci/T) - n0[7]*theta0[7]*Tci/T*tanh(theta0[7]*Tci/T))};
62
63// double n2 = (-1-Aig10[2])/Aig10[1];
64
65 Eigen::MatrixXd A(2,2), b(2,1);
66 b(0) = -1-Aig10[2]; // h0/(RT) = 1 + Aig10, so Aig = -1 if h0 = 0, move constants to other side
67 A(0,0) = Aig10[0];
68 A(0,1) = Aig10[1];
69 b(1) = -Aig10[2] + Aig00[2]; // s0/(RT) = Aig10 - Aig00, move constants to the other side
70 A(1,0) = Aig10[0] - Aig00[0];
71 A(1,1) = Aig10[1] - Aig00[1];
72 Eigen::ArrayXd n12 = A.colPivHouseholderQr().solve(b);
73 return n12;
74 }
75};
76
77
78// ***********************************************************
79// ***********************************************************
80// Pures, Reducing, Corresponding States
81// ***********************************************************
82// ***********************************************************
83
88private:
89 PureCoeffs pc;
90 std::vector<int> l_i;
91 auto get_li(std::vector<double>&el){
92 std::vector<int> li(el.size());
93 for (auto i = 0U; i < el.size(); ++i){
94 li[i] = static_cast<int>(el[i]);
95 }
96 return li;
97 }
98
99public:
100 using GetPureCoeffs = std::function<PureCoeffs(const std::string&)>;
101 GERG200XPureFluidEOS(const std::string& name, const GetPureCoeffs& get_pure_coeffs): pc(get_pure_coeffs(name)), l_i(get_li(pc.l)){}
102
103 template<typename TauType, typename DeltaType>
104 auto alphar(const TauType& tau, const DeltaType& delta) const {
105 using result = std::common_type_t<TauType, DeltaType>;
106 result r = 0.0, lntau = log(tau);
107 if (l_i.size() == 0 && pc.n.size() > 0) {
108 throw std::invalid_argument("l_i cannot be zero length if some terms are provided");
109 }
110 if (getbaseval(delta) == 0) {
111 for (auto i = 0U; i < pc.n.size(); ++i) {
112 r = r + pc.n[i] * exp(pc.t[i] * lntau - pc.c[i] * powi(delta, l_i[i])) * powi(delta, static_cast<int>(pc.d[i]));
113 }
114 }
115 else {
116 result lndelta = log(delta);
117 for (auto i = 0U; i < pc.n.size(); ++i) {
118 r = r + pc.n[i] * exp(pc.t[i] * lntau + pc.d[i] * lndelta - pc.c[i] * powi(delta, l_i[i]));
119 }
120 }
121 return forceeval(r);
122 }
123};
124
126public:
127 // As a structure to allow them to be initialized in one
128 // pass through the fluids
129 struct TcVc{ std::vector<double> Tc_K, vc_m3mol; };
130 struct Matrices {Eigen::ArrayXXd betaT, gammaT, betaV, gammaV, YT, Yv; };
131 using GetPureInfo = std::function<PureInfo(const std::string&)>;
133 using GetBetasGammas = std::function<BetasGammas(const std::string&,const std::string&)>;
135private:
136 TcVc get_Tcvc(const std::vector<std::string>& names){
137 std::vector<double> Tc(names.size()), vc(names.size());
138 std::size_t i = 0;
139 for (auto &name : names){
140 auto pd = _get_pure_info(name);
141 Tc[i] = pd.Tc_K;
142 vc[i] = 1.0/pd.rhoc_molm3;
143 i++;
144 }
145 return TcVc{Tc, vc};
146 }
147 Matrices get_matrices(const std::vector<std::string>& names){
148 Matrices m;
149 std::size_t N = names.size();
150 m.betaT.resize(N,N); m.gammaT.resize(N,N); m.betaV.resize(N,N); m.gammaV.resize(N,N); m.YT.resize(N,N); m.Yv.resize(N,N);
151 const auto& Tc = m_Tcvc.Tc_K;
152 const auto& vc = m_Tcvc.vc_m3mol;
153 for (auto i = 0U; i < N; ++i){
154 for (auto j = i+1; j < N; ++j){
155 auto bg = _get_betasgammas(names[i], names[j]);
156 m.betaT(i,j) = bg.betaT; m.betaT(j,i) = 1/bg.betaT;
157 m.gammaT(i,j) = bg.gammaT; m.gammaT(j,i) = bg.gammaT;
158 m.betaV(i,j) = bg.betaV; m.betaV(j,i) = 1/bg.betaV;
159 m.gammaV(i,j) = bg.gammaV; m.gammaV(j,i) = bg.gammaV;
160
161 m.YT(i,j) = m.betaT(i,j)*m.gammaT(i,j)*sqrt(Tc[i]*Tc[j]);
162 m.YT(j,i) = m.betaT(j,i)*m.gammaT(j,i)*sqrt(Tc[j]*Tc[i]);
163 m.Yv(i,j) = 1.0/8.0*m.betaV(i,j)*m.gammaV(i,j)*POW3(cbrt(vc[i]) + cbrt(vc[j]));
164 m.Yv(j,i) = 1.0/8.0*m.betaV(j,i)*m.gammaV(j,i)*POW3(cbrt(vc[j]) + cbrt(vc[i]));
165 }
166 m.YT(i,i) = Tc[i];
167 m.Yv(i,i) = vc[i];
168 }
169 return m;
170 }
171 const TcVc m_Tcvc;
172 const Matrices matrices;
173public:
174 GERG200XReducing(const std::vector<std::string>& names, const GetPureInfo &get_pure_info, const GetBetasGammas& get_betasgammas): _get_pure_info(get_pure_info), _get_betasgammas(get_betasgammas), m_Tcvc(get_Tcvc(names)), matrices(get_matrices(names)) {}
175
176 auto get_Tcvec() const { return m_Tcvc.Tc_K; }
177 auto get_vcvec() const { return m_Tcvc.vc_m3mol; }
178
179 template<typename MoleFractions>
180 auto Y(const MoleFractions& z, const std::vector<double>& Yc, const Eigen::ArrayXXd& beta, const Eigen::ArrayXXd& Yij) const {
181 using resulttype = std::common_type_t<decltype(z[0])>;
182 resulttype sum1 = 0.0, sum2 = 0.0;
183 std::size_t N = z.size();
184
185 for (auto i = 0U; i < N; ++i){
186 sum1 += z[i]*z[i]*Yc[i];
187 for (auto j = i+1; j < N; ++j){
188 auto denom = POW2(beta(i,j))*z[i]+z[j];
189 if (getbaseval(denom) != 0){
190 sum2 += 2.0*z[i]*z[j]*(z[i]+z[j])/denom*Yij(i,j);
191 }
192 }
193 }
194 return forceeval(sum1 + sum2);
195 }
196
197 template<typename MoleFractions>
198 auto get_Tr(const MoleFractions& z) const {
199 return Y(z, m_Tcvc.Tc_K, matrices.betaT, matrices.YT);
200 }
201
202 template<typename MoleFractions>
203 auto get_rhor(const MoleFractions& z) const{
204 return 1.0/Y(z, m_Tcvc.vc_m3mol, matrices.betaV, matrices.Yv);
205 }
206};
207
209public:
210 using GetPureCoeffs = std::function<PureCoeffs(const std::string&)>;
212
213private:
214 const std::vector<GERG200XPureFluidEOS> EOSs;
215 auto get_EOS(const std::vector<std::string>& names){
216 std::vector<GERG200XPureFluidEOS> theEOS;
217 for (auto& name: names){
218 theEOS.emplace_back(name, _get_pure_coeffs);
219 }
220 return theEOS;
221 }
222public:
223 GERG200XCorrespondingStatesTerm(const std::vector<std::string>& names, const GetPureCoeffs &get_pure_coeffs) : _get_pure_coeffs(get_pure_coeffs), EOSs(get_EOS(names)) {};
224
225 std::size_t size() const { return EOSs.size(); }
226
227 template<typename TauType, typename DeltaType, typename MoleFractions>
228 auto alphar(const TauType& tau, const DeltaType& delta, const MoleFractions& molefracs) const {
229 using resulttype = std::common_type_t<decltype(tau), decltype(molefracs[0]), decltype(delta)>; // Type promotion, without the const-ness
230 resulttype alphar = 0.0;
231 auto N = molefracs.size();
232 if (static_cast<std::size_t>(N) != size()){
233 throw std::invalid_argument("wrong size");
234 }
235 for (auto i = 0U; i < N; ++i) {
236 alphar += molefracs[i] * EOSs[i].alphar(tau, delta);
237 }
238 return forceeval(alphar);
239 }
240};
241
242// ***********************************************************
243// ***********************************************************
244// Departure
245// ***********************************************************
246// ***********************************************************
247
248
250private:
251 const DepartureCoeffs dc;
252public:
253 using GetDepartureCoeffs = std::function<DepartureCoeffs(const std::string&, const std::string&)>;
255 GERG200XDepartureFunction(const std::string& fluid1, const std::string& fluid2, const GetDepartureCoeffs& get_departurecoeffs) : dc(get_departurecoeffs(fluid1, fluid2)){}
256
257 template<typename TauType, typename DeltaType>
258 auto alphar(const TauType& tau, const DeltaType& delta) const {
259 using result = std::common_type_t<TauType, DeltaType>;
260 result r = 0.0, lntau = log(tau);
261 auto square = [](auto x) { return forceeval(x * x); };
262 if (getbaseval(delta) == 0) {
263 for (auto i = 0U; i < dc.n.size(); ++i) {
264 r += dc.n[i] * exp(dc.t[i] * lntau - dc.eta[i] * square(delta - dc.epsilon[i]) - dc.beta[i] * (delta - dc.gamma[i]))*powi(delta, static_cast<int>(dc.d[i]));
265 }
266 }
267 else {
268 result lndelta = log(delta);
269 for (auto i = 0U; i < dc.n.size(); ++i) {
270 r += dc.n[i] * exp(dc.t[i] * lntau + dc.d[i] * lndelta - dc.eta[i] * square(delta - dc.epsilon[i]) - dc.beta[i] * (delta - dc.gamma[i]));
271 }
272 }
273 return forceeval(r);
274 }
275};
276
278public:
279 using GetFij = std::function<std::optional<double>(const std::string&, const std::string&, bool)>;
281 using GetDepartureCoeffs = std::function<DepartureCoeffs(const std::string&, const std::string&)>;
283private:
284 const Eigen::ArrayXXd Fmat;
285 const std::vector<std::vector<GERG200XDepartureFunction>> depmat;
286
287 auto get_Fmat(const std::vector<std::string>& names){
288 std::size_t N = names.size();
289 Eigen::ArrayXXd mat(N, N); mat.setZero();
290 for (auto i = 0U; i < N; ++i){
291 for (auto j = i+1; j < N; ++j){
292 auto Fij = _get_Fij(names[i], names[j], true /* ok_missing */);
293 if (Fij){
294 mat(i,j) = Fij.value();
295 mat(j,i) = mat(i,j); // Fij are symmetric
296 }
297 }
298 }
299 return mat;
300 }
301 auto get_depmat(const std::vector<std::string>& names){
302 std::size_t N = names.size();
303 std::vector<std::vector<GERG200XDepartureFunction>> mat;
304 for (auto i = 0U; i < N; ++i){
305 std::vector<GERG200XDepartureFunction> row;
306 for (auto j = 0U; j < N; ++j){
307 if (i != j && Fmat(i,j) != 0){
308 row.emplace_back(names[i], names[j], _get_departurecoeffs);
309 }
310 else{
311 row.emplace_back();
312 }
313 }
314 mat.emplace_back(row);
315 }
316 return mat;
317 }
318public:
319
320 GERG200XDepartureTerm(const std::vector<std::string>& names, const GetFij& get_Fij, const GetDepartureCoeffs& get_departurecoeffs) : _get_Fij(get_Fij), _get_departurecoeffs(get_departurecoeffs), Fmat(get_Fmat(names)), depmat(get_depmat(names)) {};
321
322 template<typename TauType, typename DeltaType, typename MoleFractions>
323 auto alphar(const TauType& tau, const DeltaType& delta, const MoleFractions& molefracs) const {
324 using resulttype = std::common_type_t<decltype(tau), decltype(delta), decltype(molefracs[0])>; // Type promotion, without the const-ness
325 resulttype alphar = 0.0;
326 auto N = molefracs.size();
327 if (static_cast<std::size_t>(N) != static_cast<std::size_t>(Fmat.cols())){
328 throw std::invalid_argument("wrong size");
329 }
330
331 for (auto i = 0U; i < N; ++i){
332 for (auto j = i+1; j < N; ++j){
333 auto Fij = Fmat(i,j);
334 if (Fij != 0){
335 alphar += molefracs[i]*molefracs[j]*Fij*depmat[i][j].alphar(tau, delta);
336 }
337 }
338 }
339 return alphar;
340 }
341};
342
344public:
345 using GetPureInfo = std::function<PureInfo(const std::string&)>;
347 using GetAlphaigCoeffs = std::function<AlphaigCoeffs(const std::string&)>;
349
350 const double Rstar = 8.314510; // J/mol/K
351 const double R = 8.314472; // J/mol/K
352
353 const std::vector<double> Tc, rhoc;
354 const std::vector<AlphaigCoeffs> coeffs;
355
356private:
357 auto get_Tc(const GetPureInfo& getter, const std::vector<std::string>& names) const{
358 std::vector<double> Tc_;
359 for (auto i = 0U; i < names.size(); ++i){
360 Tc_.emplace_back(getter(names[i]).Tc_K);
361 }
362 return Tc_;
363 }
364 auto get_rhoc(const GetPureInfo& getter, const std::vector<std::string>& names) const{
365 std::vector<double> rhoc_;
366 for (auto i = 0U; i < names.size(); ++i){
367 rhoc_.emplace_back(getter(names[i]).rhoc_molm3);
368 }
369 return rhoc_;
370 }
371 auto get_coeffs(const GetAlphaigCoeffs& getter, const std::vector<std::string>& names) const{
372 std::vector<AlphaigCoeffs> coeffs_;
373 for (auto i = 0U; i < names.size(); ++i){
374 coeffs_.emplace_back(getter(names[i]));
375 auto& coeff = coeffs_.back();
376
377 // And set the integration constants to yield precisely h=s=0 at 298.15 K and 101325 Pa
378 double T0 = 298.15/* K */, p0 = 101325 /* Pa */, rho0 = p0/(R*T0);
379 auto n12 = coeff.recalc_integration_constants(T0, Tc[i], rho0, rhoc[i], Rstar/R);
380 coeff.n0[1] = n12[0];
381 coeff.n0[2] = n12[1];
382 }
383 return coeffs_;
384 }
385
386public:
387
388 GERG200XAlphaig(const std::vector<std::string> &names, const GetPureInfo &get_pure_info, const GetAlphaigCoeffs & get_alphaig_coeffs) : Tc(get_Tc(get_pure_info, names)), rhoc(get_rhoc(get_pure_info, names)), coeffs(get_coeffs(get_alphaig_coeffs,names)) {
389 if (coeffs.size() != Tc.size()){
390 throw teqp::InvalidArgument("Bad sizes");
391 }
392 };
393
394 std::size_t size() const { return Tc.size(); }
395
396 template<typename TType, typename RhoType>
397 auto alphaig_pure(const TType& T, const RhoType& rhomolar, const int i) const {
398 const auto& c = coeffs[i];
399 const std::vector<double>& n0i = c.n0;
400 const std::vector<double>& theta0i = c.theta0;
401 using std::abs;
402 double Tci = Tc[i];
403 auto out = forceeval(n0i[1] + n0i[2]*Tci/T+ n0i[3]*log(Tci/T));
404 if (theta0i[4] != 0) { out += n0i[4]*log(abs(sinh(theta0i[4]*Tci/T))); }
405 if (theta0i[6] != 0) { out += n0i[6]*log(abs(sinh(theta0i[6]*Tci/T))); }
406 if (theta0i[5] != 0) { out -= n0i[5]*log(abs(cosh(theta0i[5]*Tci/T))); }
407 if (theta0i[7] != 0) { out -= n0i[7]*log(abs(cosh(theta0i[7]*Tci/T))); }
408 return forceeval(log(rhomolar/rhoc[i]) + Rstar/R*out); // Note that the GERG-2004 manuscript has the wrong location for the ratio Rstar/R and the GERG-2008 manuscript is correct
409 }
410
411 template<typename TType, typename RhoType, typename MoleFractions>
412 auto alphaig(const TType& T, const RhoType& rhomolar, const MoleFractions& molefracs) const {
413 using resulttype = std::decay_t<std::common_type_t<decltype(T), decltype(rhomolar), decltype(molefracs[0])>>; // Type promotion, without the const-ness
414 resulttype alpha = 0.0;
415 for (auto i = 0U; i < molefracs.size(); ++i){
416 if (getbaseval(molefracs[i]) > 0){
417 // If x_i = 0, log(x_i) is -oo, but lim_{x_i -> 0}(x_i*log(x_i)) is zero
418 alpha += molefracs[i]*(alphaig_pure(T, rhomolar, i) + log(molefracs[i]));
419 }
420 }
421 return alpha;
422 }
423};
424
425}
426
427namespace GERG2004{
428
429using namespace GERGGeneral;
430
431const std::vector<std::string> component_names = {"methane", "nitrogen","carbondioxide","ethane","propane","n-butane","isobutane","n-pentane","isopentane","n-hexane","n-heptane","n-octane","hydrogen", "oxygen","carbonmonoxide","water","helium","argon"};
432
434inline PureInfo get_pure_info(const std::string& name){
435
436 // From Table A3.5 from GERG 2004 monograph
437 // Data in table are in mol/dm3, K, kg/kmol, so some conversion is needed
438 static std::map<std::string, PureInfo> data_map = {
439 {"methane", {10.139342719,190.564000000,16.042460}},
440 {"nitrogen", {11.183900000,126.192000000,28.013400}},
441 {"carbondioxide", {10.624978698,304.128200000,44.009500}},
442 {"ethane", {6.870854540,305.322000000,30.069040}},
443 {"propane", {5.000043088,369.825000000,44.095620}},
444 {"n-butane", {3.920016792,425.125000000,58.122200}},
445 {"isobutane", {3.860142940,407.817000000,58.122200}},
446 {"n-pentane", {3.215577588,469.700000000,72.148780}},
447 {"isopentane", {3.271018581,460.350000000,72.148780}},
448 {"n-hexane", {2.705877875,507.820000000,86.175360}},
449 {"n-heptane", {2.315324434,540.130000000,100.201940}},
450 {"n-octane", {2.056404127,569.320000000,114.228520}},
451 {"hydrogen", {14.940000000,33.190000000 ,2.015880}},
452 {"oxygen", {13.630000000,154.595000000,31.998800}},
453 {"carbonmonoxide", {10.850000000,132.800000000,28.010100}},
454 {"water", {17.873716090,647.096000000,18.015280}},
455 {"helium", {17.399000000,5.195300000,4.002602}},
456 {"argon", {13.407429659,150.687,39.948000}}
457 };
458 if (data_map.find(name) == data_map.end()){
459 throw std::invalid_argument("Unable to load pure info for "+name);
460 }
461 auto data = data_map.at(name);
462 data.rhoc_molm3 *= 1000; // mol/dm^3 -> mol/m^3
463 data.M_kgmol /= 1000; // kg/kmol -> kg/mol
464 return data;
465}
466
467
468inline AlphaigCoeffs get_alphaig_coeffs(const std::string& fluid){
469
470 static std::unordered_map<std::string, std::pair<std::vector<double>, std::vector<double>>> dict = {
471 {"methane", {{19.597538587, -83.959667892, 3.000880, 0.763150, 0.00460, 8.744320, -4.469210000}, {4.306474465, 0.936220902, 5.577233895, 5.722644361}}},
472 {"nitrogen", {{11.083437707, -22.202102428, 2.500310, 0.137320, -0.14660, 0.900660, 0}, {5.251822620, -5.393067706, 13.788988208, 0}}},
473 {"carbondioxide", {{11.925182741, -16.118762264, 2.500020, 2.044520, -1.060440, 2.033660, 0.013930000}, {3.022758166, -2.844425476, 1.589964364, 1.121596090}}},
474 {"ethane", {{24.675465518, -77.425313760, 3.002630, 4.339390, 1.237220, 13.19740, -6.019890000}, {1.831882406, 0.731306621, 3.378007481, 3.508721939}}},
475 {"propane", {{31.602934734, -84.463284382, 3.029390, 6.605690, 3.1970, 19.19210, -8.372670000}, {1.297521801, 0.543210978, 2.583146083, 2.777773271}}},
476 {"n-butane", {{20.884168790, -91.638478026, 3.339440, 9.448930, 6.894060, 24.46180, 14.782400000}, {1.101487798, 0.431957660, 4.502440459, 2.124516319}}},
477 {"isobutane", {{20.413751434, -94.467620036, 3.067140, 8.975750, 5.251560, 25.14230, 16.138800000 }, {1.074673199, 0.485556021, 4.671261865, 2.191583480}}},
478 {"n-pentane", {{14.536635738, -89.919548319, 3.0, 8.950430, 21.8360, 33.40320, 0}, {0.380391739, 1.789520971, 3.777411113, 0}}},
479 {"isopentane", {{15.449937973, -101.298172792, 3.0, 11.76180, 20.11010, 33.16880, 0}, {0.635392636, 1.977271641, 4.169371131, 0}}},
480 {"n-hexane", {{14.345993081,-96.165722367,3.0,11.69770,26.81420,38.61640,0}, {0.359036667, 1.691951873, 3.596924107, 0}}},
481 {"n-heptane", {{15.063809621, -97.345252349, 3.0, 13.72660, 30.47070, 43.55610, 0}, {0.314348398, 1.548136560, 3.259326458, 0}}},
482 {"n-octane", {{15.864709639, -97.370667555, 3.0, 15.68650, 33.80290, 48.17310, 0}, {0.279143540, 1.431644769, 2.973845992,0}}},
483 {"hydrogen", {{13.796474934, -175.864487294, 1.479060, 0.958060, 0.454440, 1.560390, -1.375600000}, {6.891654113, 9.847634830, 49.765290750, 50.367279301}}},
484 {"oxygen", {{10.001874708,-14.996095135,2.501460,1.075580,1.013340,0,0}, {14.461722565, 7.223325463, 0, 0}}},
485 {"carbonmonoxide", {{10.814500335, -19.843695435, 2.500550, 1.028650, 0.004930, 0, 0}, {11.675075301, 5.305158133, 0, 0}}},
486 {"water", {{8.203553050, -11.996306443, 3.003920, 0.010590, 0.987630, 3.069040, 0}, {0.415386589, 1.763895929, 3.874803739,0}}},
487 {"helium", {{13.628441975,-143.470759602,1.5,0,0,0,0}, {0,0,0,0}}},
488 {"argon", {{8.316662546, -4.946502600,1.50,0,0,0,0}, {0,0,0,0}}}
489 };
490
491 if (dict.find(fluid) != dict.end()){
492 auto [n, theta] = dict[fluid];
493 if (n.size() != 7){
494 throw std::invalid_argument(fluid + " does not have 7 n coefficients in ideal gas");
495 }
496 if (theta.size() != 4){
497 throw std::invalid_argument(fluid + " does not have 4 theta coefficients in ideal gas");
498 }
500 c.n0 = n;
501 c.n0.insert(c.n0.begin(), 0.0); // 0-pad the array to have the indexing match GERG-2004
502 c.theta0 = theta;
503 c.theta0.insert(c.theta0.begin(), 4, 0.0); // 0-pad the array to have the indexing match GERG-2004
504 return c;
505 }
506 else{
507 throw std::invalid_argument("Not able to get ideal-gas coefficients for " + fluid);
508 }
509}
510
511inline PureCoeffs get_pure_coeffs(const std::string& fluid){
512
513 // From Table A3.2 from GERG 2004 monograph
514 static std::map<std::string, std::vector<double>> n_dict_mne = {
515 {"methane", {0.57335704239162,-0.16760687523730e1,0.23405291834916,-0.21947376343441,0.16369201404128e-1,0.15004406389280e-1,0.98990489492918e-1,0.58382770929055,-0.74786867560390,0.30033302857974,0.20985543806568,-0.18590151133061e-1,-0.15782558339049,0.12716735220791,-0.32019743894346e-1,-0.68049729364536e-1,0.24291412853736e-1,0.51440451639444e-2,-0.19084949733532e-1,0.55229677241291e-2,-0.44197392976085e-2,0.40061416708429e-1,-0.33752085907575e-1,-0.25127658213357e-2}},
516 {"nitrogen", { 0.59889711801201,-0.16941557480731e1,0.24579736191718,-0.23722456755175,0.17954918715141e-1,0.14592875720215e-1,0.10008065936206,0.73157115385532,-0.88372272336366,0.31887660246708,0.20766491728799,-0.19379315454158e-1,-0.16936641554983,0.13546846041701,-0.33066712095307e-1,-0.60690817018557e-1,0.12797548292871e-1,0.58743664107299e-2,-0.18451951971969e-1,0.47226622042472e-2,-0.52024079680599e-2,0.43563505956635e-1,-0.36251690750939e-1,-0.28974026866543e-2}},
517 {"ethane", { 0.63596780450714,-0.17377981785459e1,0.28914060926272,-0.33714276845694,0.22405964699561e-1,0.15715424886913e-1,0.11450634253745,0.10612049379745e1,-0.12855224439423e1,0.39414630777652,0.31390924682041,-0.21592277117247e-1,-0.21723666564905,-0.28999574439489,0.42321173025732,0.46434100259260e-1,-0.13138398329741,0.11492850364368e-1,-0.33387688429909e-1,0.15183171583644e-1,-0.47610805647657e-2,0.46917166277885e-1,-0.39401755804649e-1,-0.32569956247611e-2}}
518 };
519
520 static std::map<std::string, std::vector<double>> n_dict_main = {
521 {"propane", {0.10403973107358e1,-0.28318404081403e1,0.84393809606294,-0.76559591850023e-1,0.94697373057280e-1,0.24796475497006e-3,0.27743760422870,-0.43846000648377e-1,-0.26991064784350,-0.69313413089860e-1,-0.29632145981653e-1,0.14040126751380e-1}},
522 {"n-butane", { 0.10626277411455e1,-0.28620951828350e1,0.88738233403777,-0.12570581155345,0.10286308708106,0.25358040602654e-3,0.32325200233982,-0.37950761057432e-1,-0.32534802014452,-0.79050969051011e-1,-0.20636720547775e-1,0.57053809334750e-2}},
523 {"isobutane", {0.10429331589100e1,-0.28184272548892e1,0.86176232397850,-0.10613619452487,0.98615749302134e-1,0.23948208682322e-3,0.30330004856950,-0.41598156135099e-1,-0.29991937470058,-0.80369342764109e-1,-0.29761373251151e-1,0.13059630303140e-1}},
524 {"n-pentane", {0.10968643098001e1,-0.29988888298061e1,0.99516886799212,-0.16170708558539,0.11334460072775,0.26760595150748e-3,0.40979881986931,-0.40876423083075e-1,-0.38169482469447,-0.10931956843993,-0.32073223327990e-1,0.16877016216975e-1}},
525 {"isopentane", {0.11017531966644e1,-0.30082368531980e1,0.99411904271336,-0.14008636562629,0.11193995351286,0.29548042541230e-3,0.36370108598133,-0.48236083488293e-1,-0.35100280270615,-0.10185043812047,-0.35242601785454e-1,0.19756797599888e-1}},
526 {"n-hexane", {0.10553238013661e1,-0.26120615890629e1,0.76613882967260,-0.29770320622459,0.11879907733358,0.27922861062617e-3,0.46347589844105,0.11433196980297e-1,-0.48256968738131,-0.93750558924659e-1,-0.67273247155994e-2,-0.51141583585428e-2}},
527 {"n-heptane", {0.10543747645262e1,-0.26500681506144e1,0.81730047827543,-0.30451391253428,0.12253868710800,0.27266472743928e-3,0.49865825681670,-0.71432815084176e-3,-0.54236895525450,-0.13801821610756,-0.61595287380011e-2,0.48602510393022e-3}},
528 {"n-octane", {0.10722544875633e1,-0.24632951172003e1,0.65386674054928,-0.36324974085628,0.12713269626764,0.30713572777930e-3,0.52656856987540,0.19362862857653e-1,-0.58939426849155,-0.14069963991934,-0.78966330500036e-2,0.33036597968109e-2}},
529 {"oxygen", { 0.88878286369701,-0.24879433312148e1,0.59750190775886,0.96501817061881e-2,0.71970428712770e-1,0.22337443000195e-3,0.18558686391474,-0.38129368035760e-1,-0.15352245383006,-0.26726814910919e-1,-0.25675298677127e-1,0.95714302123668e-2}},
530 {"carbonmonoxide", {0.92310041400851,-0.24885845205800e1,0.58095213783396,0.28859164394654e-1,0.70256257276544e-1,0.21687043269488e-3,0.13758331015182,-0.51501116343466e-1,-0.14865357483379,-0.38857100886810e-1,-0.29100433948943e-1,0.14155684466279e-1}},
531 {"argon", {0.85095714803969,-0.24003222943480e1,0.54127841476466,0.16919770692538e-1,0.68825965019035e-1,0.21428032815338e-3,0.17429895321992,-0.33654495604194e-1,-0.13526799857691,-0.16387350791552e-1,-0.24987666851475e-1,0.88769204815709e-2}}
532 };
533
534 if (n_dict_main.find(fluid) != n_dict_main.end()){
535 PureCoeffs pc;
536 pc.n = n_dict_main[fluid];
537 pc.t = {0.250,1.125,1.500,1.375,0.250,0.875,0.625,1.750,3.625,3.625,14.500,12.000};
538 pc.d = {1,1,1,2,3,7,2,5,1,4,3,4};
539 pc.c = {0,0,0,0,0,0,1,1,1,1,1,1};
540 pc.l = {0,0,0,0,0,0,1,1,2,2,3,3};
541 return pc;
542 }
543 else if (n_dict_mne.find(fluid) != n_dict_mne.end()){
544 PureCoeffs pc;
545 pc.n = n_dict_mne.at(fluid);
546 pc.t = {0.125,1.125,0.375,1.125,0.625,1.500,0.625,2.625,2.750,2.125,2.000,1.750,4.500,4.750,5.000,4.000,4.500,7.500,14.000,11.500,26.000,28.000,30.000,16.000};
547 pc.d = {1,1,2,2,4,4,1,1,1,2,3,6,2,3,3,4,4,2,3,4,5,6,6,7};
548 pc.c = {0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
549 pc.l = {0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,3,3,3,6,6,6,6};
550 return pc;
551 }
552 else if (fluid == "carbondioxide"){
553 PureCoeffs pc;
554 pc.n = {0.52646564804653,-0.14995725042592e1, 0.27329786733782, 0.12949500022786, 0.15404088341841,-0.58186950946814,-0.18022494838296,-0.95389904072812e-1,-0.80486819317679e-2,-0.35547751273090e-1,-0.28079014882405,-0.82435890081677e-1, 0.10832427979006e-1,-0.67073993161097e-2,-0.46827907600524e-2,-0.28359911832177e-1, 0.19500174744098e-1,-0.21609137507166, 0.43772794926972,-0.22130790113593, 0.15190189957331e-1,-0.15380948953300e-1};
555 pc.t = {0.000,1.250,1.625,0.375,0.375,1.375,1.125,1.375,0.125,1.625,3.750,3.500,7.500,8.000,6.000,16.000,11.000,24.000,26.000,28.000,24.000,26.000};
556 pc.d = {1,1,2,3,3,3,4,5,6,6,1,4,1,1,3,3,4,5,5,5,5,5};
557 pc.c = {0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
558 pc.l = {0,0,0,0,1,1,1,1,1,1,2,2,3,3,3,3,3,5,5,5,6,6};
559 return pc;
560 }
561 else if (fluid == "hydrogen"){
562 PureCoeffs pc;
563 pc.n = {0.53579928451252e1,-0.62050252530595e1, 0.13830241327086,-0.71397954896129e-1, 0.15474053959733e-1,-0.14976806405771,-0.26368723988451e-1, 0.56681303156066e-1,-0.60063958030436e-1,-0.45043942027132, 0.42478840244500,-0.21997640827139e-1,-0.10499521374530e-1,-0.28955902866816e-2};
564 pc.t = {0.500,0.625,0.375,0.625,1.125,2.625,0.000,0.250,1.375,4.000,4.250,5.000,8.000,8.000};
565 pc.d = {1,1,2,2,4,1,5,5,5,1,1,2,5,1};
566 pc.c = {0,0,0,0,0,1,1,1,1,1,1,1,1,1};
567 pc.l = {0,0,0,0,0,1,1,1,1,2,2,3,3,5};
568 return pc;
569 }
570 else if (fluid == "water"){
571 PureCoeffs pc;
572 pc.n = {0.82728408749586,-0.18602220416584e1,-0.11199009613744e1,0.15635753976056,0.87375844859025,-0.36674403715731,0.53987893432436e-1,0.10957690214499e1,0.53213037828563e-1,0.13050533930825e-1,-0.41079520434476,0.14637443344120,-0.55726838623719e-1,-0.11201774143800e-1,-0.66062758068099e-2,0.46918522004538e-2};
573 pc.t = {0.500,1.250,1.875,0.125,1.500,1.000,0.750,1.500,0.625,2.625,5.000,4.000,4.500,3.000,4.000,6.000};
574 pc.d = {1,1,1,2,2,3,4,1,5,5,1,2,4,4,1,1};
575 pc.c = {0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1};
576 pc.l = {0,0,0,0,0,0,0,1,1,1,2,2,2,3,5,5};
577 return pc;
578 }
579 else if (fluid == "helium"){
580 PureCoeffs pc;
581 pc.n = {-0.45579024006737,0.12516390754925e1,-0.15438231650621e1,0.20467489707221e-1,-0.34476212380781,-0.20858459512787e-1,0.16227414711778e-1,-0.57471818200892e-1,0.19462416430715e-1,-0.33295680123020e-1,-0.10863577372367e-1,-0.22173365245954e-1};
582 pc.t = {0.000,0.125,0.750,1.000,0.750,2.625,0.125,1.250,2.000,1.000,4.500,5.000};
583 pc.d = {1,1,1,4,1,3,5,5,5,2,1,2};
584 pc.c = {0,0,0,0,1,1,1,1,1,1,1,1};
585 pc.l = {0,0,0,0,1,1,1,1,1,2,3,3};
586 return pc;
587 }
588 else{
589 throw std::invalid_argument("unable to load pure coefficients for " + fluid);
590 }
591}
592
593
594
595inline BetasGammas get_betasgammas(const std::string&fluid1, const std::string &fluid2){
596
597 // From Table A3.8 of GERG 2004 monograph
598 static std::unordered_map<std::pair<std::string, std::string>,BetasGammas, boost::hash<std::pair<std::string, std::string>>> BIP_data = {
599 {{"methane","nitrogen"}, {0.998721377,1.013950311,0.998098830,0.979273013}},
600 {{"methane","carbondioxide"}, {0.999518072,1.002806594,1.022624490,0.975665369}},
601 {{"methane","ethane"}, {0.997547866,1.006617867,0.996336508,1.049707697}},
602 {{"methane","propane"}, {1.004827070,1.038470657,0.989680305,1.098655531}},
603 {{"methane","n-butane"}, {0.979105972,1.045375122,0.994174910,1.171607691}},
604 {{"methane","isobutane"}, {1.011240388,1.054319053,0.980315756,1.161117729}},
605 {{"methane","n-pentane"}, {0.948330120,1.124508039,0.992127525,1.249173968}},
606 {{"methane","isopentane"}, {1.000000000,1.343685343,1.000000000,1.188899743}},
607 {{"methane","n-hexane"}, {0.958015294,1.052643846,0.981844797,1.330570181}},
608 {{"methane","n-heptane"}, {0.962050831,1.156655935,0.977431529,1.379850328}},
609 {{"methane","n-octane"}, {0.994740603,1.116549372,0.957473785,1.449245409}},
610 {{"methane","hydrogen"}, {1.000000000,1.018702573,1.000000000,1.352643115}},
611 {{"methane","oxygen"}, {1.000000000,1.000000000,1.000000000,0.950000000}},
612 {{"methane","carbonmonoxide"}, {0.997340772,1.006102927,0.987411732,0.987473033}},
613 {{"methane","water"}, {1.012783169,1.585018334,1.063333913,0.775810513}},
614 {{"methane","helium"}, {1.000000000,0.881405683,1.000000000,3.159776855}},
615 {{"methane","argon"}, {1.034630259,1.014678542,0.990954281,0.989843388}},
616 {{"nitrogen","carbondioxide"}, {0.977794634,1.047578256,1.005894529,1.107654104}},
617 {{"nitrogen","ethane"}, {0.978880168,1.042352891,1.007671428,1.098650964}},
618 {{"nitrogen","propane"}, {0.974424681,1.081025408,1.002677329,1.201264026}},
619 {{"nitrogen","n-butane"}, {0.996082610,1.146949309,0.994515234,1.304886838}},
620 {{"nitrogen","isobutane"}, {0.986415830,1.100576129,0.992868130,1.284462634}},
621 {{"nitrogen","n-pentane"}, {1.000000000,1.078877166,1.000000000,1.419029041}},
622 {{"nitrogen","isopentane"}, {1.000000000,1.154135439,1.000000000,1.381770770}},
623 {{"nitrogen","n-hexane"}, {1.000000000,1.195952177,1.000000000,1.472607971}},
624 {{"nitrogen","n-heptane"}, {1.000000000,1.404554090,1.000000000,1.520975334}},
625 {{"nitrogen","n-octane"}, {1.000000000,1.186067025,1.000000000,1.733280051}},
626 {{"nitrogen","hydrogen"}, {0.972532065,0.970115357,0.946134337,1.175696583}},
627 {{"nitrogen","oxygen"}, {0.999521770,0.997082328,0.997190589,0.995157044}},
628 {{"nitrogen","carbonmonoxide"}, {1.000000000,1.008690943,1.000000000,0.993425388}},
629 {{"nitrogen","water"}, {1.000000000,1.094749685,1.000000000,0.968808467}},
630 {{"nitrogen","helium"}, {0.969501055,0.932629867,0.692868765,1.471831580}},
631 {{"nitrogen","argon"}, {1.004166412,1.002212182,0.999069843,0.990034831}},
632 {{"carbondioxide","ethane"}, {1.002525718,1.032876701,1.013871147,0.900949530}},
633 {{"carbondioxide","propane"}, {0.996898004,1.047596298,1.033620538,0.908772477}},
634 {{"carbondioxide","n-butane"}, {1.174760923,1.222437324,1.018171004,0.911498231}},
635 {{"carbondioxide","isobutane"}, {1.076551882,1.081909003,1.023339824,0.929982936}},
636 {{"carbondioxide","n-pentane"}, {1.024311498,1.068406078,1.027000795,0.979217302}},
637 {{"carbondioxide","isopentane"}, {1.060793104,1.116793198,1.019180957,0.961218039}},
638 {{"carbondioxide","n-hexane"}, {1.000000000,0.851343711,1.000000000,1.038675574}},
639 {{"carbondioxide","n-heptane"}, {1.205469976,1.164585914,1.011806317,1.046169823}},
640 {{"carbondioxide","n-octane"}, {1.026169373,1.104043935,1.029690780,1.074455386}},
641 {{"carbondioxide","hydrogen"}, {0.904142159,1.152792550,0.942320195,1.782924792}},
642 {{"carbondioxide","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
643 {{"carbondioxide","carbonmonoxide"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
644 {{"carbondioxide","water"}, {0.949055959,1.542328793,0.997372205,0.775453996}},
645 {{"carbondioxide","helium"}, {0.846647561,0.864141549,0.768377630,3.207456948}},
646 {{"carbondioxide","argon"}, {1.008392428,1.029205465,0.996512863,1.050971635}},
647 {{"ethane","propane"}, {0.997607277,1.003034720,0.996199694,1.014730190}},
648 {{"ethane","n-butane"}, {0.999157205,1.006179146,0.999130554,1.034832749}},
649 {{"ethane","isobutane"}, {1.000000000,1.006616886,1.000000000,1.033283811}},
650 {{"ethane","n-pentane"}, {0.993851009,1.026085655,0.998688946,1.066665676}},
651 {{"ethane","isopentane"} , {1.000000000,1.045439246,1.000000000,1.021150247}},
652 {{"ethane","n-hexane"}, {1.000000000,1.169701102,1.000000000,1.092177796}},
653 {{"ethane","n-heptane"}, {1.000000000,1.057666085,1.000000000,1.134532014}},
654 {{"ethane","n-octane"}, {1.007469726,1.071917985,0.984068272,1.168636194}},
655 {{"ethane","hydrogen"}, {0.925367171,1.106072040,0.932969831,1.902008495}},
656 {{"ethane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
657 {{"ethane","carbonmonoxide"}, {1.000000000,1.201417898,1.000000000,1.069224728}},
658 {{"ethane","water"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
659 {{"ethane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
660 {{"ethane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
661 {{"propane","n-butane"}, {0.999795868,1.003264179,1.000310289,1.007392782}},
662 {{"propane","isobutane"}, {0.999243146,1.001156119,0.998012298,1.005250774}},
663 {{"propane","n-pentane"}, {1.044919431,1.019921513,0.996484021,1.008344412}},
664 {{"propane","isopentane"}, {1.040459289,0.999432118,0.994364425,1.003269500}},
665 {{"propane","n-hexane"}, {1.000000000,1.057872566,1.000000000,1.025657518}},
666 {{"propane","n-heptane"}, {1.000000000,1.079648053,1.000000000,1.050044169}},
667 {{"propane","n-octane"}, {1.000000000,1.102764612,1.000000000,1.063694129}},
668 {{"propane","hydrogen"}, {1.000000000,1.074006110,1.000000000,2.308215191}},
669 {{"propane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
670 {{"propane","carbonmonoxide"}, {1.000000000,1.108143673,1.000000000,1.197564208}},
671 {{"propane","water"}, {1.000000000,1.011759763,1.000000000,0.600340961}},
672 {{"propane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
673 {{"propane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
674 {{"n-butane","isobutane"}, {1.000880464,1.000414440,1.000077547,1.001432824}},
675 {{"n-butane","n-pentane"}, {1.000000000,1.018159650,1.000000000,1.002143640}},
676 {{"n-butane","isopentane"}, {1.000000000,1.002728262,1.000000000,1.000792201}},
677 {{"n-butane","n-hexane"}, {1.000000000,1.034995284,1.000000000,1.009157060}},
678 {{"n-butane","n-heptane"}, {1.000000000,1.019174227,1.000000000,1.021283378}},
679 {{"n-butane","n-octane"}, {1.000000000,1.046905515,1.000000000,1.033180106}},
680 {{"n-butane","hydrogen"}, {1.000000000,1.232939523,1.000000000,2.509259945}},
681 {{"n-butane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
682 {{"n-butane","carbonmonoxide"}, {1.000000000,1.084740904,1.000000000,1.174055065}},
683 {{"n-butane","water"}, {1.000000000,1.223638763,1.000000000,0.615512682}},
684 {{"n-butane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
685 {{"n-butane","argon"}, {1.000000000,1.214638734,1.000000000,1.245039498}},
686 {{"isobutane","n-pentane"}, {1.000000000,1.002779804,1.000000000,1.002495889}},
687 {{"isobutane","isopentane"}, {1.000000000,1.002284197,1.000000000,1.001835788}},
688 {{"isobutane","n-hexane"}, {1.000000000,1.010493989,1.000000000,1.006018054}},
689 {{"isobutane","n-heptane"}, {1.000000000,1.021668316,1.000000000,1.009885760}},
690 {{"isobutane","n-octane"}, {1.000000000,1.032807063,1.000000000,1.013945424}},
691 {{"isobutane","hydrogen"}, {1.000000000,1.147595688,1.000000000,1.895305393}},
692 {{"isobutane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
693 {{"isobutane","carbonmonoxide"}, {1.000000000,1.087272232,1.000000000,1.161523504}},
694 {{"isobutane","water"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
695 {{"isobutane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
696 {{"isobutane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
697 {{"n-pentane","isopentane"}, {1.000000000,1.000024352,1.000000000,1.000050537}},
698 {{"n-pentane","n-hexane"}, {1.000000000,1.002480637,1.000000000,1.000761237}},
699 {{"n-pentane","n-heptane"}, {1.000000000,1.008972412,1.000000000,1.002441051}},
700 {{"n-pentane","n-octane"}, {1.000000000,1.069223964,1.000000000,1.016422347}},
701 {{"n-pentane","hydrogen"}, {1.000000000,1.188334783,1.000000000,2.013859174}},
702 {{"n-pentane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
703 {{"n-pentane","carbonmonoxide"}, {1.000000000,1.119954454,1.000000000,1.206195595}},
704 {{"n-pentane","water"}, {1.000000000,0.956677310,1.000000000,0.447666011}},
705 {{"n-pentane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
706 {{"n-pentane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
707 {{"isopentane","n-hexane"}, {1.000000000,1.002996055,1.000000000,1.001204174}},
708 {{"isopentane","n-heptane"}, {1.000000000,1.009928531,1.000000000,1.003194615}},
709 {{"isopentane","n-octane"}, {1.000000000,1.017880981,1.000000000,1.005647480}},
710 {{"isopentane","hydrogen"}, {1.000000000,1.184339122,1.000000000,1.996386669}},
711 {{"isopentane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
712 {{"isopentane","carbonmonoxide"}, {1.000000000,1.116693501,1.000000000,1.199475627}},
713 {{"isopentane","water"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
714 {{"isopentane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
715 {{"isopentane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
716 {{"n-hexane","n-heptane"}, {1.000000000,1.001508227,1.000000000,0.999762786}},
717 {{"n-hexane","n-octane"}, {1.000000000,1.006268954,1.000000000,1.001633952}},
718 {{"n-hexane","hydrogen"}, {1.000000000,1.243461678,1.000000000,3.021197546}},
719 {{"n-hexane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
720 {{"n-hexane","carbonmonoxide"}, {1.000000000,1.155145836,1.000000000,1.233435828}},
721 {{"n-hexane","water"}, {1.000000000,1.170217596,1.000000000,0.569681333}},
722 {{"n-hexane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
723 {{"n-hexane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
724 {{"n-heptane","n-octane"}, {1.000000000,1.006767176,1.000000000,0.998793111}},
725 {{"n-heptane","hydrogen"}, {1.000000000,1.159131722,1.000000000,3.169143057}},
726 {{"n-heptane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
727 {{"n-heptane","carbonmonoxide"}, {1.000000000,1.190354273,1.000000000,1.256295219}},
728 {{"n-heptane","water"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
729 {{"n-heptane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
730 {{"n-heptane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
731 {{"n-octane","hydrogen"}, {1.000000000,1.305249405,1.000000000,2.191555216}},
732 {{"n-octane","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
733 {{"n-octane","carbonmonoxide"}, {1.000000000,1.219206702,1.000000000,1.276744779}},
734 {{"n-octane","water"}, {1.000000000,0.599484191,1.000000000,0.662072469}},
735 {{"n-octane","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
736 {{"n-octane","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
737 {{"hydrogen","oxygen"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
738 {{"hydrogen","carbonmonoxide"}, {1.000000000,1.121416201,1.000000000,1.377504607}},
739 {{"hydrogen","water"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
740 {{"hydrogen","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
741 {{"hydrogen","argon"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
742 {{"oxygen","carbonmonoxide"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
743 {{"oxygen","water"}, {1.000000000,1.143174289,1.000000000,0.964767932}},
744 {{"oxygen","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
745 {{"oxygen","argon"}, {0.999746847,0.993907223,1.000023103,0.990430423}},
746 {{"carbonmonoxide","water"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
747 {{"carbonmonoxide","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
748 {{"carbonmonoxide","argon"}, {1.000000000,1.159720623,1.000000000,0.954215746}},
749 {{"water","helium"}, {1.000000000,1.000000000,1.000000000,1.000000000}},
750 {{"water","argon"}, {1.000000000,1.038993495,1.000000000,1.070941866}},
751 {{"helium","argon"}, {1.00000000,1.00000000,1.00000000,1.00000000}}
752 };
753 auto pair_normal = std::make_pair(fluid1, fluid2);
754 if (BIP_data.find(pair_normal) != BIP_data.end()){
755 return BIP_data[pair_normal];
756 }
757 auto pair_backwards = std::make_pair(fluid2, fluid1);
758 if (BIP_data.find(pair_backwards) != BIP_data.end()){
759 auto bg = BIP_data.at(pair_backwards);
760 // Because the order is backwards, need to take the reciprocals of the beta values
761 bg.betaT = 1/bg.betaT;
762 bg.betaV = 1/bg.betaV;
763 return bg;
764 }
765 throw std::invalid_argument("Unable to obtain BIP for the pair {" + fluid1 + "," + fluid2 + "}");
766}
767
768inline std::optional<double> get_Fij(const std::string& fluid1, const std::string& fluid2, bool ok_missing=true){
769
771 static std::map<std::pair<std::string, std::string>, double> Fij_dict = {
772 {{"methane","nitrogen"}, 1.0},
773 {{"methane","carbondioxide"}, 1.0},
774 {{"methane","ethane"}, 1.0},
775 {{"methane","propane"}, 1.0},
776 {{"methane","n-butane"}, 1.0},
777 {{"methane","isobutane"}, 0.771035405688},
778 {{"methane","hydrogen"}, 1.0},
779 {{"nitrogen","carbondioxide"}, 1.0},
780 {{"nitrogen","ethane"}, 1.0},
781 {{"ethane","propane"}, 0.130424765150},
782 {{"ethane","n-butane"}, 0.281570073085},
783 {{"ethane","isobutane"}, 0.260632376098},
784 {{"propane","n-butane"}, 0.312572600489e-1},
785 {{"propane","isobutane"}, -0.551609771024e-1},
786 {{"n-butane","isobutane"}, -0.551240293009e-1}
787 };
788 auto pair_normal = std::make_pair(fluid1, fluid2);
789 if (Fij_dict.find(pair_normal) != Fij_dict.end()){
790 return Fij_dict[pair_normal];
791 }
792 auto pair_backwards = std::make_pair(fluid2, fluid1);
793 if (Fij_dict.find(pair_backwards) != Fij_dict.end()){
794 return Fij_dict[pair_backwards];
795 }
796 if (ok_missing){
797 return std::nullopt;
798 }
799 else{
800 throw std::invalid_argument("Unable to obtain Fij for the pair {" + fluid1 + "," + fluid2 + "}");
801 }
802}
803
804
805inline DepartureCoeffs get_departurecoeffs(const std::string&fluid1, const std::string &fluid2){
806
807 std::pair<std::string, std::string> sortedpair = std::minmax(fluid1, fluid2);
808 auto sortpair = [](const std::string &n1, const std::string& n2) ->std::pair<std::string, std::string> { return std::minmax(n1, n2); };
809
810 // The set of pairnames using the generalized form
811 const std::set<std::pair<std::string, std::string>> generalized = {
812 sortpair("methane","n-butane"), sortpair("methane","isobutane"), sortpair("ethane","propane"),
813 sortpair("ethane","n-butane"), sortpair("ethane","isobutane"), sortpair("propane","n-butane"),
814 sortpair("propane","isobutane"), sortpair("n-butane","isobutane")
815 };
816
818 if (sortedpair == sortpair("methane","nitrogen")){
819 dc.n = {-0.98038985517335e-2,0.42487270143005e-3,-0.34800214576142e-1 ,-0.13333813013896 ,-0.11993694974627e-1 ,0.69243379775168e-1 ,-0.31022508148249 ,0.24495491753226 ,0.22369816716981};
820 dc.d = {1,4,1,2,2,2,2,2,3};
821 dc.t = {0.000,1.850,7.850,5.400,0.000,0.750,2.800,4.450,4.250};
822 dc.eta = {0,0,1.000,1.000,0.250,0.000,0.000,0.000,0.000};
823 dc.epsilon = {0,0,0.5,0.5,0.5,0.5,0.5,0.5,0.5};
824 dc.beta = {0,0,1.0,1.0,2.5,3.0,3.0,3.0,3.0};
825 dc.gamma = {0,0,0.500,0.500,0.500,0.500,0.500,0.500,0.500};
826 return dc;
827 }
828 if (sortedpair == sortpair("methane","carbondioxide")){
829 dc.n = {-0.10859387354942,0.80228576727389e-1,-0.93303985115717e-2,0.40989274005848e-1,-0.24338019772494,0.23855347281124};
830 dc.d = {1,2,3,1,2,3};
831 dc.t = {2.600,1.950,0.000,3.950,7.950,8.000};
832 dc.eta = {0,0,0,1.000,0.500,0.000};
833 dc.epsilon = {0,0,0,0.5,0.5,0.5};
834 dc.beta = {0,0,0,1.0,2.0,3.0};
835 dc.gamma = {0,0,0,0.500,0.500,0.500};
836 return dc;
837 }
838 if (sortedpair == sortpair("ethane", "methane")){
839 dc.n = {-0.80926050298746e-3,-0.75381925080059e-3,-0.41618768891219e-1,-0.23452173681569,0.14003840584586,0.63281744807738e-1,-0.34660425848809e-1,-0.23918747334251,0.19855255066891e-2,0.61777746171555e1,-0.69575358271105e1,0.10630185306388e1};
840 dc.t = {0.650,1.550,3.100,5.900,7.050,3.350,1.200,5.800,2.700,0.450,0.550,1.950};
841 dc.d = {3,4,1,2,2,2,2,2,2,3,3,3};
842 dc.eta = {0,0,1.000,1.000,1.000,0.875,0.750,0.500,0.000,0.000,0.000,0.000};
843 dc.epsilon = {0,0,0.500,0.500,0.500,0.500,0.500,0.500,0.500,0.500,0.500,0.500};
844 dc.beta = {0,0,1.000,1.000,1.000,1.250,1.500,2.000,3.000,3.000,3.000,3.000};
845 dc.gamma = {0,0,0.500,0.500,0.500,0.500,0.500,0.500,0.500,0.500,0.500,0.500};
846 return dc;
847 }
848 if (sortedpair == sortpair("propane", "methane")){
849 dc.n = {0.13746429958576e-1,-0.74425012129552e-2,-0.45516600213685e-2,-0.54546603350237e-2, 0.23682016824471e-2, 0.18007763721438,-0.44773942932486, 0.19327374888200e-1,-0.30632197804624};
850 dc.t = {1.850,3.950,0.000,1.850,3.850,5.250,3.850,0.200,6.500};
851 dc.d = {3,3,4,4,4,1,1,1,2};
852 dc.eta = {0,0,0,0,0,0.250,0.250,0.000,0.000};
853 dc.epsilon = {0,0,0,0,0,0.500,0.500,0.500,0.500};
854 dc.beta = {0,0,0,0,0,0.750,1.000,2.000,3.000};
855 dc.gamma = {0,0,0,0,0,0.500,0.500,0.500,0.500};
856 return dc;
857 }
858 if (sortedpair == sortpair("nitrogen", "carbondioxide")){
859 dc.n = {0.28661625028399,-0.10919833861247,-0.11374032082270e1,0.76580544237358,0.42638000926819e-2,0.17673538204534};
860 dc.t = {1.850,1.400,3.200,2.500,8.000,3.750};
861 dc.d = {2,3,1,1,1,2};
862 dc.eta = {0,0,0.250,0.250,0.000,0.000};
863 dc.epsilon = {0,0,0.500,0.500,0.500,0.500};
864 dc.beta = {0,0,0.750,1.000,2.000,3.000};
865 dc.gamma = {0,0,0.500,0.500,0.500,0.500};
866 return dc;
867 }
868 if (sortedpair == sortpair("nitrogen", "ethane")){
869 dc.n = {-0.47376518126608,0.48961193461001,-0.57011062090535e-2,-0.19966820041320,-0.69411103101723,0.69226192739021};
870 dc.d = {2,2,3,1,2,2};
871 dc.t = {0.000,0.050,0.000,3.650,4.900,4.450};
872 dc.eta = {0,0,0,1.000,1.000,0.875};
873 dc.epsilon = {0,0,0,0.500, 0.500, 0.500};
874 dc.beta = {0,0,0,1.000,1.000,1.250};
875 dc.gamma = {0,0,0,0.500,0.500,0.500};
876 return dc;
877 }
878 if (sortedpair == sortpair("methane", "hydrogen")){
879 dc.n = {-0.25157134971934,-0.62203841111983e-2,0.88850315184396e-1,-0.35592212573239e-1};
880 dc.t = {2.000,-1.000,1.750,1.400};
881 dc.d = {1,3,3,4};
882 dc.eta = {0,0,0,0};
883 dc.epsilon = {0,0,0,0};
884 dc.beta = {0,0,0,0};
885 dc.gamma = {0,0,0,0};
886 return dc;
887 }
888 if (generalized.find(sortedpair) != generalized.end()){
889 dc.n = {0.25574776844118e1,-0.79846357136353e1,0.47859131465806e1,-0.73265392369587,0.13805471345312e1,0.28349603476365,-0.49087385940425,-0.10291888921447,0.11836314681968,0.55527385721943e-4};
890 dc.d = {1,1,1,2,2,3,3,4,4,4};
891 dc.t = {1.000,1.550,1.700,0.250,1.350,0.000,1.250,0.000,0.700,5.400};
892 dc.eta = {0,0,0,0,0,0,0,0,0,0};
893 dc.epsilon = {0,0,0,0,0,0,0,0,0,0};
894 dc.beta = {0,0,0,0,0,0,0,0,0,0};
895 dc.gamma = {0,0,0,0,0,0,0,0,0,0};
896 return dc;
897 }
898
899 throw std::invalid_argument("could not get departure coeffs for {" + fluid1 + "," + fluid2 + "}");
900}
901
903public:
907 GERG2004ResidualModel(const std::vector<std::string>& names) : red(names, get_pure_info, get_betasgammas), corr(names, get_pure_coeffs), dep(names, get_Fij, get_departurecoeffs){}
908
909 template<class VecType>
910 auto R(const VecType& /*molefrac*/) const {
911 return 8.314472;
912 }
913
914 template<typename TType, typename RhoType, typename MoleFracType>
915 auto alphar(const TType &T,
916 const RhoType &rho,
917 const MoleFracType& molefrac) const {
918 auto Tred = forceeval(red.get_Tr(molefrac));
919 auto rhored = forceeval(red.get_rhor(molefrac));
920 auto delta = forceeval(rho / rhored);
921 auto tau = forceeval(Tred / T);
922 auto val = forceeval(corr.alphar(tau, delta, molefrac) + dep.alphar(tau, delta, molefrac));
923 return val;
924 }
925};
926
927
929public:
931
932 GERG2004IdealGasModel(const std::vector<std::string>& names) : aig(names, get_pure_info, get_alphaig_coeffs){}
933
934 template<class VecType>
935 auto R(const VecType& /*molefrac*/) const {
936 return 8.314472;
937 }
938
939 template<typename TType, typename RhoType, typename MoleFracType>
940 auto alphar(const TType &T,
941 const RhoType &rho,
942 const MoleFracType& molefrac) const {
943 if (static_cast<std::size_t>(molefrac.size()) != aig.size()){
944 throw std::invalid_argument("sizes don't match");
945 }
946 return aig.alphaig(T, rho, molefrac);
947 }
948};
949
950
951} /* namespace GERG2004 */
952
953
954
955
956
957
958namespace GERG2008{
959
960using namespace GERGGeneral;
961
962const std::vector<std::string> component_names = {"methane", "nitrogen","carbondioxide","ethane","propane","n-butane","isobutane","n-pentane","isopentane","n-hexane","n-heptane","n-octane","hydrogen", "oxygen","carbonmonoxide","water","helium","argon","hydrogensulfide","n-nonane","n-decane"};
963
964inline auto get_pure_info(const std::string& name){
965 // From Table A3.5 from GERG 2004 monograph
966 // Data are in mol/dm3, K, kg/kmol
967 // All others are unchanged
968 static std::map<std::string, PureInfo> data_map = {
969 {"carbonmonoxide", {10.85, 132.86, 28.010100}}, // Changed from GERG-2004
970 {"isopentane", {3.271,460.35,72.148780}}, // Changed from GERG-2004
971
972 {"n-nonane", {1.81,594.55,128.2551}}, // Added in GERG-2008
973 {"n-decane", {1.64,617.7,142.28168}}, // Added in GERG-2008
974 {"hydrogensulfide", {10.19,373.1,34.08088}} // Added in GERG-2008
975 };
976 if (data_map.find(name) != data_map.end()){
977 auto data = data_map.at(name);
978 data.rhoc_molm3 *= 1000; // mol/dm^3 -> mol/m^3
979 data.M_kgmol /= 1000; // kg/kmol -> kg/mol
980 return data;
981 }
982 else{
983 // Fallback to GERG-2004
984 return GERG2004::get_pure_info(name);
985 }
986}
987
991
992inline BetasGammas get_betasgammas(const std::string&fluid1, const std::string &fluid2){
993
994 // From Table A8 of GERG-2008 manuscript. Pairs that are unchanged
995 // from GERG-2004 are left out and are looked up from the GERG-2004
996 // coefficients.
997 static std::unordered_map<std::pair<std::string, std::string>,BetasGammas, boost::hash<std::pair<std::string, std::string>>> BIP_data = {
998
999 // This set has different values than in GERG-2004. The change
1000 // occurs because the EOS has changed for isopentane and CO and
1001 // thus the estimated interaction parameters need to be calculated
1002 // with the "new" Tc.
1003 {{"ethane","isopentane"}, {1.0, 1.045439935, 1.0, 1.021150247}},
1004 {{"n-butane","carbonmonoxide"}, {1.0, 1.084740904, 1.0, 1.173916162}},
1005 {{"n-butane","isopentane"}, {1.0, 1.002728434, 1.0, 1.000792201}},
1006 {{"isobutane","carbonmonoxide"}, {1.0, 1.087272232, 1.0, 1.161390082}},
1007 {{"isobutane","isopentane"}, {1.0, 1.002284353, 1.0, 1.001835788}},
1008 {{"n-pentane","carbonmonoxide"}, {1.0, 1.119954454, 1.0, 1.206043295}},
1009 {{"isopentane","carbonmonoxide"}, {1.0, 1.116694577, 1.0, 1.199326059}},
1010 {{"n-hexane","carbonmonoxide"}, {1.0, 1.155145836, 1.0, 1.233272781}},
1011 {{"n-heptane","carbonmonoxide"}, {1.0, 1.190354273, 1.0, 1.256123503}},
1012 {{"n-octane","carbonmonoxide"}, {1.0, 1.219206702, 1.0, 1.276565536}},
1013 {{"n-pentane","isopentane"}, {1.0, 1.000024335, 1.0, 1.000050537}},
1014 {{"isopentane","n-hexane"}, {1.0, 1.002995876, 1.0, 1.001204174}},
1015 {{"isopentane","n-heptane"}, {1.0, 1.009928206, 1.0, 1.003194615}},
1016 {{"isopentane","n-octane"}, {1.0, 1.017880545, 1.0, 1.00564748}},
1017 {{"isopentane","hydrogen"}, {1.0, 1.184340443, 1.0, 1.996386669}},
1018
1019 // The 57 new models added in GERG-2008
1020 {{"methane","n-nonane"}, {1.002852287, 1.141895355, 0.947716769, 1.528532478}},
1021 {{"methane","n-decane"}, {1.033086292, 1.146089637, 0.937777823, 1.568231489}},
1022 {{"methane","hydrogensulfide"}, {1.012599087, 1.040161207, 1.011090031, 0.961155729}},
1023 {{"nitrogen","n-nonane"}, {1.0, 1.100405929, 0.95637945, 1.749119996}},
1024 {{"nitrogen","n-decane"}, {1.0, 1.0, 0.957934447, 1.822157123}},
1025 {{"nitrogen","hydrogensulfide"}, {0.910394249, 1.256844157, 1.004692366, 0.9601742}},
1026 {{"carbondioxide","n-nonane"}, {1.0, 0.973386152, 1.00768862, 1.140671202}},
1027 {{"carbondioxide","n-decane"}, {1.000151132, 1.183394668, 1.02002879, 1.145512213}},
1028 {{"carbondioxide","hydrogensulfide"}, {0.906630564, 1.024085837, 1.016034583, 0.92601888}},
1029 {{"ethane","n-nonane"}, {1.0, 1.14353473, 1.0, 1.05603303}},
1030 {{"ethane","n-decane"}, {0.995676258, 1.098361281, 0.970918061, 1.237191558}},
1031 {{"ethane","hydrogensulfide"}, {1.010817909, 1.030988277, 0.990197354, 0.90273666}},
1032 {{"propane","n-nonane"}, {1.0, 1.199769134, 1.0, 1.109973833}},
1033 {{"propane","n-decane"}, {0.984104227, 1.053040574, 0.985331233, 1.140905252}},
1034 {{"propane","hydrogensulfide"}, {0.936811219, 1.010593999, 0.992573556, 0.905829247}},
1035 {{"n-butane","n-nonane"}, {1.0, 1.049219137, 1.0, 1.014096448}},
1036 {{"n-butane","n-decane"}, {0.976951968, 1.027845529, 0.993688386, 1.076466918}},
1037 {{"n-butane","hydrogensulfide"}, {0.908113163, 1.033366041, 0.985962886, 0.926156602}},
1038 {{"isobutane","n-nonane"}, {1.0, 1.047298475, 1.0, 1.017817492}},
1039 {{"isobutane","n-decane"}, {1.0, 1.060243344, 1.0, 1.021624748}},
1040 {{"isobutane","hydrogensulfide"}, {1.012994431, 0.988591117, 0.974550548, 0.937130844}},
1041 {{"n-pentane","n-nonane"}, {1.0, 1.034910633, 1.0, 1.103421755}},
1042 {{"n-pentane","n-decane"}, {1.0, 1.016370338, 1.0, 1.049035838}},
1043 {{"n-pentane","hydrogensulfide"}, {0.984613203, 1.076539234, 0.962006651, 0.959065662}},
1044 {{"isopentane","n-nonane"}, {1.0, 1.028994325, 1.0, 1.008191499}},
1045 {{"isopentane","n-decane"}, {1.0, 1.039372957, 1.0, 1.010825138}},
1046 {{"isopentane","hydrogensulfide"}, {1.0, 0.835763343, 1.0, 0.982651529}},
1047 {{"n-hexane","n-nonane"}, {1.0, 1.02076168, 1.0, 1.055369591}},
1048 {{"n-hexane","n-decane"}, {1.001516371, 1.013511439, 0.99764101, 1.028939539}},
1049 {{"n-hexane","hydrogensulfide"}, {0.754473958, 1.339283552, 0.985891113, 0.956075596}},
1050 {{"n-heptane","n-nonane"}, {1.0, 1.001370076, 1.0, 1.001150096}},
1051 {{"n-heptane","n-decane"}, {1.0, 1.002972346, 1.0, 1.002229938}},
1052 {{"n-heptane","hydrogensulfide"}, {0.828967164, 1.087956749, 0.988937417, 1.013453092}},
1053 {{"n-octane","n-nonane"}, {1.0, 1.001357085, 1.0, 1.000235044}},
1054 {{"n-octane","n-decane"}, {1.0, 1.002553544, 1.0, 1.007186267}},
1055 {{"n-octane","hydrogensulfide"}, {1.0, 1.0, 1.0, 1.0}},
1056 {{"n-nonane","n-decane"}, {1.0, 1.00081052, 1.0, 1.000182392}},
1057 {{"n-nonane","hydrogen"}, {1.0, 1.342647661, 1.0, 2.23435404}},
1058 {{"n-nonane","oxygen"}, {1.0, 1.0, 1.0, 1.0}},
1059 {{"n-nonane","carbonmonoxide"}, {1.0, 1.252151449, 1.0, 1.294070556}},
1060 {{"n-nonane","water"}, {1.0, 1.0, 1.0, 1.0}},
1061 {{"n-nonane","hydrogensulfide"}, {1.0, 1.082905109, 1.0, 1.086557826}},
1062 {{"n-nonane","helium"}, {1.0, 1.0, 1.0, 1.0}},
1063 {{"n-nonane","argon"}, {1.0, 1.0, 1.0, 1.0}},
1064 {{"n-decane","hydrogen"}, {1.695358382, 1.120233729, 1.064818089, 3.786003724}},
1065 {{"n-decane","oxygen"}, {1.0, 1.0, 1.0, 1.0}},
1066 {{"n-decane","carbonmonoxide"}, {1.0, 0.87018496, 1.049594632, 1.803567587}},
1067 {{"n-decane","water"}, {1.0, 0.551405318, 0.897162268, 0.740416402}},
1068 {{"n-decane","hydrogensulfide"}, {0.975187766, 1.171714677, 0.973091413, 1.103693489}},
1069 {{"n-decane","helium"}, {1.0, 1.0, 1.0, 1.0}},
1070 {{"n-decane","argon"}, {1.0, 1.0, 1.0, 1.0}},
1071 {{"hydrogen","hydrogensulfide"}, {1.0, 1.0, 1.0, 1.0}},
1072 {{"oxygen","hydrogensulfide"}, {1.0, 1.0, 1.0, 1.0}},
1073 {{"carbonmonoxide","hydrogensulfide"}, {0.795660392, 1.101731308, 1.025536736, 1.022749748}},
1074 {{"water","hydrogensulfide"}, {1.0, 1.014832832, 1.0, 0.940587083}},
1075 {{"hydrogensulfide","helium"}, {1.0, 1.0, 1.0, 1.0}},
1076 {{"hydrogensulfide","argon"}, {1.0, 1.0, 1.0, 1.0}},
1077 };
1078 auto pair_normal = std::make_pair(fluid1, fluid2);
1079 if (BIP_data.find(pair_normal) != BIP_data.end()){
1080 return BIP_data[pair_normal];
1081 }
1082 auto pair_backwards = std::make_pair(fluid2, fluid1);
1083 if (BIP_data.find(pair_backwards) != BIP_data.end()){
1084 auto bg = BIP_data.at(pair_backwards);
1085 // Because the order is backwards, need to take the reciprocals of the beta values
1086 bg.betaT = 1/bg.betaT;
1087 bg.betaV = 1/bg.betaV;
1088 return bg;
1089 }
1090 // Fall back to looking up from GERG-2004
1091 return GERG2004::get_betasgammas(fluid1, fluid2);
1092}
1093
1094inline PureCoeffs get_pure_coeffs(const std::string& fluid){
1095
1096 static std::map<std::string, std::vector<double>> n_dict_main = {
1097
1098 // Updated in GERG-2008
1099 {"carbonmonoxide", {0.90554,-0.24515e1, 0.53149, 0.24173e-1, 0.72156e-1, 0.18818e-3, 0.19405,-0.43268e-1,-0.12778,-0.27896e-1,-0.34154e-1, 0.16329e-1}},
1100 {"isopentane", { 0.10963e1,-0.30402e1,0.10317e1,-0.15410,0.11535,0.29809e-3,0.39571,-0.45881e-1,-0.35804,-0.10107,-0.35484e-1,0.18156e-1}},
1101
1102 // New in GERG-2008
1103 {"hydrogensulfide", {0.87641,-0.20367e1,0.21634,-0.50199e-1,0.66994e-1,0.19076e-3,0.20227,-0.45348e-2,-0.22230,-0.34714e-1,-0.14885e-1,0.74154e-2}},
1104 {"n-decane", {0.10461e1,-0.24807e1,0.74372,-0.52579,0.15315,0.32865e-3,0.84178,0.55424e-1, -0.73555, -0.18507, -0.20775e-1, 0.12335e-1}},
1105 {"n-nonane", { 0.11151e1,-0.27020e1, 0.83416,-0.38828, 0.13760, 0.28185e-3, 0.62037, 0.15847e-1,-0.61726,-0.15043,-0.12982e-1, 0.44325e-2}},
1106 };
1107
1108 if (n_dict_main.find(fluid) != n_dict_main.end()){
1109 PureCoeffs pc;
1110 pc.n = n_dict_main[fluid];
1111 pc.t = {0.250,1.125,1.500,1.375,0.250,0.875,0.625,1.750,3.625,3.625,14.500,12.000};
1112 pc.d = {1,1,1,2,3,7,2,5,1,4,3,4};
1113 pc.c = {0,0,0,0,0,0,1,1,1,1,1,1};
1114 pc.l = {0,0,0,0,0,0,1,1,2,2,3,3};
1115 return pc;
1116 }
1117 else{
1118 return GERG2004::get_pure_coeffs(fluid);
1119 }
1120}
1121
1122inline AlphaigCoeffs get_alphaig_coeffs(const std::string& fluid){
1123
1124 static std::unordered_map<std::string, std::pair<std::vector<double>, std::vector<double>>> dict = {
1125
1126 {"carbonmonoxide", {{10.813340744, -19.834733959, 2.50055, 1.02865, 0.00493, 0, 0}, {11.669802800, 5.302762306, 0, 0}}}, // Updated in GERG-2008
1127 {"isopentane", {{15.449907693, -101.298172792, 3.0, 11.76180, 20.11010, 33.16880, 0}, {0.635392636, 1.977271641, 4.169371131, 0}}}, // Updated in GERG-2008
1128
1129 {"n-nonane", {{16.313913248, -102.160247463, 3.0, 18.02410, 38.12350, 53.34150, 0}, {0.263819696, 1.370586158, 2.848860483, 0}}},
1130 {"n-decane", {{15.870791919, -108.858547525, 3.0, 21.00690, 43.49310, 58.36570, 0}, {0.267034159, 1.353835195, 2.833479035, 0}}},
1131 {"hydrogensulfide", {{9.336197742, -16.266508995, 3.0, 3.11942, 1.00243, 0, 0}, {4.914580541, 2.270653980, 0, 0}}},
1132 };
1133
1134 if (dict.find(fluid) != dict.end()){
1135 auto [n, theta] = dict[fluid];
1136 if (n.size() != 7){
1137 throw std::invalid_argument(fluid + " does not have 7 n coefficients in ideal gas");
1138 }
1139 if (theta.size() != 4){
1140 throw std::invalid_argument(fluid + " does not have 4 theta coefficients in ideal gas");
1141 }
1143 c.n0 = n;
1144 c.n0.insert(c.n0.begin(), 0.0); // 0-pad the array to have the indexing match GERG-2004
1145 c.theta0 = theta;
1146 c.theta0.insert(c.theta0.begin(), 4, 0.0); // 0-pad the array to have the indexing match GERG-2004
1147 return c;
1148 }
1149 else{
1150 return GERG2004::get_alphaig_coeffs(fluid);
1151 }
1152}
1153
1154
1156public:
1160 GERG2008ResidualModel(const std::vector<std::string>& names) : red(names, get_pure_info, get_betasgammas), corr(names, get_pure_coeffs), dep(names, get_Fij, get_departurecoeffs){}
1161
1162 template<class VecType>
1163 auto R(const VecType& /*molefrac*/) const {
1164 return 8.314472;
1165 }
1166
1167 template<typename TType, typename RhoType, typename MoleFracType>
1168 auto alphar(const TType &T,
1169 const RhoType &rho,
1170 const MoleFracType& molefrac) const {
1171 if (static_cast<std::size_t>(molefrac.size()) != corr.size()){
1172 throw std::invalid_argument("sizes don't match");
1173 }
1174 auto Tred = forceeval(red.get_Tr(molefrac));
1175 auto rhored = forceeval(red.get_rhor(molefrac));
1176 auto delta = forceeval(rho / rhored);
1177 auto tau = forceeval(Tred / T);
1178 auto val = forceeval(corr.alphar(tau, delta, molefrac) + dep.alphar(tau, delta, molefrac));
1179 return val;
1180 }
1181};
1182
1184public:
1186
1187 GERG2008IdealGasModel(const std::vector<std::string>& names) : aig(names, get_pure_info, get_alphaig_coeffs){}
1188
1189 template<class VecType>
1190 auto R(const VecType& /*molefrac*/) const {
1191 return 8.314472;
1192 }
1193
1194 template<typename TType, typename RhoType, typename MoleFracType>
1195 auto alphar(const TType &T,
1196 const RhoType &rho,
1197 const MoleFracType& molefrac) const {
1198 if (static_cast<std::size_t>(molefrac.size()) != aig.size()){
1199 throw std::invalid_argument("sizes don't match");
1200 }
1201 return aig.alphaig(T, rho, molefrac);
1202 }
1203};
1204
1205} /* namespace GERG2008 */
1206
1207}
auto alphar(const TType &T, const RhoType &rho, const MoleFracType &molefrac) const
Definition GERG.hpp:940
auto R(const VecType &) const
Definition GERG.hpp:935
GERG2004IdealGasModel(const std::vector< std::string > &names)
Definition GERG.hpp:932
const GERG200XReducing red
Definition GERG.hpp:904
GERG2004ResidualModel(const std::vector< std::string > &names)
Definition GERG.hpp:907
const GERG200XCorrespondingStatesTerm corr
Definition GERG.hpp:905
auto alphar(const TType &T, const RhoType &rho, const MoleFracType &molefrac) const
Definition GERG.hpp:915
auto R(const VecType &) const
Definition GERG.hpp:910
const GERG200XDepartureTerm dep
Definition GERG.hpp:906
GERG2008IdealGasModel(const std::vector< std::string > &names)
Definition GERG.hpp:1187
auto alphar(const TType &T, const RhoType &rho, const MoleFracType &molefrac) const
Definition GERG.hpp:1195
auto R(const VecType &) const
Definition GERG.hpp:1190
auto R(const VecType &) const
Definition GERG.hpp:1163
GERG2008ResidualModel(const std::vector< std::string > &names)
Definition GERG.hpp:1160
GERG200XCorrespondingStatesTerm corr
Definition GERG.hpp:1158
auto alphar(const TType &T, const RhoType &rho, const MoleFracType &molefrac) const
Definition GERG.hpp:1168
auto alphaig(const TType &T, const RhoType &rhomolar, const MoleFractions &molefracs) const
Definition GERG.hpp:412
std::size_t size() const
Definition GERG.hpp:394
std::function< PureInfo(const std::string &)> GetPureInfo
Definition GERG.hpp:345
auto alphaig_pure(const TType &T, const RhoType &rhomolar, const int i) const
Definition GERG.hpp:397
std::function< AlphaigCoeffs(const std::string &)> GetAlphaigCoeffs
Definition GERG.hpp:347
const std::vector< AlphaigCoeffs > coeffs
Definition GERG.hpp:354
GERG200XAlphaig(const std::vector< std::string > &names, const GetPureInfo &get_pure_info, const GetAlphaigCoeffs &get_alphaig_coeffs)
Definition GERG.hpp:388
const std::vector< double > Tc
Definition GERG.hpp:353
GetAlphaigCoeffs _get_alphaig_coeffs
Definition GERG.hpp:348
const std::vector< double > rhoc
Definition GERG.hpp:353
GERG200XCorrespondingStatesTerm(const std::vector< std::string > &names, const GetPureCoeffs &get_pure_coeffs)
Definition GERG.hpp:223
auto alphar(const TauType &tau, const DeltaType &delta, const MoleFractions &molefracs) const
Definition GERG.hpp:228
std::function< PureCoeffs(const std::string &)> GetPureCoeffs
Definition GERG.hpp:210
GERG200XDepartureFunction(const std::string &fluid1, const std::string &fluid2, const GetDepartureCoeffs &get_departurecoeffs)
Definition GERG.hpp:255
auto alphar(const TauType &tau, const DeltaType &delta) const
Definition GERG.hpp:258
std::function< DepartureCoeffs(const std::string &, const std::string &)> GetDepartureCoeffs
Definition GERG.hpp:253
std::function< DepartureCoeffs(const std::string &, const std::string &)> GetDepartureCoeffs
Definition GERG.hpp:281
std::function< std::optional< double >(const std::string &, const std::string &, bool)> GetFij
Definition GERG.hpp:279
GERG200XDepartureTerm(const std::vector< std::string > &names, const GetFij &get_Fij, const GetDepartureCoeffs &get_departurecoeffs)
Definition GERG.hpp:320
GetDepartureCoeffs _get_departurecoeffs
Definition GERG.hpp:282
auto alphar(const TauType &tau, const DeltaType &delta, const MoleFractions &molefracs) const
Definition GERG.hpp:323
auto alphar(const TauType &tau, const DeltaType &delta) const
Definition GERG.hpp:104
GERG200XPureFluidEOS(const std::string &name, const GetPureCoeffs &get_pure_coeffs)
Definition GERG.hpp:101
std::function< PureCoeffs(const std::string &)> GetPureCoeffs
Definition GERG.hpp:100
std::function< BetasGammas(const std::string &, const std::string &)> GetBetasGammas
Definition GERG.hpp:133
GERG200XReducing(const std::vector< std::string > &names, const GetPureInfo &get_pure_info, const GetBetasGammas &get_betasgammas)
Definition GERG.hpp:174
auto get_Tr(const MoleFractions &z) const
Definition GERG.hpp:198
auto Y(const MoleFractions &z, const std::vector< double > &Yc, const Eigen::ArrayXXd &beta, const Eigen::ArrayXXd &Yij) const
Definition GERG.hpp:180
auto get_rhor(const MoleFractions &z) const
Definition GERG.hpp:203
std::function< PureInfo(const std::string &)> GetPureInfo
Definition GERG.hpp:131
AlphaigCoeffs get_alphaig_coeffs(const std::string &fluid)
Definition GERG.hpp:468
const std::vector< std::string > component_names
Definition GERG.hpp:431
BetasGammas get_betasgammas(const std::string &fluid1, const std::string &fluid2)
Definition GERG.hpp:595
PureInfo get_pure_info(const std::string &name)
Get the pure fluid information for a fluid from GERG-2004 monograph.
Definition GERG.hpp:434
std::optional< double > get_Fij(const std::string &fluid1, const std::string &fluid2, bool ok_missing=true)
Definition GERG.hpp:768
PureCoeffs get_pure_coeffs(const std::string &fluid)
Definition GERG.hpp:511
DepartureCoeffs get_departurecoeffs(const std::string &fluid1, const std::string &fluid2)
Definition GERG.hpp:805
const std::vector< std::string > component_names
Definition GERG.hpp:962
AlphaigCoeffs get_alphaig_coeffs(const std::string &fluid)
Definition GERG.hpp:1122
PureCoeffs get_pure_coeffs(const std::string &fluid)
Definition GERG.hpp:1094
auto get_pure_info(const std::string &name)
Definition GERG.hpp:964
BetasGammas get_betasgammas(const std::string &fluid1, const std::string &fluid2)
Definition GERG.hpp:992
auto POW2(const A &x)
auto POW3(const A &x)
auto getbaseval(const T &expr)
Definition types.hpp:90
T powi(const T &x, int n)
From Ulrich Deiters.
Definition types.hpp:139
auto forceeval(T &&expr)
Definition types.hpp:52
auto recalc_integration_constants(double T, double Tci, double rho, double rhoci, double Rstar_R)
Definition GERG.hpp:49
std::vector< double > theta0
Definition GERG.hpp:37
std::set< std::size_t > sizes()
Definition GERG.hpp:38
std::vector< double > n0
Definition GERG.hpp:37
std::vector< double > gamma
Definition GERG.hpp:33
std::vector< double > eta
Definition GERG.hpp:33
std::vector< double > t
Definition GERG.hpp:33
std::vector< double > n
Definition GERG.hpp:33
std::set< std::size_t > sizes()
Definition GERG.hpp:34
std::vector< double > epsilon
Definition GERG.hpp:33
std::vector< double > beta
Definition GERG.hpp:33
std::vector< double > d
Definition GERG.hpp:33
std::vector< double > d
Definition GERG.hpp:26
std::vector< double > c
Definition GERG.hpp:26
std::set< std::size_t > sizes()
Definition GERG.hpp:27
std::vector< double > n
Definition GERG.hpp:26
std::vector< double > l
Definition GERG.hpp:26
std::vector< double > t
Definition GERG.hpp:26