OpenLB 1.7
Loading...
Searching...
No Matches
robinBoundaryLatticePostProcessor3D.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2008 Orestis Malaspinas, Andrea Parmigiani
4 * 2022 Nando Suntoyo, Adrian Kummerlaender, Shota Ito,
5 * 2024 Marc Heinzelmann
6 * E-mail contact: info@openlb.net
7 * The most recent release of OpenLB can be downloaded at
8 * <http://www.openlb.net/>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#ifndef ROBIN_BOUNDARY_LATTICE_POST_PROCESSOR_3D_H
27#define ROBIN_BOUNDARY_LATTICE_POST_PROCESSOR_3D_H
28
29#include "core/blockStructure.h"
30#include "core/postProcessing.h"
31#include "core/util.h"
33#include "utilities/omath.h"
34#include <assert.h>
35
36namespace olb {
37
38
39//======================================================================
40// ======== Robin Boundary for AD 3D ======//
41//======================================================================
42
43
58// ======== MengCurvedCorr ======== //
59template<typename T, typename DESCRIPTOR, int Normal1, int Normal2, int Normal3>
61{
64 int getPriority() const {
65 return 0;
66 }
67
68 template <typename CELL, typename PARAMETERS>
69 void apply(CELL& cell, PARAMETERS& parameters) any_platform{
70
71 T omega = parameters.template get<descriptors::OMEGA>();
72 auto v = cell.template getField<descriptors::VELOCITY>();
73 auto a = cell.template getField<descriptors::G>(); //get robin boundary coefficients
74 T a1 = a[0];
75 T a2 = a[1];
76 T a3 = a[2];
77
78 const int direction = abs(Normal1*0 + Normal2*1 + Normal3*2); // ==0,1,2
79 const int orientation = -(Normal1 + Normal2 + Normal3); // ==+-1
80 Vector<int,3> n(-Normal1, -Normal2, -Normal3); //normal points into domain
81 T NdotV = n[0]*v[0] + n[1]*v[1] + n[2]*v[2];
82 T w = descriptors::t<T,DESCRIPTOR>(1); //lattice weight = 1/8
83 T gamma = -descriptors::invCs2<T,DESCRIPTOR>() * omega; //a factor used in scheme
84
85 Vector<T,1> unknownIndices;
86 for(int iPop = 0; iPop<DESCRIPTOR::q; iPop++){
87 if(descriptors::c<DESCRIPTOR>(iPop)[direction] == orientation){
88 unknownIndices[0] = iPop;
89 }
90 }
91
93 T b1 = a1-a2*gamma*NdotV;
94 T b2 = a2*gamma;
95
97 T sum1 = cell.computeRho();
98 T sum2 = 0;
99 for (unsigned iPop : unknownIndices) {
100 sum1 -= (cell[iPop]+w + cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w);
101 sum2 += cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w;
102 }
103 T beta = (a3-b1*sum1+2*b2*sum2)/(unknownIndices.size()*w*(b1+b2));
104
105 for (unsigned iPop : unknownIndices) {
106 cell[iPop] = w * beta - (cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w) - w; //set new populations
107 }
108 }
109};
110
111// ======== Ju2020 ======== //
112template<typename T, typename DESCRIPTOR, int Normal1, int Normal2, int Normal3>
114{
117 int getPriority() const {
118 return 0;
119 }
120
121 template <typename CELL, typename PARAMETERS>
122 void apply(CELL& cell, PARAMETERS& parameters) any_platform{
123
124 T omega = parameters.template get<descriptors::OMEGA>();
125 auto v = cell.template getField<descriptors::VELOCITY>();
126 auto a = cell.template getField<descriptors::G>(); //get robin boundary coefficients
127 T a1 = a[0];
128 T a2 = a[1];
129 T a3 = a[2];
130
131 const int direction = abs(Normal1*0 + Normal2*1 + Normal3*2); // ==0,1,2
132 const int orientation = -(Normal1 + Normal2 + Normal3); // ==+-1
133 Vector<int,3> n(-Normal1, -Normal2, -Normal3); //normal points into domain
134 T NdotV = n[0]*v[0] + n[1]*v[1] + n[2]*v[2];
135 T w = descriptors::t<T,DESCRIPTOR>(1); //lattice weight = 1/8
136 T gamma = -descriptors::invCs2<T,DESCRIPTOR>() * omega; //a factor used in scheme
137
138 Vector<T,1> unknownIndices;
139 for(int iPop = 0; iPop<DESCRIPTOR::q; iPop++){
140 if(descriptors::c<DESCRIPTOR>(iPop)[direction] == orientation){
141 unknownIndices[0] = iPop;
142 }
143 }
144
146 T chi = (a2!=0.) ? 1/ (gamma*a2) : (1/omega)/(1/omega-0.5);
147 T k = a1; //reaction rate
148 T A = unknownIndices.size()-1;
149 T alpha = (-chi*k+NdotV+2*w*(1-A)) / (chi*k-NdotV+2*w*(1+A)); //bounced-back part
150
152 T B = 0;
153 for (unsigned iPop : unknownIndices) {
154 B += 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w);
155 }
156
158 for (unsigned iPop : unknownIndices) {
159 B -= 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w); //final value of B
160 T beta = (2*w*chi*a3+2*w*B) / (chi*k-NdotV+2*w*(1+A)); //reverse reaction contribution
161 cell[iPop] = alpha * (cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w) + beta - w; //set new populations
162 B += 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w); //restore B
163 }
164 }
165};
166
167// ======== Edge ======== //
168template<typename T, typename DESCRIPTOR, int Plane, int Normal1, int Normal2>
170{
173 int getPriority() const {
174 return 2;
175 }
176
177 template <typename CELL, typename PARAMETERS>
178 void apply(CELL& cell, PARAMETERS& parameters) any_platform{
179
180 bool schemeSwitch = false; //switch between two schemes; true=MengCurvedCorr, false=Ju2020
181
182 // get external values
183 T omega = parameters.template get<descriptors::OMEGA>();
184 auto v = cell.template getField<descriptors::VELOCITY>();
185 auto a = cell.template getField<descriptors::G>();
186 T a1 = a[0];
187 T a2 = a[1];
188 T a3 = a[2];
189
190 constexpr auto unknownIndices = util::subIndexOutgoing3DonEdges<DESCRIPTOR,Plane,Normal1,Normal2>();
191 assert(unknownIndices.size() == 2);
192 auto c0=descriptors::c<DESCRIPTOR>(unknownIndices[0]);
193 auto c1=descriptors::c<DESCRIPTOR>(unknownIndices[1]);
194 Vector<int,3> n(c0[0]+c1[0], c0[1]+c1[1], c0[2]+c1[2]); //normal points into domain
195
196
197 if(schemeSwitch){
199 T w = descriptors::t<T,DESCRIPTOR>(1); //lattice weight = 1/8
200 T gamma = -descriptors::invCs2<T,DESCRIPTOR>() * omega;
201 T b1 = a1-a2*gamma*(n[0]*v[0]+n[1]*v[1]+n[2]*v[2]);
202 T b2 = a2*gamma;
203
205 T sum1 = cell.computeRho();
206 T sum2 = 0;
207 for (unsigned iPop : unknownIndices) {
208 sum1 -= (cell[iPop]+w + cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w);
209 sum2 += cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w;
210 }
211 T beta = (a3-b1*sum1+2*b2*sum2)/(unknownIndices.size()*w*(b1+b2));
212
213 for (unsigned iPop : unknownIndices) {
214 cell[iPop] = w * beta - (cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w) - w; //set new populations
215 }
216 } else{
218 T w = descriptors::t<T,DESCRIPTOR>(1); //lattice weight = 1/8
219 T chi = (a2!=0.) ? -1/ (descriptors::invCs2<T,DESCRIPTOR>()*a2*omega) : (1/omega)/(1/omega-0.5);
220 T k = a1; //reaction rate
221 T NdotV = n[0]*v[0] + n[1]*v[1] + n[2]*v[2];
222 T A = unknownIndices.size()-1;
223 T alpha = (-chi*k+NdotV+2*w*(1-A)) / (chi*k-NdotV+2*w*(1+A)); //bounced-back part
224
226 T B = 0;
227 for (unsigned iPop : unknownIndices) {
228 B += 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w);
229 }
230
232 for (unsigned iPop : unknownIndices) {
233 B -= 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w); //final value of B
234 T beta = (2*w*chi*a3+2*w*B) / (chi*k-NdotV+2*w*(1+A)); //reverse reaction contribution
235 cell[iPop] = alpha * (cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w) + beta - w; //set new populations
236 B += 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w); //restore B
237 }
238 }
239 }
240};
241
242
243// ======== Corner ======== //
244template<typename T, typename DESCRIPTOR, int Normal1, int Normal2, int Normal3>
246{
249 int getPriority() const {
250 return 1;
251 }
252
253 template <typename CELL, typename PARAMETERS>
254 void apply(CELL& cell, PARAMETERS& parameters) any_platform{
255 bool schemeSwitch = false; //switch between two schemes; true=MengCurvedCorr, false=Ju2020
256
257 // get external values
258 T omega = parameters.template get<descriptors::OMEGA>();
259 auto v = cell.template getField<descriptors::VELOCITY>(); //velocity field
260 auto a = cell.template getField<descriptors::G>(); //field containing coefficients for the robin boundary condition
261 T a1 = a[0]; T a2 = a[1]; T a3 = a[2];
262 std::vector<int> n(3);
263 n[0] = -Normal1; n[1] = -Normal2; n[2] = -Normal3; //change normal to point into domain
264
265 constexpr auto unknownIndices = util::subIndexOutgoing3DonCorners<DESCRIPTOR,Normal1,Normal2,Normal3>(); //function returns the indices of missing populations
266 assert(unknownIndices.size() == 3);
267
268 if(schemeSwitch){
269 //--- MengCurvedCorr ---//
271 T w = descriptors::t<T,DESCRIPTOR>(1); //lattice weight = 1/8
272 T gamma = -descriptors::invCs2<T,DESCRIPTOR>() * omega;
273 T b1 = a1-a2*gamma*(n[0]*v[0]+n[1]*v[1]+n[2]*v[2]);
274 T b2 = a2*gamma;
275
277 T sum1 = cell.computeRho();
278 T sum2 = 0;
279 for (unsigned iPop : unknownIndices) {
280 sum1 -= (cell[iPop]+w + cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w);
281 sum2 += cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w;
282 }
283 T beta = (a3-b1*sum1+2*b2*sum2)/(unknownIndices.size()*w*(b1+b2));
284
285 for (unsigned iPop : unknownIndices) {
286 cell[iPop] = w * beta - (cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w) - w; //set new populations
287 }
288 } else{
289 //--- Ju2020 ---//
291 T w = descriptors::t<T,DESCRIPTOR>(1); //lattice weight = 1/8
292 T chi = (a2!=0.) ? -1/ (descriptors::invCs2<T,DESCRIPTOR>()*a2*omega) : (1/omega)/(1/omega-0.5);
293 T k = a1; //reaction rate
294 T NdotV = n[0]*v[0] + n[1]*v[1] + n[2]*v[2];
295 T A = unknownIndices.size()-1;
296 T alpha = (-chi*k+NdotV+2*w*(1-A)) / (chi*k-NdotV+2*w*(1+A)); //bounced-back part
297
299 T B = 0;
300 for (unsigned iPop : unknownIndices) {
301 B += 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w);
302 }
303
305 for (unsigned iPop : unknownIndices) {
306 B -= 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w); //final value of B
307 T beta = (2*w*chi*a3+2*w*B) / (chi*k-NdotV+2*w*(1+A)); //reverse reaction part
308 cell[iPop] = alpha * (cell[descriptors::opposite<DESCRIPTOR>(iPop)] + w) + beta - w; //set new populations
309 B += 2*(cell[descriptors::opposite<DESCRIPTOR>(iPop)]+w); //restore B for next iteration
310 }
311 }
312 }
313};
314
315
316
317}//end namespace
318
319#endif
Plain old scalar vector.
Definition vector.h:47
Descriptor for all types of 2D and 3D lattices.
Top level namespace for all of OpenLB.
std::enable_if_t< std::is_arithmetic< T >::type::value, T > abs(T x)
Definition util.h:396
OperatorScope
Block-wide operator application scopes.
Definition operator.h:54
@ PerCellWithParameters
Per-cell application with parameters, i.e. OPERATOR::apply is passed a CELL concept implementation an...
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
Interface for post-processing steps – header file.
static constexpr unsigned size()
Plain wrapper for list of types.
Definition meta.h:276
void apply(CELL &cell, PARAMETERS &parameters) any_platform
void apply(CELL &cell, PARAMETERS &parameters) any_platform
First scheme adapted from Xuhui Meng and Zhaoli Guo.
void apply(CELL &cell, PARAMETERS &parameters) any_platform
void apply(CELL &cell, PARAMETERS &parameters) any_platform
Set of functions commonly used in LB computations – header file.