OpenLB 1.7
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 {
45template <typename DESCRIPTOR, typename CELL,
46 typename V = typename CELL::value_t>
47inline void resetParticleRelatedFields(CELL& cell) noexcept
48{
49 if constexpr (DESCRIPTOR::template provides<descriptors::POROSITY>()) {
50 cell.template setField<descriptors::POROSITY>(
51 descriptors::POROSITY::template getInitialValue<V,DESCRIPTOR>() );
52 }
53 if constexpr (DESCRIPTOR::template provides<
55 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(
56 descriptors::VELOCITY_DENOMINATOR::template getInitialValue<V,DESCRIPTOR>() );
57 }
58 if constexpr (DESCRIPTOR::template provides<
60 cell.template setField<descriptors::VELOCITY_NUMERATOR>(
61 descriptors::VELOCITY_NUMERATOR::template getInitialValue<V,DESCRIPTOR>() );
62 }
63 if constexpr (DESCRIPTOR::template provides<descriptors::VELOCITY_SOLID>()) {
64 cell.template setField<descriptors::VELOCITY_SOLID>(
65 descriptors::VELOCITY_SOLID::template getInitialValue<V,DESCRIPTOR>() );
66 }
67}
68
69template <typename DESCRIPTOR, typename CELL,
70 typename V = typename CELL::value_t>
71inline void resetParticleContactRelatedFields(CELL& cell) noexcept
72{
73 if constexpr (DESCRIPTOR::template provides<
75 cell.template setField<descriptors::CONTACT_DETECTION>(
76 descriptors::CONTACT_DETECTION::template getInitialValue<V,DESCRIPTOR>() );
77 }
78}
79
80template <typename DESCRIPTOR, typename CELL,
81 typename V = typename CELL::value_t>
82inline void resetAllParticleRelatedFields(CELL& cell) noexcept
83{
84 resetParticleRelatedFields<DESCRIPTOR,CELL,V>(cell);
85 resetParticleContactRelatedFields<DESCRIPTOR,CELL,V>(cell);
86}
87
88} // namespace particles
89
90namespace collision {
91
92/* Implementation of the BGK collision for moving porous media (HLBM approach).
93 * As this scheme requires additionla data stored in an external field,
94 * it is meant to be used along with a PorousParticle descriptor.
95 * \param omega Lattice relaxation frequency
96 * \param momenta A standard object for the momenta computation
97 */
98template <typename COLLISION, bool isStatic=false>
101
102 static constexpr bool is_vectorizable = false;
103
104 static std::string getName() {
105 return "PorousParticle<" + COLLISION::getName() + ">" ;
106 }
107
108 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
109 struct type {
110 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
111 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
112 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
113
114 constexpr static bool is_vectorizable = false;
115
116 template <typename CELL, typename pVELOCITY, typename V=typename CELL::value_t>
117 void calculate (CELL& cell, pVELOCITY& pVelocity) {
118 if constexpr (isStatic) {
119 for (int i=0; i<DESCRIPTOR::d; i++) {
120 pVelocity[i] -= (1.-(cell.template getField<descriptors::POROSITY>())) * pVelocity[i];
121 }
122 } else {
123 for (int i=0; i<DESCRIPTOR::d; i++) {
124 pVelocity[i] += (1.-cell.template getField<descriptors::POROSITY>())
125 * (cell.template getFieldComponent<descriptors::VELOCITY_NUMERATOR>(i)
126 / cell.template getField<descriptors::VELOCITY_DENOMINATOR>() - pVelocity[i]);
127 }
128 }
129 }
130
131 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
132 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
133 V rho, u[DESCRIPTOR::d];
134 MomentaF().computeRhoU(cell, rho, u);
135
136 auto statistic = CollisionO().apply(cell, parameters);
137
138 V velDenominator = cell.template getFieldComponent<descriptors::VELOCITY_DENOMINATOR>(0);
139
140 // use Kuperstokh forcing by default
141 V uPlus[DESCRIPTOR::d]{ };
142 V diff[DESCRIPTOR::q]{ };
143
144 if (velDenominator > std::numeric_limits<V>::epsilon()) {
145 for (int iDim=0; iDim<DESCRIPTOR::d; ++iDim) {
146 uPlus[iDim] = u[iDim];
147 }
148 calculate(cell, uPlus);
149 if constexpr (!isStatic) {
150 particles::resetParticleRelatedFields<DESCRIPTOR,CELL,V>(cell);
151 }
152
153 for (int tmp_iPop=0; tmp_iPop < DESCRIPTOR::q; tmp_iPop++) {
154 diff[tmp_iPop] += EquilibriumF().compute(tmp_iPop, rho, uPlus)
155 - EquilibriumF().compute(tmp_iPop, rho, u);
156 cell[tmp_iPop] += diff[tmp_iPop];
157 }
158 }
159
160 particles::resetParticleContactRelatedFields<DESCRIPTOR,CELL,V>(cell);
161
162 return statistic;
163 }
164 };
165};
166
169template <typename COLLISION>
170struct PSM {
172
173 static constexpr bool is_vectorizable = false;
174
175 static std::string getName() {
176 return "PSM<" + 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>
186 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
187 V rho, u[DESCRIPTOR::d];
188 const V epsilon = 1. - cell.template getField<descriptors::POROSITY>();
189 const V omega = parameters.template get<descriptors::OMEGA>();
190 const V paramA = V{1.} / omega - V{0.5};
191 MomentaF().computeRhoU(cell, rho, u);
192 // velocity at the boundary
193 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
194 if (epsilon < 1e-5) {
195 return CollisionO().apply(cell, parameters);
196 }
197 else {
198 // speed up paramB
199 V paramB = (epsilon * paramA) / ((1. - epsilon) + paramA);
200 // speed up paramC
201 V paramC = (1. - paramB);
202 V omega_s[DESCRIPTOR::q];
203 V cell_tmp[DESCRIPTOR::q];
204 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
205 cell_tmp[iPop] = cell[iPop];
207 //if constexpr (MODE == 2) {
208 omega_s[iPop] = (EquilibriumF().compute(iPop, rho, u_s) - cell[iPop])
209 + (V{1} - omega) * (cell[iPop] - EquilibriumF().compute(iPop, rho, u));
210 //} else if constexpr (MODE == 3) {
211 // omega_s[iPop] = (cell[descriptors::opposite<DESCRIPTOR>(iPop)] - EquilibriumF().compute(descriptors::opposite<DESCRIPTOR>(iPop), rho, u_s))
212 // - (cell[iPop] - EquilibriumF().compute(iPop, rho, u_s));
213 //}
214 }
215 CollisionO().apply(cell, parameters);
216 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
217 cell[iPop] = cell_tmp[iPop] + paramC * (cell[iPop] - cell_tmp[iPop]);
218 cell[iPop] += paramB * omega_s[iPop];
219 }
220 for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
221 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
222 }
223 }
224
225 return {rho, util::normSqr<V,DESCRIPTOR::d>(u)};
226 }
227 };
228};
229
230// Implementation of the BGK collision step for subgridscale particles
231// extended collision step, computes local drag in a given direction
232template <typename COLLISION>
235
236 static std::string getName() {
237 return "SubgridParticle<" + COLLISION::getName() + ">";
238 }
239
240 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
241 struct type {
242 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
243 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
244
245 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
246 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
247 V rho, u[DESCRIPTOR::d];
248 MomentaF().computeRhoU(cell, rho, u);
249 V porosity = cell.template getField<descriptors::POROSITY>();
250 auto extVelocity = cell.template getFieldPointer<descriptors::LOCAL_DRAG>();
251 // if (porosity[0] != 0) {
252 // cout << "extVelocity: " << extVelocity[0] << " " << extVelocity[1] << " " << extVelocity[2] << " " << std::endl;
253 // cout << "porosity: " << porosity[0] << std::endl;
254 // }
255 for (int i=0; i<DESCRIPTOR::d; i++) {
256 u[i] *= (1.-porosity);
257 u[i] += extVelocity[i];
258 }
259
260 V uSqr = CollisionO().apply(cell, parameters);
261
262 //statistics.incrementStats(rho, uSqr);
263 cell.template setField<descriptors::POROSITY>(0);
264 cell.template setField<descriptors::VELOCITY_NUMERATOR>(0);
265 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
266
267 return {rho, uSqr};
268 }
269 };
270};
271
272// Implementation of the BGK collision for Zeta-Field formulation (Geng2019)
275
276 static constexpr bool is_vectorizable = false;
277
278 static std::string getName() {
279 return "DBBParticleBGK";
280 }
281
282 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
283 struct type {
284 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
285 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
286
287 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
288 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
289 V rho, u[DESCRIPTOR::d],eta[DESCRIPTOR::q],uPlus[DESCRIPTOR::d],tmp_cell[(DESCRIPTOR::q+1)/2];
290 MomentaF().computeRhoU(cell, rho, u);
291 const V omega = parameters.template get<descriptors::OMEGA>();
292 V tmpMomentumLoss[DESCRIPTOR::d]{ };
293 auto velNumerator = cell.template getFieldPointer<descriptors::VELOCITY_NUMERATOR>();
294 auto zeta = cell.template getFieldPointer<descriptors::ZETA>();
295 auto velDenominator = cell.template getField<descriptors::VELOCITY_DENOMINATOR>();
296
297 if (velDenominator > 1) {
298 rho /= velDenominator;
299 }
300 for (int tmp_iPop=1; 2*tmp_iPop<DESCRIPTOR::q; tmp_iPop++) {
301 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]));
302 tmp_cell[tmp_iPop]=(zeta[tmp_iPop]*(-cell[tmp_iPop]+cell[descriptors::opposite<DESCRIPTOR>(tmp_iPop)]+eta[tmp_iPop]));
303 cell[tmp_iPop]+=tmp_cell[tmp_iPop]/(1.+2.*(zeta[tmp_iPop]));
304 cell[descriptors::opposite<DESCRIPTOR>(tmp_iPop)]-=tmp_cell[tmp_iPop]/(1.+2.*(zeta[tmp_iPop]));
305 zeta[tmp_iPop] = 0.;
306 zeta[descriptors::opposite<DESCRIPTOR>(tmp_iPop)] = 0.;
307 }
308
309 cell.template setField<descriptors::POROSITY>(1.);
310 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
311
312 MomentaF().computeRhoU(cell, rho, uPlus);
313 V uPlusSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, uPlus, omega);
314
315 V diff[DESCRIPTOR::q] = {};
316 for (int tmp_iPop=0; tmp_iPop<DESCRIPTOR::q; tmp_iPop++) {
317 diff[tmp_iPop] += EquilibriumF().compute(tmp_iPop, rho, uPlus)
318 - EquilibriumF().compute(tmp_iPop, rho, u);
319
320 for (int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
321 tmpMomentumLoss[iDim] -= descriptors::c<DESCRIPTOR>(tmp_iPop,iDim) * diff[tmp_iPop];
322 }
323 }
324
325 for (int i_dim=0; i_dim<DESCRIPTOR::d; i_dim++) {
326 velNumerator[i_dim] = tmpMomentumLoss[i_dim];
327 }
328
329 return {rho, util::normSqr<V,DESCRIPTOR::d>(u)};
330 }
331 };
332};
333
334// Implementation of the HBGK collision step for a porosity model enabling
335// drag computation for many particles
336// including the Krause turbulence modell
337template <typename COLLISION>
338struct KrauseH {
340
341 static std::string getName(){
342 return "KrauseH<" + COLLISION::getName() + ">";
343 }
344
345 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
346 struct type {
347 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
348 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
349 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
350
351 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
352 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
353 V rho, u[DESCRIPTOR::d];
354 V newOmega[DESCRIPTOR::d];
355 V _fieldTmp[4];
356 _fieldTmp[0] = V{1};
357 _fieldTmp[1] = V{};
358 _fieldTmp[2] = V{};
359 _fieldTmp[3] = V{};
360
361 const V smagoConst = parameters.template get<collision::LES::Smagorinsky>();
362 V preFactor = smagoConst*smagoConst
363 * descriptors::invCs2<V,DESCRIPTOR>()*descriptors::invCs2<V,DESCRIPTOR>()
364 * 2*util::sqrt(2);
365
366 MomentaF().computeRhoU(cell, rho, u);
367
368 // compute newOmega
369 V omega = parameters.template get<descriptors::OMEGA>();
370 V uSqr = u[0]*u[0];
371 for (int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
372 uSqr += u[iDim]*u[iDim];
373 }
375 V tau_mol = 1./omega;
376 for (int iPop=0; iPop<DESCRIPTOR::q; iPop++) {
377 V fNeq = util::fabs(cell[iPop] - EquilibriumF().compute(iPop, rho, u));
379 V tau_turb = 0.5*(util::sqrt(tau_mol*tau_mol+(preFactor*fNeq))-tau_mol);
381 V tau_eff = tau_mol + tau_turb;
382 newOmega[iPop] = 1./tau_eff;
383 }
384 parameters.template set<descriptors::OMEGA>(newOmega);
385
386
387 V vel_denom = cell.template getField<descriptors::VELOCITY_DENOMINATOR>();
388 if (vel_denom > std::numeric_limits<V>::epsilon()) {
389 V porosity = cell.template getField<descriptors::POROSITY>(); // prod(1-smoothInd)
390 auto vel_num = cell.template getFieldPointer<descriptors::VELOCITY_NUMERATOR>();
391 porosity = 1.-porosity; // 1-prod(1-smoothInd)
392 for (int i=0; i<DESCRIPTOR::d; i++) {
393 u[i] += porosity * (vel_num[i] / vel_denom - u[i]);
394 }
395 }
396 uSqr = CollisionO().apply(cell, parameters);
397
398 cell.template setField<descriptors::POROSITY>(_fieldTmp[0]);
399 cell.template setField<descriptors::VELOCITY_NUMERATOR>({_fieldTmp[1], _fieldTmp[2]});
400 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(_fieldTmp[3]);
401
402 return {rho, uSqr};
403 }
404 };
405};
406
409template <typename COLLISION>
412
413 static std::string getName(){
414 return "SmallParticle<" + COLLISION::getName() + ">";
415 }
416
417 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
418 struct type {
419 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
420 using CollisionO = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
421
422 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
423 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) {
424 V rho, u[DESCRIPTOR::d];
425 MomentaF().computeRhoU(cell, rho, u);
426 V porosity = cell.template getField<descriptors::POROSITY>();
427 auto localVelocity = cell.template getFieldPointer<descriptors::LOCAL_DRAG>();
428
429 //cout << porosity[0] << " " << localVelocity[0]<< " " << localVelocity[1]<< " " << localVelocity[2]<<std::endl;
430 for (int i=0; i<DESCRIPTOR::d; i++) {
431 u[i] *= porosity;
432 u[i] += localVelocity[i];
433 }
434 V uSqr = CollisionO().apply(cell, parameters);
435
436 return {rho, uSqr};
437 }
438 };
439};
440
441} // namespace collision
442
443namespace dynamics {
444
446 static std::string getName() {
447 return "ExposePorousParticleMomenta";
448 }
449
450 template <typename DESCRIPTOR, typename MOMENTA>
452
453 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
454 using combined_equilibrium = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
455
456 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
457 using combined_collision = typename COLLISION::template type<DESCRIPTOR,MOMENTA,EQUILIBRIUM>;
458
459 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM, typename COLLISION>
460 using combined_parameters = typename COLLISION::parameters;
461};
462
463}
464
465
467template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
469 T, DESCRIPTOR,
470 MOMENTA,
474>;
475
477template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
479 T, DESCRIPTOR,
480 MOMENTA,
484>;
485
487template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
489 T, DESCRIPTOR,
490 MOMENTA,
493>;
494
495// BGK collision step for subgridscale particles
496template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
498 T, DESCRIPTOR,
499 MOMENTA,
502>;
503
504// BGK collision for Zeta-Field formulation (Geng2019)
505template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
507 T, DESCRIPTOR,
508 MOMENTA,
511>;
512
515template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
517 T, DESCRIPTOR,
518 MOMENTA,
521>;
522
524template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
526 T, DESCRIPTOR,
527 MOMENTA,
530>;
531
534template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
536 T,DESCRIPTOR,
537 MOMENTA,
540>;
541
544template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
545class ForcedPSMBGKdynamics final : public dynamics::CustomCollision<T,DESCRIPTOR,MOMENTA> {
546private:
548
549public:
550 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
551 using EquilibriumF = typename equilibria::SecondOrder::template type<DESCRIPTOR,MOMENTA>;
552
554
555 constexpr static bool is_vectorizable = false;
556 constexpr static bool has_parametrized_momenta = true;
557
558 void setMomentaParameters(decltype(_parameters) parameters) {
559 _parameters = parameters;
560 }
561
562 std::type_index id() override {
563 return typeid(ForcedPSMBGKdynamics);
564 }
565
567 return block.template getData<OperatorParameters<ForcedPSMBGKdynamics>>();
568 }
569
570 void computeU(ConstCell<T,DESCRIPTOR>& cell, T u[DESCRIPTOR::d]) const override
571 {
572 MomentaF().computeU(cell, u);
573 T epsilon = 1. - cell.template getField<descriptors::POROSITY>();
574 T omega = _parameters->template get<descriptors::OMEGA>();
575 T paramA = 1 / omega - 0.5;
576 T paramB = (epsilon * paramA) / ((1. - epsilon) + paramA);
577 T paramC = (1. - paramB);
578 for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
579 u[iVel] = paramC * (u[iVel] + cell.template getFieldComponent<descriptors::FORCE>(iVel) * 0.5)
580 + paramB * cell.template getFieldComponent<descriptors::VELOCITY_SOLID>(iVel);
581 }
582 }
583
584 void computeRhoU(ConstCell<T,DESCRIPTOR>& cell, T& rho, T u[DESCRIPTOR::d]) const override
585 {
586 MomentaF().computeRhoU(cell, rho, u);
587 T epsilon = 1. - cell.template getField<descriptors::POROSITY>();
588 T omega = _parameters->template get<descriptors::OMEGA>();
589 T paramA = 1 / omega - 0.5;
590 T paramB = (epsilon * paramA) / ((1. - epsilon) + paramA);
591 T paramC = (1. - paramB);
592 for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
593 u[iVel] = paramC * (u[iVel] + cell.template getFieldComponent<descriptors::FORCE>(iVel) * 0.5)
594 + paramB * cell.template getFieldComponent<descriptors::VELOCITY_SOLID>(iVel);
595 }
596 }
597
598 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
599 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters)
600 {
601 V omega = parameters.template get<descriptors::OMEGA>();
602 V rho, u[DESCRIPTOR::d], uSqr;
603 MomentaF().computeRhoU(cell, rho, u);
604 auto force = cell.template getField<descriptors::FORCE>();
605 for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
606 u[iVel] += force[iVel] * V{0.5};
607 }
608 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
609
610 V epsilon = V{1} - cell.template getField<descriptors::POROSITY>();
611 if (epsilon < 1e-5) {
612 uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
613 lbm<DESCRIPTOR>::addExternalForce(cell, rho, u, omega, force);
614 }
615 else {
616 V paramA = V{1} / omega - V{0.5};
617 V paramB = (epsilon * paramA) / ((V{1} - epsilon) + paramA);
618 V paramC = (V{1} - paramB);
619
620 V omega_s[DESCRIPTOR::q];
621 V cell_tmp[DESCRIPTOR::q];
622
623 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
624 cell_tmp[iPop] = cell[iPop];
625 omega_s[iPop] = (equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u_s) - cell[iPop])
626 + (V{1} - omega) * (cell[iPop] - equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u));
627 }
628
629 uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
630 lbm<DESCRIPTOR>::addExternalForce(cell, rho, u, omega, force);
631
632 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
633 cell[iPop] = cell_tmp[iPop] + paramC * (cell[iPop] - cell_tmp[iPop]);
634 cell[iPop] += paramB * omega_s[iPop];
635 }
636 for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
637 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
638 }
639 uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
640 }
641 return {rho, uSqr};
642 }
643
644 T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const override {
645 return EquilibriumF().compute(iPop, rho, u);
646 };
647
648 std::string getName() const override {
649 return "ForcedPSMBGKdynamics<" + MomentaF().getName() + ">";
650 };
651
652};
653
654}
655
656#endif
Platform-abstracted block lattice for external access and inter-block interaction.
Highest-level interface to read-only Cell data.
Definition cell.h:53
Implementation of the Partially Saturated Method (PSM), see Krüger, Timm, et al.
AbstractParameters< T, DESCRIPTOR > & getParameters(BlockLattice< T, DESCRIPTOR > &block) override
Parameters access for legacy post processors.
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.
void computeU(ConstCell< T, DESCRIPTOR > &cell, T u[DESCRIPTOR::d]) const override
Compute fluid velocity.
typename equilibria::SecondOrder::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename MOMENTA::template type< DESCRIPTOR > MomentaF
void computeRhoU(ConstCell< T, DESCRIPTOR > &cell, T &rho, T u[DESCRIPTOR::d]) const override
Compute fluid velocity and particle density.
static constexpr bool has_parametrized_momenta
std::type_index id() override
Expose unique type-identifier for RTTI.
std::string getName() const override
Return human-readable name.
meta::list< descriptors::OMEGA > parameters
static constexpr bool is_vectorizable
void setMomentaParameters(decltype(_parameters) parameters)
void resetParticleRelatedFields(CELL &cell) noexcept
void resetParticleContactRelatedFields(CELL &cell) noexcept
void resetAllParticleRelatedFields(CELL &cell) noexcept
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
Definition pack.h:106
Top level namespace for all of OpenLB.
Dynamic access interface for FIELD-valued parameters.
Return value of any collision.
Definition interface.h:43
Set of FIELD-valued parameters.
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()
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:182
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:463
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