24#ifndef FD_BOUNDARIES_2D_HH
25#define FD_BOUNDARIES_2D_HH
39template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
40template<CONCEPT(Cell) CELL>
45 T dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d];
46 T rho, u[DESCRIPTOR::d];
48 auto& dynamics = cell.getDynamics();
50 cell.computeRhoU(rho,u);
52 interpolateGradients<0>(cell, dx_u);
53 interpolateGradients<1>(cell, dy_u);
59 T omega = dynamics.getOmegaOrFallback(std::numeric_limits<T>::signaling_NaN());
60 T sToPi = - rho / descriptors::invCs2<T,DESCRIPTOR>() / omega;
62 pi[xx] = (T)2 * dx_ux * sToPi;
63 pi[yy] = (T)2 * dy_uy * sToPi;
64 pi[xy] = (dx_uy + dy_ux) * sToPi;
68 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
69 cell[iPop] = dynamics.computeEquilibrium(iPop,rho,u)
74template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
75template<
int deriveDirection,
typename CELL>
85template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
88 : x0(x0_), x1(x1_), y0(y0_), y1(y1_), uAv(uAv_)
92 this->
getName() =
"StraightConvectionBoundaryProcessor2D";
93 saveCell =
new T** [(size_t)(x1_-x0_+1)];
94 for (
int iX=0; iX<=x1_-x0_; ++iX) {
95 saveCell[iX] =
new T* [(size_t)(y1_-y0_+1)];
96 for (
int iY=0; iY<=y1_-y0_; ++iY) {
97 saveCell[iX][iY] =
new T [(size_t)(DESCRIPTOR::q)];
98 for (
int iPop=0; iPop<DESCRIPTOR::q; ++iPop) {
100 saveCell[iX][iY][iPop] = T(-1);
106template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
110 for (
int iX=0; iX<=x1-x0; ++iX) {
111 for (
int iY=0; iY<=y1-y0; ++iY) {
112 delete [] saveCell[iX][iY];
114 delete [] saveCell[iX];
119template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
125 int newX0, newX1, newY0, newY1;
129 newX0, newX1, newY0, newY1 ) ) {
132#ifdef PARALLEL_MODE_OMP
133 #pragma omp parallel for
135 for (iX=newX0; iX<=newX1; ++iX) {
136 for (
int iY=newY0; iY<=newY1; ++iY) {
138 for (
int iPop = 0; iPop < DESCRIPTOR::q ; ++iPop) {
139 if (descriptors::c<DESCRIPTOR>(iPop,direction)==-orientation) {
142 cell[iPop] = saveCell[iX-newX0][iY-newY0][iPop];
151 blockLattice.
get(iX,iY).computeRhoU(rho0,u0);
152 blockLattice.
get(iX-orientation,iY).computeRhoU(rho1,u1);
153 blockLattice.
get(iX-orientation*2,iY).computeRhoU(rho2,u2);
156 blockLattice.
get(iX,iY).computeRhoU(rho0,u0);
157 blockLattice.
get(iX,iY-orientation).computeRhoU(rho1,u1);
158 blockLattice.
get(iX,iY-orientation*2).computeRhoU(rho2,u2);
164 T uAverage = rho0*u0[direction];
168 uDelta[0]=-uAverage*0.5*(3*rho0*u0[0]-4*rho1*u1[0]+rho2*u2[0]);
169 uDelta[1]=-uAverage*0.5*(3*rho0*u0[1]-4*rho1*u1[1]+rho2*u2[1]);
171 for (
int iPop = 0; iPop < DESCRIPTOR::q ; ++iPop) {
172 if (descriptors::c<DESCRIPTOR>(iPop,direction) == -orientation) {
173 saveCell[iX-newX0][iY-newY0][iPop] = cell[iPop] + descriptors::invCs2<T,DESCRIPTOR>()*descriptors::t<T,DESCRIPTOR>(iPop)*(uDelta[0]*descriptors::c<DESCRIPTOR>(iPop,0)+uDelta[1]*descriptors::c<DESCRIPTOR>(iPop,1));
181template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
185 processSubDomain(blockLattice, x0, x1, y0, y1);
191template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
197template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
202 ( this->x0, this->x1, this->y0, this->y1, uAv);
205template<
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
210 (this->x0, this->x1, this->y0, this->y1, uAv);
216template<
typename T,
typename DESCRIPTOR>
219 : x0(x0_), x1(x1_), y0(y0_), y1(y1_)
221 this->
getName() =
"SlipBoundaryProcessor2D";
223 reflectionPop[0] = 0;
224 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
225 reflectionPop[iPop] = 0;
227 if (descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY < 0) {
229 int mirrorDirection0;
230 int mirrorDirection1;
232 if (discreteNormalX*discreteNormalY==0) {
235 mirrorDirection0 = (descriptors::c<DESCRIPTOR>(iPop,0) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY )*discreteNormalX);
236 mirrorDirection1 = (descriptors::c<DESCRIPTOR>(iPop,1) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY )*discreteNormalY);
239 for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q ; reflectionPop[iPop]++) {
240 if (descriptors::c<DESCRIPTOR>(reflectionPop[iPop],0)==mirrorDirection0 && descriptors::c<DESCRIPTOR>(reflectionPop[iPop],1)==mirrorDirection1 ) {
249template<
typename T,
typename DESCRIPTOR>
253 int newX0, newX1, newY0, newY1;
257 newX0, newX1, newY0, newY1 ) ) {
260#ifdef PARALLEL_MODE_OMP
261 #pragma omp parallel for
263 for (iX=newX0; iX<=newX1; ++iX) {
264 for (
int iY=newY0; iY<=newY1; ++iY) {
265 for (
int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
266 if (reflectionPop[iPop]!=0) {
268 blockLattice.
get(iX,iY)[iPop] = blockLattice.
get(iX,iY)[reflectionPop[iPop]];
276template<
typename T,
typename DESCRIPTOR>
280 processSubDomain(blockLattice, x0, x1, y0, y1);
285template<
typename T,
typename DESCRIPTOR>
288 :
PostProcessorGenerator2D<T,DESCRIPTOR>(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_)
291template<
typename T,
typename DESCRIPTOR>
296 ( this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
299template<
typename T,
typename DESCRIPTOR>
304 (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
309template<
typename T,
typename DESCRIPTOR>
312 : x0(x0_), x1(x1_), y0(y0_), y1(y1_), tuner(tuner_)
314 this->
getName() =
"PartialSlipBoundaryProcessor2D";
316 reflectionPop[0] = 0;
317 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
318 reflectionPop[iPop] = 0;
320 if (descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY < 0) {
322 int mirrorDirection0;
323 int mirrorDirection1;
325 if (discreteNormalX*discreteNormalY==0) {
328 mirrorDirection0 = (descriptors::c<DESCRIPTOR>(iPop,0) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY )*discreteNormalX);
329 mirrorDirection1 = (descriptors::c<DESCRIPTOR>(iPop,1) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY )*discreteNormalY);
332 for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q ; reflectionPop[iPop]++) {
333 if (descriptors::c<DESCRIPTOR>(reflectionPop[iPop],0)==mirrorDirection0 && descriptors::c<DESCRIPTOR>(reflectionPop[iPop],1)==mirrorDirection1 ) {
342template<
typename T,
typename DESCRIPTOR>
346 int newX0, newX1, newY0, newY1;
350 newX0, newX1, newY0, newY1 ) ) {
353#ifdef PARALLEL_MODE_OMP
354 #pragma omp parallel for
356 for (iX=newX0; iX<=newX1; ++iX) {
357 for (
int iY=newY0; iY<=newY1; ++iY) {
358 for (
int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
359 if (reflectionPop[iPop]!=0) {
361 blockLattice.
get(iX,iY)[iPop] = tuner*blockLattice.
get(iX,iY)[reflectionPop[iPop]];
364 for (
int iPop = 1; iPop < DESCRIPTOR::q/2 ; ++iPop) {
365 T provv = blockLattice.
get(iX,iY)[descriptors::opposite<DESCRIPTOR>(iPop)];
366 blockLattice.
get(iX,iY)[descriptors::opposite<DESCRIPTOR>(iPop)] +=
367 (1.-tuner)*blockLattice.
get(iX,iY)[iPop];
368 blockLattice.
get(iX,iY)[iPop] += (1.-tuner)*provv;
375template<
typename T,
typename DESCRIPTOR>
379 processSubDomain(blockLattice, x0, x1, y0, y1);
384template<
typename T,
typename DESCRIPTOR>
387 :
PostProcessorGenerator2D<T,DESCRIPTOR>(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), tuner(tuner_)
390template<
typename T,
typename DESCRIPTOR>
395 (tuner, this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
398template<
typename T,
typename DESCRIPTOR>
403 (tuner, this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
408template<
typename T,
typename DESCRIPTOR,
int xNormal,
int yNormal>
409template <CONCEPT(Cell) CELL>
414 T rho10 = cell.neighbor({-1*xNormal, -0*yNormal}).computeRho();
415 T rho01 = cell.neighbor({-0*xNormal, -1*yNormal}).computeRho();
417 T rho20 = cell.neighbor({-2*xNormal, -0*yNormal}).computeRho();
418 T rho02 = cell.neighbor({-0*xNormal, -2*yNormal}).computeRho();
420 T rho = (T)2/(T)3*(rho01+rho10) - (T)1/(T)6*(rho02+rho20);
422 T dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d];
430 auto& dynamics = cell.getDynamics();
431 T omega = dynamics.getOmegaOrFallback(std::numeric_limits<T>::signaling_NaN());
433 T sToPi = - rho / descriptors::invCs2<T,DESCRIPTOR>() / omega;
435 pi[xx] = (T)2 * dx_ux * sToPi;
436 pi[yy] = (T)2 * dy_uy * sToPi;
437 pi[xy] = (dx_uy + dy_ux) * sToPi;
444 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
445 cell[iPop] = dynamics.computeEquilibrium(iPop,rho,u)
452template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y>
453template <CONCEPT(Cell) CELL,
typename PARAMETERS>
456 T addend = cell.template getField<descriptors::ADDEND>();
458 T rhoAvg = cell.neighbor({-NORMAL_X,-NORMAL_Y}).computeRho();
461 for (
int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
462 rhoTmp += cell[iPop];
465 T rho = rhoAvg + addend;
473template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y>
474template <CONCEPT(Cell) CELL>
477 cell.template setField<descriptors::CHEM_POTENTIAL>(
478 cell.neighbor({-NORMAL_X,-NORMAL_Y}).template getField<descriptors::CHEM_POTENTIAL>());
480 T rho0 = cell.computeRho();
481 T rho1 = cell.neighbor({-NORMAL_X,-NORMAL_Y}).computeRho();
483 cell.template setField<descriptors::CHEM_POTENTIAL>(
484 cell.template getField<descriptors::CHEM_POTENTIAL>() + (rho1 / rho0 - 1) / descriptors::invCs2<T,DESCRIPTOR>());
487template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y>
488template <CONCEPT(Cell) CELL>
491 cell.template setField<descriptors::CHEM_POTENTIAL>(
492 cell.neighbor({-NORMAL_X,-NORMAL_Y}).template getField<descriptors::CHEM_POTENTIAL>());
497template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y>
498template <CONCEPT(Cell) CELL>
501 T rho, rho0, rho1, u[2];
503 rho0 = cell.computeRho();
505 cell.neighbor({-NORMAL_X,-NORMAL_Y}).computeRhoU(rho1, u);
511 if (normalVec[0] == 0) {
512 uPerp = normalVec[1] * u[1];
513 }
else if (normalVec[1] == 0) {
514 uPerp = normalVec[0] * u[0];
517 rho = (rho0 + uPerp * rho1) / (1. + uPerp);
Platform-abstracted block lattice for external access and inter-block interaction.
Cell< T, DESCRIPTOR > get(CellID iCell)
Get Cell interface for index iCell.
Highest-level interface to Cell data.
void apply(CELL &cell) any_platform
void apply(CELL &cell) any_platform
void apply(CELL &cell) any_platform
void apply(CELL &cell, PARAMETERS ¶meters) any_platform
void apply(CELL &cell) any_platform
This class computes a partial slip BC in 2D.
void processSubDomain(BlockLattice< T, DESCRIPTOR > &blockLattice, int x0_, int x1_, int y0_, int y1_) override
Execute post-processing step on a sublattice.
PartialSlipBoundaryProcessor2D(T tuner_, int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_)
void process(BlockLattice< T, DESCRIPTOR > &blockLattice) override
Execute post-processing step.
PartialSlipBoundaryProcessorGenerator2D(T tuner_, int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_)
PostProcessorGenerator2D< T, DESCRIPTOR > * clone() const override
PostProcessor2D< T, DESCRIPTOR > * generate() const override
Interface of 2D post-processing steps.
std::string & getName()
read and write access to name
This class computes a slip BC in 2D.
void processSubDomain(BlockLattice< T, DESCRIPTOR > &blockLattice, int x0_, int x1_, int y0_, int y1_) override
Execute post-processing step on a sublattice.
SlipBoundaryProcessor2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_)
void process(BlockLattice< T, DESCRIPTOR > &blockLattice) override
Execute post-processing step.
PostProcessorGenerator2D< T, DESCRIPTOR > * clone() const override
PostProcessor2D< T, DESCRIPTOR > * generate() const override
SlipBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_)
This class computes a convection BC on a flat wall in 2D.
StraightConvectionBoundaryProcessor2D(int x0_, int x1_, int y0_, int y1_, T *uAv_=NULL)
~StraightConvectionBoundaryProcessor2D() override
void process(BlockLattice< T, DESCRIPTOR > &blockLattice) override
Execute post-processing step.
void processSubDomain(BlockLattice< T, DESCRIPTOR > &blockLattice, int x0_, int x1_, int y0_, int y1_) override
Execute post-processing step on a sublattice.
PostProcessor2D< T, DESCRIPTOR > * generate() const override
PostProcessorGenerator2D< T, DESCRIPTOR > * clone() const override
StraightConvectionBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, T *uAv_=NULL)
This class computes the skordos BC on a flat wall in 2D but with a limited number of terms added to t...
void apply(CELL &cell) any_platform
bool intersect(int x0, int x1, int y0, int y1, int x0_, int x1_, int y0_, int y1_, int &newX0, int &newX1, int &newY0, int &newY1)
bool nearZero(const ADf< T, DIM > &a)
Top level namespace for all of OpenLB.
#define OLB_PRECONDITION(COND)
static void interpolateVector(T velDeriv[DESCRIPTOR::d], BlockLattice< T, DESCRIPTOR > const &blockLattice, int iX, int iY)
Compute number of elements of a symmetric d-dimensional tensor.
Set of functions commonly used in LB computations – header file.