OpenLB 1.7
Loading...
Searching...
No Matches
shanChenForcedPostProcessor.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 SHAN_CHEN_FORCED_POST_PROCESSOR_H
26#define SHAN_CHEN_FORCED_POST_PROCESSOR_H
27
28#define THIRD_COMPONENT
29//#define FOURTH_COMPONENT
30
31#include "core/blockStructure.h"
32#include "core/postProcessing.h"
33
34namespace olb {
35
42
43 int getPriority() const {
44 return 0;
45 }
46
47 template <typename CELL>
48 void apply(CELL& cell) any_platform
49 {
50 auto statistic = cell.template getField<descriptors::STATISTIC>();
51 statistic[0] = cell.computeRho();
52 cell.template setField<descriptors::STATISTIC>(statistic);
53 }
54};
55
56// =========================================================================//
57// ===========Shan Chen coupling without wall interaction===================//
58// =========================================================================//
59
60template <typename POTENTIAL>
63
64 struct RHO0 : public descriptors::FIELD_BASE<2> { };
65 struct G : public descriptors::FIELD_BASE<1> { };
66 struct OMEGA_A : public descriptors::FIELD_BASE<1> { };
67 struct OMEGA_B : public descriptors::FIELD_BASE<1> { };
68
69 using parameters = typename POTENTIAL::parameters::template decompose_into<
71 >;
72
73 template <typename CELLS, typename PARAMETERS>
74 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
75 {
76 using V = typename CELLS::template value_t<names::A>::value_t;
77 using DESCRIPTOR = typename CELLS::template value_t<names::A>::descriptor_t;
78
79 auto& cellA = cells.template get<names::A>();
80 auto& cellB = cells.template get<names::B>();
81
82 auto rho0 = parameters.template get<RHO0>();
83
84 Vector<V,2> rhoField{
85 cellA.template getFieldComponent<descriptors::STATISTIC>(0) * rho0[0],
86 cellB.template getFieldComponent<descriptors::STATISTIC>(0) * rho0[1]
87 };
92
93 V omegaA = parameters.template get<OMEGA_A>();
94 V omegaB = parameters.template get<OMEGA_B>();
95 // Computation of the common velocity, shared among the two populations
96 V rhoTot = rhoField[0]*omegaA
97 + rhoField[1]*omegaB;
98
99 Vector<V,DESCRIPTOR::d> uTot = (uA*rho0[0]*omegaA + uB*rho0[1]*omegaB) / rhoTot;
100
101 // Computation of the interaction potential
102 Vector<V,DESCRIPTOR::d> rhoBlockContribution{};
103 Vector<V,DESCRIPTOR::d> rhoPartnerContribution{};
104 V psi1 = POTENTIAL().compute(rhoField[0], parameters);
105 V psi2 = POTENTIAL().compute(rhoField[1], parameters);
106
107 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
108 auto nextCellA = cellA.neighbor(descriptors::c<DESCRIPTOR>(iPop));
109 auto nextCellB = cellB.neighbor(descriptors::c<DESCRIPTOR>(iPop));
110 V rhoA = POTENTIAL().compute(nextCellA.template getFieldComponent<descriptors::STATISTIC>(0)*rho0[0], parameters);
111 V rhoB = POTENTIAL().compute(nextCellB.template getFieldComponent<descriptors::STATISTIC>(0)*rho0[1], parameters);
112 rhoBlockContribution += psi2 * rhoA * descriptors::c<DESCRIPTOR>(iPop) * descriptors::t<V,DESCRIPTOR>(iPop);
113 rhoPartnerContribution += psi1 * rhoB * descriptors::c<DESCRIPTOR>(iPop) * descriptors::t<V,DESCRIPTOR>(iPop);
114 }
115
116 // Computation and storage of the final velocity, consisting
117 // of u and the momentum difference due to interaction
118 // potential plus external force
119 auto externalBlockForce = cellA.template getField<descriptors::EXTERNAL_FORCE>();
120 auto externalPartnerForce = cellB.template getField<descriptors::EXTERNAL_FORCE>();
121
122 auto g = parameters.template get<G>();
123
124 cellA.template setField<descriptors::VELOCITY>(uTot);
125 cellB.template setField<descriptors::VELOCITY>(uTot);
126 cellA.template setField<descriptors::FORCE>(externalBlockForce
127 - g*rhoPartnerContribution/rhoField[0]);
128 cellB.template setField<descriptors::FORCE>(externalPartnerForce
129 - g*rhoBlockContribution/rhoField[1]);
130 }
131
132};
133
134
135// =========================================================================//
136// ==================Multi-component-multi-phase coupling===================//
137// =========================================================================//
138
151template <typename POTENTIAL, unsigned N_COMPONENTS>
154
155 struct CHI : public descriptors::FIELD_BASE<N_COMPONENTS> { };
156 struct TEMPERATURE : public descriptors::FIELD_BASE<1> { };
157 struct G : public descriptors::FIELD_BASE<1> { };
158 struct SIGMA : public descriptors::FIELD_BASE<1> { };
159 struct EPSILON : public descriptors::FIELD_BASE<1> { };
160 struct K : public descriptors::FIELD_BASE<1> { };
161 struct A : public descriptors::FIELD_BASE<N_COMPONENTS> { };
162 struct B : public descriptors::FIELD_BASE<N_COMPONENTS> { };
163 struct MM : public descriptors::FIELD_BASE<N_COMPONENTS> { };
164 struct TCRIT : public descriptors::FIELD_BASE<N_COMPONENTS> { };
165 struct DEVI : public descriptors::FIELD_BASE<N_COMPONENTS> { };
166 struct ALPHA : public descriptors::FIELD_BASE<N_COMPONENTS*N_COMPONENTS> { };
167 struct GI : public descriptors::FIELD_BASE<N_COMPONENTS*N_COMPONENTS> { };
168 struct GII : public descriptors::FIELD_BASE<N_COMPONENTS*N_COMPONENTS> { };
169
171
172 int getPriority() const {
173 return 0;
174 }
175
176 template <typename CELLS, typename PARAMETERS>
177 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
178 {
179 using V = typename CELLS::template value_t<names::Component1>::value_t;
180 using DESCRIPTOR = typename CELLS::template value_t<names::Component1>::descriptor_t;
181
182 auto chi = parameters.template get<CHI>();
183 auto t = parameters.template get<TEMPERATURE>();
184 auto g = parameters.template get<G>();
185 auto sig = parameters.template get<SIGMA>();
186 auto eps = parameters.template get<EPSILON>();
187 auto k = parameters.template get<K>();
188 auto a = parameters.template get<A>();
189 auto b = parameters.template get<B>();
190 auto M = parameters.template get<MM>();
191 auto T_c = parameters.template get<TCRIT>();
192 auto m = parameters.template get<DEVI>();
193 auto alpha = parameters.template get<ALPHA>();
194 auto g_I = parameters.template get<GI>();
195 auto g_II = parameters.template get<GII>();
196
197 Vector<V,10> rhoField{};
198 V rhoTot = 0;
200 auto& cell1 = cells.template get<names::Component1>();
201 rhoField[0] = cell1.template getFieldComponent<descriptors::STATISTIC>(0);
203 lbm<DESCRIPTOR>::computeJ(cell1, u1);
204 u_sum += u1;
205
206 auto& cell2 = cells.template get<names::Component2>();
207 rhoField[1] = cell2.template getFieldComponent<descriptors::STATISTIC>(0);
209 lbm<DESCRIPTOR>::computeJ(cell2, u2);
210 u_sum += u2;
211
212#ifdef THIRD_COMPONENT
213 auto& cell3 = cells.template get<names::Component3>();
214 rhoField[2] = cell3.template getFieldComponent<descriptors::STATISTIC>(0);
216 lbm<DESCRIPTOR>::computeJ(cell3, u3);
217 u_sum += u3;
218#endif
219#ifdef FOURTH_COMPONENT
220 auto& cell4 = cells.template get<names::Component4>();
221 rhoField[3] = cell4.template getFieldComponent<descriptors::STATISTIC>(0);
223 lbm<DESCRIPTOR>::computeJ(cell4, u4);
224 u_sum += u4;
225#endif
226 for (unsigned n = 0; n < N_COMPONENTS; ++n) {
227 rhoTot += rhoField[n];
228 }
229
230 // Computation of the interaction potential
231 Vector<V,DESCRIPTOR::d> totalForce{};
233 //V psi = POTENTIAL().compute(rhoField, t, k, a, b, T_c, m, alpha, g_I, g_II, M);
234 V p = POTENTIAL().computeP(rhoField, t, a, b, T_c, m, alpha, g_I, g_II, M);
235 V psi = util::sqrt(util::abs(6.*(k*p - rhoTot/3.)));
236 //V psi = util::sqrt(6.*p);
237
238 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
239 Vector<V,10> rhoField_i{};
240 auto nextCell1 = cell1.neighbor(descriptors::c<DESCRIPTOR>(iPop));
241 rhoField_i[0] = nextCell1.template getFieldComponent<descriptors::STATISTIC>(0);
242 auto nextCell2 = cell2.neighbor(descriptors::c<DESCRIPTOR>(iPop));
243 rhoField_i[1] = nextCell2.template getFieldComponent<descriptors::STATISTIC>(0);
244#ifdef THIRD_COMPONENT
245 auto nextCell3 = cell3.neighbor(descriptors::c<DESCRIPTOR>(iPop));
246 rhoField_i[2] = nextCell3.template getFieldComponent<descriptors::STATISTIC>(0);
247#endif
248#ifdef FOURTH_COMPONENT
249 auto nextCell4 = cell4.neighbor(descriptors::c<DESCRIPTOR>(iPop));
250 rhoField_i[3] = nextCell4.template getFieldComponent<descriptors::STATISTIC>(0);
251#endif
252 V rhoTot_i = 0;
253 for (unsigned n = 0; n < N_COMPONENTS; ++n) {
254 rhoTot_i += rhoField_i[n];
255 }
256 V p_i = POTENTIAL().computeP(rhoField_i, t, a, b, T_c, m, alpha, g_I, g_II, M);
257 //V psi_i = POTENTIAL().compute(rhoField_i, t, k, a, b, T_c, m, alpha, g_I, g_II, M);
258 V phi_i = 6.*(k*p_i - rhoTot_i/3.)/g;
259 //V phi_i = 6.*p_i;
260 V psi_i = 0;
261 if (phi_i >= 0){
262 psi_i = util::sqrt(util::abs(phi_i));
263 }
264 else {
265 psi_i = -1*util::sqrt(util::abs(phi_i));
266 }
267 totalForce += -g * psi * psi_i * descriptors::c<DESCRIPTOR>(iPop) * descriptors::t<V,DESCRIPTOR>(iPop);
268 for (int jPop = 0; jPop < DESCRIPTOR::q; ++jPop) {
269 Vector<V,10> rhoField_j{};
270 auto nextCell1 = cell1.neighbor(descriptors::c<DESCRIPTOR>(jPop));
271 rhoField_j[0] = nextCell1.template getFieldComponent<descriptors::STATISTIC>(0);
272 auto nextCell2 = cell2.neighbor(descriptors::c<DESCRIPTOR>(jPop));
273 rhoField_j[1] = nextCell2.template getFieldComponent<descriptors::STATISTIC>(0);
274#ifdef THIRD_COMPONENT
275 auto nextCell3 = cell3.neighbor(descriptors::c<DESCRIPTOR>(jPop));
276 rhoField_j[2] = nextCell3.template getFieldComponent<descriptors::STATISTIC>(0);
277#endif
278#ifdef FOURTH_COMPONENT
279 auto nextCell4 = cell4.neighbor(descriptors::c<DESCRIPTOR>(jPop));
280 rhoField_j[3] = nextCell4.template getFieldComponent<descriptors::STATISTIC>(0);
281#endif
282 V rhoTot_j = 0;
283 for (unsigned n = 0; n < N_COMPONENTS; ++n) {
284 rhoTot_j += rhoField_j[n];
285 }
286 V p_j = POTENTIAL().computeP(rhoField_j, t, a, b, T_c, m, alpha, g_I, g_II, M);
287 //V psi_j = POTENTIAL().compute(rhoField_j, t, k, a, b, T_c, m, alpha, g_I, g_II, M);
288 V phi_j = 6.*(k*p_j - (rhoTot_j)/3.)/g;
289 //V phi_j = 6.*p_j;
290 V psi_j = 0;
291 if (phi_j >= 0){
292 psi_j = util::sqrt(util::abs(phi_j));
293 }
294 else {
295 psi_j = -1*util::sqrt(util::abs(phi_j));
296 }
299 for (int m = 0; m < DESCRIPTOR::d; ++m) {
301 V C2 = 0.;
302 for (int n = 0; n < DESCRIPTOR::d; ++n) {
303 C1[n] += descriptors::c<DESCRIPTOR>(jPop)[m] * descriptors::c<DESCRIPTOR>(jPop)[n];
304 C2 += descriptors::c<DESCRIPTOR>(jPop)[n] * descriptors::c<DESCRIPTOR>(jPop)[n] - 1./descriptors::invCs2<V,DESCRIPTOR>();
305 if (n==m){
306 C1[n] -= 1./descriptors::invCs2<V,DESCRIPTOR>();
307 }
308 }
309 for (int n = 0; n < DESCRIPTOR::d; ++n) {
310 c1[m] += descriptors::c<DESCRIPTOR>(iPop)[n] * C1[n];
311 }
312 c2[m] += descriptors::c<DESCRIPTOR>(iPop)[m] * C2;
313 }
314 A_ij = 0.5*g*descriptors::t<V,DESCRIPTOR>(iPop)*descriptors::t<V,DESCRIPTOR>(jPop)*descriptors::invCs2<V,DESCRIPTOR>()*
315 ((3./2.*eps-(sig-1))*c1 + (sig-1)*c2);
316 totalForce += A_ij * psi_i * psi_j;
317 }
318
319 }
320 // Computation of the common velocity, shared among the two populations, consisting
321 // of u and the momentum difference due to interaction potential plus external force
322 auto externalForce1 = cell1.template getField<descriptors::EXTERNAL_FORCE>();
323 Vector<V,DESCRIPTOR::d> uTot = (u_sum + totalForce/2.) / rhoTot + externalForce1/2.;
324 cell1.template setField<descriptors::FORCE>(externalForce1 + chi[0]*totalForce/rhoField[0]);
325 cell1.template setField<descriptors::VELOCITY>(uTot);
326
327 auto externalForce2 = cell2.template getField<descriptors::EXTERNAL_FORCE>();
328 cell2.template setField<descriptors::FORCE>(externalForce2 + chi[1]*totalForce/rhoField[1]);
329 cell2.template setField<descriptors::VELOCITY>(uTot);
330
331#ifdef THIRD_COMPONENT
332 auto externalForce3 = cell3.template getField<descriptors::EXTERNAL_FORCE>();
333 cell3.template setField<descriptors::FORCE>(externalForce3 + chi[2]*totalForce/rhoField[2]);
334 cell3.template setField<descriptors::VELOCITY>(uTot);
335#endif
336#ifdef FOURTH_COMPONENT
337 auto externalForce4 = cell4.template getField<descriptors::EXTERNAL_FORCE>();
338 cell4.template setField<descriptors::FORCE>(externalForce4 + chi[3]*totalForce/rhoField[3]);
339 cell4.template setField<descriptors::VELOCITY>(uTot);
340#endif
341
342 cell1.template setField<descriptors::SCALAR>(p);
343 cell2.template setField<descriptors::SCALAR>(psi);
344 }
345
346};
347
348}
349
350#endif
Plain old scalar vector.
Definition vector.h:47
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
ADf< T, DIM > abs(const ADf< T, DIM > &a)
Definition aDiff.h:1019
Top level namespace for all of OpenLB.
OperatorScope
Block-wide operator application scopes.
Definition operator.h:54
@ PerCell
Per-cell application, i.e. OPERATOR::apply is passed a CELL concept implementation.
@ PerCellWithParameters
Per-cell application with parameters, i.e. OPERATOR::apply is passed a CELL concept implementation an...
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
Interface for post-processing steps – header file.
Multi-Component-Multi-Phase Shan-Chen force with thermodynamic equation of state based on.
static constexpr OperatorScope scope
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Multiphysics class for coupling between different lattices.
static constexpr OperatorScope scope
void apply(CELL &cell) any_platform
typename POTENTIAL::parameters::template decompose_into< meta::list< RHO0, G, OMEGA_A, OMEGA_B >::template include > parameters
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Base of a field whose size is defined by [C,U_1,...,U_N]^T * [1,V_1,...V_N].
static void computeJ(CELL &cell, J &j) any_platform
Computation of momentum.
Definition lbm.h:197
Plain wrapper for list of types.
Definition meta.h:276