34#ifndef DUAL_DYNAMICS_H
35#define DUAL_DYNAMICS_H
50 return "DualPorousBGK";
53 template <
typename DESCRIPTOR,
typename MOMENTA,
typename EQUILIBRIUM>
58 template <CONCEPT(MinimalCell) CELL,
typename PARAMETERS,
typename V=
typename CELL::value_t>
62 for (
int iPop=1; iPop <= DESCRIPTOR::q/2; ++iPop) {
63 V cell_iPop = cell[iPop];
64 cell[iPop] = cell[descriptors::opposite<DESCRIPTOR>(iPop)];
65 cell[descriptors::opposite<DESCRIPTOR>(iPop)] = cell_iPop;
69 const auto pop_f = cell.template getField<descriptors::F>();
70 const auto dJdF = cell.template getFieldPointer<descriptors::DJDF>();
71 const V d = cell.template getField<descriptors::POROSITY>();
72 const V omega =
parameters.template get<descriptors::OMEGA>();
76 V u_f[DESCRIPTOR::d] { };
79 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
82 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
84 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
85 u_f[iD] += pop_f[iPop]*descriptors::c<DESCRIPTOR>(iPop,iD);
89 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
94 V pheq[DESCRIPTOR::q] { };
95 for (
int i=0; i < DESCRIPTOR::q; ++i) {
97 for (
int j=0; j < DESCRIPTOR::q; ++j) {
99 + descriptors::t<V,DESCRIPTOR>(j);
101 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
102 dot_ij += ( descriptors::c<DESCRIPTOR>(j,iD) - d*u_f[iD] )
103 * ( descriptors::c<DESCRIPTOR>(i,iD) - u_f[iD] );
105 pheq[i] += cell[j]*feq_j*( V{1} + descriptors::invCs2<V,DESCRIPTOR>()*d*dot_ij );
111 for (
int i=0; i < DESCRIPTOR::q; ++i) {
112 cell[i] = cell[i] - omega*( cell[i] - pheq[i] ) + dJdF[i];
116 V rho_phi, u_phi[DESCRIPTOR::d];
117 MomentaF().computeRhoU( cell, rho_phi, u_phi );
118 V uSqr_phi = util::normSqr<V,DESCRIPTOR::d>( u_phi );
122 for (
int iPop=1; iPop <= DESCRIPTOR::q/2; ++iPop) {
123 V cell_iPop = cell[iPop];
124 cell[iPop] = cell[descriptors::opposite<DESCRIPTOR>(iPop)];
125 cell[descriptors::opposite<DESCRIPTOR>(iPop)] = cell_iPop;
127 return {rho_phi, uSqr_phi};
134template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
145template<
typename T>
class Controller;
149template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
173template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
176 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
179 this->
getName() =
"DualForcedBGKdynamics";
183template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
187 throw std::bad_function_call();
190template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
196template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
203 auto dJdF = cell.template getFieldPointer<descriptors::DJDF>();
204 auto f = cell.template getField<descriptors::F>();
205 auto force = cell.template getFieldPointer<descriptors::FORCE>();
207 T u_f[DESCRIPTOR::d];
210 T eq_phi[DESCRIPTOR::q];
211 T force_phi[DESCRIPTOR::q];
214 T F1_phi[DESCRIPTOR::q][DESCRIPTOR::q];
215 T F2_phi[DESCRIPTOR::q][DESCRIPTOR::q];
216 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
218 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
219 f_c += force[iD]*descriptors::c<DESCRIPTOR>(iPop,iD);
221 for (
int jPop=0; jPop < DESCRIPTOR::q; ++jPop) {
223 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
224 sum += (f_c*descriptors::c<DESCRIPTOR>(iPop,iD)-force[iD]/(T)descriptors::invCs2<T,DESCRIPTOR>())*descriptors::c<DESCRIPTOR>(jPop,iD);
226 F1_phi[iPop][jPop] = descriptors::t<T,DESCRIPTOR>(iPop)*descriptors::invCs2<T,DESCRIPTOR>()*f_c;
227 F2_phi[iPop][jPop] = descriptors::t<T,DESCRIPTOR>(iPop)*descriptors::invCs2<T,DESCRIPTOR>()*descriptors::invCs2<T,DESCRIPTOR>()*sum;
232 for (
int jPop=0; jPop < DESCRIPTOR::q; ++jPop) {
234 force_phi[jPop] = T();
235 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
237 force_phi[jPop] += cell[iPop]*(F1_phi[iPop][jPop] + (1.-.5*omega)*F2_phi[iPop][jPop]);
242 for (
int jPop=0; jPop < DESCRIPTOR::q; ++jPop) {
243 cell[jPop] = cell[jPop] - omega*(cell[jPop]-eq_phi[jPop]) + force_phi[jPop] + dJdF[jPop];
248 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
249 phi2 += cell[iPop]*cell[iPop];
253 return {T(1) + cell[0], phi2};
256template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
262template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
272template<
typename T,
typename DESCRIPTOR,
typename MOMENTA=momenta::BulkTuple>
275 using MomentaF =
typename MOMENTA::template type<DESCRIPTOR>;
282 virtual void computeRhoU(
const T fPop[DESCRIPTOR::q], T& rho, T u[DESCRIPTOR::d])
const;
300template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
303 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
306 this->
getName() =
"DualPorousBGKdynamics";
310template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
314 throw std::bad_function_call();
317template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
319 int iPop, T rho,
const T u[DESCRIPTOR::d])
const
327template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
329 const T fPop[DESCRIPTOR::q], T& rho_f, T u_f[DESCRIPTOR::d])
const
332 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
335 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
337 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
338 u_f[iD] += fPop[iPop]*descriptors::c<DESCRIPTOR>(iPop,iD);
342 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
347template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
355 auto pop_f = cell.template getField<descriptors::F>();
356 auto dJdF = cell.template getFieldPointer<descriptors::DJDF>();
357 T d = cell.template getField<descriptors::POROSITY>();
360 T rho_f, u_f[DESCRIPTOR::d];
361 this->computeRhoU( pop_f.data(), rho_f, u_f);
364 T pheq[DESCRIPTOR::q];
365 for (
int i=0; i < DESCRIPTOR::q; ++i) {
367 for (
int j=0; j < DESCRIPTOR::q; ++j) {
368 T feq_j = computeEquilibrium(j, rho_f, u_f)
369 + descriptors::t<T,DESCRIPTOR>(j);
371 for (
int iD=0; iD < DESCRIPTOR::d; ++iD) {
372 dot_ij += ( descriptors::c<DESCRIPTOR>(j,iD) - d*u_f[iD] )
373 * ( descriptors::c<DESCRIPTOR>(i,iD) - u_f[iD] );
375 pheq[i] += cell[j]*feq_j*( T{1} + descriptors::invCs2<T,DESCRIPTOR>()*d*dot_ij );
381 for (
int i=0; i < DESCRIPTOR::q; ++i) {
382 cell[i] = cell[i] - omega*( cell[i] - pheq[i] ) + dJdF[i];
386 T rho_phi, u_phi[DESCRIPTOR::d];
388 T uSqr_phi = util::normSqr<T,DESCRIPTOR::d>( u_phi );
392 return {rho_phi, uSqr_phi};
395template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
401template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
Highest-level interface to Cell data.
void revert()
Revert ("bounce-back") the distribution functions.
Implementation of the dual BGK collision step with external force.
virtual void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
virtual void defineRho(Cell< T, DESCRIPTOR > &cell, T rho)
Does nothing.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const
Compute equilibrium distribution function.
DualForcedBGKdynamics(T omega_)
Constructor.
virtual CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell)
Collision step.
virtual T getOmega() const
Get local relaxation parameter of the dynamics.
Implementation of the dual BGK collision step with external force.
DualPorousBGKdynamics(T omega_)
Constructor.
virtual void defineRho(Cell< T, DESCRIPTOR > &cell, T rho)
Does nothing.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
virtual T getOmega() const
Get local relaxation parameter of the dynamics.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const
Compute equilibrium distribution function.
virtual void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
virtual CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell)
Collision step.
virtual void computeRhoU(const T fPop[DESCRIPTOR::q], T &rho, T u[DESCRIPTOR::d]) const
Compute moments.
Helper functions for the implementation of LB dynamics.
Top level namespace for all of OpenLB.
#define OLB_PRECONDITION(COND)
Return value of any collision.
virtual std::string getName() const
Return human-readable name.
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS ¶meters) any_platform
typename meta::list< descriptors::OMEGA > parameters
static std::string getName()
Dynamics constructed as a tuple of momenta, equilibrium and collision.
void computeRhoU(ConstCell< T, DESCRIPTOR > &cell, T &rho, T u[DESCRIPTOR::d]) const override
Compute fluid velocity and particle density.
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 computeRhoU(T const *cell, T &rho, T u[DESCRIPTOR::d])
Computation of hydrodynamic variables.
static T equilibrium(int iPop, int jPop, T rho, const T u[DESCRIPTOR::d])