From 94d3e79a8617f88dc0219cfdeedfa3147833719d Mon Sep 17 00:00:00 2001
From: Adrian Kummerlaender
Date: Mon, 24 Jun 2019 14:43:36 +0200
Subject: Initialize at openlb-1-3
---
src/dynamics/entropicDynamics.hh | 433 +++++++++++++++++++++++++++++++++++++++
1 file changed, 433 insertions(+)
create mode 100644 src/dynamics/entropicDynamics.hh
(limited to 'src/dynamics/entropicDynamics.hh')
diff --git a/src/dynamics/entropicDynamics.hh b/src/dynamics/entropicDynamics.hh
new file mode 100644
index 0000000..ba92962
--- /dev/null
+++ b/src/dynamics/entropicDynamics.hh
@@ -0,0 +1,433 @@
+/* This file is part of the OpenLB library
+ *
+ * Copyright (C) 2006, 2007, 2017 Orestis Malaspinas, Jonas Latt, Mathias J. Krause
+ * E-mail contact: info@openlb.net
+ * The most recent release of OpenLB can be downloaded at
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+/** \file
+ * A collection of entropic dynamics classes (e.g. Entropic, ForcedEntropic, Entropic, ForcedEntropic) with which a Cell object
+ * can be instantiated -- generic implementation.
+ */
+#ifndef ENTROPIC_LB_DYNAMICS_HH
+#define ENTROPIC_LB_DYNAMICS_HH
+
+#include
+#include
+#include "lbHelpers.h"
+#include "entropicDynamics.h"
+#include "entropicLbHelpers.h"
+
+namespace olb {
+
+//==============================================================================//
+/////////////////////////// Class EntropicEqDynamics ///////////////////////////////
+//==============================================================================//
+/** \param omega_ relaxation parameter, related to the dynamic viscosity
+ * \param momenta_ a Momenta object to know how to compute velocity momenta
+ */
+template
+EntropicEqDynamics::EntropicEqDynamics (
+ T omega_, Momenta& momenta_ )
+ : BasicDynamics(momenta_),
+ omega(omega_)
+{ }
+
+template
+T EntropicEqDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ return entropicLbHelpers::equilibrium(iPop,rho,u);
+}
+
+template
+void EntropicEqDynamics::collide (
+ Cell& cell,
+ LatticeStatistics& statistics )
+{
+ typedef DESCRIPTOR L;
+ typedef entropicLbHelpers eLbH;
+
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T uSqr = util::normSqr(u);
+
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] += omega * (eLbH::equilibrium(iPop,rho,u) - cell[iPop]);
+ }
+
+ statistics.incrementStats(rho, uSqr);
+}
+
+template
+T EntropicEqDynamics::getOmega() const
+{
+ return omega;
+}
+
+template
+void EntropicEqDynamics::setOmega(T omega_)
+{
+ omega = omega_;
+}
+
+
+//====================================================================//
+//////////////////// Class ForcedEntropicEqDynamics //////////////////////
+//====================================================================//
+
+/** \param omega_ relaxation parameter, related to the dynamic viscosity
+ */
+template
+ForcedEntropicEqDynamics::ForcedEntropicEqDynamics (
+ T omega_, Momenta& momenta_ )
+ : BasicDynamics(momenta_),
+ omega(omega_)
+{ }
+
+template
+T ForcedEntropicEqDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ return entropicLbHelpers::equilibrium(iPop,rho,u);
+}
+
+
+template
+void ForcedEntropicEqDynamics::collide (
+ Cell& cell,
+ LatticeStatistics& statistics )
+{
+ typedef DESCRIPTOR L;
+ typedef entropicLbHelpers eLbH;
+
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+
+ T* force = cell.template getFieldPointer();
+ for (int iDim=0; iDim(u);
+
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] += omega * (eLbH::equilibrium(iPop,rho,u) - cell[iPop]);
+ }
+
+ lbHelpers::addExternalForce(cell, u, omega);
+
+ statistics.incrementStats(rho, uSqr);
+}
+
+template
+T ForcedEntropicEqDynamics::getOmega() const
+{
+ return omega;
+}
+
+template
+void ForcedEntropicEqDynamics::setOmega(T omega_)
+{
+ omega = omega_;
+}
+
+
+//==============================================================================//
+/////////////////////////// Class EntropicDynamics ///////////////////////////////
+//==============================================================================//
+/** \param omega_ relaxation parameter, related to the dynamic viscosity
+ * \param momenta_ a Momenta object to know how to compute velocity momenta
+ */
+template
+EntropicDynamics::EntropicDynamics (
+ T omega_, Momenta& momenta_ )
+ : BasicDynamics(momenta_),
+ omega(omega_)
+{ }
+
+template
+T EntropicDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ return entropicLbHelpers::equilibrium(iPop,rho,u);
+}
+
+template
+void EntropicDynamics::collide (
+ Cell& cell,
+ LatticeStatistics& statistics )
+{
+ typedef DESCRIPTOR L;
+ typedef entropicLbHelpers eLbH;
+
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T uSqr = util::normSqr(u);
+
+ T f[L::q], fEq[L::q], fNeq[L::q];
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ fEq[iPop] = eLbH::equilibrium(iPop,rho,u);
+ fNeq[iPop] = cell[iPop] - fEq[iPop];
+ f[iPop] = cell[iPop] + descriptors::t(iPop);
+ fEq[iPop] += descriptors::t(iPop);
+ }
+ //==============================================================================//
+ //============= Evaluation of alpha using a Newton Raphson algorithm ===========//
+ //==============================================================================//
+
+ T alpha = 2.0;
+ bool converged = getAlpha(alpha,f,fNeq);
+ if (!converged) {
+ std::cout << "Newton-Raphson failed to converge.\n";
+ exit(1);
+ }
+
+ OLB_ASSERT(converged,"Entropy growth failed to converge!");
+
+ T omegaTot = omega / 2.0 * alpha;
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] *= (T)1-omegaTot;
+ cell[iPop] += omegaTot * (fEq[iPop]-descriptors::t(iPop));
+ }
+
+ statistics.incrementStats(rho, uSqr);
+}
+
+template
+T EntropicDynamics::getOmega() const
+{
+ return omega;
+}
+
+template
+void EntropicDynamics::setOmega(T omega_)
+{
+ omega = omega_;
+}
+
+template
+T EntropicDynamics::computeEntropy(const T f[])
+{
+ typedef DESCRIPTOR L;
+ T entropy = T();
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ OLB_ASSERT(f[iPop] > T(), "f[iPop] <= 0");
+ entropy += f[iPop]*log(f[iPop]/descriptors::t(iPop));
+ }
+
+ return entropy;
+}
+
+template
+T EntropicDynamics::computeEntropyGrowth(const T f[], const T fNeq[], const T &alpha)
+{
+ typedef DESCRIPTOR L;
+
+ T fAlphaFneq[L::q];
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ fAlphaFneq[iPop] = f[iPop] - alpha*fNeq[iPop];
+ }
+
+ return computeEntropy(f) - computeEntropy(fAlphaFneq);
+}
+
+template
+T EntropicDynamics::computeEntropyGrowthDerivative(const T f[], const T fNeq[], const T &alpha)
+{
+ typedef DESCRIPTOR L;
+
+ T entropyGrowthDerivative = T();
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ T tmp = f[iPop] - alpha*fNeq[iPop];
+ OLB_ASSERT(tmp > T(), "f[iPop] - alpha*fNeq[iPop] <= 0");
+ entropyGrowthDerivative += fNeq[iPop]*(log(tmp/descriptors::t(iPop)));
+ }
+
+ return entropyGrowthDerivative;
+}
+
+template
+bool EntropicDynamics::getAlpha(T &alpha, const T f[], const T fNeq[])
+{
+ const T epsilon = std::numeric_limits::epsilon();
+
+ T alphaGuess = T();
+ const T var = 100.0;
+ const T errorMax = epsilon*var;
+ T error = 1.0;
+ int count = 0;
+ for (count = 0; count < 10000; ++count) {
+ T entGrowth = computeEntropyGrowth(f,fNeq,alpha);
+ T entGrowthDerivative = computeEntropyGrowthDerivative(f,fNeq,alpha);
+ if ((error < errorMax) || (fabs(entGrowth) < var*epsilon)) {
+ return true;
+ }
+ alphaGuess = alpha - entGrowth /
+ entGrowthDerivative;
+ error = fabs(alpha-alphaGuess);
+ alpha = alphaGuess;
+ }
+ return false;
+}
+
+//====================================================================//
+//////////////////// Class ForcedEntropicDynamics //////////////////////
+//====================================================================//
+
+/** \param omega_ relaxation parameter, related to the dynamic viscosity
+ */
+template
+ForcedEntropicDynamics::ForcedEntropicDynamics (
+ T omega_, Momenta& momenta_ )
+ : BasicDynamics(momenta_),
+ omega(omega_)
+{ }
+
+template
+T ForcedEntropicDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ return entropicLbHelpers::equilibrium(iPop,rho,u);
+}
+
+
+template
+void ForcedEntropicDynamics::collide (
+ Cell& cell,
+ LatticeStatistics& statistics )
+{
+ typedef DESCRIPTOR L;
+ typedef entropicLbHelpers eLbH;
+
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T uSqr = util::normSqr(u);
+
+ T f[L::q], fEq[L::q], fNeq[L::q];
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ fEq[iPop] = eLbH::equilibrium(iPop,rho,u);
+ fNeq[iPop] = cell[iPop] - fEq[iPop];
+ f[iPop] = cell[iPop] + descriptors::t(iPop);
+ fEq[iPop] += descriptors::t(iPop);
+ }
+ //==============================================================================//
+ //============= Evaluation of alpha using a Newton Raphson algorithm ===========//
+ //==============================================================================//
+
+ T alpha = 2.0;
+ bool converged = getAlpha(alpha,f,fNeq);
+ if (!converged) {
+ std::cout << "Newton-Raphson failed to converge.\n";
+ exit(1);
+ }
+
+ OLB_ASSERT(converged,"Entropy growth failed to converge!");
+
+ T* force = cell.template getFieldPointer();
+ for (int iDim=0; iDim(u);
+ T omegaTot = omega / 2.0 * alpha;
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] *= (T)1-omegaTot;
+ cell[iPop] += omegaTot * eLbH::equilibrium(iPop,rho,u);
+ }
+ lbHelpers::addExternalForce(cell, u, omegaTot);
+
+ statistics.incrementStats(rho, uSqr);
+}
+
+template
+T ForcedEntropicDynamics::getOmega() const
+{
+ return omega;
+}
+
+template
+void ForcedEntropicDynamics::setOmega(T omega_)
+{
+ omega = omega_;
+}
+
+template
+T ForcedEntropicDynamics::computeEntropy(const T f[])
+{
+ typedef DESCRIPTOR L;
+ T entropy = T();
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ OLB_ASSERT(f[iPop] > T(), "f[iPop] <= 0");
+ entropy += f[iPop]*log(f[iPop]/descriptors::t(iPop));
+ }
+
+ return entropy;
+}
+
+template
+T ForcedEntropicDynamics::computeEntropyGrowth(const T f[], const T fNeq[], const T &alpha)
+{
+ typedef DESCRIPTOR L;
+
+ T fAlphaFneq[L::q];
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ fAlphaFneq[iPop] = f[iPop] - alpha*fNeq[iPop];
+ }
+
+ return computeEntropy(f) - computeEntropy(fAlphaFneq);
+}
+
+template
+T ForcedEntropicDynamics::computeEntropyGrowthDerivative(const T f[], const T fNeq[], const T &alpha)
+{
+ typedef DESCRIPTOR L;
+
+ T entropyGrowthDerivative = T();
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ T tmp = f[iPop] - alpha*fNeq[iPop];
+ OLB_ASSERT(tmp > T(), "f[iPop] - alpha*fNeq[iPop] <= 0");
+ entropyGrowthDerivative += fNeq[iPop]*log(tmp/descriptors::t(iPop));
+ }
+
+ return entropyGrowthDerivative;
+}
+
+template
+bool ForcedEntropicDynamics::getAlpha(T &alpha, const T f[], const T fNeq[])
+{
+ const T epsilon = std::numeric_limits::epsilon();
+
+ T alphaGuess = T();
+ const T var = 100.0;
+ const T errorMax = epsilon*var;
+ T error = 1.0;
+ int count = 0;
+ for (count = 0; count < 10000; ++count) {
+ T entGrowth = computeEntropyGrowth(f,fNeq,alpha);
+ T entGrowthDerivative = computeEntropyGrowthDerivative(f,fNeq,alpha);
+ if ((error < errorMax) || (fabs(entGrowth) < var*epsilon)) {
+ return true;
+ }
+ alphaGuess = alpha - entGrowth /
+ entGrowthDerivative;
+ error = fabs(alpha-alphaGuess);
+ alpha = alphaGuess;
+ }
+ return false;
+}
+
+}
+
+#endif
+
--
cgit v1.2.3