24#ifndef BOUNDARY_POST_PROCESSORS_3D_HH
25#define BOUNDARY_POST_PROCESSORS_3D_HH
39template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
40template <concepts::DynamicCell CELL>
43 using V =
typename CELL::value_t;
46 V dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d], dz_u[DESCRIPTOR::d];
47 V rho, u[DESCRIPTOR::d];
49 auto& dynamics = cell.getDynamics();
51 cell.computeRhoU(rho,u);
53 interpolateGradients<0>(cell, dx_u);
54 interpolateGradients<1>(cell, dy_u);
55 interpolateGradients<2>(cell, dz_u);
66 V omega = dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
69 pi[xx] = (V)2 * dx_ux * sToPi;
70 pi[yy] = (V)2 * dy_uy * sToPi;
71 pi[zz] = (V)2 * dz_uz * sToPi;
72 pi[xy] = (dx_uy + dy_ux) * sToPi;
73 pi[xz] = (dx_uz + dz_ux) * sToPi;
74 pi[yz] = (dy_uz + dz_uy) * sToPi;
78 V fEq[DESCRIPTOR::q] { };
79 dynamics.computeEquilibrium(cell, rho, u, fEq);
80 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
85template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
86template <
int deriveDirection,
typename CELL,
typename V>
88 CELL& cell, V velDeriv[DESCRIPTOR::d])
const
94template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
95template <concepts::DynamicCell CELL>
99 auto prevCell = cell.template getFieldPointer<PREV_CELL>();
100 for (
unsigned i=0; i < missing.size(); ++i) {
101 prevCell[i] = cell[missing[i]];
105template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
106template <concepts::DynamicCell CELL>
109 using V =
typename CELL::value_t;
112 auto prevCell = cell.template getField<PREV_CELL>();
114 for (
unsigned i=0; i < missing.size(); ++i) {
115 cell[missing[i]] = prevCell[i];
122 cell.computeRhoU(rho0, u0);
124 static_assert(direction == 0 || direction == 1 || direction ==2,
125 "Direction must be one of 0, 1 or 2");
126 if constexpr (direction == 0) {
127 cell.neighbor({-orientation ,0,0}).computeRhoU(rho1, u1);
128 cell.neighbor({-orientation*2,0,0}).computeRhoU(rho2, u2);
130 else if constexpr (direction == 1) {
131 cell.neighbor({0,-orientation ,0}).computeRhoU(rho1, u1);
132 cell.neighbor({0,-orientation*2,0}).computeRhoU(rho2, u2);
134 else if constexpr (direction == 2) {
135 cell.neighbor({0,0,-orientation }).computeRhoU(rho1, u1);
136 cell.neighbor({0,0,-orientation*2}).computeRhoU(rho2, u2);
140 V uAverage = rho0*u0[direction];
148 uDelta[0] = -uAverage*0.5*(3*rho0*u0[0]-4*rho1*u1[0]+rho2*u2[0]);
149 uDelta[1] = -uAverage*0.5*(3*rho0*u0[1]-4*rho1*u1[1]+rho2*u2[1]);
150 uDelta[2] = -uAverage*0.5*(3*rho0*u0[2]-4*rho1*u1[2]+rho2*u2[2]);
152 for (
unsigned i=0; i < missing.size(); ++i) {
153 auto iPop = missing[i];
154 prevCell[i] = cell[iPop]
161 cell.template setField<PREV_CELL>(prevCell);
166template <
typename T,
typename DESCRIPTOR,
int plane,
int normal1,
int normal2>
167template <concepts::DynamicCell CELL>
170 using V =
typename CELL::value_t;
173 constexpr auto direction1 = (plane+1)%3;
174 constexpr auto direction2 = (plane+2)%3;
176 auto& dynamics = cell.getDynamics();
178 V rho10 = getNeighborRho(cell, 1,0);
179 V rho01 = getNeighborRho(cell, 0,1);
180 V rho20 = getNeighborRho(cell, 2,0);
181 V rho02 = getNeighborRho(cell, 0,2);
182 V rho = (V)2/(V)3*(rho01+rho10)-(V)1/(V)6*(rho02+rho20);
186 interpolateGradients<plane,0> (cell, dA_uB_[0]);
187 interpolateGradients<direction1,normal1>(cell, dA_uB_[1]);
188 interpolateGradients<direction2,normal2>(cell, dA_uB_[2]);
191 for (
int iBeta=0; iBeta<3; ++iBeta) {
192 dA_uB[plane][iBeta] = dA_uB_[0][iBeta];
193 dA_uB[direction1][iBeta] = dA_uB_[1][iBeta];
194 dA_uB[direction2][iBeta] = dA_uB_[2][iBeta];
196 V omega = dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
199 pi[xx] = (V)2 * dA_uB[0][0] * sToPi;
200 pi[yy] = (V)2 * dA_uB[1][1] * sToPi;
201 pi[zz] = (V)2 * dA_uB[2][2] * sToPi;
202 pi[xy] = (dA_uB[0][1]+dA_uB[1][0]) * sToPi;
203 pi[xz] = (dA_uB[0][2]+dA_uB[2][0]) * sToPi;
204 pi[yz] = (dA_uB[1][2]+dA_uB[2][1]) * sToPi;
211 V fEq[DESCRIPTOR::q] { };
212 dynamics.computeEquilibrium(cell, rho, u, fEq);
213 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
218template <
typename T,
typename DESCRIPTOR,
int plane,
int normal1,
int normal2>
219template <
typename CELL,
typename V>
223 constexpr auto direction1 = (plane+1)%3;
224 constexpr auto direction2 = (plane+2)%3;
226 coords[direction1] = -normal1*step1;
227 coords[direction2] = -normal2*step2;
228 return cell.neighbor(coords).computeRho();
231template <
typename T,
typename DESCRIPTOR,
int plane,
int normal1,
int normal2>
232template <
int deriveDirection,
int orientation,
typename CELL,
typename V>
242template <
typename T,
typename DESCRIPTOR,
int xNormal,
int yNormal,
int zNormal>
243template <concepts::DynamicCell CELL>
246 using V =
typename CELL::value_t;
249 auto& dynamics = cell.getDynamics();
251 V rho100 = cell.neighbor({-1*xNormal, -0*yNormal, -0*zNormal}).computeRho();
252 V rho010 = cell.neighbor({-0*xNormal, -1*yNormal, -0*zNormal}).computeRho();
253 V rho001 = cell.neighbor({-0*xNormal, -0*yNormal, -1*zNormal}).computeRho();
254 V rho200 = cell.neighbor({-2*xNormal, -0*yNormal, -0*zNormal}).computeRho();
255 V rho020 = cell.neighbor({-0*xNormal, -2*yNormal, -0*zNormal}).computeRho();
256 V rho002 = cell.neighbor({-0*xNormal, -0*yNormal, -2*zNormal}).computeRho();
258 V rho = (V)4/(V)9 * (rho001 + rho010 + rho100) - (V)1/(V)9 * (rho002 + rho020 + rho200);
260 V dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d], dz_u[DESCRIPTOR::d];
274 V omega = dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
277 pi[xx] = (V)2 * dx_ux * sToPi;
278 pi[yy] = (V)2 * dy_uy * sToPi;
279 pi[zz] = (V)2 * dz_uz * sToPi;
280 pi[xy] = (dx_uy + dy_ux) * sToPi;
281 pi[xz] = (dx_uz + dz_ux) * sToPi;
282 pi[yz] = (dy_uz + dz_uy) * sToPi;
289 V fEq[DESCRIPTOR::q] { };
290 dynamics.computeEquilibrium(cell, rho, u, fEq);
291 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
298template<
typename T,
typename DESCRIPTOR>
300SlipBoundaryProcessor3D(
int x0_,
int x1_,
int y0_,
int y1_,
int z0_,
int z1_,
int discreteNormalX,
int discreteNormalY,
int discreteNormalZ)
301 : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_)
303 this->
getName() =
"SlipBoundaryProcessor3D";
305 int mirrorDirection0;
306 int mirrorDirection1;
307 int mirrorDirection2;
308 int mult = 2 / (discreteNormalX*discreteNormalX + discreteNormalY*discreteNormalY + discreteNormalZ*discreteNormalZ);
309 reflectionPop[0] = 0;
310 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
311 reflectionPop[iPop] = 0;
314 if ( scalarProduct < 0) {
328 for (
int i = 1; i < DESCRIPTOR::q; i++) {
332 reflectionPop[iPop] = i;
340template<
typename T,
typename DESCRIPTOR>
344 int newX0, newX1, newY0, newY1, newZ0, newZ1;
346 x0, x1, y0, y1, z0, z1,
347 x0_, x1_, y0_, y1_, z0_, z1_,
348 newX0, newX1, newY0, newY1, newZ0, newZ1 ) ) {
351#ifdef PARALLEL_MODE_OMP
352 #pragma omp parallel for
354 for (iX=x0; iX<=x1; ++iX) {
355 for (
int iY=y0; iY<=y1; ++iY) {
356 for (
int iZ=z0; iZ<=z1; ++iZ) {
357 for (
int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
358 if (reflectionPop[iPop]!=0) {
360 blockLattice.get(iX,iY,iZ)[iPop] = blockLattice.get(iX,iY,iZ)[reflectionPop[iPop]];
369template<
typename T,
typename DESCRIPTOR>
373 processSubDomain(blockLattice, x0, x1, y0, y1, z0, z1);
378template<
typename T,
typename DESCRIPTOR>
381 :
PostProcessorGenerator3D<T,DESCRIPTOR>(x0_, x1_, y0_, y1_, z0_, z1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), discreteNormalZ(discreteNormalZ_)
384template<
typename T,
typename DESCRIPTOR>
389 ( this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
392template<
typename T,
typename DESCRIPTOR>
397 (this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
402template<
typename T,
typename DESCRIPTOR>
404PartialSlipBoundaryProcessor3D(T tuner_,
int x0_,
int x1_,
int y0_,
int y1_,
int z0_,
int z1_,
int discreteNormalX,
int discreteNormalY,
int discreteNormalZ)
405 : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_), tuner(tuner_)
407 this->
getName() =
"PartialSlipBoundaryProcessor3D";
409 reflectionPop[0] = 0;
410 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
411 reflectionPop[iPop] = 0;
415 int mirrorDirection0;
416 int mirrorDirection1;
417 int mirrorDirection2;
418 int mult = 2 / (discreteNormalX*discreteNormalX + discreteNormalY*discreteNormalY + discreteNormalZ*discreteNormalZ);
433 for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q ; reflectionPop[iPop]++) {
443template<
typename T,
typename DESCRIPTOR>
447 int newX0, newX1, newY0, newY1, newZ0, newZ1;
450 x0, x1, y0, y1, z0, z1,
451 x0_, x1_, y0_, y1_, z0_, z1_,
452 newX0, newX1, newY0, newY1, newZ0, newZ1 ) ) {
455#ifdef PARALLEL_MODE_OMP
456 #pragma omp parallel for
458 for (iX=newX0; iX<=newX1; ++iX) {
459 for (
int iY=newY0; iY<=newY1; ++iY) {
460 for (
int iZ=newZ0; iZ<=newZ1; ++iZ) {
461 for (
int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
462 if (reflectionPop[iPop]!=0) {
464 blockLattice.get(iX,iY,iZ)[iPop] = tuner*blockLattice.get(iX,iY,iZ)[reflectionPop[iPop]];
467 for (
int iPop = 1; iPop < DESCRIPTOR::q/2 ; ++iPop) {
470 (1.-tuner)*blockLattice.get(iX,iY,iZ)[iPop];
471 blockLattice.get(iX,iY,iZ)[iPop] += (1.-tuner)*provv;
479template<
typename T,
typename DESCRIPTOR>
483 processSubDomain(blockLattice, x0, x1, y0, y1, z0, z1);
488template<
typename T,
typename DESCRIPTOR>
491 :
PostProcessorGenerator3D<T,DESCRIPTOR>(x0_, x1_, y0_, y1_, z0_, z1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), discreteNormalZ(discreteNormalZ_), tuner(tuner_)
494template<
typename T,
typename DESCRIPTOR>
499 (tuner, this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
502template<
typename T,
typename DESCRIPTOR>
507 (tuner, this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
511template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y,
int NORMAL_Z>
512template <concepts::DynamicCell CELL,
typename PARAMETERS>
515 T addend = cell.template getField<descriptors::ADDEND>();
517 T rhoBulk = cell.neighbor({-NORMAL_X, -NORMAL_Y, -NORMAL_Z}).computeRho();
520 for (
int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
521 rhoTmp += cell[iPop];
524 T rho = rhoBulk + addend;
533template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y,
int NORMAL_Z>
534template <concepts::DynamicCell CELL>
537 cell.template setField<descriptors::CHEM_POTENTIAL>(
538 cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).template getField<descriptors::CHEM_POTENTIAL>());
540 T rho0 = cell.computeRho();
541 T rho1 = cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).computeRho();
543 cell.template setField<descriptors::CHEM_POTENTIAL>(
547template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y,
int NORMAL_Z>
548template <concepts::DynamicCell CELL>
551 cell.template setField<descriptors::CHEM_POTENTIAL>(
552 cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).template getField<descriptors::CHEM_POTENTIAL>());
557template<
typename T,
typename DESCRIPTOR,
int NORMAL_X,
int NORMAL_Y,
int NORMAL_Z>
558template <concepts::DynamicCell CELL>
561 T rho, rho0, rho1, u[3];
563 rho0 = cell.computeRho();
565 cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).computeRhoU(rho1, u);
571 if (normalVec[2] == 0) {
572 if (normalVec[1] == 0) {
573 if (normalVec[0] < 0) {
578 }
else if (normalVec[0] == 0) {
579 if (normalVec[1] < 0) {
585 uPerp =
util::sqrt(u[0] * u[0] + u[1] * u[1]);
587 }
else if (normalVec[1] == 0) {
588 if (normalVec[0] == 0) {
589 if (normalVec[2] < 0) {
595 uPerp =
util::sqrt(u[0] * u[0] + u[2] * u[2]);
597 }
else if (normalVec[0] == 0) {
598 uPerp =
util::sqrt(u[1] * u[1] + u[2] * u[2]);
600 uPerp =
util::sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
603 rho = (rho0 + uPerp * rho1) / (1. + uPerp);
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
This class computes the skordos BC on a convex edge wall in 3D but with a limited number of terms add...
void apply(CELL &cell) any_platform
This class computes a partial slip BC in 3D.
PartialSlipBoundaryProcessor3D(T tuner_, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX_, int discreteNormalY_, int discreteNormalZ_)
void processSubDomain(BlockLattice< T, DESCRIPTOR > &blockLattice, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_) override
Execute post-processing step on a sublattice.
void process(BlockLattice< T, DESCRIPTOR > &blockLattice) override
Execute post-processing step.
PartialSlipBoundaryProcessorGenerator3D(T tuner_, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX_, int discreteNormalY_, int discreteNormalZ_)
PostProcessor3D< T, DESCRIPTOR > * generate() const override
PostProcessorGenerator3D< T, DESCRIPTOR > * clone() const override
This class computes the skordos BC on a plane wall in 3D but with a limited number of terms added to ...
void apply(CELL &cell) any_platform
std::string & getName()
read and write access to name
This class computes a slip BC in 3D.
SlipBoundaryProcessor3D(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX_, int discreteNormalY_, int discreteNormalZ_)
void processSubDomain(BlockLattice< T, DESCRIPTOR > &blockLattice, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_) override
Execute post-processing step on a sublattice.
void process(BlockLattice< T, DESCRIPTOR > &blockLattice) override
Execute post-processing step.
PostProcessorGenerator3D< T, DESCRIPTOR > * clone() const override
SlipBoundaryProcessorGenerator3D(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX_, int discreteNormalY_, int discreteNormalZ_)
PostProcessor3D< T, DESCRIPTOR > * generate() const override
void initialize(CELL &cell) any_platform
void apply(CELL &cell) any_platform
constexpr T invCs2() any_platform
constexpr T t(unsigned iPop, tag::CUM) any_platform
constexpr int c(unsigned iPop, unsigned iDim) any_platform
constexpr int opposite(unsigned iPop) any_platform
constexpr auto populationsContributingToVelocity() any_platform
Return array of population indices where c[iVel] == value.
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)
Top level namespace for all of OpenLB.
#define OLB_PRECONDITION(COND)
void apply(CELL &cell) any_platform
static void interpolateVector(T velDeriv[DESCRIPTOR::d], BlockLattice< T, DESCRIPTOR > const &blockLattice, int iX, int iY, int iZ)
Compute number of elements of a symmetric d-dimensional tensor.
Set of functions commonly used in LB computations – header file.