OpenLB 1.7
Loading...
Searching...
No Matches
latticeDerivatives3D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2013 Patrick Nathen, Mathias J. Krause
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 LATTICE_DERIVATIVES_3D_HH
25#define LATTICE_DERIVATIVES_3D_HH
26
29
30namespace olb {
31
32
34template <typename T>
36(BlockGeometry<T,3>& blockGeometry, BlockF3D<T>& blockFunctor, std::list<int>& matNumber)
37 : BlockF3D<T>(blockFunctor.getBlockStructure(), 3*blockFunctor.getTargetDim()), _blockGeometry(blockGeometry), _blockFunctor(blockFunctor), _matNumber(matNumber)
38{
39 this->getName() = "FiniteDifference";
40 _targetDim = _blockFunctor.getTargetDim();
41 _n[0] = this-> _blockGeometry.getNx()-1;
42 _n[1] = this-> _blockGeometry.getNy()-1;
43 _n[2] = this-> _blockGeometry.getNz()-1;
44
45}
46
47template <typename T>
48bool BlockFiniteDifference3D<T>::operator() (T output[], const int input[])
49{
50// // derivation tensor
51 std::vector<std::vector<T>> fdGrad;
52
53 fdGrad.resize(_targetDim);
54 for (int i = 0; i < _targetDim; i++) {
55 fdGrad[i].resize(3);
56 }
57
58 for (int i = 0; i < 3; i++) {
59 int fInput_p[3];
60 fInput_p[0] = input[0];
61 fInput_p[1] = input[1];
62 fInput_p[2] = input[2];
63 fInput_p[i]+=1;
64
65 int fInput_2p[3];
66 fInput_2p[0] = input[0];
67 fInput_2p[1] = input[1];
68 fInput_2p[2] = input[2];
69 fInput_2p[i]+=2;
70
71 int fInput_3p[3];
72 fInput_3p[0] = input[0];
73 fInput_3p[1] = input[1];
74 fInput_3p[2] = input[2];
75 fInput_3p[i]+=3;
76
77 int fInput_4p[3];
78 fInput_4p[0] = input[0];
79 fInput_4p[1] = input[1];
80 fInput_4p[2] = input[2];
81 fInput_4p[i]+=4;
82
83 int fInput_n[3];
84 fInput_n[0] = input[0];
85 fInput_n[1] = input[1];
86 fInput_n[2] = input[2];
87 fInput_n[i]-=1;
88
89 int fInput_2n[3];
90 fInput_2n[0] = input[0];
91 fInput_2n[1] = input[1];
92 fInput_2n[2] = input[2];
93 fInput_2n[i]-=2;
94
95 int fInput_3n[3];
96 fInput_3n[0] = input[0];
97 fInput_3n[1] = input[1];
98 fInput_3n[2] = input[2];
99 fInput_3n[i]-=3;
100
101 int fInput_4n[3];
102 fInput_4n[0] = input[0];
103 fInput_4n[1] = input[1];
104 fInput_4n[2] = input[2];
105 fInput_4n[i]-=4;
106
107 T fOutput[_targetDim];
108 _blockFunctor(fOutput,input);
109
110 if (input[i] < 3) {
111 if (std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_2p[0], fInput_2p[1], fInput_2p[2]})) == _matNumber.end()) {
112 T fOutput_p[_targetDim];
113 _blockFunctor(fOutput_p,fInput_p);
114 for (int j=0; j < _targetDim; j++) {
115 fdGrad[j][i]= -fOutput[j] + fOutput_p[j];
116 }
117 }
118 else {
119 T fOutput_p[_targetDim];
120 _blockFunctor(fOutput_p,fInput_p);
121 T fOutput_2p[_targetDim];
122 _blockFunctor(fOutput_2p,fInput_2p);
123 for (int j=0; j < _targetDim; j++) {
124 fdGrad[j][i]=fd::boundaryGradient(fOutput[j], fOutput_p[j], fOutput_2p[j]);
125 }
126 }
127 }
128 else if (input[i] > _n[i]-3) {
129 if (std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_2n[0], fInput_2n[1], fInput_2n[2]})) == _matNumber.end()) {
130 T fOutput_n[_targetDim];
131 _blockFunctor(fOutput_n,fInput_n);
132 for (int j=0; j < _targetDim; j++) {
133 fdGrad[j][i]= -fOutput_n[j] + fOutput[j];
134 }
135 }
136 else {
137 T fOutput_n[_targetDim];
138 _blockFunctor(fOutput_n,fInput_n);
139 T fOutput_2n[_targetDim];
140 _blockFunctor(fOutput_2n,fInput_2n);
141 for (int j=0; j < _targetDim; j++) {
142 fdGrad[j][i]=fd::boundaryGradient(-fOutput[j], -fOutput_n[j], -fOutput_2n[j]);
143 }
144 }
145 }
146 else {
147 if ( std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_n[0], fInput_n[1], fInput_n[2]})) == _matNumber.end() &&
148 std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_p[0], fInput_p[1], fInput_p[2]})) == _matNumber.end() ) {
149 for (int j=0; j < _targetDim; j++) {
150 fdGrad[j][i]=0.;
151 }
152 // boundary treatment with Second-order asymmetric gradient
153 }
154 else if (std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_n[0], fInput_n[1], fInput_n[2]})) == _matNumber.end()) {
155 if (std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_2p[0], fInput_2p[1], fInput_2p[2]})) == _matNumber.end()) {
156 T fOutput_p[_targetDim];
157 _blockFunctor(fOutput_p,fInput_p);
158 for (int j=0; j < _targetDim; j++) {
159 fdGrad[j][i]= -fOutput[j] + fOutput_p[j];
160 }
161 }
162 else {
163 T fOutput_p[_targetDim];
164 _blockFunctor(fOutput_p,fInput_p);
165 T fOutput_2p[_targetDim];
166 _blockFunctor(fOutput_2p,fInput_2p);
167 for (int j=0; j < _targetDim; j++) {
168 fdGrad[j][i]=fd::boundaryGradient(fOutput[j], fOutput_p[j], fOutput_2p[j]);
169 }
170 }
171 }
172 else if (std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_p[0], fInput_p[1], fInput_p[2]})) == _matNumber.end() ) {
173 if (std::find(_matNumber.begin(), _matNumber.end(), _blockGeometry.get({fInput_2n[0], fInput_2n[1], fInput_2n[2]})) == _matNumber.end()) {
174 T fOutput_n[_targetDim];
175 _blockFunctor(fOutput_n,fInput_n);
176 for (int j=0; j < _targetDim; j++) {
177 fdGrad[j][i]= -fOutput_n[j] + fOutput[j];
178 }
179 }
180 else {
181 T fOutput_n[_targetDim];
182 _blockFunctor(fOutput_n,fInput_n);
183 T fOutput_2n[_targetDim];
184 _blockFunctor(fOutput_2n,fInput_2n);
185 for (int j=0; j < _targetDim; j++) {
186 fdGrad[j][i]=fd::boundaryGradient(-fOutput[j], -fOutput_n[j], -fOutput_2n[j]);
187 }
188 }
189 }
190 else {
191 //inner domain 8th order central difference
192 T fOutput_n[_targetDim];
193 _blockFunctor(fOutput_n,fInput_n);
194
195 T fOutput_2n[_targetDim];
196 _blockFunctor(fOutput_2n,fInput_2n);
197
198 T fOutput_3n[_targetDim];
199 _blockFunctor(fOutput_3n,fInput_3n);
200
201 T fOutput_4n[_targetDim];
202 _blockFunctor(fOutput_4n,fInput_4n);
203
204 T fOutput_p[_targetDim];
205 _blockFunctor(fOutput_p,fInput_p);
206
207 T fOutput_2p[_targetDim];
208 _blockFunctor(fOutput_2p,fInput_2p);
209
210 T fOutput_3p[_targetDim];
211 _blockFunctor(fOutput_3p,fInput_3p);
212
213 T fOutput_4p[_targetDim];
214 _blockFunctor(fOutput_4p,fInput_4p);
215 for (int j=0; j < _targetDim; j++) {
216 //fdGrad[j][i]=fd::centralGradient(fOutput_p[j], fOutput_n[j]);
217 fdGrad[j][i]=((T)672*(fOutput_p[j]-fOutput_n[j])+(T)168*(fOutput_2n[j]-fOutput_2p[j])
218 +(T)32*(fOutput_3p[j]-fOutput_3n[j])+(T)3*(fOutput_4n[j]-fOutput_4p[j])) / 840.;
219 }
220 }
221 }
222 for (int i=0; i < 3; i++) {
223 for (int j=0; j < _targetDim; j++) {
224 output[j*3+i] = fdGrad[j][i];
225 }
226 }
227 }
228 return true;
229}
230
232template <typename T>
234(SuperGeometry<T,3>& sGeometry, SuperF3D<T>& sFunctor, std::list<int>& matNumber) : SuperF3D<T>(sFunctor.getSuperStructure(),3*sFunctor.getTargetDim()),
235 _sGeometry(sGeometry),_sFunctor(sFunctor), _matNumber(matNumber)
236{
237 this->getName() = "FiniteDifference";
238 int maxC = this->_superStructure.getLoadBalancer().size();
239 this->_blockF.reserve(maxC);
240 for (int iC = 0; iC < maxC; iC++) {
241 this->_blockF.emplace_back(new BlockFiniteDifference3D<T> ( _sGeometry.getBlockGeometry(iC), _sFunctor.getBlockF(iC), _matNumber ));
242 }
243}
244
246template <typename T, typename DESCRIPTOR>
248(BlockF3D<T>& blockFinDiff, const UnitConverter<T,DESCRIPTOR>& converter)
249 : BlockF3D<T>(blockFinDiff.getBlockStructure(), 3*blockFinDiff.getTargetDim()), _blockFinDiff(blockFinDiff), _converter(converter)
250{
251 this->getName() = "PhysFiniteDifference";
252 _targetDim = _blockFinDiff.getTargetDim();
253
254}
255
256template <typename T, typename DESCRIPTOR>
258{
259 _blockFinDiff(output,input);
260 for (int i = 0; i < _targetDim; i++) {
261 output[i] /= _converter.getConversionFactorLength();
262 }
263 return true;
264}
265
267template <typename T, typename DESCRIPTOR>
269(SuperGeometry<T,3>& sGeometry, SuperF3D<T>& sFunctor, std::list<int>& matNumber, const UnitConverter<T,DESCRIPTOR>& converter) : SuperF3D<T>(sFunctor.getSuperStructure(),3*sFunctor.getTargetDim()),
270 _sFinDiff(sGeometry,sFunctor,matNumber),_converter(converter)
271{
272 this->getName() = "PhysFiniteDifference";
273 int maxC = this->_superStructure.getLoadBalancer().size();
274 this->_blockF.reserve(maxC);
275 for (int iC = 0; iC < maxC; iC++) {
276 this->_blockF.emplace_back(new BlockPhysFiniteDifference3D<T,DESCRIPTOR> (_sFinDiff.getBlockF(iC), _converter ));
277 }
278}
279
280
282template <typename T>
284(BlockGeometry<T,3>& blockGeometry, BlockF3D<T>& blockFunctor,
285 bool forthOrder)
286 : BlockF3D<T>(blockFunctor.getBlockStructure(), blockFunctor.getTargetDim()),
287 _blockGeometry(blockGeometry), _blockFunctor(blockFunctor),
288 _forthOrder(forthOrder)
289{
290 this->getName() = "Laplacian(" + blockFunctor.getName() + ")";
291 _n[0] = this-> _blockGeometry.getNx()-1;
292 _n[1] = this-> _blockGeometry.getNy()-1;
293 _n[2] = this-> _blockGeometry.getNz()-1;
294}
295
296template <typename T>
297bool BlockLaplacian3D<T>::operator() (T output[], const int input[])
298{
299 for (int i=0; i<this->getTargetDim(); ++i) {
300 output[i] = 0;
301 }
302 int inputMod[3];
303 for (int j=0; j<3; ++j) {
304 inputMod[j] = input[j];
305 }
306 T u_0[this->getTargetDim()];
307 T u_m[this->getTargetDim()];
308 T u_p[this->getTargetDim()];
309
310 // only used for forth order dq
311 T u_2m[this->getTargetDim()];
312 T u_2p[this->getTargetDim()];
313
314 // compute discrete second derivatives for each direction and add them
315 for (int j=0; j<3; ++j) {
316 if (input[j] < 1) {
317 // use forward difference quotient at the boundary
318 _blockFunctor.operator()(u_m, inputMod);
319 inputMod[j] += 1;
320 _blockFunctor.operator()(u_0, inputMod);
321 inputMod[j] += 1;
322 _blockFunctor.operator()(u_p, inputMod);
323 } else if (input[j] > _n[j]-1) {
324 // use backward difference quotient at the boundary
325 _blockFunctor.operator()(u_p, inputMod);
326 inputMod[j] -= 1;
327 _blockFunctor.operator()(u_0, inputMod);
328 inputMod[j] -= 1;
329 _blockFunctor.operator()(u_m, inputMod);
330 } else {
331 // use central difference quotient
332 _blockFunctor.operator()(u_0, inputMod);
333 inputMod[j] -= 1;
334 _blockFunctor.operator()(u_m, inputMod);
335 inputMod[j] += 2;
336 _blockFunctor.operator()(u_p, inputMod);
337 }
338 inputMod[j] = input[j]; // reset
339
340 if ((_forthOrder) && (input[j] > 1) && (input[j] < _n[j]-1)) {
341 // additional evaluations
342 inputMod[j] -= 2;
343 _blockFunctor.operator()(u_2m, inputMod);
344 inputMod[j] += 4;
345 _blockFunctor.operator()(u_2p, inputMod);
346 inputMod[j] = input[j]; // reset
347
348 // forth order dq
349 for (int i=0; i<this->getTargetDim(); ++i) {
350 output[i] += fd::centralSecondDeriv(u_2m[i], u_m[i], u_0[i], u_p[i], u_2p[i]);
351 }
352 } else {
353 // second order dq
354 for (int i=0; i<this->getTargetDim(); ++i) {
355 output[i] += fd::centralSecondDeriv(u_m[i], u_0[i], u_p[i]);
356 }
357 }
358 }
359 return true;
360/*
361 // todo: enable treating all spatial directions at once?
362 _blockFunctor.operator()(u_0, inputMod);
363
364 inputMod[0] -= 1;
365 _blockFunctor.operator()(u_xm1, inputMod);
366 inputMod[0] += 2;
367 _blockFunctor.operator()(u_xp1, inputMod);
368 inputMod[0] -= 1;
369
370 inputMod[1] -= 1;
371 _blockFunctor.operator()(u_ym1, inputMod);
372 inputMod[1] += 2;
373 _blockFunctor.operator()(u_yp1, inputMod);
374 inputMod[1] -= 1;
375
376 inputMod[2] -= 1;
377 _blockFunctor.operator()(u_zm1, inputMod);
378 inputMod[2] += 2;
379 _blockFunctor.operator()(u_zp1, inputMod);
380 inputMod[2] -= 1;
381
382 for (int i=0; i<_targetDim; ++i) {
383 output[i] = fd::laplacian3D(u_xm1[i], u_ym1[i], u_zm1[i], u_0[i], u_xp1[i], u_yp1[i], u_zp1[i]);
384 }
385*/
386}
387
388
390template <typename T>
392(SuperGeometry<T,3>& sGeometry, SuperF3D<T>& sFunctor,
393 bool forthOrder)
394 : SuperF3D<T>(sFunctor.getSuperStructure(),sFunctor.getTargetDim()),
395 _sGeometry(sGeometry),_sFunctor(sFunctor)
396{
397 this->getName() = "Laplacian(" + sFunctor.getName() + ")";
398 const int maxC = this->_superStructure.getLoadBalancer().size();
399 this->_blockF.reserve(maxC);
400 for (int iC = 0; iC < maxC; iC++) {
401 this->_blockF.emplace_back(new BlockLaplacian3D<T> (
402 _sGeometry.getBlockGeometry(iC), _sFunctor.getBlockF(iC), forthOrder ));
403 }
404}
405
406
408template <typename T, typename DESCRIPTOR>
410(BlockF3D<T>& blockLaplacian, const UnitConverter<T,DESCRIPTOR>& converter,
411 bool forthOrder)
412 : BlockF3D<T>(blockLaplacian.getBlockStructure(), blockLaplacian.getTargetDim()),
413 _blockLaplacian(blockLaplacian), _converter(converter),
414 _factor(T{1} / converter.getConversionFactorLength())
415{
416 this->getName() = "Phys" + _blockLaplacian.getName();
417}
418
419template <typename T, typename DESCRIPTOR>
420bool BlockPhysLaplacian3D<T,DESCRIPTOR>::operator() (T output[], const int input[])
421{
422 _blockLaplacian(output,input);
423 for (int i = 0; i < this->getTargetDim(); i++) {
424 output[i] *= _factor * _factor;
425 }
426 return true;
427}
428
430template <typename T, typename DESCRIPTOR>
432(SuperGeometry<T,3>& sGeometry, SuperF3D<T>& sFunctor,
433 const UnitConverter<T,DESCRIPTOR>& converter,
434 bool forthOrder)
435 : SuperF3D<T>(sFunctor.getSuperStructure(),sFunctor.getTargetDim()),
436 _laplacian(sGeometry, sFunctor, forthOrder), _converter(converter)
437{
438 this->getName() = "Phys" + _laplacian.getName();
439 const int maxC = this->_superStructure.getLoadBalancer().size();
440 this->_blockF.reserve(maxC);
441
442 for (int iC = 0; iC < maxC; iC++) {
443 this->_blockF.emplace_back(new BlockPhysLaplacian3D<T,DESCRIPTOR> (
444 _laplacian.getBlockF(iC), _converter, forthOrder ));
445 }
446}
447
448
449} // end namespace olb
450#endif
represents all functors that operate on a cuboid in general, mother class of BlockLatticeF,...
functor to get pointwise finite difference Dissipation on local lattice, if globIC is not on the loca...
BlockFiniteDifference3D(BlockGeometry< T, 3 > &blockGeometry, BlockF3D< T > &blockFunctor, std::list< int > &matNumber)
bool operator()(T output[], const int input[]) override
has to be implemented for 'every' derived class
Representation of a block geometry.
functor to get pointwise finite difference Laplacian operator
BlockLaplacian3D(BlockGeometry< T, 3 > &blockGeometry, BlockF3D< T > &blockFunctor, bool forthOrder)
bool operator()(T output[], const int input[]) override
has to be implemented for 'every' derived class
BlockPhysFiniteDifference3D(BlockF3D< T > &blockFunctor, const UnitConverter< T, DESCRIPTOR > &converter)
bool operator()(T output[], const int input[]) override
has to be implemented for 'every' derived class
functor to get pointwise finite difference Laplacian operator
BlockPhysLaplacian3D(BlockF3D< T > &blockFunctor, const UnitConverter< T, DESCRIPTOR > &converter, bool forthOrder)
bool operator()(T output[], const int input[]) override
has to be implemented for 'every' derived class
int getNy() const
Read only access to block height.
int getNx() const
Read only access to block width.
int getNz() const
Read only access to block height.
std::string & getName()
read and write access to name
Definition genericF.hh:51
represents all functors that operate on a SuperStructure<T,3> in general
SuperStructure< T, 3 > & _superStructure
std::vector< std::unique_ptr< BlockF3D< W > > > _blockF
Super functors may consist of several BlockF3D<W> derived functors.
SuperFiniteDifference3D(SuperGeometry< T, 3 > &sGeometry, SuperF3D< T > &sFunctor, std::list< int > &matNumber)
Representation of a statistic for a parallel 2D geometry.
BlockGeometry< T, D > & getBlockGeometry(int locIC)
Read and write access to a single block geometry.
SuperLaplacian3D(SuperGeometry< T, 3 > &sGeometry, SuperF3D< T > &sFunctor, bool forthOrder=true)
SuperPhysFiniteDifference3D(SuperGeometry< T, 3 > &sGeometry, SuperF3D< T > &sFunctor, std::list< int > &matNumber, const UnitConverter< T, DESCRIPTOR > &converter)
SuperPhysLaplacian3D(SuperGeometry< T, 3 > &sGeometry, SuperF3D< T > &sFunctor, const UnitConverter< T, DESCRIPTOR > &converter, bool forthOrder=true)
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
Conversion between physical and lattice units, as well as discretization.
constexpr T centralSecondDeriv(T u_m1, T u_0, T u_p1) any_platform
Second order central second derivative (u_p1 = u(x+1))
constexpr T boundaryGradient(T u_0, T u_1, T u_2) any_platform
Second-order asymmetric gradient (u_1 = u(x+1))
Top level namespace for all of OpenLB.