The goal of this exercise is to familiarize with off-lattice boundary conditions (2D Curved Boundary Conditions) in Palabos
CMAKE file
At first, you need compile the CMAKE file, and produce a EXE file. For this file, you need to know where to change the project name and define the executable_name, when necessary.
Most importantly, you need set the PALABOS_ROOT. Otherwise you will face a compile error after the command cmake ..
# # # If the palabos root folder is in your path, you don't need to modify anything.
# # # In the other case you have 2 options: 1. add PALABOS_ROOT=path/to/palabos to the path of your system
# # # 2. you comment the next line and uncomment the one after, explicitly giving the path/to/palabos
# # # (NB you can use ${CMAKE_CURRENT_SOURCE_DIR} to give paths relative to the CMakeLists.txt location)
#file(TO_CMAKE_PATH $ENV{PALABOS_ROOT} PALABOS_ROOT)
set(PALABOS_ROOT "../../.")
cbc_example_2d.cpp
1
2
3
4
5
6
7
8
9
10
// Define simulation parameters: we use two ad-hoc units helper check
// simulation_parameters.h for the documentation.
constRealre=250;// NB: Obstacle reynolds!
sp::Numerics<Real,Int>lu;sp::NonDimensional<Real>dimless;dimless.initReLxLyLz(re,24,4,4).printParameters();IncomprFlowParam<Real>parameters=lu.initLrefluNodim(50,&dimless,0.01,false)//25 0.02
.printParameters().getIncomprFlowParam();// be careful with this casting, check the documentation
// LOCATION: Line #209 of File (simulationParameters.cpp)
/// Generates the parameters in lattice units from an object with the non
/// dimensional parameters and the lattice resolution, i.e. l_ref_lu_. l_ref_lu_
/// is Real, but the generated box dimension are rounded to int! \param
/// l_ref_lu_ resolution (reference length in lattice units) \param dimless_
/// NonDimensional<Real> object that has already been initialized
/// @param u_lb_ if given > 0, it overrides the Ma number in the dimless_
/// @param tau_ if given > 0, it overrides the Ma number in the dimless_
/// @return *this
template<typenameReal,typenameInt>Numerics<Real,Int>&Numerics<Real,Int>::initLrefluNodim(Intl_ref_lu_,NonDimensional<Real>*dimless_,Realu_lb_,Realtau_){assert(dimless_->initialized());l_ref_lu=l_ref_lu_;if(u_lb_>getEpsilon(1)){setUlb(u_lb_);setTau(3.*(u_lb_*l_ref_lu_/dimless_->getRe())+0.5);if(tau_>0.499)pcout<<"initLrefluNodim() Waring: you cannot set both u_lb_ ""and tau_. Giving priority to u_lb_...."<<std::endl;}elseif(tau_>0.499){setUlb(dimless_->getRe()*getNulu(tau_)/l_ref_lu_);setTau(tau_);}else{setUlb(dimless_->getMa()*getCs());setTau(getCs2Inv()*(u_lb*l_ref_lu_/dimless_->getRe())+0.5);}lx_domain=util::roundToInt(dimless_->getLx()*l_ref_lu_);ly_domain=util::roundToInt(dimless_->getLy()*l_ref_lu_);lz_domain=util::roundToInt(dimless_->getLz()*l_ref_lu_);is_initialized=true;deletedimless;dimless=dimless_;return*this;}
template<typenameReal,template<typenameU>classDescriptor>voidsetup_boundary_conditions_2d(MultiBlockLattice2D<Real,Descriptor>&lattice,IncomprFlowParam<Real>const¶meters,OnLatticeBoundaryCondition2D<Real,Descriptor>&boundaryCondition){constplintnx=parameters.getNx();constplintny=parameters.getNy();Box2Doutlet(nx-1,nx-1,1,ny-2);// Create Velocity boundary conditions everywhere
boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(0,0,1,ny-2));boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(0,nx-1,0,0));boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(0,nx-1,ny-1,ny-1));// .. except on right boundary, where we prefer an outflow condition
// (zero velocity-gradient).
boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(nx-1,nx-1,1,ny-2),boundary::outflow);setBoundaryVelocity(lattice,lattice.getBoundingBox(),PoiseuilleVelocity<Real>(parameters));setBoundaryDensity(lattice,outlet,ConstantDensity<Real>(1.));initializeAtEquilibrium(lattice,lattice.getBoundingBox(),PoiseuilleVelocityAndDensity<Real,Descriptor>(parameters));plintcx=nx/4;plintcy=ny/2+2;// cy is slightly offset to avoid full symmetry,
// and to get a Von Karman Vortex street.
plintradius=parameters.getResolution()/2.0;defineDynamics(lattice,lattice.getBoundingBox(),newCylinderShapeDomain2D<Real,Descriptor>(cx,cy,radius),newplb::BounceBack<Real,Descriptor>);lattice.initialize();}
The GIF animation for Poiseuille flow looks like:
Boundary Conditions
No-slip boundary condition: at the interface between a moving fluid and a stationary wall, both the normal and tangential components of the fluid velocity field are equal to zero.
Free-slip boundary condition: at the interface between a moving fluid and a stationary wall, the normal component of the fluid velocity field is equal to zero, but the tangential component is unrestricted.
Slip: the normal component of the velocity is zero, i.e., no flux across the boundary
Free: the tangential force is zero.
To change to Free-slip boundary condition, three aspects to modify:
In function setVelocityConditionOnBlockBoundaries use boundary::freeslip (replace boundary::outflow)
Convert the initialization and the boundary velocities to a uniform profile. You need to change PoiseuilleVelocity and PoiseuilleVelocityAndDensity to ConstantVelocity and ConstantVelocityAndDensity, respectively.
Finally put a free slip (specular reflection) on the cylinder, instead of plb::BounceBack, changing the dynamics (use plb::SpecularReflection).
// Free-slip boundary condition:
template<typenameReal,template<typenameU>classDescriptor>voidsetup_boundary_conditions_2d(MultiBlockLattice2D<Real,Descriptor>&lattice,IncomprFlowParam<Real>const¶meters,OnLatticeBoundaryCondition2D<Real,Descriptor>&boundaryCondition){constplintnx=parameters.getNx();constplintny=parameters.getNy();Box2Doutlet(nx-1,nx-1,1,ny-2);// Create Velocity boundary conditions everywhere
boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(0,0,1,ny-2));boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(0,nx-1,0,0));boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(0,nx-1,ny-1,ny-1));// .. except on right boundary, where we prefer an freeslip condition
// (zero velocity-gradient).
boundaryCondition.setVelocityConditionOnBlockBoundaries(lattice,Box2D(nx-1,nx-1,1,ny-2),boundary::freeslip);//Change#1
setBoundaryVelocity(lattice,lattice.getBoundingBox(),ConstantVelocity<Real>(parameters));//Change#2.1
setBoundaryDensity(lattice,outlet,ConstantDensity<Real>(1.));initializeAtEquilibrium(lattice,lattice.getBoundingBox(),ConstantVelocityAndDensity<Real,Descriptor>(parameters));//Change#2.2
plintcx=nx/4;plintcy=ny/2+2;// cy is slightly offset to avoid full symmetry,
// and to get a Von Karman Vortex street.
plintradius=parameters.getResolution()/2.0;defineDynamics(lattice,lattice.getBoundingBox(),newCylinderShapeDomain2D<Real,Descriptor>(cx,cy,radius),newplb::SpecularReflection<Real,Descriptor>);//Change#3
lattice.initialize();}
The GIF animation for Channel flow with free-slip boundary looks like: