OpenLB 1.8.1
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
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
49namespace Light {
50 struct ABSORPTION : public descriptors::FIELD_BASE<1> { };
51 struct SCATTERING : public descriptors::FIELD_BASE<1> { };
53 template <unsigned D, unsigned Q, unsigned...>
54 static constexpr unsigned size() {
55 return Q*Q;
56 }
57
58 template <typename DESCRIPTOR>
59 static constexpr unsigned size() {
60 return DESCRIPTOR::q * DESCRIPTOR::q;
61 }
62
63 template <typename T, typename DESCRIPTOR>
64 static constexpr auto getInitialValue() {
65 return Vector<value_type<T>, DESCRIPTOR::template size<ANISOMATRIX>()>{};
66 }
67
68 template <typename T, typename DESCRIPTOR, typename FIELD>
69 static constexpr auto isValid(FieldD<T,DESCRIPTOR,FIELD> value) {
70 return true;
71 }
72 };
73}
74
75
77 static std::string getName() {
78 return "AdvectionDifffusionExternalVelocityCollision";
79 }
80
81 template <typename DESCRIPTOR, typename MOMENTA>
82 using combined_momenta = typename MOMENTA::template type<DESCRIPTOR>;
83
84 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
85 using combined_equilibrium = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
86
87 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
88 using combined_collision = typename COLLISION::template type<
89 DESCRIPTOR,
91 typename MOMENTA::density,
93 typename MOMENTA::stress,
94 typename MOMENTA::definition
95 >,
96 EQUILIBRIUM
97 >;
98
99 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
100 using combined_parameters = typename COLLISION::parameters;
101};
102
103template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
105 T, DESCRIPTOR,
106 MOMENTA,
110>;
111
112template <typename T, typename DESCRIPTOR, typename DYNAMICS, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
113class CombinedAdvectionDiffusionRLBdynamics final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA> {
114public:
115 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
116 using EquilibriumF = typename DYNAMICS::EquilibriumF;
117
118 using parameters = typename DYNAMICS::parameters;
119
120 template <typename NEW_T>
122 NEW_T, DESCRIPTOR,
123 typename DYNAMICS::template exchange_value_type<NEW_T>,
124 MOMENTA
125 >;
126
127 template <typename M>
129
130 std::type_index id() override {
132 };
133
135 return block.template getData<OperatorParameters<CombinedAdvectionDiffusionRLBdynamics>>();
136 }
137
138 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
140 V jNeq[DESCRIPTOR::d] { };
141
142 const V rho = MomentaF().computeRho(cell);
143 const auto u = cell.template getField<descriptors::VELOCITY>();
144 MomentaF().computeJ(cell, jNeq);
145
146 for (int iD = 0; iD < DESCRIPTOR::d; ++iD) {
147 jNeq[iD] -= u[iD] * rho;
148 }
149
150 V fEq[DESCRIPTOR::q] { };
151 EquilibriumF().compute(cell, rho, u, fEq);
152 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
153 cell[iPop] = fEq[iPop] + equilibrium<DESCRIPTOR>::template fromJneqToFneq<V>(iPop, jNeq);
154 }
155
156 return typename DYNAMICS::CollisionO().apply(cell, parameters);
157 };
158
159 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
160 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
161 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
162 }
163 };
164
165 std::string getName() const override {
166 return "CombinedAdvectionDiffusionRLBdynamics<" + MomentaF().getName() + ">";
167 };
168
169};
170
171// ========= the BGK advection diffusion dynamics ========//
173template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
175 T,DESCRIPTOR,
176 MOMENTA,
180>;
181
182
183// ========= the TRT advection diffusion dynamics ========//
185template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
187 T,DESCRIPTOR,
188 MOMENTA,
192>;
193
194
195// ======= BGK advection diffusion dynamics with source term ======//
196// following Seta, T. (2013). Implicit temperature-correction-based
197// immersed-boundary thermal lattice Boltzmann method for the simulation
198// of natural convection. Physical Review E, 87(6), 063304.
199template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
201 T,DESCRIPTOR,
202 momenta::Tuple<
203 momenta::SourcedDensity<typename MOMENTA::density>,
204 typename MOMENTA::momentum,
205 typename MOMENTA::stress,
206 typename MOMENTA::definition
207 >
208> {
209 using MomentaF = typename momenta::Tuple<
211 typename MOMENTA::momentum,
212 typename MOMENTA::stress,
213 typename MOMENTA::definition
214 >::template type<DESCRIPTOR>;
215 using EquilibriumF = typename equilibria::FirstOrder::template type<DESCRIPTOR,MOMENTA>;
216
218
219 template <typename NEW_T>
221 NEW_T, DESCRIPTOR,
222 MOMENTA
223 >;
224
225 template<typename M>
227
228 std::type_index id() override {
230 };
231
233 return block.template getData<OperatorParameters<SourcedAdvectionDiffusionBGKdynamics>>();
234 }
235
236 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
238 const auto u = cell.template getField<descriptors::VELOCITY>();
239 const V temperature = MomentaF().computeRho(cell);
240 const V omega = parameters.template get<descriptors::OMEGA>();
241
242 const V uSqr = lbm<DESCRIPTOR>::adeBgkCollision(cell, temperature, u, omega);
243 const V sourceMod = cell.template getField<descriptors::SOURCE>() * (V{1} - V{0.5} * omega);
244
245 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
246 cell[iPop] += sourceMod * descriptors::t<T,DESCRIPTOR>(iPop);
247 }
248
249 return {temperature, uSqr};
250 };
251
252 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
253 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
254 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
255 }
256 };
257
258 std::string getName() const override {
259 return "SourcedAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
260 };
261};
262
263
264// ======= BGK advection diffusion dynamics with source term ======//
265// following Seta, T. (2013). Implicit temperature-correction-based
266// immersed-boundary thermal lattice Boltzmann method for the simulation
267// of natural convection. Physical Review E, 87(6), 063304.
268template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
270 T,DESCRIPTOR,
271 momenta::Tuple<
272 momenta::SourcedDensity<typename MOMENTA::density>,
273 typename MOMENTA::momentum,
274 typename MOMENTA::stress,
275 typename MOMENTA::definition
276 >
277> {
278 using MomentaF = typename momenta::Tuple<
280 typename MOMENTA::momentum,
281 typename MOMENTA::stress,
282 typename MOMENTA::definition
283 >::template type<DESCRIPTOR>;
284 using EquilibriumF = typename equilibria::FirstOrder::template type<DESCRIPTOR,MOMENTA>;
285
287
288 constexpr static bool is_vectorizable = false;
289
290 template <typename NEW_T>
292
293 template<typename M>
295
296 std::type_index id() override {
298 };
299
301 return block.template getData<OperatorParameters<SourcedLimitedAdvectionDiffusionBGKdynamics>>();
302 }
303
304 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
306 const auto u = cell.template getField<descriptors::VELOCITY>();
307 V temperature = MomentaF().computeRho(cell);
308 if (temperature < V{1.e-8}) temperature = V{1.e-8};
309 const V omega = cell.template getField<descriptors::OMEGA>();
310
311 const V uSqr = lbm<DESCRIPTOR>::adeBgkCollision(cell, temperature, u, omega);
312 const V sourceMod = cell.template getField<descriptors::SOURCE>() * (V{1} - V{0.5} * omega);
313
314 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
315 cell[iPop] += sourceMod * descriptors::t<T,DESCRIPTOR>(iPop);
316 }
317
318 return {temperature, uSqr};
319 };
320
321 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
322 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
323 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
324 }
325 };
326
327 std::string getName() const override {
328 return "SourcedLimitedAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
329 };
330};
331
332// ======= BGK advection diffusion dynamics for solid-liquid phase change ======//
333// following Huang, R. (2015). Phase interface effects in the total
334// enthalpy-based lattice Boltzmann model for solid–liquid phase change.
335// Journal of Computational Physics, 294, 345-362.
336template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
338 static constexpr bool is_vectorizable = false;
339
340 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
341 using EquilibriumF = typename equilibria::FirstOrder::template type<DESCRIPTOR,MOMENTA>;
342
352 >;
353
354 template <typename NEW_T>
356
357 template<typename M>
359
360 std::type_index id() override {
362 };
363
365 return block.template getData<OperatorParameters<TotalEnthalpyAdvectionDiffusionBGKdynamics>>();
366 }
367
368 template<typename V, typename PARAMETERS, typename ENTHALPY>
369 V computeTemperature(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const any_platform
370 {
371 using namespace TotalEnthalpy;
372
373 const V cp_s = parameters.template get<CP_S>();
374 const V cp_l = parameters.template get<CP_L>();
375 const V T_s = parameters.template get<T_S>();
376 const V T_l = parameters.template get<T_L>();
377 const V l = parameters.template get<L>();
378 const V H_s = cp_s * T_s;
379 const V H_l = cp_l * T_l + l;
380 V temperature{};
381
382 if (enthalpy <= H_s) {
383 temperature = T_s - (H_s - enthalpy) / cp_s;
384 }
385 else if (enthalpy >= H_l) {
386 temperature = T_l + (enthalpy - H_l) / cp_l;
387 }
388 else {
389 temperature = (H_l - enthalpy) / (H_l - H_s) * T_s + (enthalpy - H_s) / (H_l - H_s) * T_l;
390 }
391 return temperature;
392 }
393
394 template<typename V, typename PARAMETERS, typename ENTHALPY>
395 V computeLiquidFraction(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const any_platform
396 {
397 using namespace TotalEnthalpy;
398
399 const V cp_s = parameters.template get<CP_S>();
400 const V cp_l = parameters.template get<CP_L>();
401 const V T_s = parameters.template get<T_S>();
402 const V T_l = parameters.template get<T_L>();
403 const V l = parameters.template get<L>();
404 const V H_s = cp_s * T_s;
405 const V H_l = cp_l * T_l + l;
406 V liquid_fraction{};
407
408 if (enthalpy <= H_s) {
409 liquid_fraction = 0.;
410 }
411 else if (enthalpy >= H_l) {
412 liquid_fraction = 1.;
413 }
414 else {
415 liquid_fraction = (enthalpy - H_s) / l;
416 }
417 return liquid_fraction;
418 }
419
420 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
421 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
422 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
423 }
424 };
425
426 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
428 using namespace TotalEnthalpy;
429
430 const V lambda_s = parameters.template get<LAMBDA_S>();
431 const V lambda_l = parameters.template get<LAMBDA_L>();
432 const V cp_s = parameters.template get<CP_S>();
433 const V cp_l = parameters.template get<CP_L>();
434 const V cp_ref = V{2} * cp_s * cp_l / (cp_s + cp_l);
435
436 const V enthalpy = MomentaF().computeRho( cell );
437 const V temperature = computeTemperature<V>( parameters, enthalpy );
438 const V liquid_fraction = computeLiquidFraction<V>( parameters, enthalpy );
439 const V lambda = (V{1} - liquid_fraction) * lambda_s + liquid_fraction * lambda_l;
440 const V cp = (V{1} - liquid_fraction) * cp_s + liquid_fraction * cp_l;
441 const V omega = V{1} / ( lambda / cp_ref * descriptors::invCs2<T,DESCRIPTOR>() + V{0.5} );
442
443 const auto u = cell.template getFieldPointer<descriptors::VELOCITY>();
444
445 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
446
447 const V f_eq = enthalpy - cp_ref * temperature
448 + cp * temperature * descriptors::t<T,DESCRIPTOR>(0) * ( cp_ref / cp
449 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
451 cell[0] *= V{1} - omega;
452 cell[0] += omega * f_eq;
453 for (int iPop=1; iPop < DESCRIPTOR::q; ++iPop) {
454 V c_u{};
455 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
456 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
457 }
458 const V f_eq = cp * temperature * descriptors::t<T,DESCRIPTOR>(iPop) * ( cp_ref / cp + descriptors::invCs2<T,DESCRIPTOR>() * c_u
460 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
462 cell[iPop] *= V{1} - omega;
463 cell[iPop] += omega * f_eq;
464 }
465 return {enthalpy, uSqr};
466 };
467
468 std::string getName() const override {
469 return "TotalEnthalpyAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
470 };
471};
472
473// ======= TRT advection diffusion dynamics for solid-liquid phase change ======//
474// following Huang, R. (2015). Phase interface effects in the total
475// enthalpy-based lattice Boltzmann model for solid–liquid phase change.
476// Journal of Computational Physics, 294, 345-362.
477template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
479 static constexpr bool is_vectorizable = false;
480
481 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
482 using EquilibriumF = typename equilibria::FirstOrder::template type<DESCRIPTOR,MOMENTA>;
483
494 >;
495
496 template <typename NEW_T>
498
499 template<typename M>
501
502 std::type_index id() override {
504 };
505
507 return block.template getData<OperatorParameters<TotalEnthalpyAdvectionDiffusionTRTdynamics>>();
508 }
509
510 template<typename V, typename PARAMETERS, typename ENTHALPY>
511 V computeTemperature(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const any_platform
512 {
513 using namespace TotalEnthalpy;
514
515 const V cp_s = parameters.template get<CP_S>();
516 const V cp_l = parameters.template get<CP_L>();
517 const V T_s = parameters.template get<T_S>();
518 const V T_l = parameters.template get<T_L>();
519 const V l = parameters.template get<L>();
520 const V H_s = cp_s * T_s;
521 const V H_l = cp_l * T_l + l;
522 V temperature{};
523
524 if (enthalpy <= H_s) {
525 temperature = T_s - (H_s - enthalpy) / cp_s;
526 }
527 else if (enthalpy >= H_l) {
528 temperature = T_l + (enthalpy - H_l) / cp_l;
529 }
530 else {
531 temperature = (H_l - enthalpy) / (H_l - H_s) * T_s + (enthalpy - H_s) / (H_l - H_s) * T_l;
532 }
533 return temperature;
534 }
535
536 template<typename V, typename PARAMETERS, typename ENTHALPY>
537 V computeLiquidFraction(const PARAMETERS& parameters, const ENTHALPY& enthalpy) const any_platform
538 {
539 using namespace TotalEnthalpy;
540
541 const V cp_s = parameters.template get<CP_S>();
542 const V cp_l = parameters.template get<CP_L>();
543 const V T_s = parameters.template get<T_S>();
544 const V T_l = parameters.template get<T_L>();
545 const V l = parameters.template get<L>();
546 const V H_s = cp_s * T_s;
547 const V H_l = cp_l * T_l + l;
548 V liquid_fraction{};
549
550 if (enthalpy <= H_s) {
551 liquid_fraction = 0.;
552 }
553 else if (enthalpy >= H_l) {
554 liquid_fraction = 1.;
555 }
556 else {
557 liquid_fraction = (enthalpy - H_s) / l;
558 }
559 return liquid_fraction;
560 }
561
562 template<typename V, typename PARAMETERS, typename RHO, typename U>
563 V computeEquilibrium(int iPop, const PARAMETERS& parameters, RHO& rho, U& u) const any_platform
564 {
565 using namespace TotalEnthalpy;
566
567 const V temperature = computeTemperature<V>(parameters, rho);
568 const V liquid_fraction = computeLiquidFraction<V>(parameters, rho);
569
570 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
571 const V cp_s = parameters.template get<CP_S>();
572 const V cp_l = parameters.template get<CP_L>();
573 const V cp = (V{1} - liquid_fraction) * cp_s + liquid_fraction * cp_l;
574 const V cp_ref = V{2} * cp_s * cp_l / (cp_s + cp_l);
575
576 V c_u{};
577 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
578 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
579 }
580
581 V f_eq{};
582 if (iPop == 0) {
583 f_eq = rho - cp_ref * temperature
584 + cp * temperature * descriptors::t<T,DESCRIPTOR>(0) * ( cp_ref / cp
585 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
587 }
588 else {
589 f_eq = cp * temperature * descriptors::t<T,DESCRIPTOR>(iPop) * ( cp_ref / cp + descriptors::invCs2<T,DESCRIPTOR>() * c_u
591 - descriptors::invCs2<T,DESCRIPTOR>() * V{0.5} * uSqr )
593 }
594
595 return f_eq;
596 }
597
598 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
600 using namespace TotalEnthalpy;
601
602 const V lambda_s = parameters.template get<LAMBDA_S>();
603 const V lambda_l = parameters.template get<LAMBDA_L>();
604 const V cp_s = parameters.template get<CP_S>();
605 const V cp_l = parameters.template get<CP_L>();
606 const V cp_ref = V{2} * cp_s * cp_l / (cp_s + cp_l);
607
608 const V enthalpy = MomentaF().computeRho( cell );
609 const V liquid_fraction = computeLiquidFraction<V>( parameters, enthalpy );
610 const V lambda = (V{1} - liquid_fraction) * lambda_s + liquid_fraction * lambda_l;
611 const V omega = V{1} / ( lambda / cp_ref * descriptors::invCs2<T,DESCRIPTOR>() + V{0.5} );
612 const V magic_parameter = parameters.template get<collision::TRT::MAGIC>();
613 const V omega2 = V{1} / (magic_parameter/(V{1}/omega-V{0.5})+V{0.5});
614
615 const auto u = cell.template getField<descriptors::VELOCITY>();
616
617 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
618
619 V fPlus[DESCRIPTOR::q], fMinus[DESCRIPTOR::q] { };
620 V fEq[DESCRIPTOR::q], fEqPlus[DESCRIPTOR::q], fEqMinus[DESCRIPTOR::q] { };
621
622 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
623 fPlus[iPop] = 0.5 * ( cell[iPop] + cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
624 fMinus[iPop] = 0.5 * ( cell[iPop] - cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
625 fEq[iPop] = computeEquilibrium<V>(iPop, parameters, enthalpy, u);
626 }
627
628 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
629 fEqPlus[iPop] = 0.5 * ( fEq[iPop] + fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
630 fEqMinus[iPop] = 0.5 * ( fEq[iPop] - fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
631 }
632
633 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
634 cell[iPop] -= omega2 * (fPlus[iPop] - fEqPlus[iPop]) + omega * (fMinus[iPop] - fEqMinus[iPop]);
635 }
636
637 return {enthalpy, uSqr};
638 };
639
640 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
641 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
642 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
643 }
644 };
645
646 std::string getName() const override {
647 return "TotalEnthalpyAdvectionDiffusionTRTdynamics<" + MomentaF().getName() + ">";
648 };
649};
650
651namespace descriptors {
652
654
655}
656
657// ======= BGK advection diffusion dynamics for phase field equation ======//
658// following Fakhari, Abbas, et al. (2017). Improved locality of the phase-field
659// lattice-Boltzmann model for immiscible fluids at high density ratios.
660// Physical Review E 96.5, 053301.
661template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
663 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
664 using EquilibriumF = typename equilibria::FirstOrder::template type<DESCRIPTOR,momenta::BulkTuple>;
665
667
668 template <typename NEW_T>
670
671 template<typename M>
673
674 std::type_index id() override {
676 };
677
679 return block.template getData<OperatorParameters<PhaseFieldAdvectionDiffusionBGKdynamics>>();
680 }
681
682 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
683 CellStatistic<V> collide(CELL& cell, PARAMETERS& parameters) {
684 const V omega = parameters.template get<descriptors::OMEGA>();
685 const V interface_thickness = parameters.template get<descriptors::INTERFACE_THICKNESS>();
686
687 const V phi = MomentaF().computeRho( cell );
688 const auto u = cell.template getField<descriptors::VELOCITY>();
689 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
690 const auto mobility = (V{1} / omega - V{0.5}) / descriptors::invCs2<V,DESCRIPTOR>();
691
692 const auto n = cell.template getFieldPointer<descriptors::INTERPHASE_NORMAL>();
693 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
694 V c_u{};
695 V c_n{};
696 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
697 c_u += descriptors::c<DESCRIPTOR>(iPop,iD)*u[iD];
698 c_n += descriptors::c<DESCRIPTOR>(iPop,iD)*n[iD];
699 }
700 V f_eq = equilibrium<DESCRIPTOR>::firstOrder(iPop, phi, u);
702 * (V{4} * phi * (V{1} - phi) / interface_thickness) * c_n;
703
704 cell[iPop] *= V{1} - omega;
705 cell[iPop] += omega * f_eq;
706 }
707
708 return {phi, uSqr};
709 };
710
711 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
712 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
713 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
714 }
715 };
716
717 std::string getName() const override {
718 return "PhaseFieldAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
719 };
720};
721
722// ========= the BGK advection diffusion Stokes drag dynamics ========//
724template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
725struct ParticleAdvectionDiffusionBGKdynamics final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA> {
726public:
727 using MomentaF = typename momenta::Tuple<
728 typename MOMENTA::density,
730 typename MOMENTA::stress,
731 typename MOMENTA::definition
732 >::template type<DESCRIPTOR>;
733 using EquilibriumF = typename equilibria::FirstOrder::template type<DESCRIPTOR,MOMENTA>;
734
736
737 template <typename NEW_T>
739
740 template <typename M>
742
743 std::type_index id() override {
745 };
746
748 return block.template getData<OperatorParameters<ParticleAdvectionDiffusionBGKdynamics>>();
749 }
750
751 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
753 const V omega = parameters.template get<descriptors::OMEGA>();
754 const auto time = parameters.template get<descriptors::LATTICE_TIME>();
755 const auto u = (time % 2 == 0) ? cell.template getField<descriptors::VELOCITY>()
756 : cell.template getField<descriptors::VELOCITY2>();
757 V rho = MomentaF().computeRho(cell);
758 V uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
759 return {rho, uSqr};
760 };
761
762 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
763 for ( int iPop = 0; iPop < DESCRIPTOR::q; iPop++ ) {
764 fEq[iPop] = equilibrium<DESCRIPTOR>::firstOrder(iPop, rho, u);
765 }
766 };
767
768 std::string getName() const override {
769 return "ParticleAdvectionDiffusionBGKdynamics<" + MomentaF().getName() + ">";
770 };
771
772};
773
774//==================================================================//
775//============= BGK Model for Advection diffusion anisotropic ===//
776//==================================================================//
777template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
778struct RTLBMdynamicsMcHardy final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA>
779{
780 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
781 using EquilibriumF = typename equilibria::ZerothOrder::template type<DESCRIPTOR,MOMENTA>;
783
784 template <typename NEW_T>
786
787 template<typename M>
789
790 std::type_index id() override {
791 return typeid(RTLBMdynamicsMcHardy);
792 };
793
795 return block.template getData<OperatorParameters<RTLBMdynamicsMcHardy>>();
796 }
797
798 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
800 const V absorption = parameters.template get<Light::ABSORPTION>();
801 const V scattering = parameters.template get<Light::SCATTERING>();
802 auto anisoMatrix = parameters.template get<Light::ANISOMATRIX>();
803 V irradiance = MomentaF().computeRho(cell);
805 for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) {
806 for ( int jPop = 0; jPop < DESCRIPTOR::q; ++jPop ) {
807 V fFull = cell[jPop] + descriptors::t<V,DESCRIPTOR>(jPop);
808 feq[iPop] += fFull * anisoMatrix[jPop+iPop];
809 }
810 feq[iPop] *= descriptors::t<V,DESCRIPTOR>(iPop);
811 }
812
813 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
815 V fFull = cell[iPop] + descriptors::t<V,DESCRIPTOR>(iPop);
816 cell[iPop] = fFull
817 - normC * (absorption + scattering) * ( fFull- feq[iPop] )
818 - absorption * normC * fFull
820 }
821
822 return {irradiance, V(0)};
823 };
824
825 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T irradiance, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
826 EquilibriumF().compute(cell, irradiance, u, fEq);
827 };
828
829 std::string getName() const override {
830 return "RTLBMdynamicsMcHardy<" + MomentaF().getName() + ">";
831 };
832};
833
834
835//=======================================================================================//
836//======= BGK Model for Advection diffusion anisotropic with Runge Kutta scheme =========//
837//=======================================================================================//
838
839template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
840struct RTLBMdynamicsMcHardyRK final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA>
841{
842 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
843 using EquilibriumF = typename equilibria::ZerothOrder::template type<DESCRIPTOR,MOMENTA>;
845
846 template <typename NEW_T>
848
849 template<typename M>
851
852 std::type_index id() override {
853 return typeid(RTLBMdynamicsMcHardyRK);
854 };
855
857 return block.template getData<OperatorParameters<RTLBMdynamicsMcHardyRK>>();
858 }
859
860 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
862 const V absorption = parameters.template get<Light::ABSORPTION>();
863 const V scattering = parameters.template get<Light::SCATTERING>();
864 auto anisoMatrix = parameters.template get<Light::ANISOMATRIX>();
865 V irradiance = MomentaF().computeRho(cell);
867 Vector<V, DESCRIPTOR::q> f_pre_collision;
868
869 // calculate f_pre_collision
870 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
871 f_pre_collision[iPop] = cell[iPop] + descriptors::t<V,DESCRIPTOR>(iPop);
872 }
873
874 // preparation for RK
875 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
876 cell[iPop] += descriptors::t<V,DESCRIPTOR>(iPop);
877 }
878
879 // Runge-Kutta 4
880 computeEquilibriumAniso(cell, feq, anisoMatrix);
881 auto k1 = doCollision(cell, feq, absorption, scattering);
882
883 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
884 cell[iPop] = f_pre_collision[iPop] + 0.5 * k1[iPop];
885 }
886
887 computeEquilibriumAniso(cell, feq, anisoMatrix);
888 auto k2 = doCollision(cell, feq, absorption, scattering);
889
890 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
891 cell[iPop] = f_pre_collision[iPop] + 0.5 * k2[iPop];
892 }
893
894 computeEquilibriumAniso(cell, feq, anisoMatrix);
895 auto k3 = doCollision(cell, feq, absorption, scattering);
896
897 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
898 cell[iPop] = f_pre_collision[iPop] + k3[iPop];
899 }
900
901 computeEquilibriumAniso(cell, feq, anisoMatrix);
902 auto k4 = doCollision(cell, feq, absorption, scattering);
903
904 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
905 cell[iPop] = f_pre_collision[iPop] + (1.0 / 6.0) * (k1[iPop] + 2 * k2[iPop] + 2 * k3[iPop] + k4[iPop])
907 }
908
909 return {irradiance, V(0)};
910 };
911
912 template <typename CELL, typename MATRIX, typename V=typename CELL::value_t>
913 void computeEquilibriumAniso(CELL& cell, Vector<V, DESCRIPTOR::q>& feq, MATRIX& anisoMatrix) const {
914// feq.fill(V());
915 for (int i = 0; i < DESCRIPTOR::q; ++i) {
916 feq[i] = V();
917 }
918 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
919 for (int jPop = 0; jPop < DESCRIPTOR::q; ++jPop) {
920 feq[iPop] += cell[jPop] * anisoMatrix[jPop+iPop];
921 }
922 feq[iPop] *= descriptors::t<V, DESCRIPTOR>(iPop);
923 }
924 };
925
926 template <typename CELL, typename VECTOR, typename V=typename CELL::value_t>
927 VECTOR doCollision(CELL& cell, VECTOR& feq, V absorption, V scattering) const {
928 VECTOR k;
929 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
931 V fFull = cell[iPop];
932 k[iPop] = -normC * (absorption + scattering) * fFull
933 + normC * scattering * feq[iPop];
934 }
935 return k;
936 };
937
938 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T irradiance, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
939 EquilibriumF().compute(cell, irradiance, u, fEq);
940 };
941
942 std::string getName() const override {
943 return "RTLBMdynamicsMcHardyRK<" + MomentaF().getName() + ">";
944 };
945};
946
947
948
949
950// ========= the MRT advection diffusion dynamics ========//
953template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::AdvectionDiffusionBulkTuple>
955 T,DESCRIPTOR,
956 MOMENTA,
960>;
961
962template <typename T, typename DESCRIPTOR>
964 T, DESCRIPTOR,
968>;
969} // namespace olb
970
971#endif
std::type_index id() override
Expose unique type-identifier for RTTI.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
std::string getName() const override
Return human-readable name.
Highest-level interface to read-only Cell data.
Definition interface.h:36
Plain old scalar vector.
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
constexpr int opposite(unsigned iPop) any_platform
Definition functions.h:95
Tuple< BulkDensity, BulkMomentum, BulkStress, DefineToNEq > BulkTuple
Standard computation of momenta from the populations in the bulk.
Definition aliases.h:41
auto normSqr(const ARRAY_LIKE &u) any_platform
Compute norm square of a d-dimensional vector.
Definition util.h:145
T norm(const std::vector< T > &a)
l2 norm of a vector of arbitrary length
Top level namespace for all of OpenLB.
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:77
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:45
static constexpr unsigned size()
static constexpr auto isValid(FieldD< T, DESCRIPTOR, FIELD > value)
static constexpr auto getInitialValue()
static constexpr unsigned size()
This approach contains a slight error in the diffusion term.
std::type_index id() override
Expose unique type-identifier for RTTI.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
typename momenta::Tuple< typename MOMENTA::density, momenta::FixedVelocityMomentum, typename MOMENTA::stress, typename MOMENTA::definition >::template type< DESCRIPTOR > MomentaF
typename equilibria::FirstOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
std::string getName() const override
Return human-readable name.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
typename equilibria::FirstOrder::template type< DESCRIPTOR, momenta::BulkTuple > EquilibriumF
CellStatistic< V > collide(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.
std::string getName() const override
Return human-readable name.
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
std::type_index id() override
Expose unique type-identifier for RTTI.
void computeEquilibriumAniso(CELL &cell, Vector< V, DESCRIPTOR::q > &feq, MATRIX &anisoMatrix) const
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T irradiance, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
VECTOR doCollision(CELL &cell, VECTOR &feq, V absorption, V scattering) const
typename equilibria::ZerothOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
std::string getName() const override
Return human-readable name.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
RTLBMdynamicsMcHardyRK(T latticeAbsorption, T latticeScattering, std::array< std::array< T, DESCRIPTOR::q >, DESCRIPTOR::q > &anisoMatrix)
Constructor.
Solves RTE according Christopher McHardy et al 2016.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
RTLBMdynamicsMcHardy(T latticeAbsorption, T latticeScattering, std::array< std::array< T, DESCRIPTOR::q >, DESCRIPTOR::q > &anisoMatrix)
Constructor.
std::type_index id() override
Expose unique type-identifier for RTTI.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T irradiance, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
typename equilibria::ZerothOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
std::string getName() const override
Return human-readable name.
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
typename equilibria::FirstOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
CellStatistic< V > collide(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
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
std::string getName() const override
Return human-readable name.
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
std::type_index id() override
Expose unique type-identifier for RTTI.
std::string getName() const override
Return human-readable name.
typename equilibria::FirstOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
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.
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
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
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
V computeLiquidFraction(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const any_platform
typename MOMENTA::template type< DESCRIPTOR > MomentaF
std::string getName() const override
Return human-readable name.
V computeTemperature(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const any_platform
typename equilibria::FirstOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) 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.
typename equilibria::FirstOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
V computeEquilibrium(int iPop, const PARAMETERS &parameters, RHO &rho, U &u) const any_platform
void computeEquilibrium(ConstCell< T, DESCRIPTOR > &cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override
Return iPop equilibrium for given first and second momenta.
V computeLiquidFraction(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const any_platform
typename MOMENTA::template type< DESCRIPTOR > MomentaF
std::string getName() const override
Return human-readable name.
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
V computeTemperature(const PARAMETERS &parameters, const ENTHALPY &enthalpy) const 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.
Base of a field whose size is defined by [C_0,C_1,C_2]^T * [1,D,Q].
Definition fields.h:52
Dynamics constructed as a tuple of momenta, equilibrium and collision.
Definition interface.h:308
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:384
static V bgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
BGK collision step.
Definition lbm.h:372
Plain wrapper for list of types.
Definition meta.h:276
The velocity is stored in the external field descriptors::VELOCITY.
Definition elements.h:727
Unit conversion handling – header file.