OpenLB 1.7
Loading...
Searching...
No Matches
advectionDiffusionDynamics.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2008 Orestis Malaspinas, Andrea Parmigiani
4 * 2022 Nando Suntoyo, 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
29#ifndef ADVECTION_DIFFUSION_DYNAMICS_H
30#define ADVECTION_DIFFUSION_DYNAMICS_H
31
32#include "latticeDescriptors.h"
33#include "dynamics/dynamics.h"
34#include "core/unitConverter.h"
35#include "collisionMRT.h"
36
37namespace olb {
38
39namespace TotalEnthalpy {
40 struct T_S : public descriptors::FIELD_BASE<1> { };
41 struct T_L : public descriptors::FIELD_BASE<1> { };
42 struct CP_S : public descriptors::FIELD_BASE<1> { };
43 struct CP_L : public descriptors::FIELD_BASE<1> { };
44 struct LAMBDA_S : public descriptors::FIELD_BASE<1> { };
45 struct LAMBDA_L : public descriptors::FIELD_BASE<1> { };
46 struct L : public descriptors::FIELD_BASE<1> { };
47}
48
50 static std::string getName() {
51 return "AdvectionDifffusionExternalVelocityCollision";
52 }
53
54 template <typename DESCRIPTOR, typename MOMENTA>
55 using combined_momenta = typename MOMENTA::template type<DESCRIPTOR>;
56
57 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
58 using combined_equilibrium = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
59
60 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
61 using combined_collision = typename COLLISION::template type<
62 DESCRIPTOR,
64 typename MOMENTA::density,
66 typename MOMENTA::stress,
67 typename MOMENTA::definition
68 >,
69 EQUILIBRIUM
70 >;
71
72 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
73 using combined_parameters = typename COLLISION::parameters;
74};
75
76template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
78 T, DESCRIPTOR,
79 MOMENTA,
83>;
84
85template <typename T, typename DESCRIPTOR, typename DYNAMICS, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
86class CombinedAdvectionDiffusionRLBdynamics final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA> {
87public:
88 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
89
90 using parameters = typename DYNAMICS::parameters;
91
92 template <typename M>
94
95 std::type_index id() override {
97 };
98
100 return block.template getData<OperatorParameters<CombinedAdvectionDiffusionRLBdynamics>>();
101 }
102
103 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
105 V jNeq[DESCRIPTOR::d] { };
106
107 const V rho = MomentaF().computeRho(cell);
108 const auto u = cell.template getField<descriptors::VELOCITY>();
109 MomentaF().computeJ(cell, jNeq);
110
111 for (int iD = 0; iD < DESCRIPTOR::d; ++iD) {
112 jNeq[iD] -= u[iD] * rho;
113 }
114
115 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
116 cell[iPop] = typename DYNAMICS::EquilibriumF().compute(iPop, rho, u)
117 + equilibrium<DESCRIPTOR>::template fromJneqToFneq<V>(iPop, jNeq);
118 }
119
120 return typename DYNAMICS::CollisionO().apply(cell, parameters);
121 };
122
123 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override any_platform {
124 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
125 };
126
127 std::string getName() const override {
128 return "CombinedAdvectionDiffusionRLBdynamics<" + MomentaF().getName() + ">";
129 };
130
131};
132
133// ========= the BGK advection diffusion dynamics ========//
135template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
137 T,DESCRIPTOR,
138 MOMENTA,
142>;
143
144
145// ========= the TRT advection diffusion dynamics ========//
147template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
149 T,DESCRIPTOR,
150 MOMENTA,
154>;
155
156
157// ======= BGK advection diffusion dynamics with source term ======//
158// following Seta, T. (2013). Implicit temperature-correction-based
159// immersed-boundary thermal lattice Boltzmann method for the simulation
160// of natural convection. Physical Review E, 87(6), 063304.
161template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
163 T,DESCRIPTOR,
164 momenta::Tuple<
165 momenta::SourcedDensity<typename MOMENTA::density>,
166 typename MOMENTA::momentum,
167 typename MOMENTA::stress,
168 typename MOMENTA::definition
169 >
170> {
171 using MomentaF = typename momenta::Tuple<
173 typename MOMENTA::momentum,
174 typename MOMENTA::stress,
175 typename MOMENTA::definition
176 >::template type<DESCRIPTOR>;
177
179
180 template<typename M>
182
183 std::type_index id() override {
185 };
186
188 return block.template getData<OperatorParameters<SourcedAdvectionDiffusionBGKdynamics>>();
189 }
190
191 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
193 const auto u = cell.template getField<descriptors::VELOCITY>();
194 const V temperature = MomentaF().computeRho(cell);
195 const V omega = parameters.template get<descriptors::OMEGA>();
196
197 const V uSqr = lbm<DESCRIPTOR>::adeBgkCollision(cell, temperature, u, omega);
198 const V sourceMod = cell.template getField<descriptors::SOURCE>() * (V{1} - V{0.5} * omega);
199
200 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
201 cell[iPop] += sourceMod * descriptors::t<T,DESCRIPTOR>(iPop);
202 }
203
204 return {temperature, uSqr};
205 };
206
207 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override any_platform {
208 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
209 };
210
211 std::string getName() const override {
212 return "SourcedAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
213 };
214};
215
216
217// ======= BGK advection diffusion dynamics with source term ======//
218// following Seta, T. (2013). Implicit temperature-correction-based
219// immersed-boundary thermal lattice Boltzmann method for the simulation
220// of natural convection. Physical Review E, 87(6), 063304.
221template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
223 T,DESCRIPTOR,
224 momenta::Tuple<
225 momenta::SourcedDensity<typename MOMENTA::density>,
226 typename MOMENTA::momentum,
227 typename MOMENTA::stress,
228 typename MOMENTA::definition
229 >
230> {
231 using MomentaF = typename momenta::Tuple<
233 typename MOMENTA::momentum,
234 typename MOMENTA::stress,
235 typename MOMENTA::definition
236 >::template type<DESCRIPTOR>;
237
239
240 template<typename M>
242
243 std::type_index id() override {
245 };
246
248 return block.template getData<OperatorParameters<SourcedLimitedAdvectionDiffusionBGKdynamics>>();
249 }
250
251 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
253 const auto u = cell.template getField<descriptors::VELOCITY>();
254 V temperature = MomentaF().computeRho(cell);
255 if (temperature < V{1.e-8}) temperature = V{1.e-8};
256 const V omega = cell.template getField<descriptors::OMEGA>();
257
258 const V uSqr = lbm<DESCRIPTOR>::adeBgkCollision(cell, temperature, u, omega);
259 const V sourceMod = cell.template getField<descriptors::SOURCE>() * (V{1} - V{0.5} * omega);
260
261 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
262 cell[iPop] += sourceMod * descriptors::t<T,DESCRIPTOR>(iPop);
263 }
264
265 return {temperature, uSqr};
266 };
267
268 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const any_platform override {
269 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
270 };
271
272 std::string getName() const override {
273 return "SourcedLimitedAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
274 };
275};
276
277// ======= BGK advection diffusion dynamics for solid-liquid phase change ======//
278// following Huang, R. (2015). Phase interface effects in the total
279// enthalpy-based lattice Boltzmann model for solid–liquid phase change.
280// Journal of Computational Physics, 294, 345-362.
281template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
283 static constexpr bool is_vectorizable = false;
284
285 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
286
296 >;
297
298 template<typename M>
300
301 std::type_index id() override {
303 };
304
306 return block.template getData<OperatorParameters<TotalEnthalpyAdvectionDiffusionBGKdynamics>>();
307 }
308
309 template<typename V, typename PARAMETERS, typename ENTHALPY>
310 V computeTemperature(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const any_platform
311 {
312 using namespace TotalEnthalpy;
313
314 const V cp_s = parameters.template get<CP_S>();
315 const V cp_l = parameters.template get<CP_L>();
316 const V T_s = parameters.template get<T_S>();
317 const V T_l = parameters.template get<T_L>();
318 const V l = parameters.template get<L>();
319 const V H_s = cp_s * T_s;
320 const V H_l = cp_l * T_l + l;
321 V temperature{};
322
323 if (enthalpy <= H_s) {
324 temperature = T_s - (H_s - enthalpy) / cp_s;
325 }
326 else if (enthalpy >= H_l) {
327 temperature = T_l + (enthalpy - H_l) / cp_l;
328 }
329 else {
330 temperature = (H_l - enthalpy) / (H_l - H_s) * T_s + (enthalpy - H_s) / (H_l - H_s) * T_l;
331 }
332 return temperature;
333 }
334
335 template<typename V, typename PARAMETERS, typename ENTHALPY>
336 V computeLiquidFraction(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const any_platform
337 {
338 using namespace TotalEnthalpy;
339
340 const V cp_s = parameters.template get<CP_S>();
341 const V cp_l = parameters.template get<CP_L>();
342 const V T_s = parameters.template get<T_S>();
343 const V T_l = parameters.template get<T_L>();
344 const V l = parameters.template get<L>();
345 const V H_s = cp_s * T_s;
346 const V H_l = cp_l * T_l + l;
347 V liquid_fraction{};
348
349 if (enthalpy <= H_s) {
350 liquid_fraction = 0.;
351 }
352 else if (enthalpy >= H_l) {
353 liquid_fraction = 1.;
354 }
355 else {
356 liquid_fraction = (enthalpy - H_s) / l;
357 }
358 return liquid_fraction;
359 }
360
361 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override any_platform
362 {
363 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
364 }
365
366 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
368 using namespace TotalEnthalpy;
369
370 const V lambda_s = parameters.template get<LAMBDA_S>();
371 const V lambda_l = parameters.template get<LAMBDA_L>();
372 const V cp_s = parameters.template get<CP_S>();
373 const V cp_l = parameters.template get<CP_L>();
374 const V cp_ref = V{2} * cp_s * cp_l / (cp_s + cp_l);
375
376 const V enthalpy = MomentaF().computeRho( cell );
377 const V temperature = computeTemperature<V>( parameters, enthalpy );
378 const V liquid_fraction = computeLiquidFraction<V>( parameters, enthalpy );
379 const V lambda = (V{1} - liquid_fraction) * lambda_s + liquid_fraction * lambda_l;
380 const V cp = (V{1} - liquid_fraction) * cp_s + liquid_fraction * cp_l;
381 const V omega = V{1} / ( lambda / cp_ref * descriptors::invCs2<T,DESCRIPTOR>() + V{0.5} );
382
383 const auto u = cell.template getFieldPointer<descriptors::VELOCITY>();
384
385 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
386
387 const V f_eq = enthalpy - cp_ref * temperature
388 + cp * temperature * descriptors::t<T,DESCRIPTOR>(0) * ( cp_ref / cp
389 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
390 - descriptors::t<T,DESCRIPTOR>(0);
391 cell[0] *= V{1} - omega;
392 cell[0] += omega * f_eq;
393 for (int iPop=1; iPop < DESCRIPTOR::q; ++iPop) {
394 V c_u{};
395 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
396 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
397 }
398 const V f_eq = cp * temperature * descriptors::t<T,DESCRIPTOR>(iPop) * ( cp_ref / cp + descriptors::invCs2<T,DESCRIPTOR>() * c_u
399 + descriptors::invCs2<T,DESCRIPTOR>() * descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * c_u *c_u
400 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
401 - descriptors::t<T,DESCRIPTOR>(iPop);
402 cell[iPop] *= V{1} - omega;
403 cell[iPop] += omega * f_eq;
404 }
405 return {enthalpy, uSqr};
406 };
407
408 std::string getName() const override {
409 return "TotalEnthalpyAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
410 };
411};
412
413// ======= TRT advection diffusion dynamics for solid-liquid phase change ======//
414// following Huang, R. (2015). Phase interface effects in the total
415// enthalpy-based lattice Boltzmann model for solid–liquid phase change.
416// Journal of Computational Physics, 294, 345-362.
417template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
419 static constexpr bool is_vectorizable = false;
420
421 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
422
433 >;
434
435 template<typename M>
437
438 std::type_index id() override {
440 };
441
443 return block.template getData<OperatorParameters<TotalEnthalpyAdvectionDiffusionTRTdynamics>>();
444 }
445
446 template<typename V, typename PARAMETERS, typename ENTHALPY>
447 V computeTemperature(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const
448 {
449 using namespace TotalEnthalpy;
450
451 const V cp_s = parameters.template get<CP_S>();
452 const V cp_l = parameters.template get<CP_L>();
453 const V T_s = parameters.template get<T_S>();
454 const V T_l = parameters.template get<T_L>();
455 const V l = parameters.template get<L>();
456 const V H_s = cp_s * T_s;
457 const V H_l = cp_l * T_l + l;
458 V temperature{};
459
460 if (enthalpy <= H_s) {
461 temperature = T_s - (H_s - enthalpy) / cp_s;
462 }
463 else if (enthalpy >= H_l) {
464 temperature = T_l + (enthalpy - H_l) / cp_l;
465 }
466 else {
467 temperature = (H_l - enthalpy) / (H_l - H_s) * T_s + (enthalpy - H_s) / (H_l - H_s) * T_l;
468 }
469 return temperature;
470 }
471
472 template<typename V, typename PARAMETERS, typename ENTHALPY>
473 V computeLiquidFraction(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const
474 {
475 using namespace TotalEnthalpy;
476
477 const V cp_s = parameters.template get<CP_S>();
478 const V cp_l = parameters.template get<CP_L>();
479 const V T_s = parameters.template get<T_S>();
480 const V T_l = parameters.template get<T_L>();
481 const V l = parameters.template get<L>();
482 const V H_s = cp_s * T_s;
483 const V H_l = cp_l * T_l + l;
484 V liquid_fraction{};
485
486 if (enthalpy <= H_s) {
487 liquid_fraction = 0.;
488 }
489 else if (enthalpy >= H_l) {
490 liquid_fraction = 1.;
491 }
492 else {
493 liquid_fraction = (enthalpy - H_s) / l;
494 }
495 return liquid_fraction;
496 }
497
498 template<typename V, typename PARAMETERS, typename RHO, typename U>
499 V computeEquilibrium(int iPop, const PARAMETERS& parameters, RHO& rho, U& u) const
500 {
501 using namespace TotalEnthalpy;
502
503 const V temperature = computeTemperature<V>(parameters, rho);
504 const V liquid_fraction = computeLiquidFraction<V>(parameters, rho);
505
506 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
507 const V cp_s = parameters.template get<CP_S>();
508 const V cp_l = parameters.template get<CP_L>();
509 const V cp = (V{1} - liquid_fraction) * cp_s + liquid_fraction * cp_l;
510 const V cp_ref = V{2} * cp_s * cp_l / (cp_s + cp_l);
511
512 V c_u{};
513 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
514 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
515 }
516
517 V f_eq{};
518 if (iPop == 0) {
519 f_eq = rho - cp_ref * temperature
520 + cp * temperature * descriptors::t<T,DESCRIPTOR>(0) * ( cp_ref / cp
521 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
522 - descriptors::t<T,DESCRIPTOR>(0);
523 }
524 else {
525 f_eq = cp * temperature * descriptors::t<T,DESCRIPTOR>(iPop) * ( cp_ref / cp + descriptors::invCs2<T,DESCRIPTOR>() * c_u
526 + descriptors::invCs2<T,DESCRIPTOR>() * descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * c_u *c_u
527 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
528 - descriptors::t<T,DESCRIPTOR>(iPop);
529 }
530
531 return f_eq;
532 }
533
534 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
535 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
536 using namespace TotalEnthalpy;
537
538 const V lambda_s = parameters.template get<LAMBDA_S>();
539 const V lambda_l = parameters.template get<LAMBDA_L>();
540 const V cp_s = parameters.template get<CP_S>();
541 const V cp_l = parameters.template get<CP_L>();
542 const V cp_ref = V{2} * cp_s * cp_l / (cp_s + cp_l);
543
544 const V enthalpy = MomentaF().computeRho( cell );
545 const V liquid_fraction = computeLiquidFraction<V>( parameters, enthalpy );
546 const V lambda = (V{1} - liquid_fraction) * lambda_s + liquid_fraction * lambda_l;
547 const V omega = V{1} / ( lambda / cp_ref * descriptors::invCs2<T,DESCRIPTOR>() + V{0.5} );
548 const V magic_parameter = parameters.template get<collision::TRT::MAGIC>();
549 const V omega2 = V{1} / (magic_parameter/(V{1}/omega-V{0.5})+V{0.5});
550
551 const auto u = cell.template getField<descriptors::VELOCITY>();
552
553 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
554
555 V fPlus[DESCRIPTOR::q], fMinus[DESCRIPTOR::q] { };
556 V fEq[DESCRIPTOR::q], fEqPlus[DESCRIPTOR::q], fEqMinus[DESCRIPTOR::q] { };
557
558 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
559 fPlus[iPop] = 0.5 * ( cell[iPop] + cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
560 fMinus[iPop] = 0.5 * ( cell[iPop] - cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
561 fEq[iPop] = computeEquilibrium<V>(iPop, parameters, enthalpy, u);
562 }
563
564 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
565 fEqPlus[iPop] = 0.5 * ( fEq[iPop] + fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
566 fEqMinus[iPop] = 0.5 * ( fEq[iPop] - fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
567 }
568
569 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
570 cell[iPop] -= omega2 * (fPlus[iPop] - fEqPlus[iPop]) + omega * (fMinus[iPop] - fEqMinus[iPop]);
571 }
572
573 return {enthalpy, uSqr};
574 };
575
576 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override
577 {
578 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
579 }
580
581 std::string getName() const override {
582 return "TotalEnthalpyAdvectionDiffusionTRTdynamics<" + MomentaF().getName() + ">";
583 };
584};
585
586namespace descriptors {
587
589
590}
591
592// ======= BGK advection diffusion dynamics for phase field equation ======//
593// following Fakhari, Abbas, et al. (2017). Improved locality of the phase-field
594// lattice-Boltzmann model for immiscible fluids at high density ratios.
595// Physical Review E 96.5, 053301.
596template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
598 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
599
601
602 template<typename M>
604
605 std::type_index id() override {
607 };
608
610 return block.template getData<OperatorParameters<PhaseFieldAdvectionDiffusionBGKdynamics>>();
611 }
612
613 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
614 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
615 const V omega = parameters.template get<descriptors::OMEGA>();
616 const V interface_thickness = parameters.template get<descriptors::INTERFACE_THICKNESS>();
617
618 const V phi = MomentaF().computeRho( cell );
619 const auto u = cell.template getField<descriptors::VELOCITY>();
620 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
621 const auto mobility = (V{1} / omega - V{0.5}) / descriptors::invCs2<V,DESCRIPTOR>();
622
623 const auto n = cell.template getFieldPointer<descriptors::INTERPHASE_NORMAL>();
624 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
625 V c_u{};
626 V c_n{};
627 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
628 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
629 c_n += descriptors::c<DESCRIPTOR>(iPop,iD)*n[iD];
630 }
631 V f_eq = equilibrium<DESCRIPTOR>::firstOrder(iPop, phi, u);
632 f_eq += descriptors::t<V,DESCRIPTOR>(iPop) * mobility * descriptors::invCs2<V,DESCRIPTOR>()
633 * (V{4} * phi * (V{1} - phi) / interface_thickness) * c_n;
634
635 cell[iPop] *= V{1} - omega;
636 cell[iPop] += omega * f_eq;
637 }
638
639 return {phi, uSqr};
640 };
641
642 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override
643 {
644 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
645 }
646
647 std::string getName() const override {
648 return "PhaseFieldAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
649 };
650};
651
652// ========= the BGK advection diffusion Stokes drag dynamics ========//
654template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
655struct ParticleAdvectionDiffusionBGKdynamics final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA> {
656public:
657 using MomentaF = typename momenta::Tuple<
658 typename MOMENTA::density,
660 typename MOMENTA::stress,
661 typename MOMENTA::definition
662 >::template type<DESCRIPTOR>;
663
665
666 template <typename M>
668
669 std::type_index id() override {
671 };
672
674 return block.template getData<OperatorParameters<ParticleAdvectionDiffusionBGKdynamics>>();
675 }
676
677 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
678 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
679 const V omega = parameters.template get<descriptors::OMEGA>();
680 const std::size_t time = parameters.template get<descriptors::LATTICE_TIME>();
681 const auto u = (time % 2 == 0) ? cell.template getField<descriptors::VELOCITY>()
682 : cell.template getField<descriptors::VELOCITY2>();
683 V rho = MomentaF().computeRho(cell);
684 V uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
685 return {rho, uSqr};
686 };
687
688 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override {
689 return equilibrium<DESCRIPTOR>::template firstOrder(iPop, rho, u);
690 };
691
692 std::string getName() const override {
693 return "ParticleAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
694 };
695
696};
697
698
699
700// ========= the MRT advection diffusion dynamics ========//
703template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
705 T,DESCRIPTOR,
706 MOMENTA,
710>;
711
712template <typename T, typename DESCRIPTOR>
714 T, DESCRIPTOR,
718>;
719} // namespace olb
720
721#endif
Platform-abstracted block lattice for external access and inter-block interaction.
std::type_index id() override
Expose unique type-identifier for RTTI.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override any_platform
Return iPop equilibrium for given first and second momenta.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::string getName() const override
Return human-readable name.
Descriptor for all types of 2D and 3D lattices.
Tuple< BulkDensity, BulkMomentum, BulkStress, DefineToNEq > BulkTuple
Standard computation of momenta from the populations in the bulk.
Definition aliases.h:41
Top level namespace for all of OpenLB.
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
Dynamic access interface for FIELD-valued parameters.
typename MOMENTA::template type< DESCRIPTOR > combined_momenta
typename COLLISION::template type< DESCRIPTOR, momenta::Tuple< typename MOMENTA::density, momenta::FixedVelocityMomentum, typename MOMENTA::stress, typename MOMENTA::definition >, EQUILIBRIUM > combined_collision
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > combined_equilibrium
Return value of any collision.
Definition interface.h:43
This approach contains a slight error in the diffusion term.
std::type_index id() override
Expose unique type-identifier for RTTI.
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
typename momenta::Tuple< typename MOMENTA::density, momenta::FixedVelocityMomentum, typename MOMENTA::stress, typename MOMENTA::definition >::template type< DESCRIPTOR > MomentaF
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override
Return iPop equilibrium for given first and second momenta.
std::string getName() const override
Return human-readable name.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override
Return iPop equilibrium for given first and second momenta.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::type_index id() override
Expose unique type-identifier for RTTI.
std::string getName() const override
Return human-readable name.
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override any_platform
Return iPop equilibrium for given first and second momenta.
typename momenta::Tuple< momenta::SourcedDensity< typename MOMENTA::density >, typename MOMENTA::momentum, typename MOMENTA::stress, typename MOMENTA::definition >::template type< DESCRIPTOR > MomentaF
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::string getName() const override
Return human-readable name.
std::type_index id() override
Expose unique type-identifier for RTTI.
std::string getName() const override
Return human-readable name.
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const any_platform override
Return iPop equilibrium for given first and second momenta.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::type_index id() override
Expose unique type-identifier for RTTI.
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
typename momenta::Tuple< momenta::SourcedDensity< typename MOMENTA::density >, typename MOMENTA::momentum, typename MOMENTA::stress, typename MOMENTA::definition >::template type< DESCRIPTOR > MomentaF
V computeLiquidFraction(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const any_platform
typename MOMENTA::template type< DESCRIPTOR > MomentaF
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override any_platform
Return iPop equilibrium for given first and second momenta.
std::string getName() const override
Return human-readable name.
V computeTemperature(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const any_platform
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::type_index id() override
Expose unique type-identifier for RTTI.
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override
Return iPop equilibrium for given first and second momenta.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
V computeLiquidFraction(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const
V computeEquilibrium(int iPop, const PARAMETERS &parameters, RHO &rho, U &u) const
V computeTemperature(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const
std::string getName() const override
Return human-readable name.
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::type_index id() override
Expose unique type-identifier for RTTI.
Base of a field whose size is defined by [C,U_1,...,U_N]^T * [1,V_1,...V_N].
Dynamics constructed as a tuple of momenta, equilibrium and collision.
Definition interface.h:182
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 adeBgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
Advection diffusion BGK collision step.
Definition lbm.h:302
static V bgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
BGK collision step.
Definition lbm.h:290
Plain wrapper for list of types.
Definition meta.h:276
The velocity is stored in the external field descriptors::VELOCITY.
Definition elements.h:526
Unit conversion handling – header file.