24#ifndef FD_BOUNDARIES_2D_HH
25#define FD_BOUNDARIES_2D_HH
39template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
40template <concepts::DynamicCell CELL>
41void StraightFdBoundaryProcessor2D<T, DESCRIPTOR, direction,
42 orientation>::apply(CELL& cell)
45 using V =
typename CELL::value_t;
47 V dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d];
48 V rho, u[DESCRIPTOR::d];
50 auto& dynamics = cell.getDynamics();
52 cell.computeRhoU(rho, u);
54 interpolateGradients<0>(cell, dx_u);
55 interpolateGradients<1>(cell, dy_u);
62 dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
65 pi[xx] = (V)2 * dx_ux * sToPi;
66 pi[yy] = (V)2 * dy_uy * sToPi;
67 pi[xy] = (dx_uy + dy_ux) * sToPi;
71 V fEq[DESCRIPTOR::q] { };
72 dynamics.computeEquilibrium(cell, rho, u, fEq);
73 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
78template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
79template <
int deriveDirection,
typename CELL,
typename V>
85 deriveDirection>::interpolateVector(velDeriv,
91template <
typename T,
typename DESCRIPTOR,
int direction,
int orientation>
92template <concepts::DynamicCell CELL>
96 constexpr auto missing =
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>
108 orientation>::apply(CELL& cell)
110 using V =
typename CELL::value_t;
111 constexpr auto missing =
115 auto prevCell = cell.template getField<PREV_CELL>();
117 for (
unsigned i = 0; i < missing.size(); ++i) {
118 cell[missing[i]] = prevCell[i];
125 cell.computeRhoU(rho0, u0);
127 static_assert(direction == 0 || direction == 1
128 ,
"Direction must be one of 0 or 1 in 2D");
129 if constexpr (direction == 0) {
130 cell.neighbor({-orientation, 0}).computeRhoU(rho1, u1);
131 cell.neighbor({-orientation * 2, 0}).computeRhoU(rho2, u2);
133 else if constexpr (direction == 1) {
134 cell.neighbor({0, -orientation}).computeRhoU(rho1, u1);
135 cell.neighbor({0, -orientation * 2}).computeRhoU(rho2, u2);
139 V uAverage = rho0 * u0[direction];
142 -uAverage * 0.5 * (3 * rho0 * u0[0] - 4 * rho1 * u1[0] + rho2 * u2[0]);
144 -uAverage * 0.5 * (3 * rho0 * u0[1] - 4 * rho1 * u1[1] + rho2 * u2[1]);
146 for (
unsigned i = 0; i < missing.size(); ++i) {
147 auto iPop = missing[i];
155 cell.template setField<PREV_CELL>(prevCell);
160template <
typename T,
typename DESCRIPTOR>
162 int x0_,
int x1_,
int y0_,
int y1_,
int discreteNormalX,
169 this->
getName() =
"SlipBoundaryProcessor2D";
171 reflectionPop[0] = 0;
172 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
173 reflectionPop[iPop] = 0;
179 int mirrorDirection0;
180 int mirrorDirection1;
182 if (discreteNormalX * discreteNormalY == 0) {
199 for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q;
200 reflectionPop[iPop]++) {
213template <
typename T,
typename DESCRIPTOR>
218 int newX0, newX1, newY0, newY1;
219 if (
util::intersect(x0, x1, y0, y1, x0_, x1_, y0_, y1_, newX0, newX1, newY0,
223#ifdef PARALLEL_MODE_OMP
224#pragma omp parallel for
226 for (iX = newX0; iX <= newX1; ++iX) {
227 for (
int iY = newY0; iY <= newY1; ++iY) {
228 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
229 if (reflectionPop[iPop] != 0) {
231 blockLattice.get(iX, iY)[iPop] =
232 blockLattice.get(iX, iY)[reflectionPop[iPop]];
240template <
typename T,
typename DESCRIPTOR>
244 processSubDomain(blockLattice, x0, x1, y0, y1);
249template <
typename T,
typename DESCRIPTOR>
251 T, DESCRIPTOR>::SlipBoundaryProcessorGenerator2D(
int x0_,
int x1_,
int y0_,
253 int discreteNormalX_,
254 int discreteNormalY_)
256 , discreteNormalX(discreteNormalX_)
257 , discreteNormalY(discreteNormalY_)
260template <
typename T,
typename DESCRIPTOR>
265 this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
268template <
typename T,
typename DESCRIPTOR>
273 this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
278template <
typename T,
typename DESCRIPTOR,
int xNormal,
int yNormal>
279template <concepts::DynamicCell CELL>
284 using V =
typename CELL::value_t;
286 V rho10 = cell.neighbor({-1 * xNormal, -0 * yNormal}).computeRho();
287 V rho01 = cell.neighbor({-0 * xNormal, -1 * yNormal}).computeRho();
289 V rho20 = cell.neighbor({-2 * xNormal, -0 * yNormal}).computeRho();
290 V rho02 = cell.neighbor({-0 * xNormal, -2 * yNormal}).computeRho();
292 V rho = (V)2 / (V)3 * (rho01 + rho10) - (V)1 / (V)6 * (rho02 + rho20);
294 V dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d];
304 auto& dynamics = cell.getDynamics();
306 dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
310 pi[xx] = (V)2 * dx_ux * sToPi;
311 pi[yy] = (V)2 * dy_uy * sToPi;
312 pi[xy] = (dx_uy + dy_ux) * sToPi;
318 V fEq[DESCRIPTOR::q] { };
319 dynamics.computeEquilibrium(cell, rho, u, fEq);
320 for (
int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
void apply(CELL &cell) any_platform
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
This class computes a convection BC on a flat wall in 2D.
This class computes the skordos BC on a flat wall in 2D but with a limited number of terms added to t...
constexpr T invCs2() any_platform
constexpr T t(unsigned iPop, tag::CUM) any_platform
constexpr int c(unsigned iPop, unsigned iDim) 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.
void initialize(int *argc, char ***argv, bool multiOutput, bool verbose)
Initialize 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.