OpenLB 1.7
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 int latticeR[3];
190 _cuboid.getFloorLatticeR(latticeR, physC);
191
192 auto& block = _f.getBlockStructure();
193 auto padding = std::min(1, block.getPadding());
194
195 if (LatticeR<3>(latticeR) >= -padding && LatticeR<3>(latticeR) < block.getExtent()+padding-1) {
196 const int& locX = latticeR[0];
197 const int& locY = latticeR[1];
198 const int& locZ = latticeR[2];
199
200 Vector<T,3> physRiC;
201 Vector<T,3> physCv(physC);
202 _cuboid.getPhysR(physRiC.data(), {locX, locY, locZ});
203
204 // compute weights
205 Vector<W,3> d = (physCv - physRiC) * (1. / _cuboid.getDeltaR());
206 Vector<W,3> e = 1. - d;
207
208 W output_tmp[_f.getTargetDim()];
209 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
210 output_tmp[iD] = W();
211 }
212
213 latticeC[0] = locX;
214 latticeC[1] = locY;
215 latticeC[2] = locZ;
216 _f(output_tmp,latticeC);
217 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
218 output[iD] += output_tmp[iD] * e[0] * e[1] * e[2];
219 output_tmp[iD] = W();
220 }
221
222 latticeC[0] = locX;
223 latticeC[1] = locY + 1;
224 latticeC[2] = locZ;
225 _f(output_tmp,latticeC);
226 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
227 output[iD] += output_tmp[iD] * e[0] * d[1] * e[2];
228 output_tmp[iD] = W();
229 }
230
231 latticeC[0] = locX + 1;
232 latticeC[1] = locY;
233 latticeC[2] = locZ;
234 _f(output_tmp,latticeC);
235 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
236 output[iD] += output_tmp[iD] * d[0] * e[1] * e[2];
237 output_tmp[iD] = W();
238 }
239
240 latticeC[0] = locX + 1;
241 latticeC[1] = locY + 1;
242 latticeC[2] = locZ;
243 _f(output_tmp,latticeC);
244 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
245 output[iD] += output_tmp[iD] * d[0] * d[1] * e[2];
246 output_tmp[iD] = W();
247 }
248
249 latticeC[0] = locX;
250 latticeC[1] = locY;
251 latticeC[2] = locZ + 1;
252 _f(output_tmp,latticeC);
253 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
254 output[iD] += output_tmp[iD] * e[0] * e[1] * d[2];
255 output_tmp[iD] = W();
256 }
257
258 latticeC[0] = locX;
259 latticeC[1] = locY + 1;
260 latticeC[2] = locZ + 1;
261 _f(output_tmp,latticeC);
262 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
263 output[iD] += output_tmp[iD] * e[0] * d[1] * d[2];
264 output_tmp[iD] = W();
265 }
266
267 latticeC[0] = locX + 1;
268 latticeC[1] = locY;
269 latticeC[2] = locZ + 1;
270 _f(output_tmp,latticeC);
271 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
272 output[iD] += output_tmp[iD] * d[0] * e[1] * d[2];
273 output_tmp[iD] = W();
274 }
275
276 latticeC[0] = locX + 1;
277 latticeC[1] = locY + 1;
278 latticeC[2] = locZ + 1;
279 _f(output_tmp,latticeC);
280 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
281 output[iD] += output_tmp[iD] * d[0] * d[1] * d[2];
282 output_tmp[iD] = W();
283 }
284
285 return true;
286 }
287 else {
288 return false;
289 }
290}
291
292
293template <typename T, typename W>
295 bool communicateToAll, bool communicateOverlap)
296 : AnalyticalF3D<T,W>(f.getTargetDim()),
297 _communicateToAll(communicateToAll),
298 _communicateOverlap(communicateOverlap),
299 _f(f),
300 _cuboidGeometry(f.getSuperStructure().getCuboidGeometry())
301{
302 this->getName() = "fromSuperF";
303
305 for (int iC = 0; iC < load.size(); ++iC) {
306 this->_blockF.emplace_back(
308 _cuboidGeometry.get(load.glob(iC)))
309 );
310 }
311}
312
313template <typename T, typename W>
314bool AnalyticalFfromSuperF3D<T,W>::operator()(W output[], const T physC[])
315{
316 for (int iD = 0; iD < _f.getTargetDim(); ++iD) {
317 output[iD] = W();
318 }
319
320 int latticeR[4];
321 if (!_cuboidGeometry.getLatticeR(latticeR, physC)) {
322 return false;
323 }
324
325 if (_communicateOverlap) {
326 _f.getSuperStructure().communicate();
327 }
328
329 int dataSize = 0;
330 int dataFound = 0;
331
332 LoadBalancer<T>& load = _f.getSuperStructure().getLoadBalancer();
333 for (int iC = 0; iC < load.size(); ++iC) {
334 if (_blockF[iC]->operator()(output, physC)) {
335 dataSize += _f.getTargetDim();
336 ++dataFound;
337 }
338 }
339
340 if (_communicateToAll) {
341#ifdef PARALLEL_MODE_MPI
342 singleton::mpi().reduceAndBcast(dataFound, MPI_SUM);
343 singleton::mpi().reduceAndBcast(dataSize, MPI_SUM);
344#endif
345 dataSize /= dataFound;
346#ifdef PARALLEL_MODE_MPI
347 for (int iD = 0; iD < dataSize; ++iD) {
348 singleton::mpi().reduceAndBcast(output[iD], MPI_SUM);
349 }
350#endif
351 for (int iD = 0; iD < dataSize; ++iD) {
352 output[iD]/=dataFound;
353 }
354 }
355 else {
356 if (dataFound!=0) {
357 dataSize /= dataFound;
358 for (int iD = 0; iD < dataSize; ++iD) {
359 output[iD]/=dataFound;
360 }
361 }
362 }
363
364 if (dataFound>0) {
365 return true;
366 }
367 return false;
368}
369
370template <typename T, typename W>
372{
373 OLB_ASSERT(_blockF.size() < INT32_MAX,
374 "it is safe to cast std::size_t to int");
375 return _blockF.size();
376}
377
378template <typename T, typename W>
380{
381 OLB_ASSERT(iCloc < int(_blockF.size()) && iCloc >= 0,
382 "block functor index within bounds");
383 return *(_blockF[iCloc]);
384}
385
386
387} // end namespace olb
388
389#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
CuboidGeometry3D< T > & _cuboidGeometry
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)
represents all functors that operate on a cuboid in general, mother class of BlockLatticeF,...
A regular single 3D cuboid is the basic component of a 3D cuboid structure which defines the grid.
Definition cuboid3D.h:58
std::string & getName()
read and write access to name
Definition genericF.hh:51
Base class for all LoadBalancer.
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
SuperStructure< T, 3 > & getSuperStructure()
BlockF3D< W > & getBlockF(int iCloc)
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
Plain old scalar vector.
Definition vector.h:47
constexpr const T * data() const any_platform
Definition vector.h:161
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
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
Top level namespace for all of OpenLB.
#define OLB_ASSERT(COND, MESSAGE)
Definition olbDebug.h:45