/* This file is part of the OpenLB library
*
* Copyright (C) 2008 Orestis Malaspinas, Andrea Parmigiani, 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.
*/
#ifndef NAVIER_STOKES_ADVECTION_DIFFUSION_COUPLING_POST_PROCESSOR_2D_HH
#define NAVIER_STOKES_ADVECTION_DIFFUSION_COUPLING_POST_PROCESSOR_2D_HH
#include "latticeDescriptors.h"
#include "navierStokesAdvectionDiffusionCouplingPostProcessor2D.h"
#include "core/blockLattice2D.h"
#include "core/util.h"
#include "core/finiteDifference2D.h"
using namespace std;
namespace olb {
//=====================================================================================
//============== NavierStokesAdvectionDiffusionCouplingPostProcessor2D ===============
//=====================================================================================
template
NavierStokesAdvectionDiffusionCouplingPostProcessor2D::
NavierStokesAdvectionDiffusionCouplingPostProcessor2D(int x0_, int x1_, int y0_, int y1_,
T gravity_, T T0_, T deltaTemp_, std::vector dir_,
std::vector partners_)
: x0(x0_), x1(x1_), y0(y0_), y1(y1_),
gravity(gravity_), T0(T0_), deltaTemp(deltaTemp_),
dir(dir_), partners(partners_)
{
// we normalize the direction of force vector
T normDir = T();
for (unsigned iD = 0; iD < dir.size(); ++iD) {
normDir += dir[iD]*dir[iD];
}
normDir = sqrt(normDir);
for (unsigned iD = 0; iD < dir.size(); ++iD) {
dir[iD] /= normDir;
}
for (unsigned iD = 0; iD < dir.size(); ++iD) {
forcePrefactor[iD] = gravity * dir[iD];
}
tPartner = dynamic_cast> *>(partners[0]);
}
template
void NavierStokesAdvectionDiffusionCouplingPostProcessor2D::
processSubDomain(BlockLattice2D& blockLattice,
int x0_, int x1_, int y0_, int y1_)
{
int newX0, newX1, newY0, newY1;
if ( util::intersect (
x0, x1, y0, y1,
x0_, x1_, y0_, y1_,
newX0, newX1, newY0, newY1 ) ) {
for (int iX=newX0; iX<=newX1; ++iX) {
for (int iY=newY0; iY<=newY1; ++iY) {
// computation of the bousinessq force
T *force = blockLattice.get(iX,iY).template getFieldPointer();
T temperatureDifference = tPartner->get(iX,iY).computeRho() - T0;
for (unsigned iD = 0; iD < L::d; ++iD) {
force[iD] = forcePrefactor[iD] * temperatureDifference;
}
// Velocity coupling
T *u = tPartner->get(iX,iY).template getFieldPointer();
blockLattice.get(iX,iY).computeU(u);
}
}
}
}
template
void NavierStokesAdvectionDiffusionCouplingPostProcessor2D::
process(BlockLattice2D& blockLattice)
{
processSubDomain(blockLattice, x0, x1, y0, y1);
}
/// LatticeCouplingGenerator for advectionDiffusion coupling
template
NavierStokesAdvectionDiffusionCouplingGenerator2D::
NavierStokesAdvectionDiffusionCouplingGenerator2D(int x0_, int x1_, int y0_, int y1_,
T gravity_, T T0_, T deltaTemp_, std::vector dir_)
: LatticeCouplingGenerator2D(x0_, x1_, y0_, y1_),
gravity(gravity_), T0(T0_), deltaTemp(deltaTemp_), dir(dir_)
{ }
template
PostProcessor2D* NavierStokesAdvectionDiffusionCouplingGenerator2D::generate (
std::vector partners) const
{
return new NavierStokesAdvectionDiffusionCouplingPostProcessor2D(
this->x0,this->x1,this->y0,this->y1, gravity, T0, deltaTemp, dir,partners);
}
template
LatticeCouplingGenerator2D* NavierStokesAdvectionDiffusionCouplingGenerator2D::clone() const
{
return new NavierStokesAdvectionDiffusionCouplingGenerator2D(*this);
}
//=====================================================================================
//============== SmagorinskyBoussinesqCouplingPostProcessor2D ===============
//=====================================================================================
template
SmagorinskyBoussinesqCouplingPostProcessor2D::
SmagorinskyBoussinesqCouplingPostProcessor2D(int x0_, int x1_, int y0_, int y1_,
T gravity_, T T0_, T deltaTemp_, std::vector dir_, T PrTurb_,
std::vector partners_)
: x0(x0_), x1(x1_), y0(y0_), y1(y1_),
gravity(gravity_), T0(T0_), deltaTemp(deltaTemp_),
dir(dir_), PrTurb(PrTurb_), partners(partners_)
{
// we normalize the direction of force vector
T normDir = T();
for (unsigned iD = 0; iD < dir.size(); ++iD) {
normDir += dir[iD]*dir[iD];
}
normDir = sqrt(normDir);
for (unsigned iD = 0; iD < dir.size(); ++iD) {
dir[iD] /= normDir;
}
for (unsigned iD = 0; iD < dir.size(); ++iD) {
forcePrefactor[iD] = gravity * dir[iD];
}
tauTurbADPrefactor = descriptors::invCs2>() / descriptors::invCs2() / PrTurb;
tPartner = dynamic_cast> *>(partners[0]);
}
template
void SmagorinskyBoussinesqCouplingPostProcessor2D::
processSubDomain(BlockLattice2D& blockLattice,
int x0_, int x1_, int y0_, int y1_)
{
int newX0, newX1, newY0, newY1;
if ( util::intersect (
x0, x1, y0, y1,
x0_, x1_, y0_, y1_,
newX0, newX1, newY0, newY1 ) ) {
for (int iX=newX0; iX<=newX1; ++iX) {
for (int iY=newY0; iY<=newY1; ++iY) {
// computation of the bousinessq force
T *force = blockLattice.get(iX,iY).template getFieldPointer();
T temperatureDifference = tPartner->get(iX,iY).computeRho() - T0;
for (unsigned iD = 0; iD < L::d; ++iD) {
force[iD] = forcePrefactor[iD] * temperatureDifference;
}
// Velocity coupling
T *u = tPartner->get(iX,iY).template getFieldPointer();
// tau coupling
T *tauNS = blockLattice.get(iX,iY).template getFieldPointer();
T *tauAD = tPartner->get(iX,iY).template getFieldPointer();
T rho, pi[util::TensorVal::n];
blockLattice.get(iX,iY).computeAllMomenta(rho, u, pi);
T PiNeqNormSqr = pi[0]*pi[0] + 2.0*pi[1]*pi[1] + pi[2]*pi[2];
if (util::TensorVal::n == 6) {
PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2*pi[4]*pi[4] +pi[5]*pi[5];
}
T PiNeqNorm = sqrt(PiNeqNormSqr);
/// Molecular realaxation time
T tau_mol_NS = 1. / blockLattice.get(iX,iY).getDynamics()->getOmega();
T tau_mol_AD = 1. / tPartner->get(iX,iY).getDynamics()->getOmega();
/// Turbulent realaxation time
T tau_turb_NS = 0.5*(sqrt(tau_mol_NS*tau_mol_NS + dynamic_cast*>(blockLattice.get(iX,iY).getDynamics())->getPreFactor()/rho*PiNeqNorm) - tau_mol_NS);
/// Effective realaxation time
tauNS[0] = tau_mol_NS+tau_turb_NS;
T tau_turb_AD = tau_turb_NS * tauTurbADPrefactor;
tauAD[0] = tau_mol_AD+tau_turb_AD;
}
}
}
}
template
void SmagorinskyBoussinesqCouplingPostProcessor2D::
process(BlockLattice2D& blockLattice)
{
processSubDomain(blockLattice, x0, x1, y0, y1);
}
/// LatticeCouplingGenerator for advectionDiffusion coupling
template
SmagorinskyBoussinesqCouplingGenerator2D::
SmagorinskyBoussinesqCouplingGenerator2D(int x0_, int x1_, int y0_, int y1_,
T gravity_, T T0_, T deltaTemp_, std::vector dir_, T PrTurb_)
: LatticeCouplingGenerator2D(x0_, x1_, y0_, y1_),
gravity(gravity_), T0(T0_), deltaTemp(deltaTemp_), dir(dir_), PrTurb(PrTurb_)
{ }
template
PostProcessor2D* SmagorinskyBoussinesqCouplingGenerator2D::generate (
std::vector partners) const
{
return new SmagorinskyBoussinesqCouplingPostProcessor2D(
this->x0,this->x1,this->y0,this->y1, gravity, T0, deltaTemp, dir, PrTurb, partners);
}
template
LatticeCouplingGenerator2D* SmagorinskyBoussinesqCouplingGenerator2D::clone() const
{
return new SmagorinskyBoussinesqCouplingGenerator2D(*this);
}
//=====================================================================================
//============== MixedScaleBoussinesqCouplingPostProcessor2D ===============
//=====================================================================================
template
MixedScaleBoussinesqCouplingPostProcessor2D::
MixedScaleBoussinesqCouplingPostProcessor2D(int x0_, int x1_, int y0_, int y1_,
T gravity_, T T0_, T deltaTemp_, std::vector dir_, T PrTurb_,
std::vector partners_)
: x0(x0_), x1(x1_), y0(y0_), y1(y1_),
gravity(gravity_), T0(T0_), deltaTemp(deltaTemp_),
dir(dir_), PrTurb(PrTurb_), partners(partners_)
{
// we normalize the direction of force vector
T normDir = T();
for (unsigned iD = 0; iD < dir.size(); ++iD) {
normDir += dir[iD]*dir[iD];
}
normDir = sqrt(normDir);
for (unsigned iD = 0; iD < dir.size(); ++iD) {
dir[iD] /= normDir;
}
for (unsigned iD = 0; iD < dir.size(); ++iD) {
forcePrefactor[iD] = gravity * dir[iD];
}
tauTurbADPrefactor = descriptors::invCs2>() / descriptors::invCs2() / PrTurb;
tPartner = dynamic_cast> *>(partners[0]);
}
template
void MixedScaleBoussinesqCouplingPostProcessor2D::
processSubDomain(BlockLattice2D& blockLattice,
int x0_, int x1_, int y0_, int y1_)
{
const T C_nu = 0.04;
const T C_alpha = 0.5;
const T deltaT = 1.0;
const T invCs2_g = descriptors::invCs2>();
int newX0, newX1, newY0, newY1;
if ( util::intersect (
x0, x1, y0, y1,
x0_, x1_, y0_, y1_,
newX0, newX1, newY0, newY1 ) ) {
for (int iX=newX0; iX<=newX1; ++iX) {
for (int iY=newY0; iY<=newY1; ++iY) {
T *cutoffKinEnergy_14 = blockLattice.get(iX, iY).template getFieldPointer();
T *cutoffHeatFlux_14 = tPartner->get(iX, iY).template getFieldPointer();
// Velocity coupling
T *u = tPartner->get(iX,iY).template getFieldPointer();
// tau coupling
T *tauNS = blockLattice.get(iX,iY).template getFieldPointer();
T *tauAD = tPartner->get(iX,iY).template getFieldPointer();
/// Molecular realaxation time
T tau_mol_NS = 1. / blockLattice.get(iX,iY).getDynamics()->getOmega();
T tau_mol_AD = 1. / tPartner->get(iX,iY).getDynamics()->getOmega();
const T temperature = tPartner->get(iX,iY).computeRho();
// computation of the bousinessq force
T *force = blockLattice.get(iX,iY).template getFieldPointer();
T temperatureDifference = temperature - T0;
for (unsigned iD = 0; iD < L::d; ++iD) {
force[iD] = forcePrefactor[iD] * temperatureDifference;
}
T rho, pi[util::TensorVal::n], j[DESCRIPTOR::d];
blockLattice.get(iX,iY).computeAllMomenta(rho, u, pi);
int iPi = 0;
for (int Alpha=0; Alphaget(iX,iY).computeJ(j);
const T tmp_preFactor = invCs2_g / rho / tauAD[0];
const T jNeq[2] = {(j[0] - temperature * u[0]), (j[1] - temperature * u[1])};
const T jNeqSqr[2] = {jNeq[0]*jNeq[0], jNeq[1]*jNeq[1]};
const T jNeqSqr_prefacor = 2. * 0.25 * (jNeq[0] + jNeq[1]) * (jNeq[0] + jNeq[1]);
const T TnormSqr = jNeqSqr_prefacor*PiNeqNormSqr;
const T Tnorm = sqrt(TnormSqr);
/// Turbulent realaxation time
// T tau_turb_NS = 0.5*(sqrt(tau_mol_NS*tau_mol_NS + dynamic_cast*>(blockLattice.get(iX,iY).getDynamics())->getPreFactor()/rho*PiNeqNorm) - tau_mol_NS);
// const T tmp_A = C_nu * sqrt(sqrt(2.)/2.) * descriptors::invCs2() * descriptors::invCs2() * sqrt(PiNeqNorm / rho) * cutoffKinEnergy_14[0];
// const T tmp_A_2 = tmp_A * tmp_A;
// const T tmp_A_4 = tmp_A_2 * tmp_A_2;
// const T tau_mol_NS_2 = tau_mol_NS * tau_mol_NS;
// const T tau_mol_NS_3 = tau_mol_NS_2 * tau_mol_NS;
// const T tmp_1_3 = 1./3.;
// const T tmp_2_13 = pow(2., tmp_1_3);
// const T tmp_3_3_12 = 3. * sqrt(3.);
// const T tmp_sqrtA = sqrt(27.*tmp_A_4-4.*tmp_A_2*tau_mol_NS_3);
// // T tau_turb_NS = 1/3 ((27 A^2 + 3 sqrt(3) sqrt(27 A^4 - 4 A^2 b^3) - 2 b^3)^(1/3)/2^(1/3) + (2^(1/3) b^2)/(27 A^2 + 3 sqrt(3) sqrt(27 A^4 - 4 A^2 b^3) - 2 b^3)^(1/3) - b)
// T tau_turb_NS = ( pow(27.*tmp_A_2 + tmp_3_3_12*sqrt(27.*tmp_A_4-4.*tmp_A_2*tau_mol_NS_3)-2.*tau_mol_NS_3, tmp_1_3) / tmp_2_13
// + (tmp_2_13*tau_mol_NS_2) / pow(27.*tmp_A_2+tmp_3_3_12*sqrt(27.*tmp_A_4-4.*tmp_A_2*tau_mol_NS_3) - 2.*tau_mol_NS_3, tmp_1_3)
// - tau_mol_NS
// ) * tmp_1_3;
// if ( tau_turb_NS != tau_turb_NS )
// tau_turb_NS = 0.;
//cout << tau_turb_NS << " " << 27. * tmp_A_2 << " " << 4. * tau_mol_NS_3 << " " << PiNeqNorm << " " << " " << rho << endl;
const T tmp_A = C_nu * sqrt(sqrt(2.)/2.) * descriptors::invCs2() * descriptors::invCs2() * sqrt(PiNeqNorm / rho / tauNS[0]) * cutoffKinEnergy_14[0];
const T tau_turb_NS = tmp_A;
// T tau_turb_AD = tau_turb_NS * tauTurbADPrefactor;
const T tmp_B = C_alpha * descriptors::invCs2() / rho * sqrt(2.0 * Tnorm * invCs2_g / tauNS[0] / tauAD[0]) * cutoffHeatFlux_14[0];
const T tau_turb_AD = tmp_B;
// cout << jNeq[0] << " " << jNeq[1] << " " << sqrt(Tnorm * invCs2_g / tauNS[0] / tauAD[0]) << " " << TnormSqr << endl;
/// Effective realaxation time
tauNS[0] = tau_mol_NS+tau_turb_NS;
tauAD[0] = tau_mol_AD+tau_turb_AD;
}
}
}
}
template
void MixedScaleBoussinesqCouplingPostProcessor2D::
process(BlockLattice2D& blockLattice)
{
processSubDomain(blockLattice, x0, x1, y0, y1);
}
/// LatticeCouplingGenerator for advectionDiffusion coupling
template
MixedScaleBoussinesqCouplingGenerator2D::
MixedScaleBoussinesqCouplingGenerator2D(int x0_, int x1_, int y0_, int y1_,
T gravity_, T T0_, T deltaTemp_, std::vector dir_, T PrTurb_)
: LatticeCouplingGenerator2D(x0_, x1_, y0_, y1_),
gravity(gravity_), T0(T0_), deltaTemp(deltaTemp_), dir(dir_), PrTurb(PrTurb_)
{ }
template
PostProcessor2D* MixedScaleBoussinesqCouplingGenerator2D::generate (
std::vector partners) const
{
return new MixedScaleBoussinesqCouplingPostProcessor2D(
this->x0,this->x1,this->y0,this->y1, gravity, T0, deltaTemp, dir, PrTurb, partners);
}
template
LatticeCouplingGenerator2D* MixedScaleBoussinesqCouplingGenerator2D::clone() const
{
return new MixedScaleBoussinesqCouplingGenerator2D(*this);
}
} // namespace olb
#endif