teqp 0.22.0
Loading...
Searching...
No Matches
GrossVrabec.hpp
Go to the documentation of this file.
1#pragma once
2#include "types.hpp"
4
6
8template <typename Eta, typename MType, typename TType>
9auto get_JDD_2ij(const Eta& eta, const MType& mij, const TType& Tstarij) {
10 static Eigen::ArrayXd a_0 = (Eigen::ArrayXd(5) << 0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308).finished();
11 static Eigen::ArrayXd a_1 = (Eigen::ArrayXd(5) << 0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135).finished();
12 static Eigen::ArrayXd a_2 = (Eigen::ArrayXd(5) << -1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575).finished();
13
14 static Eigen::ArrayXd b_0 = (Eigen::ArrayXd(5) << 0.2187939, -1.1896431, 1.1626889, 0, 0).finished();
15 static Eigen::ArrayXd b_1 = (Eigen::ArrayXd(5) << -0.5873164, 1.2489132, -0.5085280, 0, 0).finished();
16 static Eigen::ArrayXd b_2 = (Eigen::ArrayXd(5) << 3.4869576, -14.915974, 15.372022, 0, 0).finished();
17
18 std::common_type_t<Eta, MType, TType> summer = 0.0;
19 for (auto n = 0; n < 5; ++n){
20 auto anij = a_0[n] + (mij-1)/mij*a_1[n] + (mij-1)/mij*(mij-2)/mij*a_2[n]; // Eq. 12
21 auto bnij = b_0[n] + (mij-1)/mij*b_1[n] + (mij-1)/mij*(mij-2)/mij*b_2[n]; // Eq. 13
22 summer += (anij + bnij/Tstarij)*pow(eta, n);
23 }
24 return forceeval(summer);
25}
26
28template <typename Eta, typename MType>
29auto get_JDD_3ijk(const Eta& eta, const MType& mijk) {
30 static Eigen::ArrayXd c_0 = (Eigen::ArrayXd(5) << -0.0646774, 0.1975882, -0.8087562, 0.6902849, 0.0).finished();
31 static Eigen::ArrayXd c_1 = (Eigen::ArrayXd(5) << -0.9520876, 2.9924258, -2.3802636, -0.2701261, 0.0).finished();
32 static Eigen::ArrayXd c_2 = (Eigen::ArrayXd(5) << -0.6260979, 1.2924686, 1.6542783, -3.4396744, 0.0).finished();
33 std::common_type_t<Eta, MType> summer = 0.0;
34 for (auto n = 0; n < 5; ++n){
35 auto cnijk = c_0[n] + (mijk-1)/mijk*c_1[n] + (mijk-1)/mijk*(mijk-2)/mijk*c_2[n]; // Eq. 14
36 summer += cnijk*pow(eta, n);
37 }
38 return forceeval(summer);
39}
40
42template <typename Eta, typename MType, typename TType>
43auto get_JQQ_2ij(const Eta& eta, const MType& mij, const TType& Tstarij) {
44 static Eigen::ArrayXd a_0 = (Eigen::ArrayXd(5) << 1.2378308, 2.4355031, 1.6330905, -1.6118152, 6.9771185).finished();
45 static Eigen::ArrayXd a_1 = (Eigen::ArrayXd(5) << 1.2854109, -11.465615, 22.086893, 7.4691383, -17.197772).finished();
46 static Eigen::ArrayXd a_2 = (Eigen::ArrayXd(5) << 1.7942954, 0.7695103, 7.2647923, 94.486699, -77.148458).finished();
47
48 static Eigen::ArrayXd b_0 = (Eigen::ArrayXd(5) << 0.4542718, -4.5016264, 3.5858868, 0.0, 0.0).finished();
49 static Eigen::ArrayXd b_1 = (Eigen::ArrayXd(5) << -0.8137340, 10.064030, -10.876631, 0.0, 0.0).finished();
50 static Eigen::ArrayXd b_2 = (Eigen::ArrayXd(5) << 6.8682675, -5.1732238, -17.240207, 0.0, 0.0).finished();
51
52 std::common_type_t<Eta, MType, TType> summer = 0.0;
53 for (auto n = 0; n < 5; ++n){
54 auto anij = a_0[n] + (mij-1)/mij*a_1[n] + (mij-1)/mij*(mij-2)/mij*a_2[n]; // Eq. 12
55 auto bnij = b_0[n] + (mij-1)/mij*b_1[n] + (mij-1)/mij*(mij-2)/mij*b_2[n]; // Eq. 13
56 summer += (anij + bnij/Tstarij)*pow(eta, n);
57 }
58 return forceeval(summer);
59}
60
62template <typename Eta, typename MType>
63auto get_JQQ_3ijk(const Eta& eta, const MType& mijk) {
64 static Eigen::ArrayXd c_0 = (Eigen::ArrayXd(5) << 0.5000437, 6.5318692, -16.014780, 14.425970, 0.0).finished();
65 static Eigen::ArrayXd c_1 = (Eigen::ArrayXd(5) << 2.0002094, -6.7838658, 20.383246, -10.895984, 0.0).finished();
66 static Eigen::ArrayXd c_2 = (Eigen::ArrayXd(5) << 3.1358271, 7.2475888, 3.0759478, 0.0, 0.0).finished();
67 std::common_type_t<Eta, MType> summer = 0.0;
68 for (auto n = 0; n < 5; ++n){
69 auto cnijk = c_0[n] + (mijk-1)/mijk*c_1[n] + (mijk-1)/mijk*(mijk-2)/mijk*c_2[n]; // Eq. 14
70 summer += cnijk*pow(eta, n);
71 }
72 return forceeval(summer);
73}
74
75
77template <typename Eta, typename MType, typename TType>
78auto get_JDQ_2ij(const Eta& eta, const MType& mij, const TType& Tstarij) {
79 static Eigen::ArrayXd a_0 = (Eigen::ArrayXd(4) << 0.6970950, -0.6335541, 2.9455090, -1.4670273).finished();
80 static Eigen::ArrayXd a_1 = (Eigen::ArrayXd(4) << -0.6734593, -1.4258991, 4.1944139, 1.0266216).finished();
81 static Eigen::ArrayXd a_2 = (Eigen::ArrayXd(4) << 0.6703408, -4.3384718, 7.2341684, 0).finished();
82
83 static Eigen::ArrayXd b_0 = (Eigen::ArrayXd(4) << -0.4840383, 1.9704055, -2.1185727, 0).finished();
84 static Eigen::ArrayXd b_1 = (Eigen::ArrayXd(4) << 0.6765101, -3.0138675, 0.4674266, 0).finished();
85 static Eigen::ArrayXd b_2 = (Eigen::ArrayXd(4) << -1.1675601, 2.1348843, 0, 0).finished();
86
87 std::common_type_t<Eta, MType, TType> summer = 0.0;
88 for (auto n = 0; n < 4; ++n){
89 auto anij = a_0[n] + (mij-1)/mij*a_1[n] + (mij-1)/mij*(mij-2)/mij*a_2[n]; // Eq. 18
90 auto bnij = b_0[n] + (mij-1)/mij*b_1[n] + (mij-1)/mij*(mij-2)/mij*b_2[n]; // Eq. 19
91 summer += (anij + bnij/Tstarij)*pow(eta, n);
92 }
93 return forceeval(summer);
94}
95
96
98template <typename Eta, typename MType>
99auto get_JDQ_3ijk(const Eta& eta, const MType& mijk) {
100 static Eigen::ArrayXd c_0 = (Eigen::ArrayXd(4) << 7.846431, 33.42700, 4.689111, 0).finished();
101 static Eigen::ArrayXd c_1 = (Eigen::ArrayXd(4) << -20.72202, -58.63904, -1.764887, 0).finished();
102 std::common_type_t<Eta, MType> summer = 0.0;
103 for (auto n = 0; n < 4; ++n){
104 auto cnijk = c_0[n] + (mijk-1)/mijk*c_1[n]; // Eq. 20
105 summer += cnijk*pow(eta, n);
106 }
107 return forceeval(summer);
108}
109
110/***
111 * \brief The dipolar contribution given in Gross and Vrabec
112 */
114private:
115 const Eigen::ArrayXd m, sigma_Angstrom, epsilon_over_k, mustar2, nmu;
116public:
117 const bool has_a_polar;
118 DipolarContributionGrossVrabec(const Eigen::ArrayX<double> &m, const Eigen::ArrayX<double> &sigma_Angstrom, const Eigen::ArrayX<double> &epsilon_over_k, const Eigen::ArrayX<double> &mustar2, const Eigen::ArrayX<double> &nmu) : m(m), sigma_Angstrom(sigma_Angstrom), epsilon_over_k(epsilon_over_k), mustar2(mustar2), nmu(nmu), has_a_polar(mustar2.cwiseAbs().sum() > 0) {
119 // Check lengths match
120 if (m.size() != mustar2.size()){
121 throw teqp::InvalidArgument("bad size of mustar2");
122 }
123 if (m.size() != nmu.size()){
124 throw teqp::InvalidArgument("bad size of n");
125 }
126 }
127
129 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
130 auto get_alpha2DD(const TTYPE& T, const RhoType& rhoN_A3, const EtaType& eta, const VecType& mole_fractions) const{
131 const auto& x = mole_fractions; // concision
132 const auto& sigma = sigma_Angstrom; // concision
133 const auto N = mole_fractions.size();
134 std::common_type_t<TTYPE, RhoType, decltype(mole_fractions[0])> summer = 0.0;
135 for (auto i = 0; i < N; ++i){
136 for (auto j = 0; j < N; ++j){
137 auto ninj = nmu[i]*nmu[j];
138 if (ninj > 0){
139 // Lorentz-Berthelot mixing rules
140 auto epskij = sqrt(epsilon_over_k[i]*epsilon_over_k[j]);
141 auto sigmaij = (sigma[i]+sigma[j])/2;
142
143 auto Tstarij = forceeval(T/epskij);
144 auto mij = std::min(sqrt(m[i]*m[j]), 2.0);
145 summer += x[i]*x[j]*epsilon_over_k[i]/T*epsilon_over_k[j]/T*POW3(sigma[i]*sigma[j]/sigmaij)*ninj*mustar2[i]*mustar2[j]*get_JDD_2ij(eta, mij, Tstarij);
146 }
147 }
148 }
149 return forceeval(-static_cast<double>(EIGEN_PI)*rhoN_A3*summer);
150 }
151
153 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
154 auto get_alpha3DD(const TTYPE& T, const RhoType& rhoN_A3, const EtaType& eta, const VecType& mole_fractions) const{
155 const auto& x = mole_fractions; // concision
156 const auto& sigma = sigma_Angstrom; // concision
157 const auto N = mole_fractions.size();
158 std::common_type_t<TTYPE, RhoType, decltype(mole_fractions[0])> summer = 0.0;
159 for (auto i = 0; i < N; ++i){
160 for (auto j = 0; j < N; ++j){
161 for (auto k = 0; k < N; ++k){
162 auto ninjnk = nmu[i]*nmu[j]*nmu[k];
163 if (ninjnk > 0){
164 // Lorentz-Berthelot mixing rules for sigma
165 auto sigmaij = (sigma[i]+sigma[j])/2;
166 auto sigmaik = (sigma[i]+sigma[k])/2;
167 auto sigmajk = (sigma[j]+sigma[k])/2;
168
169 auto mijk = std::min(pow(m[i]*m[j]*m[k], 1.0/3.0), 2.0);
170 summer += x[i]*x[j]*x[k]*epsilon_over_k[i]/T*epsilon_over_k[j]/T*epsilon_over_k[k]/T*POW3(sigma[i]*sigma[j]*sigma[k])/(sigmaij*sigmaik*sigmajk)*ninjnk*mustar2[i]*mustar2[j]*mustar2[k]*get_JDD_3ijk(eta, mijk);
171 }
172 }
173 }
174 }
175 return forceeval(-4.0*POW2(static_cast<double>(EIGEN_PI))/3.0*POW2(rhoN_A3)*summer);
176 }
177
178 /***
179 * \brief Get the dipolar contribution to \f$ \alpha = A/(NkT) \f$
180 */
181 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
182 auto eval(const TTYPE& T, const RhoType& rho_A3, const EtaType& eta, const VecType& mole_fractions) const {
183 auto alpha2 = get_alpha2DD(T, rho_A3, eta, mole_fractions);
184 auto alpha3 = get_alpha3DD(T, rho_A3, eta, mole_fractions);
185 auto alpha = forceeval(alpha2/(1.0-alpha3/alpha2));
186
187 using alpha2_t = decltype(alpha2);
188 using alpha3_t = decltype(alpha3);
189 using alpha_t = decltype(alpha);
190 struct DipolarContributionTerms{
191 alpha2_t alpha2;
192 alpha3_t alpha3;
193 alpha_t alpha;
194 };
195 return DipolarContributionTerms{alpha2, alpha3, alpha};
196 }
197};
198
199/***
200 * \brief The quadrupolar contribution from Gross, AICHEJ, doi: 10.1002/aic.10502
201 *
202 */
204private:
205 const Eigen::ArrayXd m, sigma_Angstrom, epsilon_over_k, Qstar2, nQ;
206
207public:
208 const bool has_a_polar;
209 QuadrupolarContributionGross(const Eigen::ArrayX<double> &m, const Eigen::ArrayX<double> &sigma_Angstrom, const Eigen::ArrayX<double> &epsilon_over_k, const Eigen::ArrayX<double> &Qstar2, const Eigen::ArrayX<double> &nQ) : m(m), sigma_Angstrom(sigma_Angstrom), epsilon_over_k(epsilon_over_k), Qstar2(Qstar2), nQ(nQ), has_a_polar(Qstar2.cwiseAbs().sum() > 0) {
210 // Check lengths match
211 if (m.size() != Qstar2.size()){
212 throw teqp::InvalidArgument("bad size of mustar2");
213 }
214 if (m.size() != nQ.size()){
215 throw teqp::InvalidArgument("bad size of n");
216 }
217 }
219
221 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
222 auto get_alpha2QQ(const TTYPE& T, const RhoType& rhoN_A3, const EtaType& eta, const VecType& mole_fractions) const{
223 const auto& x = mole_fractions; // concision
224 const auto& sigma = sigma_Angstrom; // concision
225 const auto N = mole_fractions.size();
226 std::common_type_t<TTYPE, RhoType, decltype(mole_fractions[0])> summer = 0.0;
227 for (auto i = 0; i < N; ++i){
228 for (auto j = 0; j < N; ++j){
229 auto ninj = nQ[i]*nQ[j];
230 if (ninj > 0){
231 // Lorentz-Berthelot mixing rules
232 auto epskij = sqrt(epsilon_over_k[i]*epsilon_over_k[j]);
233 auto sigmaij = (sigma[i]+sigma[j])/2;
234
235 auto Tstarij = forceeval(T/epskij);
236 auto mij = std::min(sqrt(m[i]*m[j]), 2.0);
237 summer += x[i]*x[j]*epsilon_over_k[i]/T*epsilon_over_k[j]/T*POW5(sigma[i]*sigma[j])/POW7(sigmaij)*ninj*Qstar2[i]*Qstar2[j]*get_JQQ_2ij(eta, mij, Tstarij);
238 }
239 }
240 }
241 return forceeval(-static_cast<double>(EIGEN_PI)*POW2(3.0/4.0)*rhoN_A3*summer);
242 }
243
245 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
246 auto get_alpha3QQ(const TTYPE& T, const RhoType& rhoN_A3, const EtaType& eta, const VecType& mole_fractions) const{
247 const auto& x = mole_fractions; // concision
248 const auto& sigma = sigma_Angstrom; // concision
249 const std::size_t N = mole_fractions.size();
250 std::common_type_t<TTYPE, RhoType, decltype(mole_fractions[0])> summer = 0.0;
251 for (std::size_t i = 0; i < N; ++i){
252 for (std::size_t j = 0; j < N; ++j){
253 for (std::size_t k = 0; k < N; ++k){
254 auto ninjnk = nQ[i]*nQ[j]*nQ[k];
255 if (ninjnk > 0){
256 // Lorentz-Berthelot mixing rules for sigma
257 auto sigmaij = (sigma[i]+sigma[j])/2;
258 auto sigmaik = (sigma[i]+sigma[k])/2;
259 auto sigmajk = (sigma[j]+sigma[k])/2;
260
261 auto mijk = std::min(pow(m[i]*m[j]*m[k], 1.0/3.0), 2.0);
262 summer += x[i]*x[j]*x[k]*epsilon_over_k[i]/T*epsilon_over_k[j]/T*epsilon_over_k[k]/T*POW5(sigma[i]*sigma[j]*sigma[k])/POW3(sigmaij*sigmaik*sigmajk)*ninjnk*Qstar2[i]*Qstar2[j]*Qstar2[k]*get_JDD_3ijk(eta, mijk);
263 }
264 }
265 }
266 }
267 return forceeval(-4.0*POW2(static_cast<double>(EIGEN_PI))/3.0*POW3(3.0/4.0)*POW2(rhoN_A3)*summer);
268 }
269
270 /***
271 * \brief Get the quadrupolar contribution to \f$ \alpha = A/(NkT) \f$
272 */
273 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
274 auto eval(const TTYPE& T, const RhoType& rho_A3, const EtaType& eta, const VecType& mole_fractions) const {
275 auto alpha2 = get_alpha2QQ(T, rho_A3, eta, mole_fractions);
276 auto alpha3 = get_alpha3QQ(T, rho_A3, eta, mole_fractions);
277 auto alpha = forceeval(alpha2/(1.0-alpha3/alpha2));
278
279 using alpha2_t = decltype(alpha2);
280 using alpha3_t = decltype(alpha3);
281 using alpha_t = decltype(alpha);
282 struct QuadrupolarContributionTerms{
283 alpha2_t alpha2;
284 alpha3_t alpha3;
285 alpha_t alpha;
286 };
287 return QuadrupolarContributionTerms{alpha2, alpha3, alpha};
288 }
289};
290
291
292/***
293 * \brief The cross dipolar-quadrupolar contribution from Vrabec and Gross
294 * doi: https://doi.org/10.1021/jp072619u
295 *
296 */
298private:
299 const Eigen::ArrayXd m, sigma_Angstrom, epsilon_over_k, mustar2, nmu, Qstar2, nQ;
300
301public:
303 const Eigen::ArrayX<double> &m,
304 const Eigen::ArrayX<double> &sigma_Angstrom,
305 const Eigen::ArrayX<double> &epsilon_over_k,
306 const Eigen::ArrayX<double> &mustar2,
307 const Eigen::ArrayX<double> &nmu,
308 const Eigen::ArrayX<double> &Qstar2,
309 const Eigen::ArrayX<double> &nQ
310 ) : m(m), sigma_Angstrom(sigma_Angstrom), epsilon_over_k(epsilon_over_k), mustar2(mustar2), nmu(nmu), Qstar2(Qstar2), nQ(nQ) {
311 // Check lengths match
312 if (m.size() != Qstar2.size()){
313 throw teqp::InvalidArgument("bad size of Qstar2");
314 }
315 if (m.size() != nQ.size()){
316 throw teqp::InvalidArgument("bad size of nQ");
317 }
318 if (m.size() != mustar2.size()){
319 throw teqp::InvalidArgument("bad size of mustar2");
320 }
321 if (m.size() != nmu.size()){
322 throw teqp::InvalidArgument("bad size of n");
323 }
324 if (Qstar2.cwiseAbs().sum() == 0 || mustar2.cwiseAbs().sum() == 0){
325 throw teqp::InvalidArgument("Invalid to have either missing polar or quadrupolar term in cross-polar term");
326 }
327 }
329
331 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
332 auto get_alpha2DQ(const TTYPE& T, const RhoType& rhoN_A3, const EtaType& eta, const VecType& mole_fractions) const{
333 const auto& x = mole_fractions; // concision
334 const auto& sigma = sigma_Angstrom; // concision
335 const auto N = mole_fractions.size();
336 std::common_type_t<TTYPE, RhoType, decltype(mole_fractions[0])> summer = 0.0;
337 for (auto i = 0; i < N; ++i){
338 for (auto j = 0; j < N; ++j){
339 auto ninj = nmu[i]*nQ[j];
340 if (ninj > 0){
341 // Lorentz-Berthelot mixing rules
342 auto epskij = sqrt(epsilon_over_k[i]*epsilon_over_k[j]);
343 auto sigmaij = (sigma[i]+sigma[j])/2;
344
345 auto Tstarij = forceeval(T/epskij);
346 auto mij = std::min(sqrt(m[i]*m[j]), 2.0);
347 summer += x[i]*x[j]*epsilon_over_k[i]/T*epsilon_over_k[j]/T*POW3(sigma[i])*POW5(sigma[j])/POW5(sigmaij)*ninj*mustar2[i]*Qstar2[j]*get_JDQ_2ij(eta, mij, Tstarij);
348 }
349 }
350 }
351 return forceeval(-static_cast<double>(EIGEN_PI)*9.0/4.0*rhoN_A3*summer);
352 }
353
355 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
356 auto get_alpha3DQ(const TTYPE& T, const RhoType& rhoN_A3, const EtaType& eta, const VecType& mole_fractions) const{
357 const auto& x = mole_fractions; // concision
358 const auto& sigma = sigma_Angstrom; // concision
359 const std::size_t N = mole_fractions.size();
360 std::common_type_t<TTYPE, RhoType, decltype(mole_fractions[0])> summer = 0.0;
361 for (std::size_t i = 0; i < N; ++i){
362 for (std::size_t j = 0; j < N; ++j){
363 for (std::size_t k = 0; k < N; ++k){
364 auto ninjnk1 = nmu[i]*nmu[j]*nQ[k];
365 auto ninjnk2 = nmu[i]*nQ[j]*nQ[k];
366 if (ninjnk1 > 0 || ninjnk2 > 0){
367 // Lorentz-Berthelot mixing rules for sigma
368 auto sigmaij = (sigma[i]+sigma[j])/2;
369 auto sigmaik = (sigma[i]+sigma[k])/2;
370 auto sigmajk = (sigma[j]+sigma[k])/2;
371
372 auto mijk = std::min(pow(m[i]*m[j]*m[k], 1.0/3.0), 2.0);
373 double alpha_GV = 1.19374; // Table 3
374 auto polars = ninjnk1*mustar2[i]*mustar2[j]*Qstar2[k] + ninjnk2*alpha_GV*mustar2[i]*Qstar2[j]*Qstar2[k];
375 summer += x[i]*x[j]*x[k]*epsilon_over_k[i]/T*epsilon_over_k[j]/T*epsilon_over_k[k]/T*POW4(sigma[i]*sigma[j]*sigma[k])/POW2(sigmaij*sigmaik*sigmajk)*polars*get_JDQ_3ijk(eta, mijk);
376 }
377 }
378 }
379 }
380 return forceeval(-POW2(rhoN_A3)*summer);
381 }
382
383 /***
384 * \brief Get the cross-polar contribution to \f$ \alpha = A/(NkT) \f$
385 */
386 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
387 auto eval(const TTYPE& T, const RhoType& rho_A3, const EtaType& eta, const VecType& mole_fractions) const {
388 auto alpha2 = get_alpha2DQ(T, rho_A3, eta, mole_fractions);
389 auto alpha3 = get_alpha3DQ(T, rho_A3, eta, mole_fractions);
390 auto alpha = forceeval(alpha2/(1.0-alpha3/alpha2));
391
392 using alpha2_t = decltype(alpha2);
393 using alpha3_t = decltype(alpha3);
394 using alpha_t = decltype(alpha);
395 struct DipolarQuadrupolarContributionTerms{
396 alpha2_t alpha2;
397 alpha3_t alpha3;
398 alpha_t alpha;
399 };
400 return DipolarQuadrupolarContributionTerms{alpha2, alpha3, alpha};
401 }
402};
403
404template<typename type>
417
419public:
421
422 const std::optional<DipolarContributionGrossVrabec> di;
423 const std::optional<QuadrupolarContributionGross> quad;
424 const std::optional<DipolarQuadrupolarContributionVrabecGross> diquad;
425
427 const Eigen::ArrayX<double> &m,
428 const Eigen::ArrayX<double> &sigma_Angstrom,
429 const Eigen::ArrayX<double> &epsilon_over_k,
430 const Eigen::ArrayX<double> &mustar2,
431 const Eigen::ArrayX<double> &nmu,
432 const Eigen::ArrayX<double> &Qstar2,
433 const Eigen::ArrayX<double> &nQ)
434 : di((((nmu*mustar2 > 0).cast<int>().sum() > 0) ? decltype(di)(DipolarContributionGrossVrabec(m, sigma_Angstrom, epsilon_over_k, mustar2, nmu)) : std::nullopt)),
435 quad((((nQ*Qstar2 > 0).cast<int>().sum() > 0) ? decltype(quad)(QuadrupolarContributionGross(m, sigma_Angstrom, epsilon_over_k, Qstar2, nQ)) : std::nullopt)),
436 diquad((di && quad) ? decltype(diquad)(DipolarQuadrupolarContributionVrabecGross(m, sigma_Angstrom, epsilon_over_k, mustar2, nmu, Qstar2, nQ)) : std::nullopt)
437 {};
438
439 template<typename TTYPE, typename RhoType, typename EtaType, typename VecType>
440 auto eval(const TTYPE& T, const RhoType& rho_A3, const EtaType& eta, const VecType& mole_fractions) const {
441
442 using type = std::common_type_t<TTYPE, RhoType, EtaType, decltype(mole_fractions[0])>;
443 type alpha2DD = 0.0, alpha3DD = 0.0, alphaDD = 0.0;
444 if (di && di.value().has_a_polar){
445 alpha2DD = di.value().get_alpha2DD(T, rho_A3, eta, mole_fractions);
446 alpha3DD = di.value().get_alpha3DD(T, rho_A3, eta, mole_fractions);
447 alphaDD = forceeval(alpha2DD/(1.0-alpha3DD/alpha2DD));
448 }
449
450 type alpha2QQ = 0.0, alpha3QQ = 0.0, alphaQQ = 0.0;
451 if (quad && quad.value().has_a_polar){
452 alpha2QQ = quad.value().get_alpha2QQ(T, rho_A3, eta, mole_fractions);
453 alpha3QQ = quad.value().get_alpha3QQ(T, rho_A3, eta, mole_fractions);
454 alphaQQ = forceeval(alpha2QQ/(1.0-alpha3QQ/alpha2QQ));
455 }
456
457 type alpha2DQ = 0.0, alpha3DQ = 0.0, alphaDQ = 0.0;
458 if (diquad){
459 alpha2DQ = diquad.value().get_alpha2DQ(T, rho_A3, eta, mole_fractions);
460 alpha3DQ = diquad.value().get_alpha3DQ(T, rho_A3, eta, mole_fractions);
461 alphaDQ = forceeval(alpha2DQ/(1.0-alpha3DQ/alpha2DQ));
462 }
463
464 auto alpha = forceeval(alphaDD + alphaQQ + alphaDQ);
465
466 return MultipolarContributionGrossVrabecTerms<type>{alpha2DD, alpha3DD, alphaDD, alpha2QQ, alpha3QQ, alphaQQ, alpha2DQ, alpha3DQ, alphaDQ, alpha};
467 }
468
469};
470
471}
auto get_alpha2DD(const TTYPE &T, const RhoType &rhoN_A3, const EtaType &eta, const VecType &mole_fractions) const
Eq. 8 from Gross and Vrabec.
auto eval(const TTYPE &T, const RhoType &rho_A3, const EtaType &eta, const VecType &mole_fractions) const
auto get_alpha3DD(const TTYPE &T, const RhoType &rhoN_A3, const EtaType &eta, const VecType &mole_fractions) const
Eq. 9 from Gross and Vrabec.
DipolarContributionGrossVrabec(const Eigen::ArrayX< double > &m, const Eigen::ArrayX< double > &sigma_Angstrom, const Eigen::ArrayX< double > &epsilon_over_k, const Eigen::ArrayX< double > &mustar2, const Eigen::ArrayX< double > &nmu)
auto get_alpha2DQ(const TTYPE &T, const RhoType &rhoN_A3, const EtaType &eta, const VecType &mole_fractions) const
Eq. 14 from Vrabec and Gross.
auto get_alpha3DQ(const TTYPE &T, const RhoType &rhoN_A3, const EtaType &eta, const VecType &mole_fractions) const
Eq. 15 from Vrabec and Gross.
DipolarQuadrupolarContributionVrabecGross & operator=(const DipolarQuadrupolarContributionVrabecGross &)=delete
DipolarQuadrupolarContributionVrabecGross(const Eigen::ArrayX< double > &m, const Eigen::ArrayX< double > &sigma_Angstrom, const Eigen::ArrayX< double > &epsilon_over_k, const Eigen::ArrayX< double > &mustar2, const Eigen::ArrayX< double > &nmu, const Eigen::ArrayX< double > &Qstar2, const Eigen::ArrayX< double > &nQ)
auto eval(const TTYPE &T, const RhoType &rho_A3, const EtaType &eta, const VecType &mole_fractions) const
MultipolarContributionGrossVrabec(const Eigen::ArrayX< double > &m, const Eigen::ArrayX< double > &sigma_Angstrom, const Eigen::ArrayX< double > &epsilon_over_k, const Eigen::ArrayX< double > &mustar2, const Eigen::ArrayX< double > &nmu, const Eigen::ArrayX< double > &Qstar2, const Eigen::ArrayX< double > &nQ)
const std::optional< DipolarQuadrupolarContributionVrabecGross > diquad
const std::optional< QuadrupolarContributionGross > quad
const std::optional< DipolarContributionGrossVrabec > di
auto eval(const TTYPE &T, const RhoType &rho_A3, const EtaType &eta, const VecType &mole_fractions) const
QuadrupolarContributionGross(const Eigen::ArrayX< double > &m, const Eigen::ArrayX< double > &sigma_Angstrom, const Eigen::ArrayX< double > &epsilon_over_k, const Eigen::ArrayX< double > &Qstar2, const Eigen::ArrayX< double > &nQ)
auto get_alpha2QQ(const TTYPE &T, const RhoType &rhoN_A3, const EtaType &eta, const VecType &mole_fractions) const
Eq. 9 from Gross, AICHEJ, doi: 10.1002/aic.10502.
auto eval(const TTYPE &T, const RhoType &rho_A3, const EtaType &eta, const VecType &mole_fractions) const
QuadrupolarContributionGross & operator=(const QuadrupolarContributionGross &)=delete
auto get_alpha3QQ(const TTYPE &T, const RhoType &rhoN_A3, const EtaType &eta, const VecType &mole_fractions) const
Eq. 10 from Gross, AICHEJ, doi: 10.1002/aic.10502.
auto get_JQQ_2ij(const Eta &eta, const MType &mij, const TType &Tstarij)
Eq. 12 from Gross and Vrabec, AICHEJ.
auto get_JDQ_3ijk(const Eta &eta, const MType &mijk)
Eq. 17 from Vrabec and Gross, JPCB, 2008. doi: 10.1021/jp072619u.
auto get_JDD_2ij(const Eta &eta, const MType &mij, const TType &Tstarij)
Eq. 10 from Gross and Vrabec.
auto get_JQQ_3ijk(const Eta &eta, const MType &mijk)
Eq. 13 from Gross and Vrabec, AICHEJ.
auto get_JDQ_2ij(const Eta &eta, const MType &mij, const TType &Tstarij)
Eq. 16 from Vrabec and Gross, JPCB, 2008. doi: 10.1021/jp072619u.
auto get_JDD_3ijk(const Eta &eta, const MType &mijk)
Eq. 11 from Gross and Vrabec.
auto POW2(const A &x)
auto POW7(const A &x)
auto POW5(const A &x)
auto POW3(const A &x)
auto pow(const double &x, const double &e)
Definition types.hpp:195
auto forceeval(T &&expr)
Definition types.hpp:52
auto POW4(const A &x)