teqp 0.22.0
Loading...
Searching...
No Matches
multifluid_eosterms.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "teqp/types.hpp"
4#include "teqp/exceptions.hpp"
7
8namespace teqp {
9
14public:
15 Eigen::ArrayXd n, t, d;
16
17 template<typename TauType, typename DeltaType>
18 auto alphar(const TauType& tau, const DeltaType& delta) const {
19 using result = std::common_type_t<TauType, DeltaType>;
20 result r = 0.0;
21 TauType lntau = log(tau);
22 double base_delta = getbaseval(delta);
23 if (base_delta == 0) {
24 for (auto i = 0; i < n.size(); ++i) {
25 r = r + n[i] * exp(t[i] * lntau)*powi(delta, static_cast<int>(d[i]));
26 }
27 }
28 else {
29 DeltaType lndelta = log(delta);
30 for (auto i = 0; i < n.size(); ++i) {
31 r += n[i] * exp(t[i] * lntau + d[i] * lndelta);
32 }
33 }
34 return forceeval(r);
35 }
36};
37
42public:
44 Eigen::ArrayXd n, t, d, c, l;
45 Eigen::ArrayXi l_i;
46 };
48
49 PowerEOSTerm(const PowerEOSTermCoeffs& coef) : coeffs(coef){}
50
51 template<typename TauType, typename DeltaType>
52 auto alphar(const TauType& tau, const DeltaType& delta) const {
53 using result = std::common_type_t<TauType, DeltaType>;
54 result r = 0.0;
55 TauType lntau = log(tau);
56 if (coeffs.l_i.size() == 0 && coeffs.n.size() > 0) {
57 throw std::invalid_argument("l_i cannot be zero length if some terms are provided");
58 }
59 if (getbaseval(delta) == 0) {
60 for (auto i = 0; i < coeffs.n.size(); ++i) {
61 r += coeffs.n[i] * exp(coeffs.t[i] * lntau - coeffs.c[i] * powi(delta, coeffs.l_i[i])) * powi(delta, static_cast<int>(coeffs.d[i]));
62 }
63 }
64 else {
65 DeltaType lndelta = log(delta);
66 result arg;
67 DeltaType dpart;
68 for (auto i = 0; i < coeffs.n.size(); ++i) {
69 dpart = coeffs.d[i] * lndelta - coeffs.c[i] * powi(delta, coeffs.l_i[i]);
70 arg = (coeffs.t[i] * lntau) + dpart;
71 r += coeffs.n[i] * exp(arg);
72 }
73 }
74 return r;
75 }
76};
77
82public:
83 Eigen::ArrayXd n, t, d, g, l;
84 Eigen::ArrayXi l_i;
85
86 template<typename TauType, typename DeltaType>
87 auto alphar(const TauType& tau, const DeltaType& delta) const {
88 using result = std::common_type_t<TauType, DeltaType>;
89 result r = 0.0, lntau = log(tau);
90 if (getbaseval(delta) == 0) {
91 for (auto i = 0; i < n.size(); ++i) {
92 r = r + n[i] * exp(t[i] * lntau - g[i] * powi(delta, l_i[i]))*powi(delta,static_cast<int>(d[i]));
93 }
94 }
95 else {
96 result lndelta = log(delta);
97 for (auto i = 0; i < n.size(); ++i) {
98 r += n[i] * exp(t[i] * lntau + d[i] * lndelta - g[i] * powi(delta, l_i[i]));
99 }
100 }
101 return forceeval(r);
102 }
103};
104
109public:
110 Eigen::ArrayXd n, t, d, gd, ld, gt, lt;
111 Eigen::ArrayXi ld_i;
112
113 template<typename TauType, typename DeltaType>
114 auto alphar(const TauType& tau, const DeltaType& delta) const {
115 using result = std::common_type_t<TauType, DeltaType>;
116 result r = 0.0, lntau = log(tau);
117 if (ld_i.size() == 0 && n.size() > 0) {
118 throw std::invalid_argument("ld_i cannot be zero length if some terms are provided");
119 }
120 if (getbaseval(delta) == 0) {
121 for (auto i = 0; i < n.size(); ++i) {
122 r = r + n[i] * powi(delta, static_cast<int>(d[i])) * exp(t[i] * lntau - gd[i]*powi(delta, ld_i[i]) - gt[i]*pow(tau, lt[i]));
123 }
124 }
125 else {
126 result lndelta = log(delta);
127 for (auto i = 0; i < n.size(); ++i) {
128 r = r + n[i] * exp(t[i] * lntau + d[i] * lndelta - gd[i]*powi(delta, ld_i[i]) - gt[i]*pow(tau, lt[i]));
129 }
130 }
131 return forceeval(r);
132 }
133};
134
139public:
140 Eigen::ArrayXd n, t, d, eta, beta, gamma, epsilon;
141
142 template<typename TauType, typename DeltaType>
143 auto alphar(const TauType& tau, const DeltaType& delta) const {
144 using result = std::common_type_t<TauType, DeltaType>;
145 result r = 0.0, lntau = log(tau);
146 auto square = [](auto x) { return x * x; };
147 if (getbaseval(delta) == 0) {
148 for (auto i = 0; i < n.size(); ++i) {
149 r = r + n[i] * exp(t[i] * lntau - eta[i] * square(delta - epsilon[i]) - beta[i] * square(tau - gamma[i]))*powi(delta, static_cast<int>(d[i]));
150 }
151 }
152 else {
153 DeltaType lndelta = log(delta);
154 DeltaType d1, d2;
155 TauType t1, t2;
156 result arg;
157 for (auto i = 0; i < n.size(); ++i) {
158 d1 = delta - epsilon[i]; d2 = d1*d1;
159 t1 = tau - gamma[i]; t2 = t1*t1;
160 arg = t[i] * lntau + d[i] * lndelta - eta[i]*d2 - beta[i]*t2;
161 r = r + n[i] * exp(arg);
162 }
163 }
164 return forceeval(r);
165 }
166};
167
172public:
173 Eigen::ArrayXd n, t, d, eta, beta, gamma, epsilon;
174
175 template<typename TauType, typename DeltaType>
176 auto alphar(const TauType& tau, const DeltaType& delta) const {
177 using result = std::common_type_t<TauType, DeltaType>;
178 result r = 0.0, lntau = log(tau);
179 auto square = [](auto x) { return x * x; };
180 if (getbaseval(delta) == 0) {
181 for (auto i = 0; i < n.size(); ++i) {
182 r = r + n[i] * exp(t[i] * lntau - eta[i] * square(delta - epsilon[i]) - beta[i] * (delta - gamma[i]))*powi(delta, static_cast<int>(d[i]));
183 }
184 }
185 else {
186 result lndelta = log(delta);
187 for (auto i = 0; i < n.size(); ++i) {
188 r = r + n[i] * exp(t[i] * lntau + d[i] * lndelta - eta[i] * square(delta - epsilon[i]) - beta[i] * (delta - gamma[i]));
189 }
190 }
191 return forceeval(r);
192 }
193};
194
195
200public:
201 Eigen::ArrayXd n, t, d, l, m;
202 Eigen::ArrayXi l_i;
203
204 template<typename TauType, typename DeltaType>
205 auto alphar(const TauType& tau, const DeltaType& delta) const {
206 using result = std::common_type_t<TauType, DeltaType>;
207 result r = 0.0, lntau = log(tau);
208 if (getbaseval(delta) == 0) {
209 for (auto i = 0; i < n.size(); ++i) {
210 r = r + n[i] * exp(t[i] * lntau - powi(delta, l_i[i]) - pow(tau, m[i]))*powi(delta, static_cast<int>(d[i]));
211 }
212 }
213 else {
214 result lndelta = log(delta);
215 for (auto i = 0; i < n.size(); ++i) {
216 r = r + n[i] * exp(t[i] * lntau + d[i] * lndelta - powi(delta, l_i[i]) - pow(tau, m[i]));
217 }
218 }
219 return forceeval(r);
220 }
221};
222
227public:
228 Eigen::ArrayXd n, t, d, eta, beta, gamma, epsilon, b;
229
230 template<typename TauType, typename DeltaType>
231 auto alphar(const TauType& tau, const DeltaType& delta) const {
232
233 using result = std::common_type_t<TauType, DeltaType>;
234 result r = 0.0, lntau = log(tau);
235 auto square = [](auto x) { return x * x; };
236 if (getbaseval(delta) == 0) {
237 for (auto i = 0; i < n.size(); ++i) {
238 r = r + n[i] * exp(t[i] * lntau - eta[i] * square(delta - epsilon[i]) + 1.0 / (beta[i] * square(tau - gamma[i]) + b[i]))*powi(delta, static_cast<int>(d[i]));
239 }
240 }
241 else {
242 result lndelta = log(delta);
243 for (auto i = 0; i < n.size(); ++i) {
244 r = r + n[i] * exp(t[i] * lntau + d[i] * lndelta - eta[i] * square(delta - epsilon[i]) + 1.0 / (beta[i] * square(tau - gamma[i]) + b[i]));
245 }
246 }
247 return forceeval(r);
248 }
249};
250
255public:
256 Eigen::ArrayXXd a;
257 double taumin = -1, taumax = -1, deltamin = -1, deltamax = -1;
258
260 template<typename vectype, typename XType>
261 static auto Clenshaw1D(const vectype &c, const XType &ind){
262 int N = static_cast<int>(c.size()) - 1;
263 std::common_type_t<typename vectype::Scalar, XType> u_k = 0, u_kp1 = 0, u_kp2 = 0;
264 for (int k = N; k >= 0; --k){
265 // Do the recurrent calculation
266 u_k = 2.0*ind*u_kp1 - u_kp2 + c[k];
267 if (k > 0){
268 // Update the values
269 u_kp2 = u_kp1; u_kp1 = u_k;
270 }
271 }
272 return (u_k - u_kp2)/2.0;
273 }
274
276 template<typename MatType, typename XType>
277 static auto Clenshaw1DByRow(const MatType& c, const XType &ind) {
278 int N = static_cast<int>(c.rows()) - 1;
279 constexpr int Cols = MatType::ColsAtCompileTime;
280 using NumType = std::common_type_t<typename MatType::Scalar, XType>;
281 static Eigen::Array<NumType, 1, Cols> u_k, u_kp1, u_kp2;
282 // Not statically sized, need to resize
283 if constexpr (Cols == Eigen::Dynamic) {
284 int M = static_cast<int>(c.rows());
285 u_k.resize(M);
286 u_kp1.resize(M);
287 u_kp2.resize(M);
288 }
289 u_k.setZero(); u_kp1.setZero(); u_kp2.setZero();
290
291 for (int k = N; k >= 0; --k) {
292 // Do the recurrent calculation
293 u_k = 2.0 * ind * u_kp1 - u_kp2 + c.row(k).template cast<XType>();
294 if (k > 0) {
295 // Update the values
296 u_kp2 = u_kp1; u_kp1 = u_k;
297 }
298 }
299 return (u_k - u_kp2) / 2.0;
300 }
301
307 template<typename MatType, typename XType, typename YType>
308 static auto Clenshaw2DEigen(const MatType& a, const XType &x, const YType &y) {
309 auto b = Clenshaw1DByRow(a, y);
310 return Clenshaw1D(b.matrix(), x);
311 }
312
313 template<typename TauType, typename DeltaType>
314 auto alphar(const TauType& tau, const DeltaType& delta) const {
315 TauType x = (2.0*tau - (taumax + taumin)) / (taumax - taumin);
316 DeltaType y = (2.0*delta - (deltamax + deltamin)) / (deltamax - deltamin);
317 return forceeval(Clenshaw2DEigen(a, x, y));
318 }
319};
320
325public:
326 template<typename TauType, typename DeltaType>
327 auto alphar(const TauType& /*tau*/, const DeltaType& /*delta*/) const {
328 return static_cast<std::common_type_t<TauType, DeltaType>>(0.0);
329 }
330};
331
333public:
334 Eigen::ArrayXd A, B, C, D, a, b, beta, n;
335
336 template<typename TauType, typename DeltaType>
337 auto alphar(const TauType& tau, const DeltaType& delta) const {
338 // The non-analytic term
339 auto square = [](auto x) { return x * x; };
340 auto delta_min1_sq = square(delta - 1.0);
341
342 using result = std::common_type_t<TauType, DeltaType>;
343 result r = 0.0;
344 for (auto i = 0; i < n.size(); ++i) {
345 auto Psi = exp(-C[i]*delta_min1_sq - D[i]*square(tau - 1.0));
346 auto k = 1.0 / (2.0 * beta[i]);
347 auto theta = (1.0 - tau) + A[i] * pow(delta_min1_sq, k);
348 auto Delta = square(theta) + B[i]*pow(delta_min1_sq, a[i]);
349 r = r + n[i]*pow(Delta, b[i])*delta*Psi;
350 }
351 result outval = forceeval(r);
352
353 // If we are really, really close to the critical point (tau=delta=1), then the term will become undefined, so let's just return 0 in that case
354 double dbl = static_cast<double>(getbaseval(outval));
355 if (std::isfinite(dbl)) {
356 return outval;
357 }
358 else {
359 return static_cast<decltype(outval)>(0.0);
360 }
361 }
362};
363
368public:
370 const std::vector<AlphaFunctionOptions> alphas_cubic;
371
372 GenericCubicTerm(const nlohmann::json& spec) :
373 Tcrit_K(spec.at("Tcrit / K")),
374 pcrit_Pa(spec.at("pcrit / Pa")),
375 R_gas(spec.at("R / J/mol/K")),
376 Delta1(spec.at("Delta1")),
377 Delta2(spec.at("Delta2")),
378 Tred_K(spec.at("Tred / K")),
379 rhored_molm3(spec.at("rhored / mol/m^3")),
380 a0_cubic(spec.at("OmegaA").get<double>() * pow2(R_gas * Tcrit_K) / pcrit_Pa),
381 b_cubic(spec.at("OmegaB").get<double>() * R_gas * Tcrit_K / pcrit_Pa),
382 alphas_cubic(build_alpha_functions(std::vector<double>(1, Tcrit_K), spec.at("alpha")))
383 {
384 if (alphas_cubic.size() != 1){
385 throw teqp::InvalidArgument("alpha should be of size 1");
386 }
387 }
388
389 template<typename TauType, typename DeltaType>
390 auto alphar(const TauType& tau, const DeltaType& delta) const {
391 auto T = Tred_K/tau;
392 auto rhomolar = delta*rhored_molm3;
393 auto alpha = forceeval(std::visit([&](auto& t) { return t(T); }, alphas_cubic[0]));
394 auto a_cubic = a0_cubic*alpha;
395 auto Psiminus = -log(1.0 - b_cubic * rhomolar);
396 auto Psiplus = log((Delta1 * b_cubic * rhomolar + 1.0) / (Delta2 * b_cubic * rhomolar + 1.0)) / (b_cubic * (Delta1 - Delta2));
397 auto val = Psiminus - a_cubic / (R_gas * T) * Psiplus;
398 return forceeval(val);
399 }
400};
401
406public:
407 const double Tred_K, rhored_molm3;
409
410 PCSAFTGrossSadowski2001Term(const nlohmann::json& spec) :
411 Tred_K(spec.at("Tred / K")),
412 rhored_molm3(spec.at("rhored / mol/m^3")),
413 pcsaft(spec) // The remaining arguments will be consumed by the constructor
414 {}
415
416 template<typename TauType, typename DeltaType>
417 auto alphar(const TauType& tau, const DeltaType& delta) const {
418 auto T = forceeval(Tred_K/tau);
419 auto rhomolar = forceeval(delta*rhored_molm3);
420 return forceeval(pcsaft.alphar(T, rhomolar, Eigen::Array<double,1,1>{}));
421 }
422};
423
424template<typename... Args>
426private:
427 using varEOSTerms = std::variant<Args...>;
428 std::vector<varEOSTerms> coll;
429public:
430
431 auto size() const { return coll.size(); }
432
433 template<typename Instance>
434 auto add_term(Instance&& instance) {
435 coll.emplace_back(instance);
436 }
437
438 template <class Tau, class Delta>
439 auto alphar(const Tau& tau, const Delta& delta) const {
440 std::common_type_t <Tau, Delta> ar = 0.0;
441 for (const auto& term : coll) {
442// // This approach is recommended to speed up visitor, but doesn't seem to make a difference in Xcode
443// if (const auto t = std::get_if<JustPowerEOSTerm>(&term)){
444// ar += t->alphar(tau, delta); continue;
445// }
446// if (const auto t = std::get_if<GaussianEOSTerm>(&term)){
447// ar += t->alphar(tau, delta); continue;
448// }
449// if (const auto t = std::get_if<PowerEOSTerm>(&term)){
450// ar += t->alphar(tau, delta); continue;
451// }
452 auto contrib = std::visit([&](auto& t) { return t.alphar(tau, delta); }, term);
453 ar += contrib;
454 }
455 return ar;
456 }
457};
458
460
462
463}; // namespace teqp
static auto Clenshaw1DByRow(const MatType &c, const XType &ind)
Clenshaw evaluation of one dimensional flattening of the Chebyshev expansion.
static auto Clenshaw1D(const vectype &c, const XType &ind)
Clenshaw evaluation of a Chebyshev expansion in 1D.
auto alphar(const TauType &tau, const DeltaType &delta) const
static auto Clenshaw2DEigen(const MatType &a, const XType &x, const YType &y)
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const Tau &tau, const Delta &delta) const
auto add_term(Instance &&instance)
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TauType &tau, const DeltaType &delta) const
GenericCubicTerm(const nlohmann::json &spec)
auto alphar(const TauType &tau, const DeltaType &delta) const
const std::vector< AlphaFunctionOptions > alphas_cubic
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TauType &, const DeltaType &) const
const saft::PCSAFT::PCSAFTPureGrossSadowski2001 pcsaft
PCSAFTGrossSadowski2001Term(const nlohmann::json &spec)
auto alphar(const TauType &tau, const DeltaType &delta) const
const PowerEOSTermCoeffs coeffs
PowerEOSTerm(const PowerEOSTermCoeffs &coef)
auto alphar(const TauType &tau, const DeltaType &delta) const
auto alphar(const TTYPE &T, const RhoType &rhomolar, const VecType &) const
auto getbaseval(const T &expr)
Definition types.hpp:90
T powi(const T &x, int n)
From Ulrich Deiters.
Definition types.hpp:139
T pow2(const T &x)
Definition types.hpp:7
auto pow(const double &x, const double &e)
Definition types.hpp:195
auto forceeval(T &&expr)
Definition types.hpp:52
auto build_alpha_functions(const TC &Tc_K, const nlohmann::json &jalphas)
Definition cubics.hpp:100