OpenLB 1.8.1
Loading...
Searching...
No Matches
boundaryPostProcessors2D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2006, 2007 Jonas Latt
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef FD_BOUNDARIES_2D_HH
25#define FD_BOUNDARIES_2D_HH
26
28
29#include "core/util.h"
31
32#include "dynamics/dynamics.h"
33#include "dynamics/lbm.h"
34
35namespace olb {
36
38
39template <typename T, typename DESCRIPTOR, int direction, int orientation>
40template <concepts::DynamicCell CELL>
41void StraightFdBoundaryProcessor2D<T, DESCRIPTOR, direction,
42 orientation>::apply(CELL& cell)
43{
44 using namespace olb::util::tensorIndices2D;
45 using V = typename CELL::value_t;
46
47 V dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d];
48 V rho, u[DESCRIPTOR::d];
49
50 auto& dynamics = cell.getDynamics();
51
52 cell.computeRhoU(rho, u);
53
54 interpolateGradients<0>(cell, dx_u);
55 interpolateGradients<1>(cell, dy_u);
56
57 V dx_ux = dx_u[0];
58 V dy_ux = dy_u[0];
59 V dx_uy = dx_u[1];
60 V dy_uy = dy_u[1];
61 V omega =
62 dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
63 V sToPi = -rho / descriptors::invCs2<V, DESCRIPTOR>() / omega;
65 pi[xx] = (V)2 * dx_ux * sToPi;
66 pi[yy] = (V)2 * dy_uy * sToPi;
67 pi[xy] = (dx_uy + dy_ux) * sToPi;
68
69 // Computation of the particle distribution functions
70 // according to the regularized formula
71 V fEq[DESCRIPTOR::q] { };
72 dynamics.computeEquilibrium(cell, rho, u, fEq);
73 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
74 cell[iPop] = fEq[iPop] + equilibrium<DESCRIPTOR>::template fromPiToFneq<V>(iPop, pi);
75 }
76}
77
78template <typename T, typename DESCRIPTOR, int direction, int orientation>
79template <int deriveDirection, typename CELL, typename V>
81 interpolateGradients(CELL& cell, V velDeriv[DESCRIPTOR::d]) const
82{
83 fd::DirectedGradients2D<V, DESCRIPTOR, direction, orientation,
84 direction ==
85 deriveDirection>::interpolateVector(velDeriv,
86 cell);
87}
88
90
91template <typename T, typename DESCRIPTOR, int direction, int orientation>
92template <concepts::DynamicCell CELL>
93void StraightConvectionBoundaryProcessor2D<T, DESCRIPTOR, direction,
94 orientation>::initialize(CELL& cell)
95{
96 constexpr auto missing =
97 util::populationsContributingToVelocity<DESCRIPTOR, direction,
98 -orientation>();
99 auto prevCell = cell.template getFieldPointer<PREV_CELL>();
100 for (unsigned i = 0; i < missing.size(); ++i) {
101 prevCell[i] = cell[missing[i]];
102 }
103}
104
105template <typename T, typename DESCRIPTOR, int direction, int orientation>
106template <concepts::DynamicCell CELL>
107void StraightConvectionBoundaryProcessor2D<T, DESCRIPTOR, direction,
108 orientation>::apply(CELL& cell)
109{
110 using V = typename CELL::value_t;
111 constexpr auto missing =
112 util::populationsContributingToVelocity<DESCRIPTOR, direction,
113 -orientation>();
114
115 auto prevCell = cell.template getField<PREV_CELL>();
116
117 for (unsigned i = 0; i < missing.size(); ++i) {
118 cell[missing[i]] = prevCell[i];
119 }
120
121 V rho0, u0[2];
122 V rho1, u1[2];
123 V rho2, u2[2];
124
125 cell.computeRhoU(rho0, u0);
126
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);
132 }
133 else if constexpr (direction == 1) {
134 cell.neighbor({0, -orientation}).computeRhoU(rho1, u1);
135 cell.neighbor({0, -orientation * 2}).computeRhoU(rho2, u2);
136 }
137
138 V uDelta[2];
139 V uAverage = rho0 * u0[direction];
140
141 uDelta[0] =
142 -uAverage * 0.5 * (3 * rho0 * u0[0] - 4 * rho1 * u1[0] + rho2 * u2[0]);
143 uDelta[1] =
144 -uAverage * 0.5 * (3 * rho0 * u0[1] - 4 * rho1 * u1[1] + rho2 * u2[1]);
145
146 for (unsigned i = 0; i < missing.size(); ++i) {
147 auto iPop = missing[i];
148 prevCell[i] =
151 (uDelta[0] * descriptors::c<DESCRIPTOR>(iPop, 0) +
152 uDelta[1] * descriptors::c<DESCRIPTOR>(iPop, 1));
153 }
154
155 cell.template setField<PREV_CELL>(prevCell);
156}
157
159
160template <typename T, typename DESCRIPTOR>
162 int x0_, int x1_, int y0_, int y1_, int discreteNormalX,
163 int discreteNormalY)
164 : x0(x0_)
165 , x1(x1_)
166 , y0(y0_)
167 , y1(y1_)
168{
169 this->getName() = "SlipBoundaryProcessor2D";
170 OLB_PRECONDITION(x0 == x1 || y0 == y1);
171 reflectionPop[0] = 0;
172 for (int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
173 reflectionPop[iPop] = 0;
174 // iPop are the directions which ointing into the fluid, discreteNormal is pointing outwarts
175 if (descriptors::c<DESCRIPTOR>(iPop, 0) * discreteNormalX +
176 descriptors::c<DESCRIPTOR>(iPop, 1) * discreteNormalY <
177 0) {
178 // std::cout << "-----" <<s td::endl;
179 int mirrorDirection0;
180 int mirrorDirection1;
181 int mult = 1;
182 if (discreteNormalX * discreteNormalY == 0) {
183 mult = 2;
184 }
185 mirrorDirection0 =
187 mult *
188 (descriptors::c<DESCRIPTOR>(iPop, 0) * discreteNormalX +
189 descriptors::c<DESCRIPTOR>(iPop, 1) * discreteNormalY) *
190 discreteNormalX);
191 mirrorDirection1 =
193 mult *
194 (descriptors::c<DESCRIPTOR>(iPop, 0) * discreteNormalX +
195 descriptors::c<DESCRIPTOR>(iPop, 1) * discreteNormalY) *
196 discreteNormalY);
197
198 // computes mirror jPop
199 for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q;
200 reflectionPop[iPop]++) {
201 if (descriptors::c<DESCRIPTOR>(reflectionPop[iPop], 0) ==
202 mirrorDirection0 &&
203 descriptors::c<DESCRIPTOR>(reflectionPop[iPop], 1) ==
204 mirrorDirection1) {
205 break;
206 }
207 }
208 //std::cout <<iPop << " to "<< jPop <<" for discreteNormal= "<< discreteNormalX << "/"<<discreteNormalY <<std::endl;
209 }
210 }
211}
212
213template <typename T, typename DESCRIPTOR>
215 BlockLattice<T, DESCRIPTOR>& blockLattice, int x0_, int x1_, int y0_,
216 int y1_)
217{
218 int newX0, newX1, newY0, newY1;
219 if (util::intersect(x0, x1, y0, y1, x0_, x1_, y0_, y1_, newX0, newX1, newY0,
220 newY1)) {
221
222 int iX;
223#ifdef PARALLEL_MODE_OMP
224#pragma omp parallel for
225#endif
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) {
230 //do reflection
231 blockLattice.get(iX, iY)[iPop] =
232 blockLattice.get(iX, iY)[reflectionPop[iPop]];
233 }
234 }
235 }
236 }
237 }
238}
239
240template <typename T, typename DESCRIPTOR>
242 BlockLattice<T, DESCRIPTOR>& blockLattice)
243{
244 processSubDomain(blockLattice, x0, x1, y0, y1);
245}
246
248
249template <typename T, typename DESCRIPTOR>
251 T, DESCRIPTOR>::SlipBoundaryProcessorGenerator2D(int x0_, int x1_, int y0_,
252 int y1_,
253 int discreteNormalX_,
254 int discreteNormalY_)
255 : PostProcessorGenerator2D<T, DESCRIPTOR>(x0_, x1_, y0_, y1_)
256 , discreteNormalX(discreteNormalX_)
257 , discreteNormalY(discreteNormalY_)
258{}
259
260template <typename T, typename DESCRIPTOR>
263{
265 this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
266}
267
268template <typename T, typename DESCRIPTOR>
271{
273 this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY);
274}
275
277
278template <typename T, typename DESCRIPTOR, int xNormal, int yNormal>
279template <concepts::DynamicCell CELL>
281 CELL& cell)
282{
283 using namespace olb::util::tensorIndices2D;
284 using V = typename CELL::value_t;
285
286 V rho10 = cell.neighbor({-1 * xNormal, -0 * yNormal}).computeRho();
287 V rho01 = cell.neighbor({-0 * xNormal, -1 * yNormal}).computeRho();
288
289 V rho20 = cell.neighbor({-2 * xNormal, -0 * yNormal}).computeRho();
290 V rho02 = cell.neighbor({-0 * xNormal, -2 * yNormal}).computeRho();
291
292 V rho = (V)2 / (V)3 * (rho01 + rho10) - (V)1 / (V)6 * (rho02 + rho20);
293
294 V dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d];
296 dx_u, cell);
298 dy_u, cell);
299 V dx_ux = dx_u[0];
300 V dy_ux = dy_u[0];
301 V dx_uy = dx_u[1];
302 V dy_uy = dy_u[1];
303
304 auto& dynamics = cell.getDynamics();
305 V omega =
306 dynamics.getOmegaOrFallback(std::numeric_limits<V>::signaling_NaN());
307
308 V sToPi = -rho / descriptors::invCs2<V, DESCRIPTOR>() / omega;
310 pi[xx] = (V)2 * dx_ux * sToPi;
311 pi[yy] = (V)2 * dy_uy * sToPi;
312 pi[xy] = (dx_uy + dy_ux) * sToPi;
313
314 // Computation of the particle distribution functions
315 // according to the regularized formula
316 V u[DESCRIPTOR::d];
317 cell.computeU(u);
318 V fEq[DESCRIPTOR::q] { };
319 dynamics.computeEquilibrium(cell, rho, u, fEq);
320 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
321 cell[iPop] = fEq[iPop] + equilibrium<DESCRIPTOR>::template fromPiToFneq<V>(iPop, pi);
322 }
323}
324
325} // namespace olb
326
327
328#endif
Interface of 2D post-processing steps.
Definition aliases.h:43
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
Definition functions.h:107
constexpr T t(unsigned iPop, tag::CUM) any_platform
Definition cum.h:108
constexpr int c(unsigned iPop, unsigned iDim) any_platform
Definition functions.h:83
constexpr auto populationsContributingToVelocity() any_platform
Return array of population indices where c[iVel] == value.
Definition util.h:222
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)
Definition util.h:85
Top level namespace for all of OpenLB.
void initialize(int *argc, char ***argv, bool multiOutput, bool verbose)
Initialize OpenLB.
Definition olbInit.cpp:49
#define OLB_PRECONDITION(COND)
Definition olbDebug.h:46
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.
Definition util.h:216
Set of functions commonly used in LB computations – header file.