OpenLB 1.7
Loading...
Searching...
No Matches
util.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2006, 2007 Jonas Latt, 2020 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
28#ifndef UTIL_H
29#define UTIL_H
30
31#include <sstream>
32#include <vector>
33#include <algorithm>
34#include <numeric>
35#include <type_traits>
36
37#include "core/baseType.h"
38#include "core/vector.h"
40#include "meta.h"
41#include "utilities/omath.h"
44
45namespace olb {
46
47namespace util {
48
49// *INDENT-OFF*
50
51template<typename T> T norm(const std::vector<T>& a);
52
53template <typename T>
54inline int sign(T val)
55{
56 return (0 < val) - (val < 0);
57}
58
59template <typename T>
60inline bool aligned_to_x(const std::vector<T>& vec)
61{
62 return (vec[0]!=0 and vec[1]==0 and vec[2]==0);
63}
64
65template <typename T>
66inline bool aligned_to_y(const std::vector<T>& vec)
67{
68 return (vec[0]==0 and vec[1]!=0 and vec[2]==0);
69}
70
71template <typename T>
72inline bool aligned_to_z(const std::vector<T>& vec)
73{
74 return (vec[0]==0 and vec[1]==0 and vec[2]!=0);
75}
76
77template <typename T>
78inline bool aligned_to_grid(const std::vector<T>& vec)
79{
80 return (aligned_to_x<T>(vec) or
81 aligned_to_y<T>(vec) or
82 aligned_to_z<T>(vec));
83}
84
85
86
87
88
89inline bool intersect (
90 int x0, int x1, int y0, int y1,
91 int x0_, int x1_, int y0_, int y1_,
92 int& newX0, int& newX1, int& newY0, int& newY1 )
93{
94 newX0 = util::max(x0,x0_);
95 newY0 = util::max(y0,y0_);
96
97 newX1 = util::min(x1,x1_);
98 newY1 = util::min(y1,y1_);
99
100 return newX1>=newX0 && newY1>=newY0;
101}
102
103inline bool intersect (
104 int x0, int x1, int y0, int y1, int z0, int z1,
105 int x0_, int x1_, int y0_, int y1_, int z0_, int z1_,
106 int& newX0, int& newX1, int& newY0, int& newY1, int& newZ0, int& newZ1 )
107{
108 newX0 = util::max(x0,x0_);
109 newY0 = util::max(y0,y0_);
110 newZ0 = util::max(z0,z0_);
111
112 newX1 = util::min(x1,x1_);
113 newY1 = util::min(y1,y1_);
114 newZ1 = util::min(z1,z1_);
115
116 return newX1>=newX0 && newY1>=newY0 && newZ1>=newZ0;
117}
118
119inline bool contained(int x, int y,
120 int x0, int x1, int y0, int y1)
121{
122 return x>=x0 && x<=x1 &&
123 y>=y0 && y<=y1;
124}
125
126inline bool contained(int x, int y, int z,
127 int x0, int x1, int y0, int y1, int z0, int z1)
128{
129 return x>=x0 && x<=x1 &&
130 y>=y0 && y<=y1 &&
131 z>=z0 && z<=z1;
132}
133
134
135template<typename T>
136T sqr(T arg)
137{
138 return arg*arg;
139}
140
142template<typename ARRAY_LIKE, unsigned D>
143auto normSqr(const ARRAY_LIKE& u) any_platform
144{
145 auto uSqr = decltype(u[0]){};
146 for (unsigned iD=0; iD < D; ++iD) {
147 uSqr += u[iD]*u[iD];
148 }
149 return uSqr;
150}
151
152template<unsigned D, typename ARRAY_LIKE>
153auto norm(const ARRAY_LIKE& u)
154{
155 return sqrt(normSqr<ARRAY_LIKE,D>(u));
156}
157
158template<typename T, unsigned D>
160{
161 auto uSqr = T{};
162 for (unsigned iD=0; iD < D; ++iD) {
163 uSqr += u[iD]*u[iD];
164 }
165 return uSqr;
166}
167
168template<typename T>
169T normSqr(std::initializer_list<T> data)
170{
171 return std::inner_product(data.begin(), data.end(), data.begin(), T(0));
172}
173
174
176template<typename T, unsigned D, typename IMPL>
178{
179 T uSqr = T();
180 for (unsigned iD=0; iD < D; ++iD) {
181 uSqr += u[iD]*u[iD];
182 }
183 return uSqr;
184}
185
186template<typename T, int d>
187T scalarProduct(const T u1[d], const T u2[d])
188{
189 T prod = T();
190 for (int iD=0; iD<d; ++iD) {
191 prod += u1[iD]*u2[iD];
192 }
193 return prod;
194}
195
196template<typename T>
197T scalarProduct(const std::vector<T>& u1, const std::vector<T>& u2)
198{
199 T prod = T();
200 if (u1.size() == u2.size()) {
201 for (int iD=0; iD<u1.size(); ++iD) {
202 prod += u1[iD]*u2[iD];
203 }
204 }
205 return prod;
206}
207
209template <typename DESCRIPTORBASE>
210struct TensorVal {
211 static constexpr int n = (DESCRIPTORBASE::d*(DESCRIPTORBASE::d+1))/2;
212};
213
215template <typename DESCRIPTOR, unsigned iVel, int value>
217 constexpr auto velocity_matches_value = [](unsigned iPop) -> bool {
218 return descriptors::c<DESCRIPTOR>(iPop,iVel) == value;
219 };
221 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches_value));
222};
223
225template <typename DESCRIPTOR, int... NORMAL>
227 constexpr auto velocity_matches_direction = [](unsigned iPop) -> bool {
228 return meta::indexed_pack_contains<NORMAL...>([iPop](unsigned iD, int x) -> bool {
229 return x != 0 && x == descriptors::c<DESCRIPTOR>(iPop,iD);
230 });
231 };
233 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches_direction));
234};
235
236template <typename DESCRIPTORBASE>
237int findVelocity(const int v[DESCRIPTORBASE::d]) any_platform
238{
239 for (int iPop=0; iPop<DESCRIPTORBASE::q; ++iPop) {
240 bool fit = true;
241 for (int iD=0; iD<DESCRIPTORBASE::d; ++iD) {
242 if (descriptors::c<DESCRIPTORBASE>(iPop,iD) != v[iD]) {
243 fit = false;
244 break;
245 }
246 }
247 if (fit) {
248 return iPop;
249 }
250 }
251 return DESCRIPTORBASE::q;
252}
253
255template <typename DESCRIPTOR, int direction, int orientation>
257 // Should be expressed in terms of populationsContributingToVelocity
258 // but std::array / std::index_sequence distinction makes this ugly
259 // To be revisitited
260 constexpr auto velocity_matches_value = [](unsigned iPop) {
261 return descriptors::c<DESCRIPTOR>(iPop,direction) == orientation;
262 };
263 constexpr auto opposite_population = [](unsigned iPop) {
264 return descriptors::opposite<DESCRIPTOR>(iPop);
265 };
267 meta::map_index_sequence(opposite_population,
268 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches_value)));
269}
270
271template <typename DESCRIPTOR, int direction, int orientation>
273 constexpr auto velocity_matches = [](unsigned iPop) {
274 for (unsigned jPop : subIndexOutgoing<DESCRIPTOR,direction,orientation>()) {
275 if (iPop == jPop) {
276 return false;
277 }
278 }
279 return true;
280 };
282 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches));
283}
284
285template <typename DESCRIPTOR, int plane, int normal1, int normal2>
287 constexpr auto velocity_matches = [](unsigned iPop) {
288 if constexpr (plane == 0) {
289 return ( descriptors::c<DESCRIPTOR>(iPop,0) * 0
290 + descriptors::c<DESCRIPTOR>(iPop,1) * (normal1 == 1 ? 1 : -1)
291 + descriptors::c<DESCRIPTOR>(iPop,2) * (normal2 == 1 ? 1 : -1)) < 0;
292 } else if constexpr (plane == 1) {
293 return ( descriptors::c<DESCRIPTOR>(iPop,0) * (normal1 == 1 ? 1 : -1)
294 + descriptors::c<DESCRIPTOR>(iPop,1) * 0
295 + descriptors::c<DESCRIPTOR>(iPop,2) * (normal2 == 1 ? 1 : -1)) < 0;
296 } else if constexpr (plane == 2) {
297 return ( descriptors::c<DESCRIPTOR>(iPop,0) * (normal1 == 1 ? 1 : -1)
298 + descriptors::c<DESCRIPTOR>(iPop,1) * (normal2 == 1 ? 1 : -1)
299 + descriptors::c<DESCRIPTOR>(iPop,2) * 0) < 0;
300 } else {
301 return false;
302 }
303 };
305 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches));
306}
307
308// For 2D Corners
309template <typename DESCRIPTOR, int normalX, int normalY>
311 constexpr auto velocity_matches = [](unsigned iPop) {
312 return ( descriptors::c<DESCRIPTOR>(iPop,0) * normalX
313 + descriptors::c<DESCRIPTOR>(iPop,1) * normalY) < 0;
314 };
316 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches));
317}
318
319// For 3D Corners
320template <typename DESCRIPTOR, int normalX, int normalY, int normalZ>
322 constexpr auto velocity_matches = [](unsigned iPop) {
323 return ( descriptors::c<DESCRIPTOR>(iPop,0) * normalX
324 + descriptors::c<DESCRIPTOR>(iPop,1) * normalY
325 + descriptors::c<DESCRIPTOR>(iPop,2) * normalZ) < 0;
326 };
328 descriptors::filter_population_indices<DESCRIPTOR>(velocity_matches));
329}
330
332template <typename DESCRIPTORBASE>
333std::vector<int> remainingIndexes(const std::vector<int> &indices)
334{
335 std::vector<int> remaining;
336 for (int iPop = 0; iPop < DESCRIPTORBASE::q; ++iPop) {
337 bool found = false;
338 for (unsigned jPop = 0; jPop < indices.size(); ++jPop) {
339 if (indices[jPop] == iPop) {
340 found = true;
341 }
342 }
343 if (!found) {
344 remaining.push_back(iPop);
345 }
346 }
347 return remaining;
348}
349
350
353template <typename T, typename DESCRIPTOR>
354int get_nearest_link(const std::vector<T>& vec)
355{
356 T max=-1;
357 int max_index = 0;
358 for (int iQ=1; iQ<DESCRIPTOR::q; ++iQ) {
359 std::vector<T> c_i(DESCRIPTOR::c[iQ], DESCRIPTOR::c[iQ]+3);
360 T tmp = util::scalarProduct<T>(c_i, vec)/util::norm(c_i);
361 if (tmp > max) {
362 max = tmp;
363 max_index = iQ;
364 }
365 }
366 return max_index;
367}
368
369namespace tensorIndices2D {
370enum { xx=0, xy=1, yy=2 };
371}
372
373namespace tensorIndices3D {
374enum { xx=0, xy=1, xz=2, yy=3, yz=4, zz=5 };
375}
376
378template <typename T, typename DESCRIPTOR>
379T densityFromPressure( T latticePressure )
380{
381 // rho = p / c_s^2 + 1
382 return latticePressure * descriptors::invCs2<T,DESCRIPTOR>() + 1.0;
383}
384
386template <typename T, typename DESCRIPTOR>
387T pressureFromDensity( T latticeDensity )
388{
389 // p = (rho - 1) * c_s^2
390 return (latticeDensity - 1.0) / descriptors::invCs2<T,DESCRIPTOR>();
391}
392
393} // namespace util
394
395template <typename T>
396std::enable_if_t<std::is_arithmetic<T>::type::value, T> abs(T x)
397{
398 return util::fabs(x);
399}
400
401// *INDENT-OFF*
402
403} // namespace olb
404
405#endif
constexpr auto array_from_index_sequence(std::index_sequence< Is... >)
Convert index sequence into an array of its values.
Definition meta.h:422
constexpr bool indexed_pack_contains(COND cond)
Returns true iff at least one VALUE satisfies COND.
Definition meta.h:404
constexpr auto map_index_sequence(MAP map, std::index_sequence< Is... >)
Definition meta.h:470
std::vector< int > remainingIndexes(const std::vector< int > &indices)
finds all the remaining indexes of a lattice given some other indexes
Definition util.h:333
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
constexpr auto subIndexOutgoingRemaining() any_platform
Definition util.h:272
bool aligned_to_grid(const std::vector< T > &vec)
Definition util.h:78
T densityFromPressure(T latticePressure)
compute lattice density from lattice pressure
Definition util.h:379
cpu::simd::Pack< T > min(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:124
constexpr auto populationsContributingToVelocity() any_platform
Return array of population indices where c[iVel] == value.
Definition util.h:216
constexpr auto subIndexOutgoing2DonCorners() any_platform
Definition util.h:310
constexpr auto subIndexOutgoing3DonEdges() any_platform
Definition util.h:286
bool contained(int x, int y, int x0, int x1, int y0, int y1)
Definition util.h:119
constexpr auto subIndexOutgoing() any_platform
Compute opposites of wall-incoming population indices.
Definition util.h:256
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
T pressureFromDensity(T latticeDensity)
compute lattice pressure from lattice density
Definition util.h:387
auto normSqr(const ARRAY_LIKE &u) any_platform
Compute norm square of a d-dimensional vector.
Definition util.h:143
T norm(const std::vector< T > &a)
l2 norm of a vector of arbitrary length
bool aligned_to_y(const std::vector< T > &vec)
Definition util.h:66
T scalarProduct(const T u1[d], const T u2[d])
Definition util.h:187
bool intersect(int x0, int x1, int y0, int y1, int x0_, int x1_, int y0_, int y1_, int &newX0, int &newX1, int &newY0, int &newY1)
Definition util.h:89
bool aligned_to_z(const std::vector< T > &vec)
Definition util.h:72
int get_nearest_link(const std::vector< T > &vec)
Util Function for Wall Model of Malaspinas get link with smallest angle to a vector.
Definition util.h:354
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
Definition pack.h:106
T sqr(T arg)
Definition util.h:136
constexpr auto subIndexOutgoing3DonCorners() any_platform
Definition util.h:321
int sign(T val)
Definition util.h:54
int findVelocity(const int v[DESCRIPTORBASE::d]) any_platform
Definition util.h:237
bool aligned_to_x(const std::vector< T > &vec)
Definition util.h:60
constexpr auto populationsContributingToDirection() any_platform
Return array of population indices where c[iPop][iD] == NORMAL[iD].
Definition util.h:226
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
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
Vector of scalars.
Compute number of elements of a symmetric d-dimensional tensor.
Definition util.h:210
static constexpr int n
result stored in n
Definition util.h:211
efficient implementation of a vector class