OpenLB 1.8.1
Loading...
Searching...
No Matches
blockStructure.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2021 Mathias Krause, Adrian Kummerlaender
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 BLOCK_STRUCTURE_H
25#define BLOCK_STRUCTURE_H
26
27#include <cstdint>
28#include <type_traits>
29
30#include "vector.h"
31#include "olbDebug.h"
32
33namespace olb {
34
36using CellID = std::uint32_t;
37
39using CellDistance = std::int64_t;
40
42template <unsigned D>
44
46template <typename T, unsigned D>
48
50
53template <unsigned D>
55protected:
59
61
62public:
63 static_assert(D >= 1 && D <= 3, "Only D={1,2,3} are supported");
64
65 BlockStructureD(Vector<int,D> size, int padding=0):
66 _core(size),
67 _size(size + 2*padding),
68 _padding(padding)
69 {
70 if constexpr (D == 3) {
71 _projection = {_size[1]*_size[2], _size[2], 1};
72 } else if constexpr (D == 2) {
73 _projection = {_size[1], 1};
74 } else if constexpr (D == 1) {
75 _projection = {1};
76 } else {
77 static_assert(D >= 1 && D <= 3, "Invalid D");
78 }
79
80 if (getNcells() > 0 && getNcells()-1 > std::numeric_limits<CellID>::max()) {
81 throw std::invalid_argument("Cell count must not exceed cell index space");
82 }
83 };
84
86 BlockStructureD(1, 0)
87 { };
88
90 {
91 _core = size;
92 _size = size + 2*_padding;
93 if constexpr (D == 3) {
94 _projection = {_size[1]*_size[2], _size[2], 1};
95 } else if constexpr (D == 2) {
96 _projection = {_size[1], 1};
97 } else if constexpr (D == 1) {
98 _projection = {1};
99 }
100 }
101
102 auto getCore() const
103 {
104 return _core;
105 }
106
108 int getNx() const
109 {
110 return _core[0];
111 };
113 int getNy() const
114 {
115 static_assert(D >= 2, "y-component only available in 2D or higher");
116 return _core[1];
117 };
119 int getNz() const
120 {
121 static_assert(D >= 3, "z-component only available in 3D or higher");
122 return _core[2];
123 };
124
126 {
127 return _core;
128 }
129
131 int getPadding() const
132 {
133 return _padding;
134 };
135
137 std::size_t getNcells() const
138 {
139 if constexpr (D == 3) {
140 return _size[0] * _size[1] * _size[2];
141 } else if constexpr (D == 2) {
142 return _size[0] * _size[1];
143 } else if constexpr (D == 1) {
144 return _size[0];
145 }
146 __builtin_unreachable();
147 }
148
151 {
152 OLB_PRECONDITION(isInside(latticeR));
153 return (latticeR+_padding) * _projection;
154 }
155
156 template <typename... L>
157 std::enable_if_t<sizeof...(L) == D, CellID>
158 getCellId(L... latticeR) const
159 {
160 return LatticeR<D>{latticeR+_padding...} * _projection;
161 }
162
164 {
165 if constexpr (D == 3) {
166 const std::int32_t iX = iCell / _projection[0];
167 const std::int32_t remainder = iCell % _projection[0];
168 const std::int32_t iY = remainder / _projection[1];
169 const std::int32_t iZ = remainder % _projection[1];
170 return LatticeR<D>{iX - _padding, iY - _padding, iZ - _padding};
171 } else {
172 const std::int32_t iX = iCell / _projection[0];
173 const std::int32_t iY = iCell % _projection[0];
174 return LatticeR<D>{iX - _padding, iY - _padding};
175 }
176 };
177
180 {
181 return dir * _projection;
182 }
183
185 bool isInside(LatticeR<D> latticeR) const
186 {
187 return latticeR >= -_padding && latticeR < _core + _padding;
188 };
189
191 bool isInsideCore(LatticeR<D> latticeR) const
192 {
193 return latticeR >= 0 && latticeR < _core;
194 };
195
197 bool isPadding(LatticeR<D> latticeR) const
198 {
199 return isInside(latticeR) && !(latticeR >= 0 && latticeR < _core);
200 };
201
202 bool isPadding(LatticeR<D> latticeR, int overlap) const
203 {
204 return isInside(latticeR)
205 && !isInsideCore(latticeR)
206 && latticeR >= -overlap
207 && latticeR < _core+overlap;
208 };
209
210 bool isPadding(CellID iCell) const
211 {
212 return isPadding(getLatticeR(iCell));
213 };
214
215 template <typename... L>
216 std::enable_if_t<sizeof...(L) == D, bool>
217 isInside(L... latticeR) const
218 {
219 return isInside({latticeR...});
220 };
221
224 {
225 auto lower = latticeR + _padding;
226 auto upper = LatticeR<D>([&](unsigned iDim) -> int {
227 int x = lower[iDim] - _size[iDim] + 1;
228 return x < 0 ? -x : 0;
229 });
230 auto y = std::min(*std::min_element(lower.data(), lower.data() + D),
231 *std::min_element(upper.data(), upper.data() + D));
232 return y;
233 };
234
235 template <typename F>
236 void forSpatialLocations(F f) const
237 {
238 using loc = typename LatticeR<D>::value_t;
239 for (loc iX=-_padding; iX < _core[0] + _padding; ++iX) {
240 if constexpr (D > 1) {
241 for (loc iY=-_padding; iY < _core[1] + _padding; ++iY) {
242 if constexpr (D == 3) {
243 for (loc iZ=-_padding; iZ < _core[2] + _padding; ++iZ) {
244 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
245 f({iX,iY,iZ});
246 } else {
247 f(iX,iY,iZ);
248 }
249 }
250 } else {
251 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
252 f({iX,iY});
253 } else {
254 f(iX,iY);
255 }
256 }
257 }
258 } else {
259 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
260 f({iX});
261 } else {
262 f(iX);
263 }
264 }
265 }
266 };
267
268 template <typename F>
270 {
271 using loc = typename LatticeR<D>::value_t;
272 if constexpr (D > 1) {
273 #ifdef PARALLEL_MODE_OMP
274 #pragma omp parallel for schedule(dynamic,1)
275 #endif
276 for (loc iX=-_padding; iX < _core[0] + _padding; ++iX) {
277 for (loc iY=-_padding; iY < _core[1] + _padding; ++iY) {
278 if constexpr (D == 3) {
279 for (loc iZ=-_padding; iZ < _core[2] + _padding; ++iZ) {
280 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
281 f({iX,iY,iZ});
282 } else {
283 f(iX,iY,iZ);
284 }
285 }
286 } else {
287 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
288 f({iX,iY});
289 } else {
290 f(iX,iY);
291 }
292 }
293 }
294 }
295 } else {
296 #ifdef PARALLEL_MODE_OMP
297 #pragma omp parallel for schedule(static)
298 #endif
299 for (loc iX=-_padding; iX < _core[0] + _padding; ++iX) {
300 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
301 f({iX});
302 } else {
303 f(iX);
304 }
305 }
306 }
307 }
308
309 template <typename F>
311 {
312 using loc = typename LatticeR<D>::value_t;
313 for (loc iX=std::max(-_padding, min[0]); iX < std::min(_core[0] + _padding, max[0]+1); ++iX) {
314 if constexpr (D > 1) {
315 for (loc iY=std::max(-_padding, min[1]); iY < std::min(_core[1] + _padding, max[1]+1); ++iY) {
316 if constexpr (D == 3) {
317 for (loc iZ=std::max(-_padding, min[2]); iZ < std::min(_core[2] + _padding, max[2]+1); ++iZ) {
318 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
319 f({iX,iY,iZ});
320 } else {
321 f(iX,iY,iZ);
322 }
323 }
324 } else {
325 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
326 f({iX,iY});
327 } else {
328 f(iX,iY);
329 }
330 }
331 }
332 } else {
333 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
334 f({iX});
335 } else {
336 f(iX);
337 }
338 }
339 }
340 };
341
342 template <typename F>
344 {
345 using loc = typename LatticeR<D>::value_t;
346 for (loc iX=0; iX < _core[0]; ++iX) {
347 if constexpr (D > 1) {
348 for (loc iY=0; iY < _core[1]; ++iY) {
349 if constexpr (D == 3) {
350 for (loc iZ=0; iZ < _core[2]; ++iZ) {
351 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
352 f({iX,iY,iZ});
353 } else {
354 f(iX,iY,iZ);
355 }
356 }
357 } else {
358 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
359 f({iX,iY});
360 } else {
361 f(iX,iY);
362 }
363 }
364 }
365 } else {
366 if constexpr (std::is_invocable_v<F, LatticeR<D>>) {
367 f({iX});
368 } else {
369 f(iX);
370 }
371 }
372 }
373 };
374
375 template <typename F>
376 void forCellIndices(F f) const
377 {
378 for (CellID iCell=0; iCell < getNcells(); ++iCell) {
379 f(iCell);
380 }
381 }
382
383};
384
385template <typename DESCRIPTOR>
387
388
389}
390
391#endif
Base of a regular block.
CellDistance getNeighborDistance(LatticeR< D > dir) const
Get 1D neighbor distance.
void forCellIndices(F f) const
std::size_t getNcells() const
Get number of cells.
bool isInsideCore(LatticeR< D > latticeR) const
Return whether location is inside core.
BlockStructureD(Vector< int, D > size, int padding=0)
bool isPadding(CellID iCell) const
int getNy() const
Read only access to block height.
void forSpatialLocations(F f) const
void forSpatialLocationsParallel(F f) const
CellDistance getNeighborhoodRadius(LatticeR< D > latticeR) const
Return maximum valid neighborhood sphere radius w.r.t. latticeR.
LatticeR< D > getLatticeR(CellID iCell) const
int getPadding() const
Read only access to padding.
void forCoreSpatialLocations(F f) const
LatticeR< D > _projection
bool isPadding(LatticeR< D > latticeR) const
Return whether location is valid.
int getNx() const
Read only access to block width.
CellID getCellId(LatticeR< D > latticeR) const
Get 1D cell ID.
int getNz() const
Read only access to block height.
bool isPadding(LatticeR< D > latticeR, int overlap) const
void forSpatialLocations(LatticeR< D > min, LatticeR< D > max, F f) const
bool isInside(LatticeR< D > latticeR) const
Return whether location is valid.
std::enable_if_t< sizeof...(L)==D, bool > isInside(L... latticeR) const
void resize(Vector< int, D > size)
std::enable_if_t< sizeof...(L)==D, CellID > getCellId(L... latticeR) const
LatticeR< D > getExtent() const
Plain old scalar vector.
Top level namespace for all of OpenLB.
std::uint32_t CellID
Type for sequential block-local cell indices.
std::int64_t CellDistance
Type for in-memory distance of block-local cell indices.
Vector< std::int32_t, D > LatticeR
Type for spatial block-local lattice coordinates.
#define OLB_PRECONDITION(COND)
Definition olbDebug.h:46
efficient implementation of a vector class