OpenLB 1.7
Loading...
Searching...
No Matches
indicatorBase.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2014-2016 Cyril Masquelier, Albert Mink, Mathias J. Krause, Benjamin Förster
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 WITHOUS 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
25#ifndef INDICATOR_BASE_H
26#define INDICATOR_BASE_H
27
28#include "core/util.h"
30
31namespace olb {
32
33namespace util {
34
35template <typename S, unsigned D, typename F1, typename F2>
36bool distance(S& distance, const Vector<S,D>& origin, const Vector<S,D>& direction,
37 S precision, S pitch, F1 isInside, F2 isInsideBoundingBox)
38{
39 // Check if point is on surface
40 bool isInsideDistance;
41 bool isInsideOppDistance;
42 Vector<S,D> currentPoint = origin + 10*precision*direction;
43 isInside(&isInsideDistance, currentPoint.data());
44 currentPoint = origin - 10*precision*direction;
45 isInside(&isInsideOppDistance, currentPoint.data());
46 if (isInsideDistance == !isInsideOppDistance) {
47 distance = 0;
48 return true;
49 }
50
51 bool originValue;
52 bool currentValue;
53
54 isInside(&originValue, origin.data());
55
56 // start at origin and move into given direction
57 currentPoint = origin;
58 currentValue = originValue;
59
60 while (currentValue == originValue && isInsideBoundingBox(currentPoint)) {
61 currentPoint += direction;
62 // update currentValue until the first point on the other side (inside/outside) is found
63 isInside(&currentValue, currentPoint.data());
64 }
65
66 // return false if no point was found in given direction
67 if (!isInsideBoundingBox(currentPoint) && !originValue) {
68 return false;
69 }
70
71
72 while (pitch >= precision) {
73 if (!isInsideBoundingBox(currentPoint) && originValue) {
74 currentPoint -= pitch * direction;
75 pitch *= 0.5;
76 }
77 else {
78 isInside(&currentValue, currentPoint.data());
79 if (currentValue == originValue) {
80 currentPoint += pitch * direction;
81 pitch *= 0.5;
82 }
83 else {
84 currentPoint -= pitch * direction;
85 pitch *= 0.5;
86 }
87 }
88 }
89
90 distance = norm(currentPoint - origin);
91 return true;
92}
93
94template <typename S, unsigned D, typename F1, typename F2>
95bool distance(S& distance, const Vector<S,D>& origin, const Vector<S,D>& direction,
96 S precision, F1 sdf, F2 isInsideBoundingBox, const unsigned maxIt = 1e6)
97{
98 S signedDistance{sdf(origin)};
99 Vector<S,D> currPos{origin};
100 const Vector<S,D> dir{util::sign(signedDistance) * normalize(direction)};
101
102 if (util::fabs(signedDistance) <= precision) {
103 distance = util::fabs(signedDistance);
104 return true;
105 }
106
107 distance = S{0};
108 for(unsigned i=0; util::fabs(signedDistance) > precision && i<maxIt; ++i) {
109 distance += signedDistance;
110 currPos += signedDistance * dir;
111 signedDistance = sdf(currPos);
112 if (!isInsideBoundingBox(currPos)) {
113 distance = S{0};
114 return false;
115 }
116 }
117
119 return true;
120}
121
122template <typename S, unsigned D, bool normalizeDirection = true>
123bool distance(S& distance, const Vector<S,D>& origin, const Vector<S,D>& direction,
124 S precision, std::function<S(const Vector<S,D>&)> sdf, S maxDistance, const unsigned maxIt = 1e6)
125{
126 S signedDistance{sdf(origin)};
127 Vector<S,D> currPos{origin};
128 Vector<S,D> dir;
129 if constexpr(normalizeDirection) {
130 dir = util::sign(signedDistance) * normalize(direction);
131 }
132 else {
133 dir = util::sign(signedDistance) * direction;
134 }
135
136 if (util::fabs(signedDistance) <= precision) {
137 distance = util::fabs(signedDistance);
138 return true;
139 }
140
141 distance = S{0};
142 for(unsigned i=0; util::fabs(signedDistance) > precision && i<maxIt; ++i) {
143 distance += signedDistance;
144 currPos += signedDistance * dir;
145 signedDistance = sdf(currPos);
146 if (signedDistance > maxDistance) {
147 distance = S{0};
148 return false;
149 }
150 }
151
153 return true;
154}
155
156
167template <typename S, unsigned D, typename F1, typename F2>
168bool bisectDistance(S& distance, const Vector<S,D>& origin, const Vector<S,D>& direction,
169 S pitch, S precision, F1 isInside, F2 isInsideBoundingBox)
170{
171 distance = S(0);
172 Vector<S,D> dir = normalize(direction);
173
174 // Check if origin is on surface
175 bool isInsideDistance = isInside(origin + 5*precision*dir);
176 bool isInsideOppDistance = isInside(origin - 5*precision*dir);
177 if (isInsideDistance == !isInsideOppDistance) {
178 return true;
179 }
180
181 Vector<S,D> startPoint = origin;
182 S fixedDistance = S(0);
183 S oldDistance = distance;
184 std::function<Vector<S,D>()> calcCurrPoint = [&startPoint, &pitch, &dir]() {
185 return startPoint + pitch * dir;
186 };
187 Vector<S,D> currPoint = calcCurrPoint();
188
189 bool originValue = isInside(startPoint);
190 bool currentValue = isInside(currPoint);
191
192 // if aforementioned requirement for pitch is not given, try to find a proper pitch
193 while (originValue == currentValue) {
194 pitch *= 1.5;
195 currPoint = calcCurrPoint();
196 currentValue = isInside(currPoint);
197
198 // if both points are outside the bounding box return false indicating that no distance was found
199 if (!currentValue && !isInsideBoundingBox(startPoint) && !isInsideBoundingBox(currPoint)) {
200 return false;
201 }
202 }
203
204 for (unsigned iD=0; iD<D; ++iD) {
205 if (!std::isfinite(currPoint[iD])) {
206 return false;
207 }
208 }
209
210 // if we have one point inside and another outside, we can keep halving the line from origin to currPoint until we find the wanted precision
211 distance = norm(startPoint - currPoint);
212 while ( util::abs(distance - oldDistance) > precision ) {
213 pitch *= 0.5;
214 currPoint = calcCurrPoint();
215
216 // set distances
217 oldDistance = distance;
218 distance = norm(startPoint - currPoint);
219
220 // if both points are outside or inside run take result of same function with different start point (= current point)
221 currentValue = isInside(currPoint);
222 if (currentValue == originValue) {
223 startPoint = currPoint;
224 fixedDistance += distance;
225 // convert distances to distance to new start point
226 oldDistance -= distance;
227 distance = S(0);
228 }
229 }
230 distance += fixedDistance;
231
232 return true;
233}
234
235template <typename S, unsigned D, typename F1>
236Vector<S,D> surfaceNormal(const Vector<S,D>& pos, const S meshSize, F1 sdf)
237{
238 Vector<S,D> normal( S(0) );
239
240 for (unsigned iD=0; iD<D; ++iD) {
241 Vector<S,D> delta(S(0));
242 delta[iD] = meshSize;
243 normal[iD] = (sdf(pos+delta) - sdf(pos-delta)) / (2*meshSize);
244 }
245
246 return normal;
247}
248
249} //namespace util
250
251} //namespace olb
252
253
254#endif
Plain old scalar vector.
Definition vector.h:47
constexpr const T * data() const any_platform
Definition vector.h:161
ADf< T, DIM > abs(const ADf< T, DIM > &a)
Definition aDiff.h:1019
bool distance(S &distance, const Vector< S, D > &origin, const Vector< S, D > &direction, S precision, S pitch, F1 isInside, F2 isInsideBoundingBox)
bool bisectDistance(S &distance, const Vector< S, D > &origin, const Vector< S, D > &direction, S pitch, S precision, F1 isInside, F2 isInsideBoundingBox)
Using a bisect to find the unsigned distance (false if distance was not found, true if distance was f...
Vector< S, D > surfaceNormal(const Vector< S, D > &pos, const S meshSize, F1 sdf)
T norm(const std::vector< T > &a)
l2 norm of a vector of arbitrary length
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
Definition pack.h:106
Vector< T, D > normalize(const Vector< T, D > &a)
int sign(T val)
Definition util.h:54
Top level namespace for all of OpenLB.
Set of functions commonly used in LB computations – header file.