OpenLB 1.8.1
Loading...
Searching...
No Matches
porousBGKdynamics.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2021 Adrian Kummerlaender, Nando Suntoyo
4 *
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 POROUS_BGK_DYNAMICS_H
26#define POROUS_BGK_DYNAMICS_H
27
28#include "interface.h"
29#include "collision.h"
31
32namespace olb {
33
35template <typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
37 T, DESCRIPTOR,
41>;
42
43
44namespace particles {
45
46template <typename DESCRIPTOR, typename CELL,
47 typename V = typename CELL::value_t>
48inline void resetParticleRelatedFields(CELL& cell) noexcept
49{
50 if constexpr (DESCRIPTOR::template provides<descriptors::POROSITY>()) {
51 cell.template setField<descriptors::POROSITY>(
52 descriptors::POROSITY::template getInitialValue<V,DESCRIPTOR>() );
53 }
54 if constexpr (DESCRIPTOR::template provides<
56 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(
57 descriptors::VELOCITY_DENOMINATOR::template getInitialValue<V,DESCRIPTOR>() );
58 }
59 if constexpr (DESCRIPTOR::template provides<
61 cell.template setField<descriptors::VELOCITY_NUMERATOR>(
62 descriptors::VELOCITY_NUMERATOR::template getInitialValue<V,DESCRIPTOR>() );
63 }
64 if constexpr (DESCRIPTOR::template provides<descriptors::VELOCITY_SOLID>()) {
65 cell.template setField<descriptors::VELOCITY_SOLID>(
66 descriptors::VELOCITY_SOLID::template getInitialValue<V,DESCRIPTOR>() );
67 }
68}
69
70template <typename DESCRIPTOR, typename CELL,
71 typename V = typename CELL::value_t>
72inline void resetParticleContactRelatedFields(CELL& cell) noexcept
73{
74 if constexpr (DESCRIPTOR::template provides<
76 cell.template setField<descriptors::CONTACT_DETECTION>(
77 descriptors::CONTACT_DETECTION::template getInitialValue<V,DESCRIPTOR>() );
78 }
79}
80
81template <typename DESCRIPTOR, typename CELL,
82 typename V = typename CELL::value_t>
88
89} // namespace particles
90
91namespace collision {
92
93/* Implementation of the BGK collision for moving porous media (HLBM approach).
94 * As this scheme requires additionla data stored in an external field,
95 * it is meant to be used along with a PorousParticle descriptor.
96 * \param omega Lattice relaxation frequency
97 * \param momenta A standard object for the momenta computation
98 */
99template <typename COLLISION, bool isStatic=false>
102
103 static constexpr bool is_vectorizable = false;
104
105 static std::string getName() {
106 return "PorousParticle<" + COLLISION::getName() + ">" ;
107 }
108
109 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
110 struct type {
111 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
112 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
113 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
114
115 constexpr static bool is_vectorizable = false;
116
117 template <typename CELL, typename pVELOCITY, typename V=typename CELL::value_t>
118 void calculate (CELL& cell, pVELOCITY& pVelocity) {
119 if constexpr (isStatic) {
120 for (int i=0; i<DESCRIPTOR::d; i++) {
121 pVelocity[i] -= (1.-(cell.template getField<descriptors::POROSITY>())) * pVelocity[i];
122 }
123 } else {
124 for (int i=0; i<DESCRIPTOR::d; i++) {
125 pVelocity[i] += (1.-cell.template getField<descriptors::POROSITY>())
126 * (cell.template getFieldComponent<descriptors::VELOCITY_NUMERATOR>(i)
127 / cell.template getField<descriptors::VELOCITY_DENOMINATOR>() - pVelocity[i]);
128 }
129 }
130 }
131
132 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
133 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
134 V rho, u[DESCRIPTOR::d];
135 MomentaF().computeRhoU(cell, rho, u);
136
137 auto statistic = CollisionO().apply(cell, parameters);
138
139 V velDenominator = cell.template getFieldComponent<descriptors::VELOCITY_DENOMINATOR>(0);
140
141 // use Kuperstokh forcing by default
142 V uPlus[DESCRIPTOR::d]{ };
143 V diff[DESCRIPTOR::q]{ };
144 V fEqPlus[DESCRIPTOR::q]{ };
145 V fEq[DESCRIPTOR::q]{ };
146
147 if (velDenominator > std::numeric_limits<V>::epsilon()) {
148 for (int iDim=0; iDim<DESCRIPTOR::d; ++iDim) {
149 uPlus[iDim] = u[iDim];
150 }
151 calculate(cell, uPlus);
152 if constexpr (!isStatic) {
154 }
155
156 EquilibriumF().compute(cell, rho, uPlus, fEqPlus);
157 EquilibriumF().compute(cell, rho, u, fEq);
158 for (int tmp_iPop=0; tmp_iPop < DESCRIPTOR::q; tmp_iPop++) {
159 diff[tmp_iPop] += fEqPlus[tmp_iPop] - fEq[tmp_iPop];
160 cell[tmp_iPop] += diff[tmp_iPop];
161 }
162 }
163
165
166 return statistic;
167 }
168 };
169};
170
171template <typename COLLISION>
174
175 static std::string getName() {
176 return "MovingPorosity<" + COLLISION::getName() + ">" ;
177 }
178
179 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
180 struct type {
181 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
182 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
183 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
184
185 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
188 MomentaF().computeU(cell, u);
189
190 auto statistic = CollisionO().apply(cell, parameters);
191
192 // use Kuperstokh forcing
193 Vector<V,DESCRIPTOR::d> uPlus = u;
194 uPlus += (V{1} - cell.template getField<descriptors::POROSITY>())
195 * (cell.template getField<descriptors::VELOCITY>() - uPlus);
196
197 // TODO replace by single EquilibriumF()::compute
198 V fEq[DESCRIPTOR::q] { };
199 V fEq2[DESCRIPTOR::q] { };
200 EquilibriumF().compute(cell, statistic.rho, u, fEq);
201 EquilibriumF().compute(cell, statistic.rho, uPlus, fEq2);
202 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
203 cell[iPop] += fEq2[iPop] - fEq[iPop];
204 }
205
206 return statistic;
207 }
208 };
209};
210
213template <typename COLLISION>
214struct PSM {
216
217 static constexpr bool is_vectorizable = false;
218
219 static std::string getName() {
220 return "PSM<" + COLLISION::getName() + ">" ;
221 }
222
223 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
224 struct type {
225 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
226 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
227 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
228
229 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
230 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
231 V rho, u[DESCRIPTOR::d];
232 const V epsilon = 1. - cell.template getField<descriptors::POROSITY>();
233 const V omega = parameters.template get<descriptors::OMEGA>();
234 const V paramA = V{1.} / omega - V{0.5};
235 MomentaF().computeRhoU(cell, rho, u);
236 // velocity at the boundary
237 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
238 if (epsilon < 1e-5) {
239 return CollisionO().apply(cell, parameters);
240 }
241 else {
242 // speed up paramB
243 V paramB = (epsilon * paramA) / ((1. - epsilon) + paramA);
244 // speed up paramC
245 V paramC = (1. - paramB);
246 V omega_s[DESCRIPTOR::q];
247 V cell_tmp[DESCRIPTOR::q];
248
249 V fEq[DESCRIPTOR::q] { };
250 V fEq_s[DESCRIPTOR::q] { };
251 EquilibriumF().compute(cell, rho, u, fEq);
252 EquilibriumF().compute(cell, rho, u_s, fEq_s);
253 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
254 cell_tmp[iPop] = cell[iPop];
256 //if constexpr (MODE == 2) {
257 omega_s[iPop] = (fEq_s[iPop] - cell[iPop]) + (V{1} - omega) * (cell[iPop] - fEq[iPop]);
258 //} else if constexpr (MODE == 3) {
259 // omega_s[iPop] = (cell[descriptors::opposite<DESCRIPTOR>(iPop)] - fEq_s[descriptors::opposite<DESCRIPTOR>(iPop)])
260 // - (cell[iPop] - fEq_s[iPop]);
261 //}
262 }
263 CollisionO().apply(cell, parameters);
264 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
265 cell[iPop] = cell_tmp[iPop] + paramC * (cell[iPop] - cell_tmp[iPop]);
266 cell[iPop] += paramB * omega_s[iPop];
267 }
268 for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
269 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
270 }
271 }
272
273 return {rho, util::normSqr<V,DESCRIPTOR::d>(u)};
274 }
275 };
276};
277
278// Implementation of the BGK collision step for subgridscale particles
279// extended collision step, computes local drag in a given direction
280template <typename COLLISION>
283
284 static std::string getName() {
285 return "SubgridParticle<" + COLLISION::getName() + ">";
286 }
287
288 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
289 struct type {
290 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
291 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
292
293 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
294 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
295 V rho, u[DESCRIPTOR::d];
296 MomentaF().computeRhoU(cell, rho, u);
297 V porosity = cell.template getField<descriptors::POROSITY>();
298 auto extVelocity = cell.template getFieldPointer<descriptors::LOCAL_DRAG>();
299 // if (porosity[0] != 0) {
300 // cout << "extVelocity: " << extVelocity[0] << " " << extVelocity[1] << " " << extVelocity[2] << " " << std::endl;
301 // cout << "porosity: " << porosity[0] << std::endl;
302 // }
303 for (int i=0; i<DESCRIPTOR::d; i++) {
304 u[i] *= (1.-porosity);
305 u[i] += extVelocity[i];
306 }
307
308 V uSqr = CollisionO().apply(cell, parameters);
309
310 //statistics.incrementStats(rho, uSqr);
311 cell.template setField<descriptors::POROSITY>(0);
312 cell.template setField<descriptors::VELOCITY_NUMERATOR>(0);
313 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
314
315 return {rho, uSqr};
316 }
317 };
318};
319
320// Implementation of the BGK collision for Zeta-Field formulation (Geng2019)
323
324 static constexpr bool is_vectorizable = false;
325
326 static std::string getName() {
327 return "DBBParticleBGK";
328 }
329
330 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
331 struct type {
332 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
333 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
334
335 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
336 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
337 V rho, u[DESCRIPTOR::d],eta[DESCRIPTOR::q],uPlus[DESCRIPTOR::d],tmp_cell[(DESCRIPTOR::q+1)/2];
338 MomentaF().computeRhoU(cell, rho, u);
339 const V omega = parameters.template get<descriptors::OMEGA>();
340 V tmpMomentumLoss[DESCRIPTOR::d]{ };
341 auto velNumerator = cell.template getFieldPointer<descriptors::VELOCITY_NUMERATOR>();
342 auto zeta = cell.template getFieldPointer<descriptors::ZETA>();
343 auto velDenominator = cell.template getField<descriptors::VELOCITY_DENOMINATOR>();
344
345 if (velDenominator > 1) {
346 rho /= velDenominator;
347 }
348 for (int tmp_iPop=1; 2*tmp_iPop<DESCRIPTOR::q; tmp_iPop++) {
349 eta[tmp_iPop]=6.*descriptors::t<V,DESCRIPTOR>(tmp_iPop)*rho*(descriptors::c<DESCRIPTOR>(tmp_iPop,0)*(velNumerator[0])+descriptors::c<DESCRIPTOR>(tmp_iPop,1)*(velNumerator[1]));
350 tmp_cell[tmp_iPop]=(zeta[tmp_iPop]*(-cell[tmp_iPop]+cell[descriptors::opposite<DESCRIPTOR>(tmp_iPop)]+eta[tmp_iPop]));
351 cell[tmp_iPop]+=tmp_cell[tmp_iPop]/(1.+2.*(zeta[tmp_iPop]));
352 cell[descriptors::opposite<DESCRIPTOR>(tmp_iPop)]-=tmp_cell[tmp_iPop]/(1.+2.*(zeta[tmp_iPop]));
353 zeta[tmp_iPop] = 0.;
354 zeta[descriptors::opposite<DESCRIPTOR>(tmp_iPop)] = 0.;
355 }
356
357 cell.template setField<descriptors::POROSITY>(1.);
358 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
359
360 MomentaF().computeRhoU(cell, rho, uPlus);
361 V uPlusSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, uPlus, omega);
362
363 V diff[DESCRIPTOR::q] = {};
364 V fEqPlus[DESCRIPTOR::q] = {};
365 V fEq[DESCRIPTOR::q] = {};
366 EquilibriumF().compute(cell, rho, uPlus, fEqPlus);
367 EquilibriumF().compute(cell, rho, u, fEq);
368 for (int tmp_iPop=0; tmp_iPop<DESCRIPTOR::q; tmp_iPop++) {
369 diff[tmp_iPop] += fEqPlus[tmp_iPop] - fEq[tmp_iPop];
370
371 for (int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
372 tmpMomentumLoss[iDim] -= descriptors::c<DESCRIPTOR>(tmp_iPop,iDim) * diff[tmp_iPop];
373 }
374 }
375
376 for (int i_dim=0; i_dim<DESCRIPTOR::d; i_dim++) {
377 velNumerator[i_dim] = tmpMomentumLoss[i_dim];
378 }
379
380 return {rho, util::normSqr<V,DESCRIPTOR::d>(u)};
381 }
382 };
383};
384
385// Implementation of the HBGK collision step for a porosity model enabling
386// drag computation for many particles
387// including the Krause turbulence modell
388template <typename COLLISION>
389struct KrauseH {
391
392 static std::string getName(){
393 return "KrauseH<" + COLLISION::getName() + ">";
394 }
395
396 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
397 struct type {
398 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
399 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
400 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
401
402 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
403 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
404 V rho, u[DESCRIPTOR::d];
405 V newOmega[DESCRIPTOR::d];
406 V _fieldTmp[4];
407 _fieldTmp[0] = V{1};
408 _fieldTmp[1] = V{};
409 _fieldTmp[2] = V{};
410 _fieldTmp[3] = V{};
411
412 const V smagoConst = parameters.template get<collision::LES::SMAGORINSKY>();
413 V preFactor = smagoConst*smagoConst
415 * 2*util::sqrt(2);
416
417 MomentaF().computeRhoU(cell, rho, u);
418
419 // compute newOmega
420 V omega = parameters.template get<descriptors::OMEGA>();
421 V uSqr = u[0]*u[0];
422 for (int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
423 uSqr += u[iDim]*u[iDim];
424 }
426 V tau_mol = 1./omega;
427 V fEq[DESCRIPTOR::q] { };
428 EquilibriumF().compute(cell, rho, u, fEq);
429 for (int iPop=0; iPop<DESCRIPTOR::q; iPop++) {
430 V fNeq = util::fabs(cell[iPop] - fEq[iPop]);
432 V tau_turb = 0.5*(util::sqrt(tau_mol*tau_mol+(preFactor*fNeq))-tau_mol);
434 V tau_eff = tau_mol + tau_turb;
435 newOmega[iPop] = 1./tau_eff;
436 }
437 parameters.template set<descriptors::OMEGA>(newOmega);
438
439
440 V vel_denom = cell.template getField<descriptors::VELOCITY_DENOMINATOR>();
441 if (vel_denom > std::numeric_limits<V>::epsilon()) {
442 V porosity = cell.template getField<descriptors::POROSITY>(); // prod(1-smoothInd)
443 auto vel_num = cell.template getFieldPointer<descriptors::VELOCITY_NUMERATOR>();
444 porosity = 1.-porosity; // 1-prod(1-smoothInd)
445 for (int i=0; i<DESCRIPTOR::d; i++) {
446 u[i] += porosity * (vel_num[i] / vel_denom - u[i]);
447 }
448 }
449 uSqr = CollisionO().apply(cell, parameters);
450
451 cell.template setField<descriptors::POROSITY>(_fieldTmp[0]);
452 cell.template setField<descriptors::VELOCITY_NUMERATOR>({_fieldTmp[1], _fieldTmp[2]});
453 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(_fieldTmp[3]);
454
455 return {rho, uSqr};
456 }
457 };
458};
459
462template <typename COLLISION>
465
466 static std::string getName(){
467 return "SmallParticle<" + COLLISION::getName() + ">";
468 }
469
470 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
471 struct type {
472 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
473 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
474
475 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
476 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
477 V rho, u[DESCRIPTOR::d];
478 MomentaF().computeRhoU(cell, rho, u);
479 V porosity = cell.template getField<descriptors::POROSITY>();
480 auto localVelocity = cell.template getFieldPointer<descriptors::LOCAL_DRAG>();
481
482 //cout << porosity[0] << " " << localVelocity[0]<< " " << localVelocity[1]<< " " << localVelocity[2]<<std::endl;
483 for (int i=0; i<DESCRIPTOR::d; i++) {
484 u[i] *= porosity;
485 u[i] += localVelocity[i];
486 }
487 V uSqr = CollisionO().apply(cell, parameters);
488
489 return {rho, uSqr};
490 }
491 };
492};
493
494} // namespace collision
495
496namespace dynamics {
497
499 static std::string getName() {
500 return "ExposePorousParticleMomenta";
501 }
502
503 template <typename DESCRIPTOR, typename MOMENTA>
505
506 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
507 using combined_equilibrium = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
508
509 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
510 using combined_collision = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
511
512 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
513 using combined_parameters = typename COLLISION::parameters;
514};
515
516}
517
518
520template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
522 T, DESCRIPTOR,
523 MOMENTA,
527>;
528
530template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
532 T, DESCRIPTOR,
533 MOMENTA,
537>;
538
540template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
542 T, DESCRIPTOR,
543 MOMENTA,
546>;
547
548// BGK collision step for subgridscale particles
549template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
551 T, DESCRIPTOR,
552 MOMENTA,
555>;
556
557// BGK collision for Zeta-Field formulation (Geng2019)
558template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
560 T, DESCRIPTOR,
561 MOMENTA,
564>;
565
568template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
570 T, DESCRIPTOR,
571 MOMENTA,
574>;
575
577template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
579 T, DESCRIPTOR,
580 MOMENTA,
583>;
584
587template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
589 T,DESCRIPTOR,
590 MOMENTA,
593>;
594
597template<typename T, typename DESCRIPTOR>
598struct ForcedPSMBGKdynamics final : public dynamics::CustomCollision<T,DESCRIPTOR,momenta::ForcedPSMBulkTuple> {
599
600 using MomentaF = typename momenta::ForcedPSMBulkTuple::template type<DESCRIPTOR>;
601 using EquilibriumF = typename equilibria::SecondOrder::template type<DESCRIPTOR,momenta::ForcedPSMBulkTuple>;
602
604
605 constexpr static bool is_vectorizable = false;
606
607 template <typename NEW_T>
609
610 std::type_index id() override {
611 return typeid(ForcedPSMBGKdynamics);
612 }
613
615 return block.template getData<OperatorParameters<ForcedPSMBGKdynamics>>();
616 }
617
618 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
620 {
621 V omega = parameters.template get<descriptors::OMEGA>();
622 V rho, u[DESCRIPTOR::d], uSqr;
623 lbm<DESCRIPTOR>::computeRhoU(cell, rho, u);
624 auto force = cell.template getField<descriptors::FORCE>();
625 for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
626 u[iVel] += force[iVel] * V{0.5};
627 }
628 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
629
630 V epsilon = V{1} - cell.template getField<descriptors::POROSITY>();
631 if (epsilon < 1e-5) {
632 uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
633 lbm<DESCRIPTOR>::addExternalForce(cell, rho, u, omega, force);
634 }
635 else {
636 V paramA = V{1} / omega - V{0.5};
637 V paramB = (epsilon * paramA) / ((V{1} - epsilon) + paramA);
638 V paramC = (V{1} - paramB);
639
640 V omega_s[DESCRIPTOR::q];
641 V cell_tmp[DESCRIPTOR::q];
642
643 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
644 cell_tmp[iPop] = cell[iPop];
645 omega_s[iPop] = (equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u_s) - cell[iPop])
646 + (V{1} - omega) * (cell[iPop] - equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u));
647 }
648
649 uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
650 lbm<DESCRIPTOR>::addExternalForce(cell, rho, u, omega, force);
651
652 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
653 cell[iPop] = cell_tmp[iPop] + paramC * (cell[iPop] - cell_tmp[iPop]);
654 cell[iPop] += paramB * omega_s[iPop];
655 }
656 for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
657 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
658 }
660 }
661 return {rho, uSqr};
662 }
663
664 void computeEquilibrium(ConstCell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d], T fEq[DESCRIPTOR::q]) const override {
665 EquilibriumF().compute(cell, rho, u, fEq);
666 };
667
668 std::string getName() const override {
669 return "ForcedPSMBGKdynamics<" + MomentaF().getName() + ">";
670 };
671
672};
673
674}
675
676#endif
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
void resetParticleRelatedFields(CELL &cell) noexcept
void resetParticleContactRelatedFields(CELL &cell) noexcept
void resetAllParticleRelatedFields(CELL &cell) noexcept
Expr sqrt(Expr x)
Definition expr.cpp:225
auto normSqr(const ARRAY_LIKE &u) any_platform
Compute norm square of a d-dimensional vector.
Definition util.h:145
Expr fabs(Expr x)
Definition expr.cpp:230
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.
Return value of any collision.
Definition interface.h:45
Implementation of the Partially Saturated Method (PSM), see Krüger, Timm, et al.
typename equilibria::SecondOrder::template type< DESCRIPTOR, momenta::ForcedPSMBulkTuple > EquilibriumF
typename momenta::ForcedPSMBulkTuple::template type< DESCRIPTOR > MomentaF
CellStatistic< V > collide(CELL &cell, PARAMETERS &parameters) any_platform
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.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
static constexpr bool is_vectorizable
std::type_index id() override
Expose unique type-identifier for RTTI.
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename MOMENTA::template type< DESCRIPTOR > MomentaF
static constexpr bool is_vectorizable
typename meta::list< descriptors::OMEGA > parameters
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
static std::string getName()
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
typename MOMENTA::template type< DESCRIPTOR > MomentaF
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename meta::list< descriptors::OMEGA > parameters
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
typename MOMENTA::template type< DESCRIPTOR > MomentaF
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
Implementation of the Partially Saturated Method (PSM), see Krüger, Timm, et al.
typename meta::list< descriptors::OMEGA > parameters
static std::string getName()
static constexpr bool is_vectorizable
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
typename MOMENTA::template type< DESCRIPTOR > MomentaF
void calculate(CELL &cell, pVELOCITY &pVelocity)
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
static constexpr bool is_vectorizable
typename meta::list< descriptors::OMEGA > parameters
Compute dynamics parameter OMEGA locally using Smagorinsky LES model.
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
typename MOMENTA::template type< DESCRIPTOR > MomentaF
Implementation of the BGK collision step for a small particles enabling two way coupling.
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters)
typename meta::list< descriptors::OMEGA > parameters
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > combined_collision
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > combined_equilibrium
typename momenta::PorousParticle< MOMENTA >::template type< DESCRIPTOR > combined_momenta
typename COLLISION::parameters combined_parameters
Dynamics constructed as a tuple of momenta, equilibrium and collision.
Definition interface.h:308
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 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 computeRhoU(CELL &cell, RHO &rho, U &u) any_platform
Computation of hydrodynamic variables.
Definition lbm.h:301
Plain wrapper for list of types.
Definition meta.h:276