OpenLB 1.8.1
Loading...
Searching...
No Matches
lbm.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2006, 2007 Jonas Latt
4 * 2021 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 DYNAMICS_LBM_H
26#define DYNAMICS_LBM_H
27
28#include "core/concepts.h"
29#include "core/util.h"
30
31namespace olb {
32
33template <typename DESCRIPTOR>
36 template <typename RHO, typename U, typename V=RHO>
37 static V firstOrder(int iPop, const RHO& rho, const U& u) any_platform
38 {
39 V c_u{};
40 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
41 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
42 }
43 return rho
45 * ( V{1} + c_u * descriptors::invCs2<V,DESCRIPTOR>() )
47 }
48
50 template <typename RHO, typename U, typename USQR, typename V=RHO>
51 static V secondOrder(int iPop, const RHO& rho, const U& u, const USQR& uSqr) any_platform
52 {
53 V c_u{};
54 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
55 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
56 }
57 return rho
59 * ( V{1}
62 - descriptors::invCs2<V,DESCRIPTOR>() * V{0.5} * uSqr)
64 }
66 template <typename RHO, typename U, typename V=RHO>
67 static V secondOrder(int iPop, const RHO& rho, const U& u) any_platform
68 {
69 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
70 return secondOrder(iPop, rho, u, uSqr);
71 }
72
74 template <typename RHO, typename U, typename USQR, typename V=RHO>
75 static V thirdOrder(int iPop, const RHO& rho, const U& u, const USQR& uSqr) any_platform
76 {
77 V c_u{};
78 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
79 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
80 }
82
83 V aEqThrdXXY = u[0] * u[0] * u[1];
84 V aEqThrdXYY = u[0] * u[1] * u[1];
85
86 //Hermite polynomes https://doi.org/10.1017/S0022112005008153
88 V hermite2XY = descriptors::c<DESCRIPTOR>(iPop,0)*descriptors::c<DESCRIPTOR>(iPop,1);
90
91 V hermite3XXY = hermite2XX * descriptors::c<DESCRIPTOR>(iPop,1);
93
94 V thirdOrderTerms = V{1. / 2.} * reciSpeedOfSoundHc * (hermite3XXY + hermite3XYY) * (aEqThrdXXY + aEqThrdXYY)
95 + V{1. / 6.} * reciSpeedOfSoundHc * (hermite3XXY - hermite3XYY) * (aEqThrdXXY - aEqThrdXYY);
96 if constexpr (DESCRIPTOR::d == 3) {
97 V aEqThrdXXZ = u[0] * u[0] * u[2];
98 V aEqThrdXZZ = u[0] * u[2] * u[2];
99 V aEqThrdYYZ = u[1] * u[1] * u[2];
100 V aEqThrdYZZ = u[1] * u[2] * u[2];
101
102 V hermite2YZ = descriptors::c<DESCRIPTOR>(iPop,1)*descriptors::c<DESCRIPTOR>(iPop,2);
103 V hermite2XZ = descriptors::c<DESCRIPTOR>(iPop,0)*descriptors::c<DESCRIPTOR>(iPop,2);
104
105 V hermite3XXZ = hermite2XX * descriptors::c<DESCRIPTOR>(iPop,2);
106 V hermite3XZZ = hermite2XZ * descriptors::c<DESCRIPTOR>(iPop,2) - descriptors::c<DESCRIPTOR>(iPop,0)/descriptors::invCs2<V,DESCRIPTOR>();
107 V hermite3YYZ = hermite2YY * descriptors::c<DESCRIPTOR>(iPop,2);
108 V hermite3YZZ = hermite2YZ * descriptors::c<DESCRIPTOR>(iPop,2) - descriptors::c<DESCRIPTOR>(iPop,1)/descriptors::invCs2<V,DESCRIPTOR>();
109
110 thirdOrderTerms += V{1. / 2.} * reciSpeedOfSoundHc * (hermite3XZZ + hermite3YZZ) * (aEqThrdXZZ + aEqThrdYZZ)
111 + V{1. / 2.} * reciSpeedOfSoundHc * (hermite3YYZ + hermite3XXZ) * (aEqThrdYYZ + aEqThrdXXZ)
112 + V{1. / 6.} * reciSpeedOfSoundHc * (hermite3XZZ - hermite3YZZ) * (aEqThrdXZZ - aEqThrdYZZ)
113 + V{1. / 6.} * reciSpeedOfSoundHc * (hermite3YYZ - hermite3XXZ) * (aEqThrdYYZ - aEqThrdXXZ);
114 }
115 return rho
117 * ( V{1}
120 - descriptors::invCs2<V,DESCRIPTOR>() * V{0.5} * uSqr
121 + thirdOrderTerms)
123 }
125 template <typename RHO, typename U, typename V=RHO>
126 static V thirdOrder(int iPop, const RHO& rho, const U& u) any_platform
127 {
128 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
129 return thirdOrder(iPop, rho, u, uSqr);
130 }
131
132 // compute equilibrium f^eq_i eq. (5.32) from DOI:10.1002/9780470177013
133 template <typename RHO, typename U, typename V=RHO>
134 static V P1(int iPop, const RHO& rho, const U& u) any_platform
135 {
136 V c_u{};
137 // compute scalar product of c[iPop]*u
138 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
139 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
140 }
141 return descriptors::t<V,DESCRIPTOR>(iPop) * (rho + c_u)
143 }
144
145 template <typename J, typename JSQR, typename PRESSURE, typename V=PRESSURE>
146 static V incompressible(int iPop, const J& j, const JSQR& jSqr, const PRESSURE& pressure) any_platform
147 {
148 V c_j{};
149 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
150 c_j += descriptors::c<DESCRIPTOR>(iPop,iD)*j[iD];
151 }
153 * ( descriptors::invCs2<V,DESCRIPTOR>() * pressure
156 - descriptors::invCs2<V,DESCRIPTOR>()/V{2} * jSqr )
158 }
159 template <typename J, typename PRESSURE, typename V=PRESSURE>
160 static V incompressible(int iPop, const J& j, const PRESSURE& pressure) any_platform
161 {
162 const V jSqr = util::normSqr<J,DESCRIPTOR::d>(j);
163 return incompressible(iPop, j, jSqr, pressure);
164 }
165
166 template <typename RHO, typename U, typename USQR, typename PRESSURE, typename V=PRESSURE>
167 static V mpincompressible(int iPop, const RHO& rho, const U& u, const USQR& uSqr, const PRESSURE& pressure) any_platform
168 {
169 V c_u{};
170 if (iPop == 0) {
171 return descriptors::invCs2<V,DESCRIPTOR>() * pressure * (descriptors::t<V,DESCRIPTOR>(iPop)-V{1})
173 }
174 else {
175 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
176 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
177 }
179 * ( pressure + rho*(c_u + descriptors::invCs2<V,DESCRIPTOR>()*V{0.5}*c_u*c_u - uSqr*V{0.5}) );
180 }
181 }
182 template <typename RHO, typename U, typename PRESSURE, typename V=PRESSURE>
183 static V mpincompressible(int iPop, const RHO& rho, const U& u, const PRESSURE& pressure) any_platform
184 {
185 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
186 return mpincompressible(iPop, rho, u, uSqr, pressure);
187 }
188
191 template <typename V>
192 static V fromJgradToFneq(int iPop,
193 const V Jgrad[DESCRIPTOR::d * DESCRIPTOR::d],
194 V omega) any_platform
195 {
196 using L = DESCRIPTOR;
197 V fNeq{};
198 int iJgrad = 0;
199 for (int iAlpha=0; iAlpha < L::d; ++iAlpha) {
200 for (int iBeta=0; iBeta < L::d; ++iBeta) {
201 V toAdd = descriptors::c<L>(iPop,iAlpha) * descriptors::c<L>(iPop,iBeta);
202 if (iAlpha == iBeta) {
203 toAdd -= 1./descriptors::invCs2<V,L>();
204 }
205 else {
206 toAdd *= V{2};
207 }
208 toAdd *= Jgrad[iJgrad++];
209 fNeq += toAdd;
210 }
211 }
212 fNeq *= - descriptors::t<V,L>(iPop) * descriptors::invCs2<V,L>() / omega;
213 return fNeq;
214 }
215
217
224 template <typename V, typename PI>
225 static V fromPiToFneq(int iPop, const PI& pi) any_platform
226 {
227 using L = DESCRIPTOR;
228 V fNeq{};
229 int iPi = 0;
230 // Iterate only over superior triangle + diagonal, and add
231 // the elements under the diagonal by symmetry
232 for (int iAlpha=0; iAlpha < L::d; ++iAlpha) {
233 for (int iBeta=iAlpha; iBeta < L::d; ++iBeta) {
234 V toAdd = descriptors::c<L>(iPop,iAlpha)*descriptors::c<L>(iPop,iBeta);
235 if (iAlpha == iBeta) {
236 toAdd -= V{1}/descriptors::invCs2<V,L>();
237 }
238 else {
239 toAdd *= V{2}; // multiply off-diagonal elements by 2
240 } // because the Q tensor is symmetric
241 toAdd *= pi[iPi++];
242 fNeq += toAdd;
243 }
244 }
246 return fNeq;
247 }
248
249 template <typename V>
250 static V fromJneqToFneq(int iPop, const V jNeq[DESCRIPTOR::d]) any_platform
251 {
252 V fNeq{};
253 for (int iD = 0; iD < DESCRIPTOR::d; ++iD) {
254 fNeq += descriptors::c<DESCRIPTOR>(iPop,iD) * jNeq[iD];
255 }
257 return fNeq;
258 }
259
260};
261
263template <typename DESCRIPTOR>
264struct lbm {
266 template <concepts::MinimalCell CELL, typename V=typename CELL::value_t>
267 static V computeRho(CELL& cell) any_platform
268 {
269 V rho = V();
270 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
271 rho += cell[iPop];
272 }
273 rho += V{1};
274 return rho;
275 }
276
278 template <concepts::MinimalCell CELL, typename J, typename V=typename CELL::value_t>
279 static void computeJ(CELL& cell, J& j) any_platform
280 {
281 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
282 j[iD] = V();
283 }
284 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
285 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
286 j[iD] += cell[iPop]*descriptors::c<DESCRIPTOR>(iPop,iD);
287 }
288 }
289 }
290
292 template <concepts::MinimalCell CELL, typename RHO, typename J, typename V=typename CELL::value_t>
293 static void computeRhoJ(CELL& cell, RHO& rho, J& j) any_platform
294 {
295 rho = computeRho(cell);
296 computeJ(cell, j);
297 }
298
300 template <concepts::MinimalCell CELL, typename RHO, typename U, typename V=typename CELL::value_t>
301 static void computeRhoU(CELL& cell, RHO& rho, U& u) any_platform
302 {
303 computeRhoJ(cell, rho, u);
304 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
305 u[iD] /= rho;
306 }
307 }
308
310 template <concepts::MinimalCell CELL, typename RHO, typename U, typename PI, typename V=typename CELL::value_t>
311 static void computeStress(CELL& cell, const RHO& rho, const U& u, PI& pi) any_platform
312 {
313 int iPi = 0;
314 for (int iAlpha=0; iAlpha < DESCRIPTOR::d; ++iAlpha) {
315 for (int iBeta=iAlpha; iBeta < DESCRIPTOR::d; ++iBeta) {
316 pi[iPi] = V();
317 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
318 pi[iPi] += descriptors::c<DESCRIPTOR>(iPop,iAlpha)*
319 descriptors::c<DESCRIPTOR>(iPop,iBeta) * cell[iPop];
320 }
321 // stripe off equilibrium contribution
322 pi[iPi] -= rho*u[iAlpha]*u[iBeta];
323 if (iAlpha==iBeta) {
324 pi[iPi] -= V{1} / descriptors::invCs2<V,DESCRIPTOR>()*(rho-V{1});
325 }
326 ++iPi;
327 }
328 }
329 }
330
332 template <concepts::MinimalCell CELL, typename RHO, typename U, typename PI, typename V=typename CELL::value_t>
333 static void computeAllMomenta(CELL& cell, RHO& rho, U& u, PI& pi) any_platform
334 {
335 computeRhoU(cell, rho, u);
336 computeStress(cell, rho, u, pi);
337 }
338
339 template <concepts::MinimalCell CELL, typename FEQ, typename V=typename CELL::value_t>
340 static void computeFeq(CELL& cell, FEQ& fEq) any_platform
341 {
342 V rho {};
343 V u[DESCRIPTOR::d] {};
344 computeRhoU(cell, rho, u);
345 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
346 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
347 fEq[iPop] = equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr);
348 }
349 }
350
352 template <concepts::MinimalCell CELL, typename FNEQ, typename RHO, typename U, typename V=typename CELL::value_t>
353 static void computeFneq(CELL& cell, FNEQ& fNeq, const RHO& rho, const U& u) any_platform
354 {
355 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
356 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
357 fNeq[iPop] = cell[iPop] - equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr);
358 }
359 }
360
361 template <concepts::MinimalCell CELL, typename FNEQ, typename V=typename CELL::value_t>
362 static void computeFneq(CELL& cell, FNEQ& fNeq) any_platform
363 {
364 V rho{};
365 V u[DESCRIPTOR::d] {};
366 computeRhoU(cell, rho, u);
367 computeFneq(cell, fNeq, rho, u);
368 }
369
371 template <concepts::MinimalCell CELL, typename RHO, typename VELOCITY, typename OMEGA, typename V=typename CELL::value_t>
372 static V bgkCollision(CELL& cell, const RHO& rho, const VELOCITY& u, const OMEGA& omega) any_platform
373 {
375 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
376 cell[iPop] *= V{1} - omega;
377 cell[iPop] += omega * equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr);
378 }
379 return uSqr;
380 }
381
383 template <concepts::MinimalCell CELL, typename RHO, typename VELOCITY, typename OMEGA, typename V=typename CELL::value_t>
384 static V adeBgkCollision(CELL& cell, const RHO& rho, const VELOCITY& u, const OMEGA& omega) any_platform
385 {
387 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
388 cell[iPop] *= V{1} - omega;
389 cell[iPop] += omega * equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
390 }
391 return uSqr;
392 }
393
395 template <concepts::MinimalCell CELL, typename PRESSURE, typename J, typename OMEGA, typename V=typename CELL::value_t>
396 static V incBgkCollision(CELL& cell, const PRESSURE& pressure, const J& j, const OMEGA& omega) any_platform
397 {
398 const V jSqr = util::normSqr<J,DESCRIPTOR::d>(j);
399 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
400 cell[iPop] *= V{1} - omega;
401 cell[iPop] += omega * equilibrium<DESCRIPTOR>::template incompressible<J,V,V>(iPop, j, jSqr, pressure);
402 }
403 return jSqr;
404 }
405
407 template <concepts::MinimalCell CELL, typename RHO, typename U, typename RATIORHO, typename OMEGA, typename V=typename CELL::value_t>
408 static V constRhoBgkCollision(CELL& cell, const RHO& rho, const U& u,
409 const RATIORHO& ratioRho, const OMEGA& omega) any_platform
410 {
411 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
412 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
413 V feq = equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr);
414 cell[iPop] =
416 (V{1}-omega)*(cell[iPop]-feq);
417 }
418 return uSqr;
419 }
420
422 template <concepts::MinimalCell CELL, typename RHO, typename U, typename OMEGA, typename V=typename CELL::value_t>
423 static V rlbCollision(CELL& cell, const RHO& rho, const U& u, const OMEGA& omega) any_platform
424 {
425 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
426 // First-order moment for the regularization
427 V j1[DESCRIPTOR::d];
428 for ( int iD = 0; iD < DESCRIPTOR::d; ++iD ) {
429 j1[iD] = V();
430 }
431
432 V fEq[DESCRIPTOR::q];
433 for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) {
434 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder( iPop, rho, u );
435 for ( int iD = 0; iD < DESCRIPTOR::d; ++iD ) {
436 j1[iD] += descriptors::c<DESCRIPTOR>(iPop,iD) * ( cell[iPop] - fEq[iPop] );
437 }
438 }
439
440 // Collision step
441 for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) {
442 V fNeq = V();
443 for ( int iD = 0; iD < DESCRIPTOR::d; ++iD ) {
444 fNeq += descriptors::c<DESCRIPTOR>(iPop,iD) * j1[iD];
445 }
447 cell[iPop] = fEq[iPop] + ( V{1} - omega ) * fNeq;
448 }
449 return uSqr;
450 }
451
453 template <concepts::MinimalCell CELL, typename RHO, typename U, typename PI, typename OMEGA, typename V=typename CELL::value_t>
454 static V rlbCollision(CELL& cell, const RHO& rho, const U& u, const PI& pi, const OMEGA& omega) any_platform
455 {
456 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
457 cell[0] = equilibrium<DESCRIPTOR>::secondOrder(0, rho, u, uSqr)
458 + (V{1}-omega) * equilibrium<DESCRIPTOR>::template fromPiToFneq<V>(0, pi);
459 for (int iPop=1; iPop <= DESCRIPTOR::q/2; ++iPop) {
460 cell[iPop] = equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr);
461 cell[iPop+DESCRIPTOR::q/2] = equilibrium<DESCRIPTOR>::secondOrder(iPop+DESCRIPTOR::q/2, rho, u, uSqr);
462
463 V fNeq = (V{1}-omega) * equilibrium<DESCRIPTOR>::template fromPiToFneq<V>(iPop, pi);
464 cell[iPop] += fNeq;
465 cell[iPop+DESCRIPTOR::q/2] += fNeq;
466 }
467 return uSqr;
468 }
469
470 template <concepts::MinimalCell CELL, typename NEWRHO, typename NEWU, typename V=typename CELL::value_t>
471 static void defineEqFirstOrder(CELL& cell, const NEWRHO& newRho, const NEWU& newU) any_platform
472 {
473 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
474 cell[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, newRho, newU);
475 }
476 }
477
478 template <concepts::MinimalCell CELL, typename OLDRHO, typename OLDU, typename NEWRHO, typename NEWU, typename V=typename CELL::value_t>
479 static void defineNEq(CELL& cell,
480 const OLDRHO& oldRho, const OLDU& oldU,
481 const NEWRHO& newRho, const NEWU& newU) any_platform
482 {
483 const V oldUSqr = util::normSqr<OLDU,DESCRIPTOR::d>(oldU);
484 const V newUSqr = util::normSqr<NEWU,DESCRIPTOR::d>(newU);
485 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
486 cell[iPop] += equilibrium<DESCRIPTOR>::secondOrder(iPop, newRho, newU, newUSqr)
487 - equilibrium<DESCRIPTOR>::secondOrder(iPop, oldRho, oldU, oldUSqr);
488 }
489 }
490
491 template <concepts::MinimalCell CELL, typename RHO, typename U, typename PI, typename V=typename CELL::value_t>
492 static void defineNEqFromPi(CELL& cell,
493 const RHO& rho,
494 const U& u,
495 const PI& pi) any_platform
496 {
497 const V uSqr = util::normSqr<U,DESCRIPTOR::d>(u);
498 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
499 cell[iPop] = equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr)
500 + equilibrium<DESCRIPTOR>::template fromPiToFneq<V>(iPop, pi);
501 }
502 }
503
505 template <concepts::MinimalCell CELL, typename FORCE, typename V=typename CELL::value_t>
506 static V computePiNeqNormSqr(CELL& cell, const FORCE& force) any_platform
507 {
508 V rho, u[DESCRIPTOR::d], pi[util::TensorVal<DESCRIPTOR>::n];
509 computeAllMomenta(cell, rho, u, pi);
510 V ForceTensor[util::TensorVal<DESCRIPTOR>::n];
511 // Creation of body force tensor (rho/2.)*(G_alpha*U_beta + U_alpha*G_Beta)
512 int iPi = 0;
513 for (int Alpha=0; Alpha<DESCRIPTOR::d; ++Alpha) {
514 for (int Beta=Alpha; Beta<DESCRIPTOR::d; ++Beta) {
515 ForceTensor[iPi] = rho/2.*(force[Alpha]*u[Beta] + u[Alpha]*force[Beta]);
516 ++iPi;
517 }
518 }
519 // Creation of second-order moment off-equilibrium tensor
520 for (int iPi=0; iPi < util::TensorVal<DESCRIPTOR >::n; ++iPi) {
521 pi[iPi] += ForceTensor[iPi];
522 }
523 V PiNeqNormSqr = pi[0]*pi[0] + 2.*pi[1]*pi[1] + pi[2]*pi[2];
524 if constexpr (util::TensorVal<DESCRIPTOR>::n == 6) {
525 PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2.*pi[4]*pi[4] +pi[5]*pi[5];
526 }
527 return PiNeqNormSqr;
528 }
529
531 template <concepts::MinimalCell CELL, typename V=typename CELL::value_t>
533 {
534 V rho, u[DESCRIPTOR::d], pi[util::TensorVal<DESCRIPTOR>::n];
535 computeAllMomenta(cell, rho, u, pi);
536 V PiNeqNormSqr = pi[0]*pi[0] + 2.*pi[1]*pi[1] + pi[2]*pi[2];
537 if constexpr (util::TensorVal<DESCRIPTOR >::n == 6) {
538 PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2.*pi[4]*pi[4] +pi[5]*pi[5];
539 }
540 return PiNeqNormSqr;
541 }
542
544 template <concepts::MinimalCell CELL, typename RHO, typename U, typename OMEGA, typename FORCE, typename V=typename CELL::value_t>
545 static void addExternalForce(CELL& cell, const RHO& rho, const U& u, const OMEGA& omega, const FORCE& force) any_platform
546 {
547 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
548 V c_u{};
549 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
550 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
551 }
553 V forceTerm{};
554 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
555 forceTerm +=
557 + c_u * descriptors::c<DESCRIPTOR>(iPop,iD)
558 )
559 * force[iD];
560 }
561 forceTerm *= descriptors::t<V,DESCRIPTOR>(iPop);
562 forceTerm *= V{1} - omega * V{0.5};
563 forceTerm *= rho;
564 cell[iPop] += forceTerm;
565 }
566 }
567
569 template <typename CELL, typename RHO, typename NABLARHO, typename U, typename OMEGA, typename FORCE, typename V=typename CELL::value_t>
570 static void addLiangForce(CELL& cell, const RHO& rho, const NABLARHO& nablarho, const U& u, const OMEGA& omega, const FORCE& force) any_platform
571 {
572 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
573 V c_u{};
574 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
575 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
576 }
577 V forceTerm{};
578 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
579 forceTerm += descriptors::c<DESCRIPTOR>(iPop,iD) * force[iD] * rho +c_u * descriptors::c<DESCRIPTOR>(iPop,iD) * nablarho[iD];
580 }
582 forceTerm *= V{1} - omega * V{0.5};
583 cell[iPop] += forceTerm;
584 }
585 }
586
588 template <typename CELL, typename OMEGA, typename FORCE, typename V=typename CELL::value_t>
589 static void addAllenCahnForce(CELL& cell, const OMEGA& omega, const FORCE& force) any_platform
590 {
591 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
592 V forceTerm{};
593 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
594 forceTerm += descriptors::c<DESCRIPTOR>(iPop,iD) * force[iD];
595 }
597 forceTerm *= V{1} - omega * V{0.5};
598 cell[iPop] += forceTerm;
599 }
600 }
601
603 template <typename CELL, typename OMEGA, typename SOURCE, typename V=typename CELL::value_t>
604 static void addAllenCahnSource(CELL& cell, const OMEGA& omega, const SOURCE& source) any_platform
605 {
606 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
607 cell[iPop] += descriptors::t<V,DESCRIPTOR>(iPop)*source;
608 }
609 }
610};
611
612
613
614}
615
616#endif
617
618//#include "lbm.cse.h"
constexpr T invCs2() any_platform
Definition functions.h:107
constexpr T t(unsigned iPop, tag::CUM) any_platform
Definition cum.h:108
constexpr int c(unsigned iPop, unsigned iDim) any_platform
Definition functions.h:83
auto normSqr(const ARRAY_LIKE &u) any_platform
Compute norm square of a d-dimensional vector.
Definition util.h:145
Top level namespace for all of OpenLB.
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:77
static V fromPiToFneq(int iPop, const PI &pi) any_platform
Compute off-equilibrium part of the f's from the stress tensor Pi.
Definition lbm.h:225
static V secondOrder(int iPop, const RHO &rho, const U &u) any_platform
Computation of equilibrium distribution, second order in u.
Definition lbm.h:67
static V incompressible(int iPop, const J &j, const JSQR &jSqr, const PRESSURE &pressure) any_platform
Definition lbm.h:146
static V thirdOrder(int iPop, const RHO &rho, const U &u, const USQR &uSqr) any_platform
Computation of equilibrium distribution, third order in u.
Definition lbm.h:75
static V fromJneqToFneq(int iPop, const V jNeq[DESCRIPTOR::d]) any_platform
Definition lbm.h:250
static V P1(int iPop, const RHO &rho, const U &u) any_platform
Definition lbm.h:134
static V thirdOrder(int iPop, const RHO &rho, const U &u) any_platform
Computation of equilibrium distribution, third order in u.
Definition lbm.h:126
static V secondOrder(int iPop, const RHO &rho, const U &u, const USQR &uSqr) any_platform
Computation of equilibrium distribution, second order in u.
Definition lbm.h:51
static V fromJgradToFneq(int iPop, const V Jgrad[DESCRIPTOR::d *DESCRIPTOR::d], V omega) any_platform
compute off-equilibrium part of the populations from gradient of the flux for asymmetric regularizati...
Definition lbm.h:192
static V mpincompressible(int iPop, const RHO &rho, const U &u, const USQR &uSqr, const PRESSURE &pressure) any_platform
Definition lbm.h:167
static V firstOrder(int iPop, const RHO &rho, const U &u) any_platform
Computation of equilibrium distribution, first order in u.
Definition lbm.h:37
static V mpincompressible(int iPop, const RHO &rho, const U &u, const PRESSURE &pressure) any_platform
Definition lbm.h:183
static V incompressible(int iPop, const J &j, const PRESSURE &pressure) any_platform
Definition lbm.h:160
Collection of common computations for LBM.
Definition lbm.h:264
static V adeBgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
Advection diffusion BGK collision step.
Definition lbm.h:384
static void defineEqFirstOrder(CELL &cell, const NEWRHO &newRho, const NEWU &newU) any_platform
Definition lbm.h:471
static V constRhoBgkCollision(CELL &cell, const RHO &rho, const U &u, const RATIORHO &ratioRho, const OMEGA &omega) any_platform
BGK collision step with density correction.
Definition lbm.h:408
static void computeFeq(CELL &cell, FEQ &fEq) any_platform
Definition lbm.h:340
static V computePiNeqNormSqr(CELL &cell) any_platform
Computes squared norm of non-equilibrium part of 2nd momentum for standard (non-forced) dynamics.
Definition lbm.h:532
static void computeJ(CELL &cell, J &j) any_platform
Computation of momentum.
Definition lbm.h:279
static void computeFneq(CELL &cell, FNEQ &fNeq, const RHO &rho, const U &u) any_platform
Computation of non-equilibrium distribution.
Definition lbm.h:353
static void computeAllMomenta(CELL &cell, RHO &rho, U &u, PI &pi) any_platform
Computation of all hydrodynamic variables.
Definition lbm.h:333
static V rlbCollision(CELL &cell, const RHO &rho, const U &u, const PI &pi, const OMEGA &omega) any_platform
Renormalized DESCRIPTOR Boltzmann collision operator, fIn --> fOut.
Definition lbm.h:454
static void computeFneq(CELL &cell, FNEQ &fNeq) any_platform
Definition lbm.h:362
static void addAllenCahnForce(CELL &cell, const OMEGA &omega, const FORCE &force) any_platform
Add a force term after BGK collision for constructing local Allen-Cahn-equation from Liang et al....
Definition lbm.h:589
static void addLiangForce(CELL &cell, const RHO &rho, const NABLARHO &nablarho, const U &u, const OMEGA &omega, const FORCE &force) any_platform
Add a force term after BGK collision for incompressible binary fluid model (Allen-Cahn phase-field) f...
Definition lbm.h:570
static V computePiNeqNormSqr(CELL &cell, const FORCE &force) any_platform
Computes squared norm of non-equilibrium part of 2nd momentum for forced dynamics.
Definition lbm.h:506
static V rlbCollision(CELL &cell, const RHO &rho, const U &u, const OMEGA &omega) any_platform
RLB advection diffusion collision step.
Definition lbm.h:423
static void addAllenCahnSource(CELL &cell, const OMEGA &omega, const SOURCE &source) any_platform
Add a source term after BGK collision for constructing non-local Allen-Cahn-equation from Liu et al....
Definition lbm.h:604
static void computeRhoJ(CELL &cell, RHO &rho, J &j) any_platform
Computation of hydrodynamic variables.
Definition lbm.h:293
static V computeRho(CELL &cell) any_platform
Computation of density.
Definition lbm.h:267
static void addExternalForce(CELL &cell, const RHO &rho, const U &u, const OMEGA &omega, const FORCE &force) any_platform
Add a force term after BGK collision.
Definition lbm.h:545
static V bgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
BGK collision step.
Definition lbm.h:372
static void computeStress(CELL &cell, const RHO &rho, const U &u, PI &pi) any_platform
Computation of stress tensor.
Definition lbm.h:311
static void defineNEq(CELL &cell, const OLDRHO &oldRho, const OLDU &oldU, const NEWRHO &newRho, const NEWU &newU) any_platform
Definition lbm.h:479
static V incBgkCollision(CELL &cell, const PRESSURE &pressure, const J &j, const OMEGA &omega) any_platform
Incompressible BGK collision step.
Definition lbm.h:396
static void defineNEqFromPi(CELL &cell, const RHO &rho, const U &u, const PI &pi) any_platform
Definition lbm.h:492
static void computeRhoU(CELL &cell, RHO &rho, U &u) any_platform
Computation of hydrodynamic variables.
Definition lbm.h:301
Compute number of elements of a symmetric d-dimensional tensor.
Definition util.h:216
Set of functions commonly used in LB computations – header file.