25#ifndef POROUS_BGK_DYNAMICS_H
26#define POROUS_BGK_DYNAMICS_H
35template <
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
46template <
typename DESCRIPTOR,
typename CELL,
47 typename V =
typename CELL::value_t>
50 if constexpr (DESCRIPTOR::template provides<descriptors::POROSITY>()) {
51 cell.template setField<descriptors::POROSITY>(
52 descriptors::POROSITY::template getInitialValue<V,DESCRIPTOR>() );
54 if constexpr (DESCRIPTOR::template provides<
56 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(
57 descriptors::VELOCITY_DENOMINATOR::template getInitialValue<V,DESCRIPTOR>() );
59 if constexpr (DESCRIPTOR::template provides<
61 cell.template setField<descriptors::VELOCITY_NUMERATOR>(
62 descriptors::VELOCITY_NUMERATOR::template getInitialValue<V,DESCRIPTOR>() );
64 if constexpr (DESCRIPTOR::template provides<descriptors::VELOCITY_SOLID>()) {
65 cell.template setField<descriptors::VELOCITY_SOLID>(
66 descriptors::VELOCITY_SOLID::template getInitialValue<V,DESCRIPTOR>() );
70template <
typename DESCRIPTOR,
typename CELL,
71 typename V =
typename CELL::value_t>
74 if constexpr (DESCRIPTOR::template provides<
76 cell.template setField<descriptors::CONTACT_DETECTION>(
77 descriptors::CONTACT_DETECTION::template getInitialValue<V,DESCRIPTOR>() );
81template <
typename DESCRIPTOR,
typename CELL,
82 typename V =
typename CELL::value_t>
99template <
typename COLLISION,
bool isStatic=false>
106 return "PorousParticle<" + COLLISION::getName() +
">" ;
109 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
117 template <
typename CELL,
typename pVELOCITY,
typename V=
typename CELL::value_t>
119 if constexpr (isStatic) {
120 for (
int i=0; i<DESCRIPTOR::d; i++) {
121 pVelocity[i] -= (1.-(cell.template getField<descriptors::POROSITY>())) * pVelocity[i];
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]);
132 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
134 V rho, u[DESCRIPTOR::d];
135 MomentaF().computeRhoU(cell, rho, u);
139 V velDenominator = cell.template getFieldComponent<descriptors::VELOCITY_DENOMINATOR>(0);
142 V uPlus[DESCRIPTOR::d]{ };
143 V diff[DESCRIPTOR::q]{ };
144 V fEqPlus[DESCRIPTOR::q]{ };
145 V fEq[DESCRIPTOR::q]{ };
147 if (velDenominator > std::numeric_limits<V>::epsilon()) {
148 for (
int iDim=0; iDim<DESCRIPTOR::d; ++iDim) {
149 uPlus[iDim] = u[iDim];
152 if constexpr (!isStatic) {
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];
171template <
typename COLLISION>
176 return "MovingPorosity<" + COLLISION::getName() +
">" ;
179 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
185 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
194 uPlus += (V{1} - cell.template getField<descriptors::POROSITY>())
195 * (cell.template getField<descriptors::VELOCITY>() - uPlus);
198 V fEq[DESCRIPTOR::q] { };
199 V fEq2[DESCRIPTOR::q] { };
201 EquilibriumF().compute(cell, statistic.rho, uPlus, fEq2);
202 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
203 cell[iPop] += fEq2[iPop] - fEq[iPop];
213template <
typename COLLISION>
220 return "PSM<" + COLLISION::getName() +
">" ;
223 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
229 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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);
237 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
238 if (epsilon < 1e-5) {
243 V paramB = (epsilon * paramA) / ((1. - epsilon) + paramA);
245 V paramC = (1. - paramB);
246 V omega_s[DESCRIPTOR::q];
247 V cell_tmp[DESCRIPTOR::q];
249 V fEq[DESCRIPTOR::q] { };
250 V fEq_s[DESCRIPTOR::q] { };
253 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
254 cell_tmp[iPop] = cell[iPop];
257 omega_s[iPop] = (fEq_s[iPop] - cell[iPop]) + (V{1} - omega) * (cell[iPop] - fEq[iPop]);
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];
268 for (
int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
269 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
280template <
typename COLLISION>
285 return "SubgridParticle<" + COLLISION::getName() +
">";
288 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
293 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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>();
303 for (
int i=0; i<DESCRIPTOR::d; i++) {
304 u[i] *= (1.-porosity);
305 u[i] += extVelocity[i];
311 cell.template setField<descriptors::POROSITY>(0);
312 cell.template setField<descriptors::VELOCITY_NUMERATOR>(0);
313 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
327 return "DBBParticleBGK";
330 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
335 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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>();
345 if (velDenominator > 1) {
346 rho /= velDenominator;
348 for (
int tmp_iPop=1; 2*tmp_iPop<DESCRIPTOR::q; tmp_iPop++) {
351 cell[tmp_iPop]+=tmp_cell[tmp_iPop]/(1.+2.*(zeta[tmp_iPop]));
357 cell.template setField<descriptors::POROSITY>(1.);
358 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
360 MomentaF().computeRhoU(cell, rho, uPlus);
363 V diff[DESCRIPTOR::q] = {};
364 V fEqPlus[DESCRIPTOR::q] = {};
365 V fEq[DESCRIPTOR::q] = {};
368 for (
int tmp_iPop=0; tmp_iPop<DESCRIPTOR::q; tmp_iPop++) {
369 diff[tmp_iPop] += fEqPlus[tmp_iPop] - fEq[tmp_iPop];
371 for (
int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
376 for (
int i_dim=0; i_dim<DESCRIPTOR::d; i_dim++) {
377 velNumerator[i_dim] = tmpMomentumLoss[i_dim];
388template <
typename COLLISION>
393 return "KrauseH<" + COLLISION::getName() +
">";
396 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
402 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
404 V rho, u[DESCRIPTOR::d];
405 V newOmega[DESCRIPTOR::d];
412 const V smagoConst =
parameters.template get<collision::LES::SMAGORINSKY>();
413 V preFactor = smagoConst*smagoConst
417 MomentaF().computeRhoU(cell, rho, u);
420 V omega =
parameters.template get<descriptors::OMEGA>();
422 for (
int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
423 uSqr += u[iDim]*u[iDim];
426 V tau_mol = 1./omega;
427 V fEq[DESCRIPTOR::q] { };
429 for (
int iPop=0; iPop<DESCRIPTOR::q; 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;
437 parameters.template set<descriptors::OMEGA>(newOmega);
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>();
443 auto vel_num = cell.template getFieldPointer<descriptors::VELOCITY_NUMERATOR>();
444 porosity = 1.-porosity;
445 for (
int i=0; i<DESCRIPTOR::d; i++) {
446 u[i] += porosity * (vel_num[i] / vel_denom - u[i]);
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]);
462template <
typename COLLISION>
467 return "SmallParticle<" + COLLISION::getName() +
">";
470 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
475 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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>();
483 for (
int i=0; i<DESCRIPTOR::d; i++) {
485 u[i] += localVelocity[i];
500 return "ExposePorousParticleMomenta";
503 template <
typename DESCRIPTOR,
typename MOMENTA>
506 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
509 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM,
typename COLLISION>
512 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM,
typename COLLISION>
520template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
530template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
540template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
549template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
558template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
568template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
577template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
587template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
597template<
typename T,
typename DESCRIPTOR>
600 using MomentaF =
typename momenta::ForcedPSMBulkTuple::template type<DESCRIPTOR>;
601 using EquilibriumF =
typename equilibria::SecondOrder::template type<DESCRIPTOR,momenta::ForcedPSMBulkTuple>;
607 template <
typename NEW_T>
610 std::type_index
id()
override {
615 return block.template getData<OperatorParameters<ForcedPSMBGKdynamics>>();
618 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
621 V omega =
parameters.template get<descriptors::OMEGA>();
622 V rho, u[DESCRIPTOR::d], uSqr;
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};
628 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
630 V epsilon = V{1} - cell.template getField<descriptors::POROSITY>();
631 if (epsilon < 1e-5) {
636 V paramA = V{1} / omega - V{0.5};
637 V paramB = (epsilon * paramA) / ((V{1} - epsilon) + paramA);
638 V paramC = (V{1} - paramB);
640 V omega_s[DESCRIPTOR::q];
641 V cell_tmp[DESCRIPTOR::q];
643 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
644 cell_tmp[iPop] = cell[iPop];
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];
656 for (
int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
657 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
669 return "ForcedPSMBGKdynamics<" +
MomentaF().getName() +
">";
Highest-level interface to read-only Cell data.
constexpr T invCs2() any_platform
constexpr T t(unsigned iPop, tag::CUM) any_platform
constexpr int c(unsigned iPop, unsigned iDim) any_platform
constexpr int opposite(unsigned iPop) any_platform
void resetParticleRelatedFields(CELL &cell) noexcept
void resetParticleContactRelatedFields(CELL &cell) noexcept
void resetAllParticleRelatedFields(CELL &cell) noexcept
auto normSqr(const ARRAY_LIKE &u) any_platform
Compute norm square of a d-dimensional vector.
Top level namespace for all of OpenLB.
Dynamic access interface for FIELD-valued parameters.
Return value of any collision.
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 ¶meters) 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 ¶meters)
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename MOMENTA::template type< DESCRIPTOR > MomentaF
static constexpr bool is_vectorizable
static std::string getName()
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 ¶meters)
static std::string getName()
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
CellStatistic< V > apply(CELL &cell, PARAMETERS ¶meters) any_platform
typename MOMENTA::template type< DESCRIPTOR > MomentaF
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename meta::list< descriptors::OMEGA > parameters
static std::string getName()
CellStatistic< V > apply(CELL &cell, PARAMETERS ¶meters)
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 ¶meters)
static constexpr bool is_vectorizable
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
static std::string getName()
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 ¶meters)
typename MOMENTA::template type< DESCRIPTOR > MomentaF
Implementation of the BGK collision step for a small particles enabling two way coupling.
static std::string getName()
typename COLLISION::template type< DESCRIPTOR, MOMENTA, EQUILIBRIUM > CollisionO
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS ¶meters)
typename meta::list< descriptors::OMEGA > parameters
static std::string getName()
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
static std::string getName()
Dynamics constructed as a tuple of momenta, equilibrium and collision.
static V secondOrder(int iPop, const RHO &rho, const U &u, const USQR &uSqr) any_platform
Computation of equilibrium distribution, second order in u.
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.
static V bgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
BGK collision step.
static void computeRhoU(CELL &cell, RHO &rho, U &u) any_platform
Computation of hydrodynamic variables.