28#ifndef ENTROPIC_LB_DYNAMICS_HH
29#define ENTROPIC_LB_DYNAMICS_HH
45template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
47 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
50 this->
getName() =
"EntropicEqDynamics";
53template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
59template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
66 T rho, u[DESCRIPTOR::d];
67 MOMENTA().computeRhoU(cell, rho, u);
68 T uSqr = util::normSqr<T,L::d>(u);
70 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
71 cell[iPop] += omega * (eLbH::equilibrium(iPop,rho,u) - cell[iPop]);
77template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
83template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
96template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
98 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
101 this->
getName() =
"ForcedEntropicEqDynamics";
104template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
111template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
115 typedef DESCRIPTOR L;
118 T rho, u[DESCRIPTOR::d];
119 MOMENTA().computeRhoU(cell, rho, u);
121 T* force = cell.template getFieldPointer<descriptors::FORCE>();
122 for (
int iDim=0; iDim<DESCRIPTOR::d; ++iDim) {
123 u[iDim] += force[iDim] / (T)2.;
125 T uSqr = util::normSqr<T,L::d>(u);
127 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
128 cell[iPop] += omega * (eLbH::equilibrium(iPop,rho,u) - cell[iPop]);
136template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
142template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
155template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
157 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
160 this->
getName() =
"EntropicDynamics";
163template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
169template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
173 typedef DESCRIPTOR L;
176 T rho, u[DESCRIPTOR::d];
177 MOMENTA().computeRhoU(cell, rho, u);
178 T uSqr = util::normSqr<T,L::d>(u);
180 T f[L::q], fEq[L::q], fNeq[L::q];
181 for (
int iPop = 0; iPop < L::q; ++iPop) {
182 fEq[iPop] = eLbH::equilibrium(iPop,rho,u);
183 fNeq[iPop] = cell[iPop] - fEq[iPop];
184 f[iPop] = cell[iPop] + descriptors::t<T,L>(iPop);
185 fEq[iPop] += descriptors::t<T,L>(iPop);
192 bool converged = getAlpha(alpha,f,fNeq);
194 std::cout <<
"Newton-Raphson failed to converge.\n";
198 OLB_ASSERT(converged,
"Entropy growth failed to converge!");
200 T omegaTot = omega / 2.0 * alpha;
201 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
202 cell[iPop] *= (T)1-omegaTot;
203 cell[iPop] += omegaTot * (fEq[iPop]-descriptors::t<T,L>(iPop));
209template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
215template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
221template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
224 typedef DESCRIPTOR L;
226 for (
int iPop = 0; iPop < L::q; ++iPop) {
228 entropy += f[iPop]*
util::log(f[iPop]/descriptors::t<T,L>(iPop));
234template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
235T EntropicDynamics<T,DESCRIPTOR,MOMENTA>::computeEntropyGrowth(
const T f[],
const T fNeq[],
const T &alpha)
237 typedef DESCRIPTOR L;
240 for (
int iPop = 0; iPop < L::q; ++iPop) {
241 fAlphaFneq[iPop] = f[iPop] - alpha*fNeq[iPop];
244 return computeEntropy(f) - computeEntropy(fAlphaFneq);
247template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
248T EntropicDynamics<T,DESCRIPTOR,MOMENTA>::computeEntropyGrowthDerivative(
const T f[],
const T fNeq[],
const T &alpha)
250 typedef DESCRIPTOR L;
252 T entropyGrowthDerivative = T();
253 for (
int iPop = 0; iPop < L::q; ++iPop) {
254 T tmp = f[iPop] - alpha*fNeq[iPop];
255 OLB_ASSERT(tmp > T(),
"f[iPop] - alpha*fNeq[iPop] <= 0");
256 entropyGrowthDerivative += fNeq[iPop]*(
util::log(tmp/descriptors::t<T,L>(iPop)));
259 return entropyGrowthDerivative;
262template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
263bool EntropicDynamics<T,DESCRIPTOR,MOMENTA>::getAlpha(T &alpha,
const T f[],
const T fNeq[])
265 const T epsilon = std::numeric_limits<T>::epsilon();
269 const T errorMax = epsilon*var;
272 for (count = 0; count < 10000; ++count) {
273 T entGrowth = computeEntropyGrowth(f,fNeq,alpha);
274 T entGrowthDerivative = computeEntropyGrowthDerivative(f,fNeq,alpha);
275 if ((error < errorMax) || (
util::fabs(entGrowth) < var*epsilon)) {
278 alphaGuess = alpha - entGrowth /
292template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
294 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
297 this->
getName() =
"ForcedEntropicDynamics";
300template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
307template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
311 typedef DESCRIPTOR L;
314 T rho, u[DESCRIPTOR::d];
315 MOMENTA().computeRhoU(cell, rho, u);
316 T uSqr = util::normSqr<T,L::d>(u);
318 T f[L::q], fEq[L::q], fNeq[L::q];
319 for (
int iPop = 0; iPop < L::q; ++iPop) {
320 fEq[iPop] = eLbH::equilibrium(iPop,rho,u);
321 fNeq[iPop] = cell[iPop] - fEq[iPop];
322 f[iPop] = cell[iPop] + descriptors::t<T,L>(iPop);
323 fEq[iPop] += descriptors::t<T,L>(iPop);
330 bool converged = getAlpha(alpha,f,fNeq);
332 std::cout <<
"Newton-Raphson failed to converge.\n";
336 OLB_ASSERT(converged,
"Entropy growth failed to converge!");
338 T* force = cell.template getFieldPointer<descriptors::FORCE>();
339 for (
int iDim=0; iDim<DESCRIPTOR::d; ++iDim) {
340 u[iDim] += force[iDim] / (T)2.;
342 uSqr = util::normSqr<T,L::d>(u);
343 T omegaTot = omega / 2.0 * alpha;
344 for (
int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
345 cell[iPop] *= (T)1-omegaTot;
346 cell[iPop] += omegaTot * eLbH::equilibrium(iPop,rho,u);
353template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
359template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
365template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
368 typedef DESCRIPTOR L;
370 for (
int iPop = 0; iPop < L::q; ++iPop) {
372 entropy += f[iPop]*
util::log(f[iPop]/descriptors::t<T,L>(iPop));
378template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
379T ForcedEntropicDynamics<T,DESCRIPTOR,MOMENTA>::computeEntropyGrowth(
const T f[],
const T fNeq[],
const T &alpha)
381 typedef DESCRIPTOR L;
384 for (
int iPop = 0; iPop < L::q; ++iPop) {
385 fAlphaFneq[iPop] = f[iPop] - alpha*fNeq[iPop];
388 return computeEntropy(f) - computeEntropy(fAlphaFneq);
391template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
392T ForcedEntropicDynamics<T,DESCRIPTOR,MOMENTA>::computeEntropyGrowthDerivative(
const T f[],
const T fNeq[],
const T &alpha)
394 typedef DESCRIPTOR L;
396 T entropyGrowthDerivative = T();
397 for (
int iPop = 0; iPop < L::q; ++iPop) {
398 T tmp = f[iPop] - alpha*fNeq[iPop];
399 OLB_ASSERT(tmp > T(),
"f[iPop] - alpha*fNeq[iPop] <= 0");
400 entropyGrowthDerivative += fNeq[iPop]*
util::log(tmp/descriptors::t<T,L>(iPop));
403 return entropyGrowthDerivative;
406template<
typename T,
typename DESCRIPTOR,
typename MOMENTA>
407bool ForcedEntropicDynamics<T,DESCRIPTOR,MOMENTA>::getAlpha(T &alpha,
const T f[],
const T fNeq[])
409 const T epsilon = std::numeric_limits<T>::epsilon();
413 const T errorMax = epsilon*var;
416 for (count = 0; count < 10000; ++count) {
417 T entGrowth = computeEntropyGrowth(f,fNeq,alpha);
418 T entGrowthDerivative = computeEntropyGrowthDerivative(f,fNeq,alpha);
419 if ((error < errorMax) || (
util::fabs(entGrowth) < var*epsilon)) {
422 alphaGuess = alpha - entGrowth /
Highest-level interface to Cell data.
Implementation of the entropic collision step.
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const override
Compute equilibrium distribution function.
CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell) override
Collision step.
void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
T getOmega() const
Get local relaxation parameter of the dynamics.
EntropicDynamics(T omega_)
Constructor.
EntropicEqDynamics(T omega_)
Constructor.
T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const override
Compute equilibrium distribution function.
CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell) override
Collision step.
void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
T getOmega() const
Get local relaxation parameter of the dynamics.
Implementation of the forced entropic collision step.
virtual void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
ForcedEntropicDynamics(T omega_)
Constructor.
virtual T getOmega() const
Get local relaxation parameter of the dynamics.
virtual CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell)
Collision step.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
Compute equilibrium distribution function.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) 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 T getOmega() const
Get local relaxation parameter of the dynamics.
ForcedEntropicEqDynamics(T omega_)
Constructor.
A collection of entropic dynamics classes (e.g.
A collection of dynamics classes (e.g.
ADf< T, DIM > log(const ADf< T, DIM > &a)
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
Top level namespace for all of OpenLB.
#define OLB_ASSERT(COND, MESSAGE)
Return value of any collision.
virtual std::string getName() const
Return human-readable name.
static T equilibrium(int iPop, T rho, const T u[DESCRIPTOR::d])
Computation of equilibrium distribution.
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.