OpenLB 1.7
Loading...
Searching...
No Matches
boundaryPostProcessors3D.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 BOUNDARY_POST_PROCESSORS_3D_HH
25#define BOUNDARY_POST_PROCESSORS_3D_HH
26
28
30#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 <CONCEPT(Cell) CELL>
42{
43 using namespace olb::util::tensorIndices3D;
44
45 T dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d], dz_u[DESCRIPTOR::d];
46 T rho, u[DESCRIPTOR::d];
47
48 auto& dynamics = cell.getDynamics();
49
50 cell.computeRhoU(rho,u);
51
52 interpolateGradients<0>(cell, dx_u);
53 interpolateGradients<1>(cell, dy_u);
54 interpolateGradients<2>(cell, dz_u);
55
56 T dx_ux = dx_u[0];
57 T dy_ux = dy_u[0];
58 T dz_ux = dz_u[0];
59 T dx_uy = dx_u[1];
60 T dy_uy = dy_u[1];
61 T dz_uy = dz_u[1];
62 T dx_uz = dx_u[2];
63 T dy_uz = dy_u[2];
64 T dz_uz = dz_u[2];
65 T omega = dynamics.getOmegaOrFallback(std::numeric_limits<T>::signaling_NaN());
66 T sToPi = - rho / descriptors::invCs2<T,DESCRIPTOR>() / omega;
68 pi[xx] = (T)2 * dx_ux * sToPi;
69 pi[yy] = (T)2 * dy_uy * sToPi;
70 pi[zz] = (T)2 * dz_uz * sToPi;
71 pi[xy] = (dx_uy + dy_ux) * sToPi;
72 pi[xz] = (dx_uz + dz_ux) * sToPi;
73 pi[yz] = (dy_uz + dz_uy) * sToPi;
74
75 // Computation of the particle distribution functions
76 // according to the regularized formula
77 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
78 cell[iPop] = dynamics.computeEquilibrium(iPop,rho,u)
79 + equilibrium<DESCRIPTOR>::template fromPiToFneq<T>(iPop, pi);
80 }
81}
82
83template <typename T, typename DESCRIPTOR, int direction, int orientation>
84template <int deriveDirection, typename CELL>
86 CELL& cell, T velDeriv[DESCRIPTOR::d]) const
87{
89 ::interpolateVector(velDeriv, cell);
90}
91
92template <typename DESCRIPTOR, int direction, int orientation>
93template <CONCEPT(Cell) CELL>
95{
96 constexpr auto missing = util::populationsContributingToVelocity<DESCRIPTOR,direction,-orientation>();
97 auto prevCell = cell.template getFieldPointer<PREV_CELL>();
98 for (unsigned i=0; i < missing.size(); ++i) {
99 prevCell[i] = cell[missing[i]];
100 }
101}
102
103template <typename DESCRIPTOR, int direction, int orientation>
104template <CONCEPT(Cell) CELL>
106{
107 using V = typename CELL::value_t;
108 constexpr auto missing = util::populationsContributingToVelocity<DESCRIPTOR,direction,-orientation>();
109
110 auto prevCell = cell.template getField<PREV_CELL>();
111
112 for (unsigned i=0; i < missing.size(); ++i) {
113 cell[missing[i]] = prevCell[i];
114 }
115
116 V rho0, u0[3];
117 V rho1, u1[3];
118 V rho2, u2[3];
119
120 cell.computeRhoU(rho0, u0);
121
122 static_assert(direction == 0 || direction == 1 || direction ==2,
123 "Direction must be one of 0, 1 or 2");
124 if constexpr (direction == 0) {
125 cell.neighbor({-orientation ,0,0}).computeRhoU(rho1, u1);
126 cell.neighbor({-orientation*2,0,0}).computeRhoU(rho2, u2);
127 }
128 else if constexpr (direction == 1) {
129 cell.neighbor({0,-orientation ,0}).computeRhoU(rho1, u1);
130 cell.neighbor({0,-orientation*2,0}).computeRhoU(rho2, u2);
131 }
132 else if constexpr (direction == 2) {
133 cell.neighbor({0,0,-orientation }).computeRhoU(rho1, u1);
134 cell.neighbor({0,0,-orientation*2}).computeRhoU(rho2, u2);
135 }
136
137 V uDelta[3];
138 V uAverage = rho0*u0[direction];
139 //if (uAv!=nullptr) {
140 // rho0 = V{1};
141 // rho1 = V{1};
142 // rho2 = V{1};
143 // uAverage = *uAv * rho0;
144 //}
145
146 uDelta[0] = -uAverage*0.5*(3*rho0*u0[0]-4*rho1*u1[0]+rho2*u2[0]);
147 uDelta[1] = -uAverage*0.5*(3*rho0*u0[1]-4*rho1*u1[1]+rho2*u2[1]);
148 uDelta[2] = -uAverage*0.5*(3*rho0*u0[2]-4*rho1*u1[2]+rho2*u2[2]);
149
150 for (unsigned i=0; i < missing.size(); ++i) {
151 auto iPop = missing[i];
152 prevCell[i] = cell[iPop]
153 + descriptors::invCs2<V,DESCRIPTOR>()*descriptors::t<V,DESCRIPTOR>(iPop)
154 * ( uDelta[0]*descriptors::c<DESCRIPTOR>(iPop,0)
155 + uDelta[1]*descriptors::c<DESCRIPTOR>(iPop,1)
156 + uDelta[2]*descriptors::c<DESCRIPTOR>(iPop,2));
157 }
158
159 cell.template setField<PREV_CELL>(prevCell);
160}
161
163
164template <typename T, typename DESCRIPTOR, int plane, int normal1, int normal2>
165template <CONCEPT(Cell) CELL>
167{
168 using namespace olb::util::tensorIndices3D;
169
170 constexpr auto direction1 = (plane+1)%3;
171 constexpr auto direction2 = (plane+2)%3;
172
173 auto& dynamics = cell.getDynamics();
174
175 T rho10 = getNeighborRho(cell, 1,0);
176 T rho01 = getNeighborRho(cell, 0,1);
177 T rho20 = getNeighborRho(cell, 2,0);
178 T rho02 = getNeighborRho(cell, 0,2);
179 T rho = (T)2/(T)3*(rho01+rho10)-(T)1/(T)6*(rho02+rho20);
180
181 T dA_uB_[3][3];
182
183 interpolateGradients<plane,0> (cell, dA_uB_[0]);
184 interpolateGradients<direction1,normal1>(cell, dA_uB_[1]);
185 interpolateGradients<direction2,normal2>(cell, dA_uB_[2]);
186
187 T dA_uB[3][3];
188 for (int iBeta=0; iBeta<3; ++iBeta) {
189 dA_uB[plane][iBeta] = dA_uB_[0][iBeta];
190 dA_uB[direction1][iBeta] = dA_uB_[1][iBeta];
191 dA_uB[direction2][iBeta] = dA_uB_[2][iBeta];
192 }
193 T omega = dynamics.getOmegaOrFallback(std::numeric_limits<T>::signaling_NaN());
194 T sToPi = - rho / descriptors::invCs2<T,DESCRIPTOR>() / omega;
196 pi[xx] = (T)2 * dA_uB[0][0] * sToPi;
197 pi[yy] = (T)2 * dA_uB[1][1] * sToPi;
198 pi[zz] = (T)2 * dA_uB[2][2] * sToPi;
199 pi[xy] = (dA_uB[0][1]+dA_uB[1][0]) * sToPi;
200 pi[xz] = (dA_uB[0][2]+dA_uB[2][0]) * sToPi;
201 pi[yz] = (dA_uB[1][2]+dA_uB[2][1]) * sToPi;
202
203 // Computation of the particle distribution functions
204 // according to the regularized formula
205 T u[DESCRIPTOR::d];
206 cell.computeU(u);
207
208 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
209 cell[iPop] = dynamics.computeEquilibrium(iPop,rho,u)
210 + equilibrium<DESCRIPTOR>::template fromPiToFneq<T>(iPop, pi);
211 }
212}
213
214template <typename T, typename DESCRIPTOR, int plane, int normal1, int normal2>
215template <typename CELL>
217 ::getNeighborRho(CELL& cell, int step1, int step2)
218{
219 constexpr auto direction1 = (plane+1)%3;
220 constexpr auto direction2 = (plane+2)%3;
221 int coords[3] { };
222 coords[direction1] = -normal1*step1;
223 coords[direction2] = -normal2*step2;
224 return cell.neighbor(coords).computeRho();
225}
226
227template <typename T, typename DESCRIPTOR, int plane, int normal1, int normal2>
228template <int deriveDirection, int orientation, typename CELL>
230 ::interpolateGradients(CELL& cell, T velDeriv[DESCRIPTOR::d]) const
231{
233 ::interpolateVector(velDeriv, cell);
234}
235
237
238template <typename T, typename DESCRIPTOR, int xNormal, int yNormal, int zNormal>
239template <CONCEPT(Cell) CELL>
241{
242 using namespace olb::util::tensorIndices3D;
243
244 auto& dynamics = cell.getDynamics();
245
246 T rho100 = cell.neighbor({-1*xNormal, -0*yNormal, -0*zNormal}).computeRho();
247 T rho010 = cell.neighbor({-0*xNormal, -1*yNormal, -0*zNormal}).computeRho();
248 T rho001 = cell.neighbor({-0*xNormal, -0*yNormal, -1*zNormal}).computeRho();
249 T rho200 = cell.neighbor({-2*xNormal, -0*yNormal, -0*zNormal}).computeRho();
250 T rho020 = cell.neighbor({-0*xNormal, -2*yNormal, -0*zNormal}).computeRho();
251 T rho002 = cell.neighbor({-0*xNormal, -0*yNormal, -2*zNormal}).computeRho();
252
253 T rho = (T)4/(T)9 * (rho001 + rho010 + rho100) - (T)1/(T)9 * (rho002 + rho020 + rho200);
254
255 T dx_u[DESCRIPTOR::d], dy_u[DESCRIPTOR::d], dz_u[DESCRIPTOR::d];
259
260 T dx_ux = dx_u[0];
261 T dy_ux = dy_u[0];
262 T dz_ux = dz_u[0];
263 T dx_uy = dx_u[1];
264 T dy_uy = dy_u[1];
265 T dz_uy = dz_u[1];
266 T dx_uz = dx_u[2];
267 T dy_uz = dy_u[2];
268 T dz_uz = dz_u[2];
269 T omega = dynamics.getOmegaOrFallback(std::numeric_limits<T>::signaling_NaN());
270 T sToPi = - rho / descriptors::invCs2<T,DESCRIPTOR>() / omega;
272 pi[xx] = (T)2 * dx_ux * sToPi;
273 pi[yy] = (T)2 * dy_uy * sToPi;
274 pi[zz] = (T)2 * dz_uz * sToPi;
275 pi[xy] = (dx_uy + dy_ux) * sToPi;
276 pi[xz] = (dx_uz + dz_ux) * sToPi;
277 pi[yz] = (dy_uz + dz_uy) * sToPi;
278
279 // Computation of the particle distribution functions
280 // according to the regularized formula
281 T u[DESCRIPTOR::d];
282 cell.computeU(u);
283
284 for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) {
285 cell[iPop] = dynamics.computeEquilibrium(iPop,rho,u)
286 + equilibrium<DESCRIPTOR>::template fromPiToFneq<T>(iPop, pi);
287 }
288}
289
291
292template<typename T, typename DESCRIPTOR>
294SlipBoundaryProcessor3D(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX, int discreteNormalY, int discreteNormalZ)
295 : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_)
296{
297 this->getName() = "SlipBoundaryProcessor3D";
298 OLB_PRECONDITION(x0==x1 || y0==y1 || z0==z1);
299 int mirrorDirection0;
300 int mirrorDirection1;
301 int mirrorDirection2;
302 int mult = 2 / (discreteNormalX*discreteNormalX + discreteNormalY*discreteNormalY + discreteNormalZ*discreteNormalZ);
303 reflectionPop[0] = 0;
304 for (int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
305 reflectionPop[iPop] = 0;
306 // iPop are the directions which pointing into the fluid, discreteNormal is pointing outwarts
307 int scalarProduct = descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY + descriptors::c<DESCRIPTOR>(iPop,2)*discreteNormalZ;
308 if ( scalarProduct < 0) {
309 // bounce back for the case discreteNormalX = discreteNormalY = discreteNormalZ = 1, that is mult=0
310 if (mult == 0) {
311 mirrorDirection0 = -descriptors::c<DESCRIPTOR>(iPop,0);
312 mirrorDirection1 = -descriptors::c<DESCRIPTOR>(iPop,1);
313 mirrorDirection2 = -descriptors::c<DESCRIPTOR>(iPop,2);
314 }
315 else {
316 mirrorDirection0 = descriptors::c<DESCRIPTOR>(iPop,0) - mult*scalarProduct*discreteNormalX;
317 mirrorDirection1 = descriptors::c<DESCRIPTOR>(iPop,1) - mult*scalarProduct*discreteNormalY;
318 mirrorDirection2 = descriptors::c<DESCRIPTOR>(iPop,2) - mult*scalarProduct*discreteNormalZ;
319 }
320
321 // run through all lattice directions and look for match of direction
322 for (int i = 1; i < DESCRIPTOR::q; i++) {
323 if (descriptors::c<DESCRIPTOR>(i,0)==mirrorDirection0
324 && descriptors::c<DESCRIPTOR>(i,1)==mirrorDirection1
325 && descriptors::c<DESCRIPTOR>(i,2)==mirrorDirection2) {
326 reflectionPop[iPop] = i;
327 break;
328 }
329 }
330 }
331 }
332}
333
334template<typename T, typename DESCRIPTOR>
336processSubDomain(BlockLattice<T,DESCRIPTOR>& blockLattice, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
337{
338 int newX0, newX1, newY0, newY1, newZ0, newZ1;
339 if ( util::intersect (
340 x0, x1, y0, y1, z0, z1,
341 x0_, x1_, y0_, y1_, z0_, z1_,
342 newX0, newX1, newY0, newY1, newZ0, newZ1 ) ) {
343
344 int iX;
345#ifdef PARALLEL_MODE_OMP
346 #pragma omp parallel for
347#endif
348 for (iX=x0; iX<=x1; ++iX) {
349 for (int iY=y0; iY<=y1; ++iY) {
350 for (int iZ=z0; iZ<=z1; ++iZ) {
351 for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
352 if (reflectionPop[iPop]!=0) {
353 //do reflection
354 blockLattice.get(iX,iY,iZ)[iPop] = blockLattice.get(iX,iY,iZ)[reflectionPop[iPop]];
355 }
356 }
357 }
358 }
359 }
360 }
361}
362
363template<typename T, typename DESCRIPTOR>
366{
367 processSubDomain(blockLattice, x0, x1, y0, y1, z0, z1);
368}
369
371
372template<typename T, typename DESCRIPTOR>
374SlipBoundaryProcessorGenerator3D(int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX_, int discreteNormalY_, int discreteNormalZ_)
375 : PostProcessorGenerator3D<T,DESCRIPTOR>(x0_, x1_, y0_, y1_, z0_, z1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), discreteNormalZ(discreteNormalZ_)
376{ }
377
378template<typename T, typename DESCRIPTOR>
381{
383 ( this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
384}
385
386template<typename T, typename DESCRIPTOR>
389{
391 (this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
392}
393
395
396template<typename T, typename DESCRIPTOR>
398PartialSlipBoundaryProcessor3D(T tuner_, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX, int discreteNormalY, int discreteNormalZ)
399 : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_), tuner(tuner_)
400{
401 this->getName() = "PartialSlipBoundaryProcessor3D";
402 OLB_PRECONDITION(x0==x1 || y0==y1 || z0==z1);
403 reflectionPop[0] = 0;
404 for (int iPop = 1; iPop < DESCRIPTOR::q; iPop++) {
405 reflectionPop[iPop] = 0;
406 // iPop are the directions which pointing into the fluid, discreteNormal is pointing outwarts
407 if (descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY + descriptors::c<DESCRIPTOR>(iPop,2)*discreteNormalZ < 0) {
408 //std::cout << "-----" <<std::endl;
409 int mirrorDirection0;
410 int mirrorDirection1;
411 int mirrorDirection2;
412 int mult = 2 / (discreteNormalX*discreteNormalX + discreteNormalY*discreteNormalY + discreteNormalZ*discreteNormalZ);
413
414 mirrorDirection0 = (descriptors::c<DESCRIPTOR>(iPop,0) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY + descriptors::c<DESCRIPTOR>(iPop,2)*discreteNormalZ)*discreteNormalX);
415
416 mirrorDirection1 = (descriptors::c<DESCRIPTOR>(iPop,1) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY + descriptors::c<DESCRIPTOR>(iPop,2)*discreteNormalZ)*discreteNormalY);
417 mirrorDirection2 = (descriptors::c<DESCRIPTOR>(iPop,2) - mult*(descriptors::c<DESCRIPTOR>(iPop,0)*discreteNormalX + descriptors::c<DESCRIPTOR>(iPop,1)*discreteNormalY + descriptors::c<DESCRIPTOR>(iPop,2)*discreteNormalZ)*discreteNormalZ);
418
419 // bounce back for the case discreteNormalX = discreteNormalY = discreteNormalZ = 1, that is mult=0
420 if (mult == 0) {
421 mirrorDirection0 = -descriptors::c<DESCRIPTOR>(iPop,0);
422 mirrorDirection1 = -descriptors::c<DESCRIPTOR>(iPop,1);
423 mirrorDirection2 = -descriptors::c<DESCRIPTOR>(iPop,2);
424 }
425
426 // computes mirror jPop
427 for (reflectionPop[iPop] = 1; reflectionPop[iPop] < DESCRIPTOR::q ; reflectionPop[iPop]++) {
428 if (descriptors::c<DESCRIPTOR>(reflectionPop[iPop],0)==mirrorDirection0 && descriptors::c<DESCRIPTOR>(reflectionPop[iPop],1)==mirrorDirection1 && descriptors::c<DESCRIPTOR>(reflectionPop[iPop],2)==mirrorDirection2) {
429 break;
430 }
431 }
432 //std::cout <<iPop << " to "<< jPop <<" for discreteNormal= "<< discreteNormalX << "/"<<discreteNormalY <<std::endl;
433 }
434 }
435}
436
437template<typename T, typename DESCRIPTOR>
439processSubDomain(BlockLattice<T,DESCRIPTOR>& blockLattice, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_)
440{
441 int newX0, newX1, newY0, newY1, newZ0, newZ1;
442
443 if ( util::intersect (
444 x0, x1, y0, y1, z0, z1,
445 x0_, x1_, y0_, y1_, z0_, z1_,
446 newX0, newX1, newY0, newY1, newZ0, newZ1 ) ) {
447
448 int iX;
449#ifdef PARALLEL_MODE_OMP
450 #pragma omp parallel for
451#endif
452 for (iX=newX0; iX<=newX1; ++iX) {
453 for (int iY=newY0; iY<=newY1; ++iY) {
454 for (int iZ=newZ0; iZ<=newZ1; ++iZ) {
455 for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
456 if (reflectionPop[iPop]!=0) {
457 //do reflection
458 blockLattice.get(iX,iY,iZ)[iPop] = tuner*blockLattice.get(iX,iY,iZ)[reflectionPop[iPop]];
459 }
460 }
461 for (int iPop = 1; iPop < DESCRIPTOR::q/2 ; ++iPop) {
462 T provv = blockLattice.get(iX,iY,iZ)[descriptors::opposite<DESCRIPTOR>(iPop)];
463 blockLattice.get(iX,iY,iZ)[descriptors::opposite<DESCRIPTOR>(iPop)] +=
464 (1.-tuner)*blockLattice.get(iX,iY,iZ)[iPop];
465 blockLattice.get(iX,iY,iZ)[iPop] += (1.-tuner)*provv;
466 }
467 }
468 }
469 }
470 }
471}
472
473template<typename T, typename DESCRIPTOR>
476{
477 processSubDomain(blockLattice, x0, x1, y0, y1, z0, z1);
478}
479
481
482template<typename T, typename DESCRIPTOR>
484PartialSlipBoundaryProcessorGenerator3D(T tuner_, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int discreteNormalX_, int discreteNormalY_, int discreteNormalZ_)
485 : PostProcessorGenerator3D<T,DESCRIPTOR>(x0_, x1_, y0_, y1_, z0_, z1_), discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), discreteNormalZ(discreteNormalZ_), tuner(tuner_)
486{ }
487
488template<typename T, typename DESCRIPTOR>
491{
493 (tuner, this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
494}
495
496template<typename T, typename DESCRIPTOR>
499{
501 (tuner, this->x0, this->x1, this->y0, this->y1, this->z0, this->z1, discreteNormalX, discreteNormalY, discreteNormalZ);
502}
503
505template<typename T, typename DESCRIPTOR, int NORMAL_X, int NORMAL_Y, int NORMAL_Z>
506template <CONCEPT(Cell) CELL, typename PARAMETERS>
508
509 T addend = cell.template getField<descriptors::ADDEND>();
510
511 T rhoBulk = cell.neighbor({-NORMAL_X, -NORMAL_Y, -NORMAL_Z}).computeRho();
512 T rhoTmp = 0.;
513
514 for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
515 rhoTmp += cell[iPop];
516 }
517
518 T rho = rhoBulk + addend;
519 rho -= rhoTmp;
520
521 cell[0] = rho - 1.;
522
523}
524
525
527template<typename T, typename DESCRIPTOR, int NORMAL_X, int NORMAL_Y, int NORMAL_Z>
528template <CONCEPT(Cell) CELL>
530
531 cell.template setField<descriptors::CHEM_POTENTIAL>(
532 cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).template getField<descriptors::CHEM_POTENTIAL>());
533
534 T rho0 = cell.computeRho();
535 T rho1 = cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).computeRho();
536
537 cell.template setField<descriptors::CHEM_POTENTIAL>(
538 cell.template getField<descriptors::CHEM_POTENTIAL>() + (rho1 / rho0 - 1) / descriptors::invCs2<T,DESCRIPTOR>());
539}
540
541template<typename T, typename DESCRIPTOR, int NORMAL_X, int NORMAL_Y, int NORMAL_Z>
542template <CONCEPT(Cell) CELL>
544
545 cell.template setField<descriptors::CHEM_POTENTIAL>(
546 cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).template getField<descriptors::CHEM_POTENTIAL>());
547}
548
549
551template<typename T, typename DESCRIPTOR, int NORMAL_X, int NORMAL_Y, int NORMAL_Z>
552template <CONCEPT(Cell) CELL>
554
555 T rho, rho0, rho1, u[3];
556
557 rho0 = cell.computeRho();
558
559 cell.neighbor({-NORMAL_X,-NORMAL_Y,-NORMAL_Z}).computeRhoU(rho1, u);
560
561 T uPerp = 0;
562
563 Vector<T, 3> normalVec({NORMAL_X,NORMAL_Y,NORMAL_Z});
564
565 if (normalVec[2] == 0) {
566 if (normalVec[1] == 0) {
567 if (normalVec[0] < 0) {
568 uPerp = -u[0];
569 } else {
570 uPerp = u[0];
571 }
572 } else if (normalVec[0] == 0) {
573 if (normalVec[1] < 0) {
574 uPerp = -u[1];
575 } else {
576 uPerp = u[1];
577 }
578 } else {
579 uPerp = util::sqrt(u[0] * u[0] + u[1] * u[1]);
580 }
581 } else if (normalVec[1] == 0) {
582 if (normalVec[0] == 0) {
583 if (normalVec[2] < 0) {
584 uPerp = -u[2];
585 } else {
586 uPerp = u[2];
587 }
588 } else {
589 uPerp = util::sqrt(u[0] * u[0] + u[2] * u[2]);
590 }
591 } else if (normalVec[0] == 0) {
592 uPerp = util::sqrt(u[1] * u[1] + u[2] * u[2]);
593 } else {
594 uPerp = util::sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
595 }
596
597 rho = (rho0 + uPerp * rho1) / (1. + uPerp);
598 cell.defineRho(rho);
599}
600
601
602} // namespace olb
603
604#endif
Platform-abstracted block lattice for external access and inter-block interaction.
Cell< T, DESCRIPTOR > get(CellID iCell)
Get Cell interface for index iCell.
void apply(CELL &cell, PARAMETERS &parameters) any_platform
This class computes the skordos BC on a convex edge wall in 3D but with a limited number of terms add...
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
Plain old scalar vector.
Definition vector.h:47
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
constexpr auto populationsContributingToVelocity() any_platform
Return array of population indices where c[iVel] == value.
Definition util.h:216
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:89
Top level namespace for all of OpenLB.
#define OLB_PRECONDITION(COND)
Definition olbDebug.h:46
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.
Definition util.h:210
Set of functions commonly used in LB computations – header file.