25#ifndef POROUS_BGK_DYNAMICS_H
26#define POROUS_BGK_DYNAMICS_H
35template <
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
45template <
typename DESCRIPTOR,
typename CELL,
46 typename V =
typename CELL::value_t>
49 if constexpr (DESCRIPTOR::template provides<descriptors::POROSITY>()) {
50 cell.template setField<descriptors::POROSITY>(
51 descriptors::POROSITY::template getInitialValue<V,DESCRIPTOR>() );
53 if constexpr (DESCRIPTOR::template provides<
55 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(
56 descriptors::VELOCITY_DENOMINATOR::template getInitialValue<V,DESCRIPTOR>() );
58 if constexpr (DESCRIPTOR::template provides<
60 cell.template setField<descriptors::VELOCITY_NUMERATOR>(
61 descriptors::VELOCITY_NUMERATOR::template getInitialValue<V,DESCRIPTOR>() );
63 if constexpr (DESCRIPTOR::template provides<descriptors::VELOCITY_SOLID>()) {
64 cell.template setField<descriptors::VELOCITY_SOLID>(
65 descriptors::VELOCITY_SOLID::template getInitialValue<V,DESCRIPTOR>() );
69template <
typename DESCRIPTOR,
typename CELL,
70 typename V =
typename CELL::value_t>
73 if constexpr (DESCRIPTOR::template provides<
75 cell.template setField<descriptors::CONTACT_DETECTION>(
76 descriptors::CONTACT_DETECTION::template getInitialValue<V,DESCRIPTOR>() );
80template <
typename DESCRIPTOR,
typename CELL,
81 typename V =
typename CELL::value_t>
84 resetParticleRelatedFields<DESCRIPTOR,CELL,V>(cell);
85 resetParticleContactRelatedFields<DESCRIPTOR,CELL,V>(cell);
98template <
typename COLLISION,
bool isStatic=false>
105 return "PorousParticle<" + COLLISION::getName() +
">" ;
108 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
116 template <
typename CELL,
typename pVELOCITY,
typename V=
typename CELL::value_t>
118 if constexpr (isStatic) {
119 for (
int i=0; i<DESCRIPTOR::d; i++) {
120 pVelocity[i] -= (1.-(cell.template getField<descriptors::POROSITY>())) * pVelocity[i];
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]);
131 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
133 V rho, u[DESCRIPTOR::d];
134 MomentaF().computeRhoU(cell, rho, u);
138 V velDenominator = cell.template getFieldComponent<descriptors::VELOCITY_DENOMINATOR>(0);
141 V uPlus[DESCRIPTOR::d]{ };
142 V diff[DESCRIPTOR::q]{ };
144 if (velDenominator > std::numeric_limits<V>::epsilon()) {
145 for (
int iDim=0; iDim<DESCRIPTOR::d; ++iDim) {
146 uPlus[iDim] = u[iDim];
149 if constexpr (!isStatic) {
150 particles::resetParticleRelatedFields<DESCRIPTOR,CELL,V>(cell);
153 for (
int tmp_iPop=0; tmp_iPop < DESCRIPTOR::q; tmp_iPop++) {
154 diff[tmp_iPop] +=
EquilibriumF().compute(tmp_iPop, rho, uPlus)
156 cell[tmp_iPop] += diff[tmp_iPop];
160 particles::resetParticleContactRelatedFields<DESCRIPTOR,CELL,V>(cell);
169template <
typename COLLISION>
176 return "PSM<" + COLLISION::getName() +
">" ;
179 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
185 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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);
193 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
194 if (epsilon < 1e-5) {
199 V paramB = (epsilon * paramA) / ((1. - epsilon) + paramA);
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];
208 omega_s[iPop] = (
EquilibriumF().compute(iPop, rho, u_s) - cell[iPop])
209 + (V{1} - omega) * (cell[iPop] -
EquilibriumF().compute(iPop, rho, u));
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];
220 for (
int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
221 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
225 return {rho, util::normSqr<V,DESCRIPTOR::d>(u)};
232template <
typename COLLISION>
237 return "SubgridParticle<" + COLLISION::getName() +
">";
240 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
245 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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>();
255 for (
int i=0; i<DESCRIPTOR::d; i++) {
256 u[i] *= (1.-porosity);
257 u[i] += extVelocity[i];
263 cell.template setField<descriptors::POROSITY>(0);
264 cell.template setField<descriptors::VELOCITY_NUMERATOR>(0);
265 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
279 return "DBBParticleBGK";
282 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
287 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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>();
297 if (velDenominator > 1) {
298 rho /= velDenominator;
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]));
306 zeta[descriptors::opposite<DESCRIPTOR>(tmp_iPop)] = 0.;
309 cell.template setField<descriptors::POROSITY>(1.);
310 cell.template setField<descriptors::VELOCITY_DENOMINATOR>(0);
312 MomentaF().computeRhoU(cell, rho, uPlus);
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)
320 for (
int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
321 tmpMomentumLoss[iDim] -= descriptors::c<DESCRIPTOR>(tmp_iPop,iDim) * diff[tmp_iPop];
325 for (
int i_dim=0; i_dim<DESCRIPTOR::d; i_dim++) {
326 velNumerator[i_dim] = tmpMomentumLoss[i_dim];
329 return {rho, util::normSqr<V,DESCRIPTOR::d>(u)};
337template <
typename COLLISION>
342 return "KrauseH<" + COLLISION::getName() +
">";
345 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
351 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
353 V rho, u[DESCRIPTOR::d];
354 V newOmega[DESCRIPTOR::d];
361 const V smagoConst =
parameters.template get<collision::LES::Smagorinsky>();
362 V preFactor = smagoConst*smagoConst
363 * descriptors::invCs2<V,DESCRIPTOR>()*descriptors::invCs2<V,DESCRIPTOR>()
366 MomentaF().computeRhoU(cell, rho, u);
369 V omega =
parameters.template get<descriptors::OMEGA>();
371 for (
int iDim=0; iDim<DESCRIPTOR::d; iDim++) {
372 uSqr += u[iDim]*u[iDim];
375 V tau_mol = 1./omega;
376 for (
int iPop=0; iPop<DESCRIPTOR::q; iPop++) {
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;
384 parameters.template set<descriptors::OMEGA>(newOmega);
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>();
390 auto vel_num = cell.template getFieldPointer<descriptors::VELOCITY_NUMERATOR>();
391 porosity = 1.-porosity;
392 for (
int i=0; i<DESCRIPTOR::d; i++) {
393 u[i] += porosity * (vel_num[i] / vel_denom - u[i]);
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]);
409template <
typename COLLISION>
414 return "SmallParticle<" + COLLISION::getName() +
">";
417 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
422 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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>();
430 for (
int i=0; i<DESCRIPTOR::d; i++) {
432 u[i] += localVelocity[i];
447 return "ExposePorousParticleMomenta";
450 template <
typename DESCRIPTOR,
typename MOMENTA>
453 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
456 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM,
typename COLLISION>
459 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM,
typename COLLISION>
467template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
477template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
487template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
496template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
505template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
515template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
524template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
534template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
544template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
550 using MomentaF =
typename MOMENTA::template type<DESCRIPTOR>;
551 using EquilibriumF =
typename equilibria::SecondOrder::template type<DESCRIPTOR,MOMENTA>;
562 std::type_index
id()
override {
567 return block.template getData<OperatorParameters<ForcedPSMBGKdynamics>>();
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);
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);
598 template <
typename CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
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};
608 auto u_s = cell.template getField<descriptors::VELOCITY_SOLID>();
610 V epsilon = V{1} - cell.template getField<descriptors::POROSITY>();
611 if (epsilon < 1e-5) {
616 V paramA = V{1} / omega - V{0.5};
617 V paramB = (epsilon * paramA) / ((V{1} - epsilon) + paramA);
618 V paramC = (V{1} - paramB);
620 V omega_s[DESCRIPTOR::q];
621 V cell_tmp[DESCRIPTOR::q];
623 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
624 cell_tmp[iPop] = cell[iPop];
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];
636 for (
int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
637 u[iVel] = paramC * u[iVel] + paramB * u_s[iVel];
639 uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
649 return "ForcedPSMBGKdynamics<" +
MomentaF().getName() +
">";
Platform-abstracted block lattice for external access and inter-block interaction.
Highest-level interface to read-only Cell data.
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 ¶meters)
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)
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
Top level namespace for all of OpenLB.
Dynamic access interface for FIELD-valued parameters.
Return value of any collision.
Set of FIELD-valued parameters.
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()
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.