OpenLB 1.8.1
Loading...
Searching...
No Matches
interactionPotential.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2024 Tim Bingert, Luiz Czelusniak,
4 * Maximilian Schecher, Adrian Kummerlaender
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23*/
24
25#ifndef INTERACTION_POTENTIAL_H
26#define INTERACTION_POTENTIAL_H
27
28
35namespace olb {
36
37//Calculate VLEs with PR EoS with non-classical Huron-Vidal mixing rule for n-component mixtures
39public:
40 MultiComponentPengRobinson(double p_, double T_, std::vector<double> z_, std::vector<double> a_L, std::vector<double> b_L,
41 std::vector<double> M_L, std::vector<double> Tc_L, std::vector<double> pc_L, std::vector<double> omega_, std::vector<double> devi,
42 std::vector<double> alpha_, std::vector<double> gI_L, std::vector<double> gII_L);
43 double G_Excess(std::vector<double> x_i, std::vector<double> g_jk, std::vector<double> beta_jk);
44 double b_mix(std::vector<double> x_i);
45 double a_mix(std::vector<double> x_i, std::vector<double> a_i, double b, double G_E);
46 double p_PR(double v, double a_m, double b_m);
47 double gamma_i(std::vector<double> x_i, double a_i, std::vector<double> g_jk, std::vector<double> beta_jk, double _T, int i);
48 double lnfugacity_i(std::vector<double> x_i, double v, double a_m, double b_m, double gamma_i, double _T, int i);
49 std::vector<double> iterate_VLE(double residuum, double beta0);
50 std::vector<double> getChis(int n);
51private:
52 double p, T;
53 std::vector<double> z;
54 const double G{-1.};
55 const double R{1.};
56 const double lambda{0.6232252401};
57 int num_comp;
58 std::vector<double> a_c;
59 std::vector<double> b;
60 std::vector<double> M;
61 std::vector<double> T_c;
62 std::vector<double> p_c;
63 std::vector<double> omega;
64 std::vector<double> m;
65 std::vector<double> alpha;
66 std::vector<double> g_I;
67 std::vector<double> g_II;
68 std::vector<double> init_v = {0.105,120.0};
69 std::vector<double> volatilities = {1.,0.,0.,0.};
70 std::vector<double> chis = {0.5,0.5,0.5,0.5};
71};
72
73namespace interaction {
74
75// established -- only multicomponent flow
78
79 template <typename V, typename PARAMETERS>
80 V compute(V rho, PARAMETERS& params) any_platform {
81 return rho;
82 };
83};
84
85struct ShanChen94 {
87
88 template <typename V, typename PARAMETERS>
89 V compute(V rho, PARAMETERS& params) any_platform {
90 return 4 * util::exp(-200 / rho);
91 };
92};
93
95 struct G : public descriptors::FIELD_BASE<1> {
96 template <typename T, typename DESCRIPTOR,typename FIELD>
97 static constexpr auto isValid(FieldD<T,DESCRIPTOR,FIELD> value) {
98 return value != 0;
99 }
100 };
101 struct A : public descriptors::FIELD_BASE<1> {
102 template <typename T, typename DESCRIPTOR,typename FIELD>
103 static constexpr auto isValid(FieldD<T,DESCRIPTOR,FIELD> value) {
104 return value > 0;
105 }
106 };
107 struct B : public descriptors::FIELD_BASE<1> {
108 template <typename T, typename DESCRIPTOR,typename FIELD>
109 static constexpr auto isValid(FieldD<T,DESCRIPTOR,FIELD> value) {
110 return value > 0;
111 }
112 };
113 struct T : public descriptors::FIELD_BASE<1> {
114 template <typename T, typename DESCRIPTOR,typename FIELD>
115 static constexpr auto isValid(FieldD<T,DESCRIPTOR,FIELD> value) {
116 return value > 0;
117 }
118 };
119
121
122 template <typename V, typename PARAMETERS>
123 V compute(V rho, PARAMETERS& params) any_platform {
124 V c = params.template get<B>() * rho / V{4};
125 V p = rho
126 * (V(0.18727 / 0.4963) * params.template get<A>() / params.template get<B>())
127 * params.template get<T>()
128 * ((V{1} +c+c*c-c*c*c) / (V{1}-c) / (V{1}-c) / (V{1}-c))
129 - params.template get<A>() * rho*rho;
130 return util::sqrt(V{6}*(p-rho/V{3})/ params.template get<G>());
131 };
132};
133
134// Polinomial EOS
136 struct G : public descriptors::FIELD_BASE<1> { };
137 struct KAPPAP : public descriptors::FIELD_BASE<1> { };
138
139 struct RHOV : public descriptors::FIELD_BASE<1> { };
140 struct RHOL : public descriptors::FIELD_BASE<1> { };
141 struct THICKNESS : public descriptors::FIELD_BASE<1> { };
142 struct SURFTENSION : public descriptors::FIELD_BASE<1> { };
143
144 struct RHOC : public descriptors::FIELD_BASE<1> { };
145 struct PC : public descriptors::FIELD_BASE<1> { };
146
148
149 template <typename V, typename COUPLING>
150 static void computeParameters(COUPLING& coupling) {
151 // Set G
152 const V g = V(-1.);
153 coupling.template setParameter<interaction::Polinomial::G>(g);
154 // Compute and set rhoc (critical density)
155 auto rhov = coupling.template getParameter<interaction::Polinomial::RHOV>()[0];
156 auto rhol = coupling.template getParameter<interaction::Polinomial::RHOL>()[0];
157 const V rhoc = 0.5 * ( rhov + rhol );
158 coupling.template setParameter<interaction::Polinomial::RHOC>(rhoc);
159 // Compute p_c
160 const V rho1 = rhov + V(0.33) * ( rhol - rhov );
161 const V rho2 = rhov + V(0.67) * ( rhol - rhov );
162 // Coefficients
163 const V A = 1. / ( rhol - rhov );
164 const V B = 1. / 2. / sqrt(rhol) / ( sqrt(rhol) - sqrt(rhov) );
165 const V C = 1. / 2. / sqrt(rhol) / ( sqrt(rhov) + sqrt(rhol) );
166 // f1
167 const V f1 = A * log( sqrt(rho1) - sqrt(rhov) )
168 - B * log( sqrt(rhol) - sqrt(rho1) )
169 - C * log( sqrt(rho1) + sqrt(rhol) );
170 // f2
171 const V f2 = A * log( sqrt(rho2) - sqrt(rhov) )
172 - B * log( sqrt(rhol) - sqrt(rho2) )
173 - C * log( sqrt(rho2) + sqrt(rhol) );
174 // p_c
175 auto thickness = coupling.template getParameter<interaction::Polinomial::THICKNESS>()[0];
176 const V pc = rhoc * rhoc * rhoc / V(6.) * pow( ( f2 - f1 ) / thickness, 2 );
177 coupling.template setParameter<interaction::Polinomial::PC>(pc);
178 // Compute kappap
179 const V a = V(1./4.);
180 const V b = rhol / V(2.);
181 const V c = sqrt(rhov) / V(3.);
182 const V d = sqrt(rhov) * rhol;
183 // g1
184 const V g1 = a * rhov * rhov - b * rhov - c * pow( rhov, V(1.5) ) + d * sqrt( rhov );
185 // g2
186 const V g2 = a * rhol * rhol - b * rhol - c * pow( rhol, V(1.5) ) + d * sqrt( rhol );
187 // kappaLi
188 auto gamma = coupling.template getParameter<interaction::Polinomial::SURFTENSION>()[0];
189 const V kappaP = V(9.) * sqrt( rhoc * rhoc * rhoc ) *gamma
190 / g / sqrt( V(6.) * pc ) / ( g2 - g1 ) ;
191 coupling.template setParameter<interaction::Polinomial::KAPPAP>(kappaP);
192 }
193
194 template <typename V, typename PARAMETERS>
195 V compute( V Rho, PARAMETERS& params ) any_platform {
196 V p = computeP( Rho, params );
197 auto g = params.template get<G>(); // critical density
198 V psi = util::sqrt( V(2.)*( p - Rho/V(3.) )/g );
199 return psi;
200 };
201
202 template <typename V, typename PARAMETERS>
203 V computeP(V Rho, PARAMETERS& params ) any_platform {
204 auto rho_c = params.template get<RHOC>(); // critical density
205 auto p_c = params.template get<PC>(); // critical pressure
206 auto rho_v = params.template get<RHOV>(); // vapor density
207 auto rho_l = params.template get<RHOL>(); // liquid density
208 const V sqrt_rho_v = sqrt(rho_v);
209 const V sqrt_Rho = sqrt(Rho);
210 V p = p_c / rho_c / rho_c / rho_c * (
211 V(2.) * Rho * Rho * Rho + ( rho_v - V(2.) * rho_l ) * Rho * Rho
212 - V(3.) * sqrt_rho_v * Rho* Rho * sqrt_Rho + V(2.) * sqrt_rho_v * rho_l * Rho * sqrt_Rho
213 + sqrt_rho_v * rho_l * rho_l * sqrt_Rho );
214 return p;
215 };
216};
217
218template <unsigned N_COMPONENTS>
220 template <typename X_I, typename G_JK, typename BETA_JK, typename V=typename X_I::value_t>
221 V G_Excess(const X_I& x_i, const G_JK& g_jk, const BETA_JK& beta_jk) any_platform {
222 V G_E = 0;
223 for(unsigned i = 0; i < N_COMPONENTS; i++){
224 V sum1 = 0;
225 V sum2 = 0;
226 for(unsigned j = 0; j < N_COMPONENTS; j++){
227 sum1 = sum1 + x_i[j]*g_jk[i+N_COMPONENTS*j]*beta_jk[i+N_COMPONENTS*j];
228 sum2 = sum2 + x_i[j]*beta_jk[i+N_COMPONENTS*j];
229 }
230 G_E = G_E + x_i[i] * sum1/sum2;
231 }
232 return G_E;
233 };
234
235 template <typename X_I, typename B, typename V=typename X_I::value_t>
236 V b_mix(const X_I& x_i, const B& b) any_platform {
237 V b_m = 0;
238 for(unsigned i = 0; i < N_COMPONENTS; i++){
239 b_m += b[i]*x_i[i];
240 }
241 return b_m;
242 };
243
244 template <typename X_I, typename A_I, typename B, typename V=typename X_I::value_t>
245 V a_mix(const X_I& x_i, const A_I& a_i, const B& b, V b_m, V G_E) any_platform {
246 V a_sum = 0;
247 for(unsigned i = 0; i < N_COMPONENTS; i++){
248 a_sum = a_sum + x_i[i]*a_i[i]/b[i];
249 }
250 /*double a_m = 0;
251 for(unsigned i = 0; i < N_COMPONENTS; i++){
252 for(unsigned j = 0; j < N_COMPONENTS; j++){
253 a_m += x_i[i]*x_i[j]*util::pow(a_i[i]*a_i[j],0.5);
254 }
255 }
256 return a_m;*/
257 return b_m * (a_sum - G_E / 0.6232252401);
258 };
259
260 template <typename RHO_FIELD, typename __T, typename K, typename A_C, typename B, typename T_C, typename M, typename ALPHA, typename G_I, typename G_II, typename BIG_M, typename V=typename RHO_FIELD::value_t>
261 V compute(const RHO_FIELD& rhoField, const __T& _T, const K& k, const A_C& a_c, const B& b, const T_C& T_c, const M& m, const ALPHA& alpha, const G_I& g_I, const G_II& g_II, const BIG_M& _M) any_platform {
262 Vector<V,N_COMPONENTS> molarRhoField{}, a_i{}, x_i{};
263 Vector<V,N_COMPONENTS*N_COMPONENTS> g_jk{}, beta_jk{};
264 V R = 1;
265 V molarRho = 0;
266 V Rho = 0;
267 for(unsigned i = 0; i < N_COMPONENTS; i++){
268 a_i[i] = a_c[i] * util::pow((1 + m[i] * (1 - util::pow((_T/T_c[i]),0.5))),2);
269 for(unsigned j = 0; j < N_COMPONENTS; j++){
270 g_jk[N_COMPONENTS*i+j] = g_I[N_COMPONENTS*i+j] + g_II[N_COMPONENTS*i+j] * _T;
271 beta_jk[N_COMPONENTS*i+j] = b[j] * util::exp(-alpha[N_COMPONENTS*i+j]*g_jk[N_COMPONENTS*i+j]/(R*_T));
272 }
273 molarRhoField[i] = rhoField[i]/_M[i];
274 molarRho += molarRhoField[i];
275 Rho += rhoField[i];
276 }
277 for(unsigned i = 0; i < N_COMPONENTS; i++){
278 x_i[i] = molarRhoField[i]/molarRho;
279 }
280 V g_E = G_Excess(x_i, g_jk, beta_jk);
281 V b_m = b_mix(x_i, b);
282 V a_m = a_mix(x_i, a_i, b, b_m, g_E);
283 V p = molarRho*R*_T/(1-b_m*molarRho) - a_m*molarRho*molarRho/(1+2*b_m*molarRho-b_m*molarRho*b_m*molarRho);
284 V psi = util::sqrt(-6.*(k*p - Rho/3.));
285 return psi;
286 };
287
288 template <typename RHO_FIELD, typename A_C, typename B, typename T_C, typename M, typename ALPHA, typename G_I, typename G_II, typename BIG_M, typename V=typename RHO_FIELD::value_t>
289 V computeP(const RHO_FIELD& rhoField, V _T, const A_C& a_c, const B& b, const T_C& T_c, const M& m, const ALPHA& alpha, const G_I& g_I, const G_II& g_II, const BIG_M& _M) any_platform {
290 olb::Vector<V,N_COMPONENTS> molarRhoField{}, a_i{}, x_i{};
292 V R = 1;
293 V molarRho = 0;
294 for(unsigned i = 0; i < N_COMPONENTS; i++){
295 a_i[i] = a_c[i] * util::pow((1 + m[i] * (1 - util::pow((_T/T_c[i]),0.5))),2);
296 for(unsigned j = 0; j < N_COMPONENTS; j++){
297 g_jk[N_COMPONENTS*i+j] = g_I[N_COMPONENTS*i+j] + g_II[N_COMPONENTS*i+j] * _T;
298 beta_jk[N_COMPONENTS*i+j] = b[j] * util::exp(-alpha[N_COMPONENTS*i+j]*g_jk[N_COMPONENTS*i+j]/(R*_T));
299 }
300 molarRhoField[i] = rhoField[i]/_M[i];
301 molarRho += molarRhoField[i];
302 }
303 for(unsigned i = 0; i < N_COMPONENTS; i++){
304 x_i[i] = molarRhoField[i]/molarRho;
305 }
306 V g_E = G_Excess(x_i, g_jk, beta_jk);
307 V b_m = b_mix(x_i, b);
308 V a_m = a_mix(x_i, a_i, b, b_m, g_E);
309 V p = molarRho*R*_T/(1-b_m*molarRho) - a_m*molarRho*molarRho/(1+2*b_m*molarRho-b_m*molarRho*b_m*molarRho);
310 return p;
311 }
312
313};
314
315}
316
317#ifndef USING_LEGACY_CODEGEN
318
319// established -- original for both single- and multicomponent flow
320
321template <typename T, typename S>
322class ShanChen93 : public AnalyticalF<1,T,S> {
323private:
324 T _rhoZero;
325public:
326 ShanChen93(T rhoZero=1.);
327 bool operator() (T psi[], const S rho[]);
328};
329
330// established -- only multicomponent flow
331
332template <typename T, typename S>
333class PsiEqualsRho : public AnalyticalF<1,T,S> {
334private:
335public:
336 PsiEqualsRho();
337 bool operator() (T psi[], const S rho[]) override;
338};
339
340// established -- only singlecomponent flow
341
342template <typename T, typename S>
343class ShanChen94 : public AnalyticalF<1,T,S> {
344private:
345 T _rhoZero;
346 T _psiZero;
347public:
348 ShanChen94(T rhoZero=200., T psiZero=4.);
349 bool operator() (T psi[], const S rho[]) override;
350};
351
352template <typename T, typename S>
353class PengRobinson : public AnalyticalF<1,T,S> {
354private:
355 T _G;
356 T _acentricFactor;
357 T _a;
358 T _b;
359 T _R;
360 T _alpha;
361 T _t;
362 T _tc;
363public:
364 PengRobinson(T G, T acentricFactor=0.334, T a=2./49., T b=2./21., T tr=.8);
365 bool operator() (T psi[], const S rho[]);
366 // second operator allows to incorporate temperature changes
367 bool operator() (T psi[], const S rho[], const S t[]);
368};
369
370template <typename T, typename S>
371class CarnahanStarling : public AnalyticalF<1,T,S> {
372private:
373 T _G;
374 T _a;
375 T _b;
376 T _R;
377 T _t;
378public:
379 CarnahanStarling(T G, T a=1., T b=4., T tr=.7);
380 bool operator() (T psi[], const S rho[]) override;
381 // second operator allows to incorporate temperature changes
382 bool operator() (T psi[], const S rho[], const S t[]);
383};
384
385// under development -- for singlecomponent flow
386
387// 0.5 -> psiZero=0.65
388// 1 -> psiZero=1.9
389// 1.5 -> psiZero=3.5
390// 2. -> psiZero=5,45
391template <typename T, typename S>
392class Krause : public AnalyticalF<1,T,S> {
393private:
394 T _rhoZero;
395 T _psiZero;
396public:
397 Krause(T rhoZero=1., T psiZero=1.9);
398 bool operator() (T psi[], const S rho[]);
399};
400
401template <typename T, typename S> // density of liquid phase always equals rhoZero for G=-1
402class WeisbrodKrause : public AnalyticalF<1,T,S> {
403private:
404 T _rhoZero;
405 T _sigmu;
406public:
407 WeisbrodKrause(T rhoZero=1., T sigmu=1.);
408 bool operator() (T psi[], const S rho[]);
409};
410
411template <typename T, typename S> // not very good
412class Normal : public AnalyticalF<1,T,S> {
413private:
414 T _sigma;
415 T _mu;
416public:
417 Normal(T sigma=1., T mu=1.);
418 bool operator() (T psi[], const S rho[]);
419};
420
421#endif // not USING_LEGACY_CODEGEN
422
423} // end namespace olb
424
425#endif
426
AnalyticalF are applications from DD to XD, where X is set by the constructor.
bool operator()(T psi[], const S rho[]) override
has to be implemented for 'every' derived class
CarnahanStarling(T G, T a=1., T b=4., T tr=.7)
bool operator()(T psi[], const S rho[])
has to be implemented for 'every' derived class
Krause(T rhoZero=1., T psiZero=1.9)
std::vector< double > iterate_VLE(double residuum, double beta0)
double a_mix(std::vector< double > x_i, std::vector< double > a_i, double b, double G_E)
double b_mix(std::vector< double > x_i)
double p_PR(double v, double a_m, double b_m)
double G_Excess(std::vector< double > x_i, std::vector< double > g_jk, std::vector< double > beta_jk)
MultiComponentPengRobinson(double p_, double T_, std::vector< double > z_, std::vector< double > a_L, std::vector< double > b_L, std::vector< double > M_L, std::vector< double > Tc_L, std::vector< double > pc_L, std::vector< double > omega_, std::vector< double > devi, std::vector< double > alpha_, std::vector< double > gI_L, std::vector< double > gII_L)
std::vector< double > getChis(int n)
double lnfugacity_i(std::vector< double > x_i, double v, double a_m, double b_m, double gamma_i, double _T, int i)
double gamma_i(std::vector< double > x_i, double a_i, std::vector< double > g_jk, std::vector< double > beta_jk, double _T, int i)
bool operator()(T psi[], const S rho[])
has to be implemented for 'every' derived class
Normal(T sigma=1., T mu=1.)
bool operator()(T psi[], const S rho[])
has to be implemented for 'every' derived class
PengRobinson(T G, T acentricFactor=0.334, T a=2./49., T b=2./21., T tr=.8)
bool operator()(T psi[], const S rho[]) override
has to be implemented for 'every' derived class
bool operator()(T psi[], const S rho[])
has to be implemented for 'every' derived class
ShanChen94(T rhoZero=200., T psiZero=4.)
bool operator()(T psi[], const S rho[]) override
has to be implemented for 'every' derived class
Plain old scalar vector.
bool operator()(T psi[], const S rho[])
has to be implemented for 'every' derived class
WeisbrodKrause(T rhoZero=1., T sigmu=1.)
Expr sqrt(Expr x)
Definition expr.cpp:225
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
Expr exp(Expr x)
Definition expr.cpp:240
Top level namespace for all of OpenLB.
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:77
Base of a field whose size is defined by [C_0,C_1,C_2]^T * [1,D,Q].
Definition fields.h:52
static constexpr auto isValid(FieldD< T, DESCRIPTOR, FIELD > value)
static constexpr auto isValid(FieldD< T, DESCRIPTOR, FIELD > value)
static constexpr auto isValid(FieldD< T, DESCRIPTOR, FIELD > value)
static constexpr auto isValid(FieldD< T, DESCRIPTOR, FIELD > value)
V compute(V rho, PARAMETERS &params) any_platform
V b_mix(const X_I &x_i, const B &b) any_platform
V compute(const RHO_FIELD &rhoField, const __T &_T, const K &k, const A_C &a_c, const B &b, const T_C &T_c, const M &m, const ALPHA &alpha, const G_I &g_I, const G_II &g_II, const BIG_M &_M) any_platform
V a_mix(const X_I &x_i, const A_I &a_i, const B &b, V b_m, V G_E) any_platform
V computeP(const RHO_FIELD &rhoField, V _T, const A_C &a_c, const B &b, const T_C &T_c, const M &m, const ALPHA &alpha, const G_I &g_I, const G_II &g_II, const BIG_M &_M) any_platform
V G_Excess(const X_I &x_i, const G_JK &g_jk, const BETA_JK &beta_jk) any_platform
V computeP(V Rho, PARAMETERS &params) any_platform
V compute(V Rho, PARAMETERS &params) any_platform
static void computeParameters(COUPLING &coupling)
V compute(V rho, PARAMETERS &params) any_platform
V compute(V rho, PARAMETERS &params) any_platform
Plain wrapper for list of types.
Definition meta.h:276