OpenLB 1.8.1
Loading...
Searching...
No Matches
interpolationF3D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2012-2017 Lukas Baron, Tim Dornieden, Mathias J. Krause,
4 * Albert Mink, Fabian Klemens, Benjamin Förster, Marie-Luise Maier,
5 * Adrian Kummerlönder
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 INTERPOLATION_F_3D_HH
27#define INTERPOLATION_F_3D_HH
28
29#include <algorithm>
30
31#include "interpolationF3D.h"
32#include "dynamics/lbm.h" // for computation of lattice rho and velocity
33
34namespace olb {
35
36
39template <typename T, typename W>
41 BlockF3D<W>& f, Cuboid3D<T>& cuboid,
42 Vector<T,3> delta, T scale)
43 : AnalyticalF3D<T,W>(f.getTargetDim()), _f(f), _cuboid(cuboid), _delta(delta), _scale(scale)
44{
45 this->getName() = "fromBlockF";
46}
47
48
49template <typename T, typename W>
50bool SpecialAnalyticalFfromBlockF3D<T,W>::operator()(W output[], const T physC[])
51{
52 Vector<T,3> origin = _cuboid.getOrigin();
53
54 // scale physC in all 3 dimensions
55 Vector<T,3> physCv;
56 for (int i=0; i<3; i++) {
57 physCv[i] = origin[i] + (physC[i] - origin[i]) * ( _cuboid.getDeltaR() / _delta[i] );
58 }
59
60 int latticeR[3];
61 for (int i=0; i<3; i++) {
62 latticeR[i] = util::max((int)util::floor( (physCv[i] - origin[i])/
63 _cuboid.getDeltaR()), 0);
64 }
65 Vector<T,3> physRiC;
66 Vector<W,3> d, e;
67 W output_tmp[3];
68 Vector<T,3> latticeRv;
69
70 for (int i=0; i<3; i++) {
71 latticeRv[i] = (T) latticeR[i];
72 }
73 physRiC = origin + latticeRv * _cuboid.getDeltaR();
74 T dr = 1. / _cuboid.getDeltaR();
75
76 // compute weights
77 d = (physCv - physRiC) * dr;
78 e = 1. - d;
79
80 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
81 output[iD] = W();
82 output_tmp[iD] = W();
83 }
84
85 //0=1=2=
86 _f(output_tmp, latticeR);
87 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
88 output[iD] += output_tmp[iD] * e[0]*e[1]*e[2];
89 }
90
91 if (_cuboid.getNy() != 1) {
92 latticeR[1]++;
93 }
94
95 //0=1+2=
96 _f(output_tmp, latticeR);
97 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
98 output[iD] += output_tmp[iD] * e[0]*d[1]*e[2];
99 }
100
101 if (_cuboid.getNx() != 1) {
102 latticeR[0]++;
103 }
104 if (_cuboid.getNy() != 1) {
105 latticeR[1]--;
106 }
107 //0+1=2=
108 _f(output_tmp, latticeR);
109 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
110 output[iD] += output_tmp[iD] * d[0]*e[1]*e[2];
111 }
112
113 if (_cuboid.getNy() != 1) {
114 latticeR[1]++;
115 }
116 //0+1+2=
117 _f(output_tmp, latticeR);
118 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
119 output[iD] += output_tmp[iD] * d[0]*d[1]*e[2];
120 }
121
122 if (_cuboid.getNx() != 1) {
123 latticeR[0]--;
124 }
125 if (_cuboid.getNy() != 1) {
126 latticeR[1]--;
127 }
128 if (_cuboid.getNz() != 1) {
129 latticeR[2]++;
130 }
131 //0=1=2+
132 _f(output_tmp, latticeR);
133 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
134 output[iD] += output_tmp[iD] * e[0]*e[1]*d[2];
135 }
136
137 if (_cuboid.getNy() != 1) {
138 latticeR[1]++;
139 }
140 //0=1+2+
141 _f(output_tmp, latticeR);
142 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
143 output[iD] += output_tmp[iD] * e[0]*d[1]*d[2];
144 }
145
146 if (_cuboid.getNx() != 1) {
147 latticeR[0]++;
148 }
149 if (_cuboid.getNy() != 1) {
150 latticeR[1]--;
151 }
152 //0+1=2+
153 _f(output_tmp, latticeR);
154 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
155 output[iD] += output_tmp[iD] * d[0]*e[1]*d[2];
156 }
157
158 if (_cuboid.getNy() != 1) {
159 latticeR[1]++;
160 }
161 //0+1+2+
162 _f(output_tmp, latticeR);
163 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
164 output[iD] += output_tmp[iD] * d[0]*d[1]*d[2];
165 }
166
167 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
168 output[iD] *= _scale;
169 }
170
171 return true;
172}
173
174
175template <typename T, typename W>
177 BlockF3D<W>& f, Cuboid3D<T>& cuboid)
178 : AnalyticalF3D<T,W>(f.getTargetDim()),
179 _f(f), _cuboid(cuboid)
180{
181 this->getName() = "fromBlockF";
182}
183
185template <typename T, typename W>
186bool AnalyticalFfromBlockF3D<T,W>::operator()(W output[], const T physC[])
187{
188 int latticeC[3];
189 auto latticeR = _cuboid.getFloorLatticeR(physC);
190
191 auto& block = _f.getBlockStructure();
192 auto padding = std::min(1, block.getPadding());
193
194 if (latticeR >= -padding && latticeR < block.getExtent()+padding-1) {
195 const int& locX = latticeR[0];
196 const int& locY = latticeR[1];
197 const int& locZ = latticeR[2];
198
199 Vector<T,3> physCv(physC);
200 Vector<T,3> physRiC = _cuboid.getPhysR({locX, locY, locZ});
201
202 // compute weights
203 Vector<W,3> d = (physCv - physRiC) * (1. / _cuboid.getDeltaR());
204 Vector<W,3> e = 1. - d;
205
206 W output_tmp[_f.getTargetDim()];
207 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
208 output_tmp[iD] = W();
209 }
210
211 latticeC[0] = locX;
212 latticeC[1] = locY;
213 latticeC[2] = locZ;
214 _f(output_tmp,latticeC);
215 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
216 output[iD] += output_tmp[iD] * e[0] * e[1] * e[2];
217 output_tmp[iD] = W();
218 }
219
220 latticeC[0] = locX;
221 latticeC[1] = locY + 1;
222 latticeC[2] = locZ;
223 _f(output_tmp,latticeC);
224 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
225 output[iD] += output_tmp[iD] * e[0] * d[1] * e[2];
226 output_tmp[iD] = W();
227 }
228
229 latticeC[0] = locX + 1;
230 latticeC[1] = locY;
231 latticeC[2] = locZ;
232 _f(output_tmp,latticeC);
233 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
234 output[iD] += output_tmp[iD] * d[0] * e[1] * e[2];
235 output_tmp[iD] = W();
236 }
237
238 latticeC[0] = locX + 1;
239 latticeC[1] = locY + 1;
240 latticeC[2] = locZ;
241 _f(output_tmp,latticeC);
242 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
243 output[iD] += output_tmp[iD] * d[0] * d[1] * e[2];
244 output_tmp[iD] = W();
245 }
246
247 latticeC[0] = locX;
248 latticeC[1] = locY;
249 latticeC[2] = locZ + 1;
250 _f(output_tmp,latticeC);
251 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
252 output[iD] += output_tmp[iD] * e[0] * e[1] * d[2];
253 output_tmp[iD] = W();
254 }
255
256 latticeC[0] = locX;
257 latticeC[1] = locY + 1;
258 latticeC[2] = locZ + 1;
259 _f(output_tmp,latticeC);
260 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
261 output[iD] += output_tmp[iD] * e[0] * d[1] * d[2];
262 output_tmp[iD] = W();
263 }
264
265 latticeC[0] = locX + 1;
266 latticeC[1] = locY;
267 latticeC[2] = locZ + 1;
268 _f(output_tmp,latticeC);
269 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
270 output[iD] += output_tmp[iD] * d[0] * e[1] * d[2];
271 output_tmp[iD] = W();
272 }
273
274 latticeC[0] = locX + 1;
275 latticeC[1] = locY + 1;
276 latticeC[2] = locZ + 1;
277 _f(output_tmp,latticeC);
278 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
279 output[iD] += output_tmp[iD] * d[0] * d[1] * d[2];
280 output_tmp[iD] = W();
281 }
282
283 return true;
284 }
285 else {
286 return false;
287 }
288}
289
290
291template <typename T, typename W>
293 bool communicateToAll, bool communicateOverlap)
294 : AnalyticalF3D<T,W>(f.getTargetDim()),
295 _communicateToAll(communicateToAll),
296 _communicateOverlap(communicateOverlap),
297 _f(f),
298 _cuboidDecomposition(f.getSuperStructure().getCuboidDecomposition())
299{
300 this->getName() = "fromSuperF("+ f.getName()+")";
301
303 for (int iC = 0; iC < load.size(); ++iC) {
304 this->_blockF.emplace_back(
306 _cuboidDecomposition.get(load.glob(iC)))
307 );
308 }
309}
310
311template <typename T, typename W>
312bool AnalyticalFfromSuperF3D<T,W>::operator()(W output[], const T physC[])
313{
314 const auto targetDim = _f.getTargetDim();
315 for (int iD = 0; iD < targetDim; ++iD) {
316 output[iD] = W();
317 }
318
319 LatticeR<4> latticeR;
320 if (auto tmp = _cuboidDecomposition.getLatticeR(physC)) {
321 latticeR = *tmp;
322 } else {
323 return false;
324 }
325
326 if (_communicateOverlap) {
327 _f.getSuperStructure().communicate();
328 }
329
330 int dataFound = 0;
331
332 const LoadBalancer<T>& load = _f.getSuperStructure().getLoadBalancer();
333 for (int iC = 0; iC < load.size(); ++iC) {
334 if (_blockF[iC]->operator()(output, physC)) {
335 ++dataFound;
336 }
337 }
338
339 if (_communicateToAll) {
340#ifdef PARALLEL_MODE_MPI
341 singleton::mpi().reduceAndBcast(dataFound, MPI_SUM);
342 for (int iD = 0; iD < targetDim; ++iD) {
343 singleton::mpi().reduceAndBcast(output[iD], MPI_SUM);
344 }
345#endif
346 for (int iD = 0; iD < targetDim; ++iD) {
347 output[iD]/=dataFound;
348 }
349 }
350 else {
351 if (dataFound!=0) {
352 for (int iD = 0; iD < targetDim; ++iD) {
353 output[iD]/=dataFound;
354 }
355 }
356 }
357
358 if (dataFound>0) {
359 return true;
360 }
361 return false;
362}
363
364template <typename T, typename W>
366{
367 OLB_ASSERT(_blockF.size() < INT32_MAX,
368 "it is safe to cast std::size_t to int");
369 return _blockF.size();
370}
371
372template <typename T, typename W>
374{
375 OLB_ASSERT(iCloc < int(_blockF.size()) && iCloc >= 0,
376 "block functor index within bounds");
377 return *(_blockF[iCloc]);
378}
379
380
381} // end namespace olb
382
383#endif
AnalyticalF are applications from DD to XD, where X is set by the constructor.
Converts block functors to analytical functors.
AnalyticalFfromBlockF3D(BlockF3D< W > &f, Cuboid3D< T > &cuboid)
bool operator()(W output[], const T physC[]) override
trilinear interpolation on cubic lattice
AnalyticalFfromSuperF3D(SuperF3D< T, W > &f, bool communicateToAll=false, bool communicateOverlap=true)
bool operator()(W output[], const T physC[]) override
std::vector< std::unique_ptr< AnalyticalFfromBlockF3D< T, W > > > _blockF
AnalyticalFfromBlockF3D< T, W > & getBlockF(int iCloc)
CuboidDecomposition< T, 3 > & _cuboidDecomposition
represents all functors that operate on a cuboid in general, mother class of BlockLatticeF,...
Definition aliases.h:174
const Cuboid< T, D > & get(int iC) const
Read access to a single cuboid.
std::string & getName()
read and write access to name
Definition genericF.hh:51
Base class for all LoadBalancer.
Definition vtiWriter.h:42
int glob(int loc) const
SpecialAnalyticalFfromBlockF3D(BlockF3D< W > &f, Cuboid3D< T > &cuboid, Vector< T, 3 > delta, T scale=1.)
trilinear interpolation for rectangular lattice with dimensions delta[i]; if the cuboid is a plane (e...
bool operator()(W output[], const T physC[]) override
represents all functors that operate on a SuperStructure<T,3> in general
Definition aliases.h:184
SuperStructure< T, 3 > & getSuperStructure()
BlockF3D< W > & getBlockF(int iCloc)
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
Plain old scalar vector.
void reduceAndBcast(T &reductVal, MPI_Op op, int root=0, MPI_Comm comm=MPI_COMM_WORLD)
Reduction operation, followed by a broadcast.
MpiManager & mpi()
ADf< T, DIM > floor(const ADf< T, DIM > &a)
Definition aDiff.h:869
Expr max(Expr a, Expr b)
Definition expr.cpp:245
Top level namespace for all of OpenLB.
#define OLB_ASSERT(COND, MESSAGE)
Definition olbDebug.h:45