summaryrefslogtreecommitdiff
path: root/src/dynamics/dynamics.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynamics/dynamics.hh')
-rw-r--r--src/dynamics/dynamics.hh2026
1 files changed, 2026 insertions, 0 deletions
diff --git a/src/dynamics/dynamics.hh b/src/dynamics/dynamics.hh
new file mode 100644
index 0000000..12b77bf
--- /dev/null
+++ b/src/dynamics/dynamics.hh
@@ -0,0 +1,2026 @@
+/* This file is part of the OpenLB library
+ *
+ * Copyright (C) 2006-2015 Jonas Latt, Mathias J. Krause
+ * E-mail contact: info@openlb.net
+ * The most recent release of OpenLB can be downloaded at
+ * <http://www.openlb.net/>
+ *
+ * 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 dynamics classes (e.g. BGK) with which a Cell object
+ * can be instantiated -- generic implementation.
+ */
+#ifndef LB_DYNAMICS_HH
+#define LB_DYNAMICS_HH
+
+#include <type_traits>
+#include <numeric>
+#include "dynamics.h"
+#include "core/cell.h"
+#include "lbHelpers.h"
+#include "firstOrderLbHelpers.h"
+#include "d3q13Helpers.h"
+
+namespace olb {
+
+////////////////////// Class Dynamics ////////////////////////
+
+template<typename T, typename DESCRIPTOR>
+T Dynamics<T,DESCRIPTOR>::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ return lbHelpers<T,DESCRIPTOR>::equilibrium(iPop, rho, u, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+void Dynamics<T,DESCRIPTOR>::iniEquilibrium(Cell<T,DESCRIPTOR>& cell, T rho, const T u[DESCRIPTOR::d])
+{
+ T uSqr = util::normSqr<T,DESCRIPTOR::d>(u);
+ for (int iPop=0; iPop<DESCRIPTOR::q; ++iPop) {
+ cell[iPop] = computeEquilibrium(iPop, rho, u, uSqr);
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void Dynamics<T,DESCRIPTOR>::setBoundaryIntersection(int iPop, T distance)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+bool Dynamics<T,DESCRIPTOR>::getBoundaryIntersection(int iPop, T point[DESCRIPTOR::d])
+{
+ return 0;
+}
+
+template<typename T, typename DESCRIPTOR>
+void Dynamics<T,DESCRIPTOR>::defineRho(int iPop, T rho)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void Dynamics<T,DESCRIPTOR>::defineU(const T u[DESCRIPTOR::d])
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void Dynamics<T,DESCRIPTOR>::defineU(int iPop, const T u[DESCRIPTOR::d])
+{ }
+
+template<typename T, typename DESCRIPTOR>
+T Dynamics<T,DESCRIPTOR>::getVelocityCoefficient(int iPop)
+{
+ return 0;
+}
+
+////////////////////// Class BasicDynamics ////////////////////////
+
+template<typename T, typename DESCRIPTOR>
+BasicDynamics<T,DESCRIPTOR>::BasicDynamics(Momenta<T,DESCRIPTOR>& momenta)
+ : _momenta(momenta)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+T BasicDynamics<T,DESCRIPTOR>::computeRho(Cell<T,DESCRIPTOR> const& cell) const
+{
+ return _momenta.computeRho(cell);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::computeU (
+ Cell<T,DESCRIPTOR> const& cell,
+ T u[DESCRIPTOR::d]) const
+{
+ _momenta.computeU(cell, u);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::computeJ (
+ Cell<T,DESCRIPTOR> const& cell,
+ T j[DESCRIPTOR::d]) const
+{
+ _momenta.computeJ(cell, j);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::computeStress (
+ Cell<T,DESCRIPTOR> const& cell,
+ T rho, const T u[DESCRIPTOR::d],
+ T pi[util::TensorVal<DESCRIPTOR >::n] ) const
+{
+ _momenta.computeStress(cell, rho, u, pi);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::computeRhoU (
+ Cell<T,DESCRIPTOR> const& cell,
+ T& rho, T u[DESCRIPTOR::d]) const
+{
+ _momenta.computeRhoU(cell, rho, u);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::computeAllMomenta (
+ Cell<T,DESCRIPTOR> const& cell,
+ T& rho, T u[DESCRIPTOR::d],
+ T pi[util::TensorVal<DESCRIPTOR >::n] ) const
+{
+ this->computeRhoU(cell, rho, u);
+ this->computeStress(cell, rho, u, pi);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::defineRho(Cell<T,DESCRIPTOR>& cell, T rho)
+{
+ _momenta.defineRho(cell, rho);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::defineU (
+ Cell<T,DESCRIPTOR>& cell,
+ const T u[DESCRIPTOR::d])
+{
+ _momenta.defineU(cell, u);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::defineRhoU (
+ Cell<T,DESCRIPTOR>& cell,
+ T rho, const T u[DESCRIPTOR::d])
+{
+ _momenta.defineRhoU(cell, rho, u);
+}
+
+template<typename T, typename DESCRIPTOR>
+void BasicDynamics<T,DESCRIPTOR>::defineAllMomenta (
+ Cell<T,DESCRIPTOR>& cell,
+ T rho, const T u[DESCRIPTOR::d],
+ const T pi[util::TensorVal<DESCRIPTOR >::n] )
+{
+ _momenta.defineAllMomenta(cell, rho, u, pi);
+}
+
+
+////////////////////// Class BGKdynamics //////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+BGKdynamics<T,DESCRIPTOR>::BGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta),
+ _omega(omega)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void BGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T uSqr = lbHelpers<T,DESCRIPTOR>::bgkCollision(cell, rho, u, _omega);
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T BGKdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void BGKdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+
+////////////////////// Class TRTdynamics //////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+TRTdynamics<T,DESCRIPTOR>::TRTdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta, T magicParameter )
+ : BasicDynamics<T,DESCRIPTOR>(momenta),
+ _omega(omega), _omega2(1/(magicParameter/(1/omega-0.5)+0.5)), _magicParameter(magicParameter)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void TRTdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ // T uSqr = lbHelpers<T,DESCRIPTOR>::bgkCollision(cell, rho, u, _omega);
+ const T uSqr = util::normSqr<T,DESCRIPTOR::d>(u);
+ T fPlus[DESCRIPTOR::q], fMinus[DESCRIPTOR::q];
+ T fEq[DESCRIPTOR::q], fEqPlus[DESCRIPTOR::q], fEqMinus[DESCRIPTOR::q];
+
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ fPlus[iPop] = 0.5 * ( cell[iPop] + cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ fMinus[iPop] = 0.5 * ( cell[iPop] - cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ fEq[iPop] = lbHelpers<T, DESCRIPTOR>::equilibrium(iPop, rho, u, uSqr);
+ }
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ fEqPlus[iPop] = 0.5 * ( fEq[iPop] + fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ fEqMinus[iPop] = 0.5 * ( fEq[iPop] - fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ }
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] -= _omega * (fPlus[iPop] - fEqPlus[iPop]) + _omega2 * (fMinus[iPop] - fEqMinus[iPop]);
+ }
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T TRTdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void TRTdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+////////////////////// Class ConstRhoBGKdynamics //////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+ConstRhoBGKdynamics<T,DESCRIPTOR>::ConstRhoBGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta),
+ _omega(omega)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void ConstRhoBGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+
+ T deltaRho = (T)1 - (statistics).getAverageRho();
+ T ratioRho = (T)1 + deltaRho/rho;
+
+ T uSqr = lbHelpers<T,DESCRIPTOR>::constRhoBgkCollision (
+ cell, rho, u, ratioRho, _omega );
+ statistics.incrementStats(rho+deltaRho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T ConstRhoBGKdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void ConstRhoBGKdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+////////////////////// Class IncBGKdynamics //////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+IncBGKdynamics<T,DESCRIPTOR>::IncBGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta), _omega(omega)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void IncBGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho = this->_momenta.computeRho(cell);
+ T p = rho / descriptors::invCs2<T,DESCRIPTOR>();
+ T j[DESCRIPTOR::d];
+ this->_momenta.computeJ(cell, j);
+ T uSqr = lbHelpers<T,DESCRIPTOR>::incBgkCollision(cell, p, j, _omega);
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T IncBGKdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void IncBGKdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+
+
+////////////////////// Class RLBdynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+RLBdynamics<T,DESCRIPTOR>::RLBdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta),
+ _omega(omega)
+{ }
+
+template<typename T, typename DESCRIPTOR>
+void RLBdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d], pi[util::TensorVal<DESCRIPTOR >::n];
+ this->_momenta.computeAllMomenta(cell, rho, u, pi);
+ T uSqr = rlbHelpers<T,DESCRIPTOR>::rlbCollision(cell, rho, u, pi, _omega);
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T RLBdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void RLBdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+////////////////////// Class CombinedRLBdynamics /////////////////////////
+
+template<typename T, typename DESCRIPTOR, typename Dynamics>
+CombinedRLBdynamics<T,DESCRIPTOR,Dynamics>::CombinedRLBdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta),
+ _boundaryDynamics(omega, momenta)
+{ }
+
+template<typename T, typename DESCRIPTOR, typename Dynamics>
+T CombinedRLBdynamics<T,DESCRIPTOR,Dynamics>::
+computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ return _boundaryDynamics.computeEquilibrium(iPop, rho, u, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR, typename Dynamics>
+void CombinedRLBdynamics<T,DESCRIPTOR,Dynamics>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ typedef DESCRIPTOR L;
+
+ T rho, u[L::d], pi[util::TensorVal<DESCRIPTOR >::n];
+ this->_momenta.computeAllMomenta(cell,rho,u,pi);
+
+ T uSqr = util::normSqr<T,L::d>(u);
+
+ for (int iPop = 0; iPop < L::q; ++iPop) {
+ cell[iPop] = computeEquilibrium(iPop,rho,u,uSqr) +
+ firstOrderLbHelpers<T,DESCRIPTOR>::fromPiToFneq(iPop, pi);
+ }
+
+ _boundaryDynamics.collide(cell, statistics);
+}
+
+template<typename T, typename DESCRIPTOR, typename Dynamics>
+T CombinedRLBdynamics<T,DESCRIPTOR,Dynamics>::getOmega() const
+{
+ return _boundaryDynamics.getOmega();
+}
+
+template<typename T, typename DESCRIPTOR, typename Dynamics>
+void CombinedRLBdynamics<T,DESCRIPTOR,Dynamics>::setOmega(T omega)
+{
+ _boundaryDynamics.setOmega(omega);
+}
+
+
+////////////////////// Class ForcedBGKdynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+ForcedBGKdynamics<T,DESCRIPTOR>::ForcedBGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta), _omega(omega)
+{
+ OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::FORCE>() );
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedBGKdynamics<T,DESCRIPTOR>::computeU (Cell<T,DESCRIPTOR> const& cell, T u[DESCRIPTOR::d] ) const
+{
+ T rho;
+ this->_momenta.computeRhoU(cell, rho, u);
+ const T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ for (int iVel=0; iVel < DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / (T)2.;
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedBGKdynamics<T,DESCRIPTOR>::computeRhoU (Cell<T,DESCRIPTOR> const& cell, T& rho, T u[DESCRIPTOR::d] ) const
+{
+ this->_momenta.computeRhoU(cell, rho, u);
+ const T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / (T)2.;
+ }
+}
+
+
+template<typename T, typename DESCRIPTOR>
+void ForcedBGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ const T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / (T)2.;
+ }
+ T uSqr = lbHelpers<T,DESCRIPTOR>::bgkCollision(cell, rho, u, _omega);
+ lbHelpers<T,DESCRIPTOR>::addExternalForce(cell, u, _omega, rho);
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T ForcedBGKdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedBGKdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+////////////////////// Class ForcedKupershtokhBGKdynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+ForcedKupershtokhBGKdynamics<T,DESCRIPTOR>::ForcedKupershtokhBGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta), _omega(omega)
+{
+ OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::FORCE>() );
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedKupershtokhBGKdynamics<T,DESCRIPTOR>::computeU (Cell<T,DESCRIPTOR> const& cell, T u[DESCRIPTOR::d] ) const
+{
+ T rho;
+ this->_momenta.computeRhoU(cell, rho, u);
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += cell.template getFieldPointer<descriptors::FORCE>()[iVel] / (T)2.;
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedKupershtokhBGKdynamics<T,DESCRIPTOR>::computeRhoU (Cell<T,DESCRIPTOR> const& cell, T& rho, T u[DESCRIPTOR::d] ) const
+{
+ this->_momenta.computeRhoU(cell, rho, u);
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += cell.template getFieldPointer<descriptors::FORCE>()[iVel] / (T)2.;
+ }
+}
+
+
+template<typename T, typename DESCRIPTOR>
+void ForcedKupershtokhBGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d], uPlusDeltaU[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ T uSqr = lbHelpers<T,DESCRIPTOR>::bgkCollision(cell, rho, u, _omega);
+
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ uPlusDeltaU[iVel] = u[iVel] + force[iVel];
+ }
+ const T uPlusDeltaUSqr = util::normSqr<T,DESCRIPTOR::d>(uPlusDeltaU);
+
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] += lbHelpers<T, DESCRIPTOR>::equilibrium(iPop, rho, uPlusDeltaU, uPlusDeltaUSqr)
+ - lbHelpers<T, DESCRIPTOR>::equilibrium(iPop, rho, u, uSqr);
+ }
+
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T ForcedKupershtokhBGKdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedKupershtokhBGKdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta Momenta object to know how to compute velocity momenta
+ * \param sink counterpart of a source term
+ */
+template<typename T, typename DESCRIPTOR>
+PoissonDynamics<T,DESCRIPTOR>::PoissonDynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta , T sink)
+ : BasicDynamics<T,DESCRIPTOR>(momenta), _omega(omega), _sink(sink)
+{
+}
+
+template<typename T, typename DESCRIPTOR>
+T PoissonDynamics<T,DESCRIPTOR>::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr ) const
+{
+ return descriptors::t<T,DESCRIPTOR>(iPop) * rho - descriptors::t<T,DESCRIPTOR>(iPop);
+}
+
+
+template<typename T, typename DESCRIPTOR>
+T PoissonDynamics<T,DESCRIPTOR>::computeRho(Cell<T,DESCRIPTOR> const& cell) const
+{
+ return lbHelpers<T,DESCRIPTOR>::computeRho(cell);
+}
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::computeU(Cell<T,DESCRIPTOR> const& cell, T u[DESCRIPTOR::d]) const
+{
+ for ( int iDim = 0; iDim < DESCRIPTOR::d; iDim++ ) {
+ u[iDim] = T();
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::computeJ(Cell<T,DESCRIPTOR> const& cell, T j[DESCRIPTOR::d]) const
+{
+ lbHelpers<T,DESCRIPTOR>::computeJ(cell, j);
+}
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::computeStress(Cell<T,DESCRIPTOR> const& cell, T rho,
+ const T u[DESCRIPTOR::d], T pi[util::TensorVal<DESCRIPTOR>::n] ) const
+{
+ for ( int iDim = 0; iDim < DESCRIPTOR::d; iDim++ ) {
+ pi[iDim] = T();
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::computeRhoU( Cell<T,DESCRIPTOR> const& cell, T& rho, T u[DESCRIPTOR::d]) const
+{
+ rho = computeRho(cell);
+ computeU(cell, u);
+}
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::computeAllMomenta( Cell<T,DESCRIPTOR> const& cell, T &rho,
+ T u[DESCRIPTOR::q], T pi[util::TensorVal<DESCRIPTOR>::n] ) const
+{
+ rho = computeRho(cell);
+ computeU(cell, u);
+ computeStress(cell, rho, u, pi);
+}
+
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::collide( Cell<T,DESCRIPTOR>& cell, LatticeStatistics<T>& statistics )
+{
+ T rho = computeRho(cell);
+
+ for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) {
+ cell[iPop] = (1 - _omega) * (cell[iPop] + descriptors::t<T,DESCRIPTOR>(iPop))
+ + _omega * descriptors::t<T,DESCRIPTOR>(iPop) * rho
+ - _sink*(cell[iPop] + descriptors::t<T,DESCRIPTOR>(iPop)) - descriptors::t<T,DESCRIPTOR>(iPop);
+ }
+
+// // add spherical harmonic definition f_i = 3*pi/4 *density + pi/4 *flux \cdot e_i
+// T density_post_collision = lbDynamicsHelpers<T,DESCRIPTOR>::computeRho(cell);
+// T flux_post_collision[DESCRIPTOR::q];
+// lbDynamicsHelpers<T,DESCRIPTOR>::computeJ(cell,flux_post_collision);
+// T s = flux_post_collision[0]*descriptors::t<T,DESCRIPTOR>(0)+
+// flux_post_collision[1]*descriptors::t<T,DESCRIPTOR>(1)+
+// flux_post_collision[2]*descriptors::t<T,DESCRIPTOR>(2);
+// std::cout << "s " << s << std::endl;
+// for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) {
+// cell[iPop] = 3*M_PI/4. *density_post_collision
+// + M_PI/4. *s;
+// }
+ statistics.incrementStats(rho, 0);
+}
+
+template<typename T, typename DESCRIPTOR>
+T PoissonDynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void PoissonDynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+
+template<typename T, typename DESCRIPTOR>
+P1Dynamics<T,DESCRIPTOR>::P1Dynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta , T absorption, T scattering)
+ : BasicDynamics<T,DESCRIPTOR>(momenta), _omega(omega), _absorption(absorption), _scattering(scattering)
+{
+}
+
+template<typename T, typename DESCRIPTOR>
+T P1Dynamics<T,DESCRIPTOR>::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr ) const
+{
+ return descriptors::t<T,DESCRIPTOR>(iPop) * rho - descriptors::t<T,DESCRIPTOR>(iPop);
+}
+
+
+template<typename T, typename DESCRIPTOR>
+T P1Dynamics<T,DESCRIPTOR>::computeRho(Cell<T,DESCRIPTOR> const& cell) const
+{
+ return lbHelpers<T,DESCRIPTOR>::computeRho(cell);
+}
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::computeU(Cell<T,DESCRIPTOR> const& cell, T u[DESCRIPTOR::d]) const
+{
+ for ( int iDim = 0; iDim < DESCRIPTOR::d; iDim++ ) {
+ u[iDim] = T();
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::computeJ(Cell<T,DESCRIPTOR> const& cell, T j[DESCRIPTOR::d]) const
+{
+ lbHelpers<T,DESCRIPTOR>::computeJ(cell, j);
+}
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::computeStress(Cell<T,DESCRIPTOR> const& cell, T rho,
+ const T u[DESCRIPTOR::d], T pi[util::TensorVal<DESCRIPTOR>::n] ) const
+{
+ for ( int iDim = 0; iDim < DESCRIPTOR::d; iDim++ ) {
+ pi[iDim] = T();
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::computeRhoU( Cell<T,DESCRIPTOR> const& cell, T& rho, T u[DESCRIPTOR::d]) const
+{
+ rho = computeRho(cell);
+ computeU(cell, u);
+}
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::computeAllMomenta( Cell<T,DESCRIPTOR> const& cell, T &rho,
+ T u[DESCRIPTOR::q], T pi[util::TensorVal<DESCRIPTOR>::n] ) const
+{
+ rho = computeRho(cell);
+ computeU(cell, u);
+ computeStress(cell, rho, u, pi);
+}
+
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::collide( Cell<T,DESCRIPTOR>& cell, LatticeStatistics<T>& statistics )
+{
+ T rho = computeRho(cell);
+
+ // compute equilibrium f^eq_i eq. (5.32) from DOI:10.1002/9780470177013
+
+ // ----move to computeEq
+ // give me a std::array, please
+ std::array<T,DESCRIPTOR::q> cellShifted;
+ for (int iPop = 0; iPop <DESCRIPTOR::q; ++iPop) {
+ cellShifted[iPop] = cell[iPop] + descriptors::t<T,DESCRIPTOR>(iPop);
+ }
+ double moment0 = std::accumulate(cellShifted.begin(),cellShifted.end(), T(0));
+ std::array<T,DESCRIPTOR::d> moment1;
+ moment1.fill( T(0) );
+ // sum_j v_j f_j
+ for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
+ for (int iDim = 0; iDim < DESCRIPTOR::d; ++iDim) {
+ moment1[iDim] += descriptors::c<DESCRIPTOR>(iPop,iDim)*cellShifted[iPop];
+ }
+ }
+ // do scalar product in eq. sum_j v_j f_j * v_i
+ std::array<T,DESCRIPTOR::q> moment1_v;
+ moment1_v.fill( T(0) );
+ for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
+ // scalar product
+ for (int iDim = 0; iDim < DESCRIPTOR::d; ++iDim) {
+ moment1_v[iPop] += moment1[iDim]*descriptors::c<DESCRIPTOR>(iPop,iDim);
+ }
+ }
+ std::array<T,DESCRIPTOR::q> fEq;
+ for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
+ fEq[iPop] = descriptors::t<T,DESCRIPTOR>(iPop) *(moment0 +moment1_v[iPop]);
+ //fEq[iPop] = 1./(4*M_PI) *moment0 +3./(4*M_PI) * moment1_v[iPop] -descriptors::t<T,DESCRIPTOR>(iPop);
+ }
+
+
+ std::array<T,DESCRIPTOR::q> relaxCell;
+ for (int iPop = 0; iPop <DESCRIPTOR::q; ++iPop) {
+ relaxCell[iPop] =
+ cellShifted[iPop]
+ - _scattering*(cellShifted[iPop] - fEq[iPop])
+ - (_absorption+_scattering)*descriptors::t<T,DESCRIPTOR>(iPop)*cellShifted[iPop];
+ }
+
+ for (int iPop = 0; iPop <DESCRIPTOR::q; ++iPop) {
+ cell[iPop] = relaxCell[iPop] - descriptors::t<T,DESCRIPTOR>(iPop);
+ }
+
+ statistics.incrementStats(rho, 0);
+}
+
+template<typename T, typename DESCRIPTOR>
+T P1Dynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void P1Dynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+
+////////////////////// Class ResettingForcedBGKdynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+ResettingForcedBGKdynamics<T,DESCRIPTOR>::ResettingForcedBGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : ForcedBGKdynamics<T,DESCRIPTOR>(omega, momenta)
+{
+ OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::FORCE>() );
+}
+
+template<typename T, typename DESCRIPTOR>
+void ResettingForcedBGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ if ( !util::nearZero(force[0]) || !util::nearZero(force[1]) || !util::nearZero(force[2]) ) // TODO: unnecessary??
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / (T)2.;
+ }
+// if (force[2] != 0)
+// std::cout << force[0] << " " << force[1] << " " << force[2] << std::endl;
+ T uSqr = lbHelpers<T,DESCRIPTOR>::bgkCollision(cell, rho, u, this->_omega);
+ lbHelpers<T,DESCRIPTOR>::addExternalForce(cell, u, this->_omega, rho);
+ statistics.incrementStats(rho, uSqr);
+
+ force[0] = _frc[0];
+ force[1] = _frc[1];
+ force[2] = _frc[2];
+// force[0] = 0.;
+// force[1] = 0.;
+// force[2] = 0.;
+}
+
+////////////////////// Class ForcedShanChenBGKdynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+ForcedShanChenBGKdynamics<T,DESCRIPTOR>::ForcedShanChenBGKdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : ForcedBGKdynamics<T,DESCRIPTOR>(omega, momenta )
+{
+ OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::FORCE>() );
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedShanChenBGKdynamics<T,DESCRIPTOR>::computeU (Cell<T,DESCRIPTOR> const& cell, T u[DESCRIPTOR::d] ) const
+{
+ T rho;
+ this->_momenta.computeRhoU(cell, rho, u);
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += cell.template getFieldPointer<descriptors::FORCE>()[iVel] / (T)2.;
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedShanChenBGKdynamics<T,DESCRIPTOR>::computeRhoU (Cell<T,DESCRIPTOR> const& cell, T& rho, T u[DESCRIPTOR::d] ) const
+{
+ this->_momenta.computeRhoU(cell, rho, u);
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += cell.template getFieldPointer<descriptors::FORCE>()[iVel] / (T)2.;
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedShanChenBGKdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / this->getOmega();
+ }
+ T uSqr = lbHelpers<T,DESCRIPTOR>::bgkCollision(cell, rho, u, this->getOmega() );
+ uSqr=0.;
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / (T)2.;
+ u[iVel] -= force[iVel] / this->getOmega();
+ uSqr += u[iVel]*u[iVel];
+ }
+ statistics.incrementStats(rho, uSqr);
+}
+
+////////////////////// Class ForcedTRTdynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+ForcedTRTdynamics<T,DESCRIPTOR>::ForcedTRTdynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta, T magicParameter )
+ : BasicDynamics<T,DESCRIPTOR>(momenta),
+ _omega(omega), _omega2(1/(magicParameter/(1/omega-0.5)+0.5)), _magicParameter(magicParameter)
+{
+ OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::FORCE>() );
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedTRTdynamics<T,DESCRIPTOR>::computeU (Cell<T,DESCRIPTOR> const& cell, T u[DESCRIPTOR::d] ) const
+{
+ T rho;
+ this->_momenta.computeRhoU(cell, rho, u);
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += cell.template getFieldPointer<descriptors::FORCE>()[iVel] / (T)2.;
+ }
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedTRTdynamics<T,DESCRIPTOR>::computeRhoU (Cell<T,DESCRIPTOR> const& cell, T& rho, T u[DESCRIPTOR::d] ) const
+{
+ this->_momenta.computeRhoU(cell, rho, u);
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += cell.template getFieldPointer<descriptors::FORCE>()[iVel] / (T)2.;
+ }
+}
+
+
+template<typename T, typename DESCRIPTOR>
+void ForcedTRTdynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T* force = cell.template getFieldPointer<descriptors::FORCE>();
+ for (int iVel=0; iVel<DESCRIPTOR::d; ++iVel) {
+ u[iVel] += force[iVel] / (T)2.;
+ }
+ const T uSqr = util::normSqr<T,DESCRIPTOR::d>(u);
+ T fPlus[DESCRIPTOR::q], fMinus[DESCRIPTOR::q];
+ T fEq[DESCRIPTOR::q], fEqPlus[DESCRIPTOR::q], fEqMinus[DESCRIPTOR::q];
+
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ fPlus[iPop] = 0.5 * ( cell[iPop] + cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ fMinus[iPop] = 0.5 * ( cell[iPop] - cell[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ fEq[iPop] = lbHelpers<T, DESCRIPTOR>::equilibrium(iPop, rho, u, uSqr);
+ }
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ fEqPlus[iPop] = 0.5 * ( fEq[iPop] + fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ fEqMinus[iPop] = 0.5 * ( fEq[iPop] - fEq[descriptors::opposite<DESCRIPTOR>(iPop)] );
+ }
+ for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
+ cell[iPop] -= _omega * (fPlus[iPop] - fEqPlus[iPop]) + _omega2 * (fMinus[iPop] - fEqMinus[iPop]);
+ }
+ lbHelpers<T,DESCRIPTOR>::addExternalForce(cell, u, _omega, rho);
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T ForcedTRTdynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return _omega;
+}
+
+template<typename T, typename DESCRIPTOR>
+void ForcedTRTdynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ _omega = omega;
+}
+////////////////////// Class D3Q13dynamics /////////////////////////
+
+/** \param omega relaxation parameter, related to the dynamic viscosity
+ * \param momenta a Momenta object to know how to compute velocity momenta
+ */
+template<typename T, typename DESCRIPTOR>
+D3Q13dynamics<T,DESCRIPTOR>::D3Q13dynamics (
+ T omega, Momenta<T,DESCRIPTOR>& momenta )
+ : BasicDynamics<T,DESCRIPTOR>(momenta)
+{
+ setOmega(omega);
+}
+
+template<typename T, typename DESCRIPTOR>
+T D3Q13dynamics<T,DESCRIPTOR>::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const
+{
+ // To get at the equilibrium, execute collision with relaxation parameters 1
+ Cell<T,DESCRIPTOR> tmp;
+ for (int pop=0; pop<DESCRIPTOR::q; ++pop) {
+ tmp[pop] = descriptors::t<T,DESCRIPTOR>(pop);
+ }
+ d3q13Helpers<T>::collision(tmp, rho, u, (T)1, (T)1);
+ return tmp[iPop];
+}
+
+template<typename T, typename DESCRIPTOR>
+void D3Q13dynamics<T,DESCRIPTOR>::collide (
+ Cell<T,DESCRIPTOR>& cell,
+ LatticeStatistics<T>& statistics )
+{
+ T rho, u[DESCRIPTOR::d];
+ this->_momenta.computeRhoU(cell, rho, u);
+ T uSqr = d3q13Helpers<T>::collision (
+ cell, rho, u, lambda_nu, lambda_nu_prime );
+ statistics.incrementStats(rho, uSqr);
+}
+
+template<typename T, typename DESCRIPTOR>
+T D3Q13dynamics<T,DESCRIPTOR>::getOmega() const
+{
+ return (T)4 / ( (T)3/lambda_nu + (T)1/(T)2 );
+}
+
+template<typename T, typename DESCRIPTOR>
+void D3Q13dynamics<T,DESCRIPTOR>::setOmega(T omega)
+{
+ lambda_nu = (T)3 / ( (T)4/omega - (T)1/(T)2 );
+ lambda_nu_prime = (T)3 / ( (T)2/omega + (T)1/(T)2 );
+}
+
+////////////////////// Class Momenta //////////////////////////////
+
+template<typename T, typename DESCRIPTOR>
+void Momenta<T,DESCRIPTOR>::computeRhoU (
+ Cell<T,DESCRIPTOR> const& cell,
+ T& rho, T u[DESCRIPTOR::d]) const
+{
+ rho = this->computeRho(cell);
+ this->computeU(cell, u);
+
+}
+
+template<typename T, typename DESCRIPTOR>
+void Momenta<T,DESCRIPTOR>::computeAllMomenta (
+ Cell<T,DESCRIPTOR> const& cell,
+ T& rho, T u[DESCRIPTOR::d],
+ T pi[util::TensorVal<DESCRIPTOR >::n] ) const
+{
+ this->computeRhoU(cell, rho, u);
+ this->computeStress(cell, rho, u, pi);
+}
+
+template<typename T, typename DESCRIPTOR>
+void Momenta<T,DESCRIPTOR>::defineRhoU (
+ Cell<T,DESCRIPTOR>& cell,
+ T rho, const T u[DESCRIPTOR::d])
+{
+ this->defineRho(cell, rho);
+ this->defineU(cell, u);
+
+}
+
+////////////////////// Class BulkMomenta //////////////////////////
+
+template<typename T, typename DESCRIPTOR>
+T BulkMomenta<T,DESCRIPTOR>::computeRho(Cell<T,DESCRIPTOR> const