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