/* This file is part of the OpenLB library
*
* Copyright (C) 2006, 2007 Jonas Latt
* 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
* Template specializations for some computationally intensive LB
* functions of the header file lbHelpers.h, for the D2Q5 grid.
*/
#ifndef LB_HELPERS_D2Q5_H
#define LB_HELPERS_D2Q5_H
#include "mrtLatticeDescriptors.h"
namespace olb {
// Efficient specialization for D2Q5 lattice
template
struct lbDynamicsHelpers > {
using SpecializedCellBase = CellBase>;
static T equilibrium( int iPop, T rho, const T u[2], T uSqr )
{
typedef descriptors::D2Q5<> L;
T c_u = descriptors::c(iPop,0)*u[0] + descriptors::c(iPop,1)*u[1];
return rho * descriptors::t(iPop) * (
1. + 3.*c_u + 4.5*c_u*c_u - 1.5*uSqr )
- descriptors::t(iPop);
}
/// equilibrium distribution
static T equilibriumFirstOrder( int iPop, T rho, const T u[2] )
{
typedef descriptors::D2Q5<> L;
T c_u = descriptors::c(iPop,0) * u[0] + descriptors::c(iPop,1) * u[1];
return rho * descriptors::t(iPop) * ( ( T )1 + c_u * descriptors::invCs2() ) - descriptors::t(iPop);
}
/// RLB advection diffusion collision step
static T rlbCollision( SpecializedCellBase& cell, T rho, const T u[2], T omega )
{
typedef descriptors::D2Q5<> L;
const T uSqr = u[0] * u[0] + u[1] * u[1];
const T Cs2 = ( T )1 / descriptors::invCs2();
T rho_1 = rho - ( T )1;
cell[0] = ( ( T )1 - ( T )2 * Cs2 ) * rho_1; //f[0]=(1-2c_s^2)(rho-1)
const T omega_ = ( T )1 - omega;
const T f1_3 = ( T )0.5 * omega_ * ( cell[1] - cell[3] );
const T f2_4 = ( T )0.5 * omega_ * ( cell[2] - cell[4] );
rho_1 *= ( T )0.5 * Cs2;
const T ux_ = ( T )0.5 * omega * rho * u[0];
cell[1] = rho_1 + f1_3 - ux_; //f[1]=1/2*(c_s^2(rho-1)+(1-omega)*(f[1]-f[3])-omega*rho*u[x])
cell[3] = rho_1 - f1_3 + ux_; //f[3]=1/2*(c_s^2(rho-1)-(1-omega)*(f[1]-f[3])+omega*rho*u[x])
const T uy_ = ( T )0.5 * omega * rho * u[1];
cell[2] = rho_1 + f2_4 - uy_; //f[2]=1/2*(c_s^2(rho-1)+(1-omega)*(f[2]-f[4])-omega*rho*u[y])
cell[4] = rho_1 - f2_4 + uy_; //f[4]=1/2*(c_s^2(rho-1)-(1-omega)*(f[2]-f[4])+omega*rho*u[y])
return uSqr;
}
// BGK advection diffusion collision step
static T bgkCollision( SpecializedCellBase& cell, T rho, const T u[2], T omega )
{
typedef descriptors::D2Q5<> L;
const T Cs2 = ( T )1 / descriptors::invCs2();
const T uSqr = u[0] * u[0] + u[1] * u[1];
const T omega_ = ( T )1 - omega;
const T omega_2 = ( T )0.5 * omega;
T rho_ = ( rho - ( T )1 );
cell[0] = omega_ * cell[0] + omega * ( ( T )1 - ( T )2 * Cs2 ) * rho_;
const T jx = rho * u[0];
const T jy = rho * u[1];
rho_ *= Cs2;
cell[1] = omega_ * cell[1] + omega_2 * ( rho_ - jx );
cell[2] = omega_ * cell[2] + omega_2 * ( rho_ - jy );
cell[3] = omega_ * cell[3] + omega_2 * ( rho_ + jx );
cell[4] = omega_ * cell[4] + omega_2 * ( rho_ + jy );
return uSqr;
}
static void computeMomentaEquilibrium( T momentaEq[5], T rho, const T u[2], T uSqr )
{
momentaEq[0] = rho;
momentaEq[1] = rho*u[0];
momentaEq[2] = rho*u[1];
momentaEq[3] = -rho*(T)2/(T)3;
momentaEq[4] = T();
}
static void computeMomenta( T momenta[5], SpecializedCellBase const& cell )
{
momenta[0] = cell[0] + cell[1] + cell[2] + cell[3] + cell[4];
momenta[1] = -cell[1] + cell[3];
momenta[2] = -cell[2] + cell[4];
momenta[3] = -(T)4*cell[0] + cell[1] + cell[2] + cell[3] + cell[4] - (T)2 / (T)3;
momenta[4] = cell[1] - cell[2] + cell[3] - cell[4];
}
static T mrtCollision( SpecializedCellBase& cell, T rho, const T u[2], T invM_S[5][5] )
{
T uSqr = util::normSqr(u);
T momenta[5];
T momentaEq[5];
computeMomenta(momenta, cell);
computeMomentaEquilibrium(momentaEq, rho, u, uSqr);
T mom1 = momenta[1] - momentaEq[1];
T mom2 = momenta[2] - momentaEq[2];
T mom3 = momenta[3] - momentaEq[3];
T mom4 = momenta[4] - momentaEq[4];
cell[0] -= invM_S[0][1]*mom1 + invM_S[0][2]*mom2 +
invM_S[0][3]*mom3 + invM_S[0][4]*mom4;
cell[1] -= invM_S[1][1]*mom1 + invM_S[1][2]*mom2 +
invM_S[1][3]*mom3 + invM_S[1][4]*mom4;
cell[2] -= invM_S[2][1]*mom1 + invM_S[2][2]*mom2 +
invM_S[2][3]*mom3 + invM_S[2][4]*mom4;
cell[3] -= invM_S[3][1]*mom1 + invM_S[3][2]*mom2 +
invM_S[3][3]*mom3 + invM_S[3][4]*mom4;
cell[4] -= invM_S[4][1]*mom1 + invM_S[4][2]*mom2 +
invM_S[4][3]*mom3 + invM_S[4][4]*mom4;
return uSqr;
}
static void computeFneq ( SpecializedCellBase const& cell, T fNeq[5], T rho, const T u[2] )
{
for (int iPop=0; iPop < 5; ++iPop) {
// printf("WARNING: First order equilibrium function is used for the calculation of the non-equilibrium parts!\n");
fNeq[iPop] = cell[iPop] - equilibriumFirstOrder(iPop, rho, u);
}
}
static T computeRho(SpecializedCellBase const& cell)
{
T rho = cell[0] + cell[1] + cell[2] + cell[3] + cell[4] + (T)1;
return rho;
}
static void computeRhoU(SpecializedCellBase const& cell, T& rho, T u[2])
{
rho = cell[0] + cell[1] + cell[2] + cell[3] + cell[4] + (T)1;
T invRho= 1./rho;
u[0] = (cell[3] - cell[1])*invRho;
u[1] = (cell[4] - cell[2])*invRho;
}
static void computeRhoJ(SpecializedCellBase const& cell, T& rho, T j[2])
{
rho = cell[0] + cell[1] + cell[2] + cell[3] + cell[4] + (T)1;
j[0] = (cell[3] - cell[1]);
j[1] = (cell[4] - cell[2]);
}
static void computeJ(SpecializedCellBase const& cell, T j[2])
{
j[0] = (cell[3] - cell[1]);
j[1] = (cell[4] - cell[2]);
}
static void computeStress(SpecializedCellBase const& cell, T rho, const T u[2], T pi[6])
{
// printf("ERROR: Stress tensor not defined in D2Q5!\n");
}
static void computeAllMomenta(SpecializedCellBase const& cell, T& rho, T u[2], T pi[6])
{
rho = cell[0] + cell[1] + cell[2] + cell[3] + cell[4] + (T)1;
T invRho= 1./rho;
u[0] = (cell[3] - cell[1])*invRho;
u[1] = (cell[4] - cell[2])*invRho;
assert(false);
}
};
} // namespace olb
#endif