/* 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. */ #ifndef FD_BOUNDARIES_2D_HH #define FD_BOUNDARIES_2D_HH #include "boundaryPostProcessors2D.h" #include "core/finiteDifference2D.h" #include "core/blockLattice2D.h" #include "core/util.h" #include "dynamics/lbHelpers.h" #include "dynamics/firstOrderLbHelpers.h" namespace olb { /////////// StraightFdBoundaryProcessor2D /////////////////////////////////// template StraightFdBoundaryProcessor2D:: StraightFdBoundaryProcessor2D(int x0_, int x1_, int y0_, int y1_) : x0(x0_), x1(x1_), y0(y0_), y1(y1_) { OLB_PRECONDITION(x0==x1 || y0==y1); } template void StraightFdBoundaryProcessor2D:: processSubDomain(BlockLattice2D& blockLattice, int x0_, int x1_, int y0_, int y1_) { using namespace olb::util::tensorIndices2D; int newX0, newX1, newY0, newY1; if ( util::intersect ( x0, x1, y0, y1, x0_, x1_, y0_, y1_, newX0, newX1, newY0, newY1 ) ) { int iX; #ifdef PARALLEL_MODE_OMP #pragma omp parallel for #endif for (iX=newX0; iX<=newX1; ++iX) { T dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d]; for (int iY=newY0; iY<=newY1; ++iY) { Cell& cell = blockLattice.get(iX,iY); Dynamics* dynamics = blockLattice.getDynamics(iX, iY); T rho, u[DESCRIPTOR::d]; cell.computeRhoU(rho,u); interpolateGradients<0>(blockLattice, dx_u, iX, iY); interpolateGradients<1>(blockLattice, dy_u, iX, iY); T dx_ux = dx_u[0]; T dy_ux = dy_u[0]; T dx_uy = dx_u[1]; T dy_uy = dy_u[1]; T omega = dynamics->getOmega(); T sToPi = - rho / descriptors::invCs2() / omega; T pi[util::TensorVal::n]; pi[xx] = (T)2 * dx_ux * sToPi; pi[yy] = (T)2 * dy_uy * sToPi; pi[xy] = (dx_uy + dy_ux) * sToPi; // Computation of the particle distribution functions // according to the regularized formula T uSqr = util::normSqr(u); for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = dynamics -> computeEquilibrium(iPop,rho,u,uSqr) + firstOrderLbHelpers::fromPiToFneq(iPop, pi); } } } } } template void StraightFdBoundaryProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } template template void StraightFdBoundaryProcessor2D:: interpolateGradients(BlockLattice2D const& blockLattice, T velDeriv[DESCRIPTOR::d], int iX, int iY) const { fd::DirectedGradients2D:: interpolateVector(velDeriv, blockLattice, iX, iY); } //////// StraightFdBoundaryProcessorGenerator2D //////////////////////////////// template StraightFdBoundaryProcessorGenerator2D:: StraightFdBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_) { } template PostProcessor2D* StraightFdBoundaryProcessorGenerator2D::generate() const { return new StraightFdBoundaryProcessor2D ( this->x0, this->x1, this->y0, this->y1); } template PostProcessorGenerator2D* StraightFdBoundaryProcessorGenerator2D::clone() const { return new StraightFdBoundaryProcessorGenerator2D (this->x0, this->x1, this->y0, this->y1); } //////// StraightConvectionBoundaryProcessor2D //////////////////////////////// template StraightConvectionBoundaryProcessor2D:: StraightConvectionBoundaryProcessor2D(int x0_, int x1_, int y0_, int y1_, T* uAv_) : x0(x0_), x1(x1_), y0(y0_), y1(y1_), uAv(uAv_) { OLB_PRECONDITION(x0==x1 || y0==y1); saveCell = new T** [(size_t)(x1_-x0_+1)]; for (int iX=0; iX<=x1_-x0_; ++iX) { saveCell[iX] = new T* [(size_t)(y1_-y0_+1)]; for (int iY=0; iY<=y1_-y0_; ++iY) { saveCell[iX][iY] = new T [(size_t)(DESCRIPTOR::q)]; for (int iPop=0; iPop StraightConvectionBoundaryProcessor2D:: ~StraightConvectionBoundaryProcessor2D() { for (int iX=0; iX<=x1-x0; ++iX) { for (int iY=0; iY<=y1-y0; ++iY) { delete [] saveCell[iX][iY]; } delete [] saveCell[iX]; } delete [] saveCell; } template void StraightConvectionBoundaryProcessor2D:: processSubDomain(BlockLattice2D& blockLattice, int x0_, int x1_, int y0_, int y1_) { using namespace olb::util::tensorIndices2D; int newX0, newX1, newY0, newY1; if ( util::intersect ( x0, x1, y0, y1, x0_, x1_, y0_, y1_, newX0, newX1, newY0, newY1 ) ) { int iX; #ifdef PARALLEL_MODE_OMP #pragma omp parallel for #endif for (iX=newX0; iX<=newX1; ++iX) { for (int iY=newY0; iY<=newY1; ++iY) { Cell& cell = blockLattice.get(iX,iY); for (int iPop = 0; iPop < DESCRIPTOR::q ; ++iPop) { if (descriptors::c(iPop,direction)==-orientation) { // using default -1 avoids wrong first call if (!util::nearZero(1 + saveCell[iX-newX0][iY-newY0][iPop]) ){ cell[iPop] = saveCell[iX-newX0][iY-newY0][iPop]; } } } T rho0, u0[2]; T rho1, u1[2]; T rho2, u2[2]; if (direction==0) { blockLattice.get(iX,iY).computeRhoU(rho0,u0); blockLattice.get(iX-orientation,iY).computeRhoU(rho1,u1); blockLattice.get(iX-orientation*2,iY).computeRhoU(rho2,u2); } else { blockLattice.get(iX,iY).computeRhoU(rho0,u0); blockLattice.get(iX,iY-orientation).computeRhoU(rho1,u1); blockLattice.get(iX,iY-orientation*2).computeRhoU(rho2,u2); } // rho0 = T(1); rho1 = T(1); rho2 = T(1); T uDelta[2]; T uAverage = rho0*u0[direction]; if (uAv!=nullptr) { uAverage = *uAv; } uDelta[0]=-uAverage*0.5*(3*rho0*u0[0]-4*rho1*u1[0]+rho2*u2[0]); uDelta[1]=-uAverage*0.5*(3*rho0*u0[1]-4*rho1*u1[1]+rho2*u2[1]); for (int iPop = 0; iPop < DESCRIPTOR::q ; ++iPop) { if (descriptors::c(iPop,direction) == -orientation) { saveCell[iX-newX0][iY-newY0][iPop] = cell[iPop] + descriptors::invCs2()*descriptors::t(iPop)*(uDelta[0]*descriptors::c(iPop,0)+uDelta[1]*descriptors::c(iPop,1)); } } } } } } template void StraightConvectionBoundaryProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } //////// StraightConvectionBoundaryProcessorGenerator2D //////////////////////////////// template StraightConvectionBoundaryProcessorGenerator2D:: StraightConvectionBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, T* uAv_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), uAv(uAv_) { } template PostProcessor2D* StraightConvectionBoundaryProcessorGenerator2D::generate() const { return new StraightConvectionBoundaryProcessor2D ( this->x0, this->x1, this->y0, this->y1, uAv); } template PostProcessorGenerator2D* StraightConvectionBoundaryProcessorGenerator2D::clone() const { return new StraightConvectionBoundaryProcessorGenerator2D (this->x0, this->x1, this->y0, this->y1, uAv); } //////// SlipBoundaryProcessor2D //////////////////////////////// template SlipBoundaryProcessor2D:: SlipBoundaryProcessor2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX, int discreteNormalY) : x0(x0_), x1(x1_), y0(y0_), y1(y1_) { OLB_PRECONDITION(x0==x1 || y0==y1); reflectionPop[0] = 0; for (int iPop = 1; iPop < DESCRIPTOR::q; iPop++) { reflectionPop[iPop] = 0; // iPop are the directions which ointing into the fluid, discreteNormal is pointing outwarts if (descriptors::c(iPop,0)*discreteNormalX + descriptors::c(iPop,1)*discreteNormalY < 0) { // std::cout << "-----" <(iPop,0) - mult*(descriptors::c(iPop,0)*discreteNormalX + descriptors::c(iPop,1)*discreteNormalY )*discreteNormalX); mirrorDirection1 = (descriptors::c(iPop,1) - mult*(descriptors::c(iPop,0)*discreteNormalX + descriptors::c(iPop,1)*discreteNormalY )*discreteNormalY); // computes mirror jPop for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q ; reflectionPop[iPop]++) { if (descriptors::c(reflectionPop[iPop],0)==mirrorDirection0 && descriptors::c(reflectionPop[iPop],1)==mirrorDirection1 ) { break; } } //std::cout < void SlipBoundaryProcessor2D:: 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 ) ) { int iX; #ifdef PARALLEL_MODE_OMP #pragma omp parallel for #endif for (iX=newX0; iX<=newX1; ++iX) { for (int iY=newY0; iY<=newY1; ++iY) { for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) { if (reflectionPop[iPop]!=0) { //do reflection blockLattice.get(iX,iY)[iPop] = blockLattice.get(iX,iY)[reflectionPop[iPop]]; } } } } } } template void SlipBoundaryProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } //////// SlipBoundaryProcessorGenerator2D //////////////////////////////// template SlipBoundaryProcessorGenerator2D:: SlipBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_) { } template PostProcessor2D* SlipBoundaryProcessorGenerator2D::generate() const { return new SlipBoundaryProcessor2D ( this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY); } template PostProcessorGenerator2D* SlipBoundaryProcessorGenerator2D::clone() const { return new SlipBoundaryProcessorGenerator2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY); } //////// PartialSlipBoundaryProcessor2D //////////////////////////////// template PartialSlipBoundaryProcessor2D:: PartialSlipBoundaryProcessor2D(T tuner_, int x0_, int x1_, int y0_, int y1_, int discreteNormalX, int discreteNormalY) : x0(x0_), x1(x1_), y0(y0_), y1(y1_), tuner(tuner_) { OLB_PRECONDITION(x0==x1 || y0==y1); reflectionPop[0] = 0; for (int iPop = 1; iPop < DESCRIPTOR::q; iPop++) { reflectionPop[iPop] = 0; // iPop are the directions which ointing into the fluid, discreteNormal is pointing outwarts if (descriptors::c(iPop,0)*discreteNormalX + descriptors::c(iPop,1)*discreteNormalY < 0) { //std::cout << "-----" <(iPop,0) - mult*(descriptors::c(iPop,0)*discreteNormalX + descriptors::c(iPop,1)*discreteNormalY )*discreteNormalX); mirrorDirection1 = (descriptors::c(iPop,1) - mult*(descriptors::c(iPop,0)*discreteNormalX + descriptors::c(iPop,1)*discreteNormalY )*discreteNormalY); // computes mirror jPop for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q ; reflectionPop[iPop]++) { if (descriptors::c(reflectionPop[iPop],0)==mirrorDirection0 && descriptors::c(reflectionPop[iPop],1)==mirrorDirection1 ) { break; } } //std::cout < void PartialSlipBoundaryProcessor2D:: 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 ) ) { int iX; #ifdef PARALLEL_MODE_OMP #pragma omp parallel for #endif for (iX=newX0; iX<=newX1; ++iX) { for (int iY=newY0; iY<=newY1; ++iY) { for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) { if (reflectionPop[iPop]!=0) { //do reflection blockLattice.get(iX,iY)[iPop] = tuner*blockLattice.get(iX,iY)[reflectionPop[iPop]]; } } for (int iPop = 1; iPop < DESCRIPTOR::q/2 ; ++iPop) { T provv = blockLattice.get(iX,iY)[descriptors::opposite(iPop)]; blockLattice.get(iX,iY)[descriptors::opposite(iPop)] += (1.-tuner)*blockLattice.get(iX,iY)[iPop]; blockLattice.get(iX,iY)[iPop] += (1.-tuner)*provv; } } } } } template void PartialSlipBoundaryProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } //////// PartialSlipBoundaryProcessorGenerator2D //////////////////////////////// template PartialSlipBoundaryProcessorGenerator2D:: PartialSlipBoundaryProcessorGenerator2D(T tuner_, int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), tuner(tuner_) { } template PostProcessor2D* PartialSlipBoundaryProcessorGenerator2D::generate() const { return new PartialSlipBoundaryProcessor2D (tuner, this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY); } template PostProcessorGenerator2D* PartialSlipBoundaryProcessorGenerator2D::clone() const { return new PartialSlipBoundaryProcessorGenerator2D (tuner, this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY); } /////////// OuterVelocityCornerProcessor2D ///////////////////////////////////// template OuterVelocityCornerProcessor2D:: OuterVelocityCornerProcessor2D(int x_, int y_) : x(x_), y(y_) { } template void OuterVelocityCornerProcessor2D:: process(BlockLattice2D& blockLattice) { using namespace olb::util::tensorIndices2D; T rho10 = blockLattice.get(x-1*xNormal, y-0*yNormal).computeRho(); T rho01 = blockLattice.get(x-0*xNormal, y-1*yNormal).computeRho(); T rho20 = blockLattice.get(x-2*xNormal, y-0*yNormal).computeRho(); T rho02 = blockLattice.get(x-0*xNormal, y-2*yNormal).computeRho(); T rho = (T)2/(T)3*(rho01+rho10) - (T)1/(T)6*(rho02+rho20); T dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d]; fd::DirectedGradients2D::interpolateVector(dx_u, blockLattice, x,y); fd::DirectedGradients2D::interpolateVector(dy_u, blockLattice, x,y); T dx_ux = dx_u[0]; T dy_ux = dy_u[0]; T dx_uy = dx_u[1]; T dy_uy = dy_u[1]; Cell& cell = blockLattice.get(x,y); Dynamics* dynamics = blockLattice.getDynamics(x, y); T omega = dynamics -> getOmega(); T sToPi = - rho / descriptors::invCs2() / omega; T pi[util::TensorVal::n]; pi[xx] = (T)2 * dx_ux * sToPi; pi[yy] = (T)2 * dy_uy * sToPi; pi[xy] = (dx_uy + dy_ux) * sToPi; // Computation of the particle distribution functions // according to the regularized formula T u[DESCRIPTOR::d]; blockLattice.get(x,y).computeU(u); T uSqr = util::normSqr(u); for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = dynamics -> computeEquilibrium(iPop,rho,u,uSqr) + firstOrderLbHelpers::fromPiToFneq(iPop, pi); } } template void OuterVelocityCornerProcessor2D:: processSubDomain(BlockLattice2D& blockLattice, int x0_, int x1_, int y0_, int y1_ ) { if (util::contained(x, y, x0_, x1_, y0_, y1_)) { process(blockLattice); } } //////// OuterVelocityCornerProcessorGenerator2D //////////////////////////// template OuterVelocityCornerProcessorGenerator2D:: OuterVelocityCornerProcessorGenerator2D(int x_, int y_) : PostProcessorGenerator2D(x_, x_, y_, y_) { } template PostProcessor2D* OuterVelocityCornerProcessorGenerator2D::generate() const { return new OuterVelocityCornerProcessor2D ( this->x0, this->y0); } template PostProcessorGenerator2D* OuterVelocityCornerProcessorGenerator2D:: clone() const { return new OuterVelocityCornerProcessorGenerator2D ( this->x0, this->y0); } template FreeEnergyWallProcessor2D:: FreeEnergyWallProcessor2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_, T addend_) : x0(x0_), x1(x1_), y0(y0_), y1(y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), addend(addend_) { } template void FreeEnergyWallProcessor2D:: 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) { T rhoAvg = blockLattice.get(iX-discreteNormalX, iY-discreteNormalY).computeRho(); T rhoTmp = 0.; for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) { rhoTmp += blockLattice.get(iX,iY)[iPop]; } T rho = rhoAvg + addend; rho -= rhoTmp; blockLattice.get(iX,iY)[0] = rho-1.; } } } } template void FreeEnergyWallProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } template FreeEnergyWallProcessorGenerator2D:: FreeEnergyWallProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_, T addend_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), addend(addend_) { } template PostProcessor2D* FreeEnergyWallProcessorGenerator2D::generate() const { return new FreeEnergyWallProcessor2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY, addend); } template PostProcessorGenerator2D* FreeEnergyWallProcessorGenerator2D::clone() const { return new FreeEnergyWallProcessorGenerator2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY, addend); } //////// FreeEnergyChemPotBoundaryProcessor2D //////////////////////////// template FreeEnergyChemPotBoundaryProcessor2D:: FreeEnergyChemPotBoundaryProcessor2D( int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_, int latticeNumber_) : x0(x0_), x1(x1_), y0(y0_), y1(y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), latticeNumber(latticeNumber_) { } template void FreeEnergyChemPotBoundaryProcessor2D:: 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) { blockLattice.get(iX,iY).template setField( blockLattice.get(iX-discreteNormalX, iY-discreteNormalY).template getField() ); if (latticeNumber == 1) { T rho0 = blockLattice.get(iX, iY).computeRho(); T rho1 = blockLattice.get(iX-discreteNormalX, iY-discreteNormalY).computeRho(); *(blockLattice.get(iX,iY).template getFieldPointer()) += (rho1 / rho0 - 1) / descriptors::invCs2(); } } } } } template void FreeEnergyChemPotBoundaryProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } //////// FreeEnergyChemPotBoundaryProcessorGenerator2D //////////////////////////// template FreeEnergyChemPotBoundaryProcessorGenerator2D:: FreeEnergyChemPotBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_, int latticeNumber_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), latticeNumber(latticeNumber_) { } template PostProcessor2D* FreeEnergyChemPotBoundaryProcessorGenerator2D::generate() const { return new FreeEnergyChemPotBoundaryProcessor2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY, latticeNumber); } template PostProcessorGenerator2D* FreeEnergyChemPotBoundaryProcessorGenerator2D::clone() const { return new FreeEnergyChemPotBoundaryProcessorGenerator2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY, latticeNumber); } //////// FreeEnergyConvectiveProcessor2D //////////////////////////// template FreeEnergyConvectiveProcessor2D:: FreeEnergyConvectiveProcessor2D( int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_) : x0(x0_), x1(x1_), y0(y0_), y1(y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_) { } template void FreeEnergyConvectiveProcessor2D:: 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) { T rho, rho0, rho1, u[2]; rho0 = blockLattice.get(iX,iY).computeRho(); blockLattice.get(iX-discreteNormalX,iY-discreteNormalY).computeRhoU(rho1, u); T uPerp = 0; if (discreteNormalX == 0) { uPerp = discreteNormalY * u[1]; } else if (discreteNormalY == 0) { uPerp = discreteNormalX * u[0]; } rho = (rho0 + uPerp * rho1) / (1. + uPerp); blockLattice.get(iX,iY).defineRho(rho); } } } } template void FreeEnergyConvectiveProcessor2D:: process(BlockLattice2D& blockLattice) { processSubDomain(blockLattice, x0, x1, y0, y1); } //////// FreeEnergyConvectiveProcessorGenerator2D //////////////////////////// template FreeEnergyConvectiveProcessorGenerator2D:: FreeEnergyConvectiveProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_) : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_) { } template PostProcessor2D* FreeEnergyConvectiveProcessorGenerator2D::generate() const { return new FreeEnergyConvectiveProcessor2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY); } template PostProcessorGenerator2D* FreeEnergyConvectiveProcessorGenerator2D::clone() const { return new FreeEnergyConvectiveProcessorGenerator2D (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY); } } // namespace olb #endif