OpenLB 1.7
Loading...
Searching...
No Matches
smoothIndicatorF3D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2014-2016 Cyril Masquelier, Mathias J. Krause, Albert Mink
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 SMOOTH_INDICATOR_F_3D_HH
25#define SMOOTH_INDICATOR_F_3D_HH
26
27#include <vector>
28#include "utilities/omath.h"
29#include <sstream>
30
31#include "smoothIndicatorF3D.h"
38
39#ifndef M_PI
40#define M_PI 3.14159265358979323846
41#endif
42#ifndef M_PI2
43#define M_PI2 1.57079632679489661923
44#endif
45
46namespace olb {
47
48//Constructor: SmoothIndicatorCuboid3D
49template <typename T, typename S, bool PARTICLE>
51 S epsilon, Vector<S,3> theta)
52 :SmoothIndicatorCuboid3D(ind.getxLength(), ind.getyLength(), ind.getzLength(), ind.getCenter(), epsilon, theta)
53{ }
54
55template <typename T, typename S, bool PARTICLE>
57 Vector<S,3> center, S epsilon, Vector<S,3> theta)
58 :_ind(xLength, yLength, zLength, center)
59{
60 this->_epsilon = epsilon;
61 if constexpr (!PARTICLE) {
62 this->_pos = _ind.getCenter();
63 this->_theta = util::degreeToRadian(theta);
64 }
65
66 this->_circumRadius = .5*(util::sqrt(xLength*xLength+yLength*yLength+zLength*zLength))+0.5*epsilon;
67 if constexpr (!PARTICLE) {
68 this->_myMin = {
69 this->_pos[0] - this->getCircumRadius(),
70 this->_pos[1] - this->getCircumRadius(),
71 this->_pos[2] - this->getCircumRadius()
72 };
73
74 this->_myMax = {
75 this->_pos[0] + this->getCircumRadius(),
76 this->_pos[1] + this->getCircumRadius(),
77 this->_pos[2] + this->getCircumRadius()
78 };
79 this->init();
80 }
81}
82
83template <typename T, typename S, bool PARTICLE>
87
88template <typename T, typename S, bool PARTICLE>
90{
91 return _ind.getxLength()*_ind.getyLength()*_ind.getzLength();
92}
93
94template <typename T, typename S, bool PARTICLE>
96{
97 T const xLength = _ind.getxLength();
98 T const yLength = _ind.getyLength();
99 T const zLength = _ind.getzLength();
100 T const mass = getVolume()*density;
101 T const xLength2 = xLength*xLength;
102 T const yLength2 = yLength*yLength;
103 T const zLength2 = zLength*zLength;
104 Vector<S,3> mofi;
105 mofi[0] = 1./12.*mass*(yLength2+zLength2);
106 mofi[1] = 1./12.*mass*(xLength2+zLength2);
107 mofi[2] = 1./12.*mass*(yLength2+xLength2);
108 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
109}
110
111template <typename T, typename S, bool PARTICLE>
113{
114 return _ind.surfaceNormal(pos, meshSize);
115}
116
117template <typename T, typename S, bool PARTICLE>
119{
120 Vector<S,3> p;
121 if constexpr(!PARTICLE) {
122 // counter-clockwise rotation by _theta=-theta around the current position of the center of mass & translation
123 p = util::executeRotation<S,3,true>(input, this->_rotMat, this->getPos());
124 }
125 else {
126 p = input;
127 }
128 return _ind.signedDistance(p + _ind.getCenter());
129}
130
131
132//Constructor: SmoothIndicatorEllipsoid3D
133template <typename T, typename S, bool PARTICLE>
135 S epsilon, Vector<S,3> theta)
136 :SmoothIndicatorEllipsoid3D(ind.getCenter(), ind.getRadius(), epsilon, theta)
137{ }
138
139template <typename T, typename S, bool PARTICLE>
141 S epsilon, Vector<S,3> theta)
142 :_ind(center, radius)
143{
144 this->_epsilon = epsilon;
145 if constexpr (!PARTICLE) {
146 this->_pos = center;
147 this->_theta = util::degreeToRadian(theta);
148 }
149
150 T const max_axis = util::max( radius[0], util::max(radius[1], radius[2]) );
151 this->_circumRadius = max_axis+0.5*epsilon;
152 if constexpr (!PARTICLE) {
153 this->_myMin = {
154 this->_pos[0] - this->getCircumRadius(),
155 this->_pos[1] - this->getCircumRadius(),
156 this->_pos[2] - this->getCircumRadius()
157 };
158 this->_myMax = {
159 this->_pos[0] + this->getCircumRadius(),
160 this->_pos[1] + this->getCircumRadius(),
161 this->_pos[2] + this->getCircumRadius()
162 };
163 this->init();
164 }
165}
166
167template <typename T, typename S, bool PARTICLE>
171
172template <typename T, typename S, bool PARTICLE>
174{
175 Vector<S,3> const radius = _ind.getRadius();
176 return 4./3.*M_PI*radius[0]*radius[1]*radius[2];
177}
178
179template <typename T, typename S, bool PARTICLE>
181{
182 Vector<S,3> const radius = _ind.getRadius();
183 T const mass = getVolume()*density;
184 T const xHalfAxis2 = radius[0]*radius[0];
185 T const yHalfAxis2 = radius[1]*radius[1];
186 T const zHalfAxis2 = radius[2]*radius[2];
187 Vector<S,3> mofi;
188 mofi[0] = 0.2*mass*(yHalfAxis2+zHalfAxis2);
189 mofi[1] = 0.2*mass*(xHalfAxis2+zHalfAxis2);
190 mofi[2] = 0.2*mass*(yHalfAxis2+xHalfAxis2);
191 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
192}
193
194template <typename T, typename S, bool PARTICLE>
196{
197 return _ind.surfaceNormal(pos, meshSize);
198}
199
200template <typename T, typename S, bool PARTICLE>
202{
203 // counter-clockwise rotation by _theta=-theta around the center of mass
204 Vector<S,3> p;
205 if constexpr(!PARTICLE) {
206 // counter-clockwise rotation by _theta=-theta around the current position of the center of mass & translation
207 p = util::executeRotation<S,3,true>(input, this->_rotMat, this->getPos());
208 }
209 else {
210 p = input;
211 }
212 return _ind.signedDistance(p + _ind.getCenter());
213}
214
215// TODO: Check for correctness
216template <typename T, typename S, bool PARTICLE>
218{
219 Vector<T,3> pos(0.);
220 Vector<T,9> rotMatrix = {1, 0, 0, 0, 1, 0, 0, 0, 1};
221 if constexpr (!PARTICLE) {
222 pos = this->getPos();
223 rotMatrix = this->getRotationMatrix();
224 }
225
226 //1.Calculate distance between point and center of unrotated indicator
227 T xDist = input[0] - pos[0];
228 T yDist = input[1] - pos[1];
229 T zDist = input[2] - pos[2];
230
231 //2.Calculate point projected to rotated indicator
232 // counter-clockwise rotation by _theta=-theta around center
233 T x = pos[0] + rotMatrix[0]*xDist + rotMatrix[3]*yDist + rotMatrix[6]*zDist;
234 T y = pos[1] + rotMatrix[1]*xDist + rotMatrix[4]*yDist + rotMatrix[7]*zDist;
235 T z = pos[2] + rotMatrix[2]*xDist + rotMatrix[5]*yDist + rotMatrix[8]*zDist;
236
237 T a = (x - pos[0]) / (_ind.getRadius()[0] - 0.5*this->getEpsilon() );
238 T b = (y - pos[1]) / (_ind.getRadius()[1] - 0.5*this->getEpsilon() );
239 T c = (z - pos[2]) / (_ind.getRadius()[2] - 0.5*this->getEpsilon() );
240 T aEps = (x - pos[0]) / (_ind.getRadius()[0] + 0.5*this->getEpsilon() );
241 T bEps = (y - pos[1]) / (_ind.getRadius()[1] + 0.5*this->getEpsilon() );
242 T cEps = (z - pos[2]) / (_ind.getRadius()[2] + 0.5*this->getEpsilon() );
243
244 if ( (a*a+b*b+c*c) <= 1. ) {
245 output[0] = 1.;
246 return true;
247 }
248 if ( (aEps*aEps+bEps*bEps+cEps*cEps) <= 1. ) {
249 // TODO: Here the correct distance to the ellipsoid has to be calculated for smooth transition
250 // For now the epsilon region is taken to be 0.5
251 output[0] = .5;
252 return true;
253 }
254 output[0] = 0.;
255 return false;
256}
257
258
259//Constructor: SmoothIndicatorSuperEllipsoid3D
260template <typename T, typename S, bool PARTICLE>
262 S epsilon, Vector<S,3> theta)
263 :SmoothIndicatorSuperEllipsoid3D(ind.getCenter(), ind.getXHalfAxis(), ind.getYHalfAxis(), ind.getZHalfAxis(), ind.getExponent1(), ind.getExponent2(), epsilon, theta)
264{ }
265
266template <typename T, typename S, bool PARTICLE>
268 S xHalfAxis, S yHalfAxis, S zHalfAxis, S exponent1, S exponent2,
269 S epsilon, Vector<S,3> theta)
270 :_ind(center, xHalfAxis, yHalfAxis, zHalfAxis, exponent1, exponent2)
271{
272 this->_epsilon = epsilon;
273 if constexpr (!PARTICLE) {
274 this->_pos = _ind.getCenter();
275 this->_theta = util::degreeToRadian(theta);
276 }
277
278 T const max_axis = util::max( xHalfAxis, util::max(yHalfAxis, zHalfAxis) );
279 this->_circumRadius = util::sqrt(2.)*max_axis+0.5*epsilon;
280 if constexpr (!PARTICLE) {
281 this->_myMin = {
282 this->_pos[0] - this->getCircumRadius(),
283 this->_pos[1] - this->getCircumRadius(),
284 this->_pos[2] - this->getCircumRadius()
285 };
286 this->_myMax = {
287 this->_pos[0] + this->getCircumRadius(),
288 this->_pos[1] + this->getCircumRadius(),
289 this->_pos[2] + this->getCircumRadius()
290 };
291 this->init();
292 }
293}
294
295template <typename T, typename S, bool PARTICLE>
299
300template <typename T, typename S, bool PARTICLE>
302{
303 return moments(0., 0., 0.);
304}
305
306template <typename T, typename S, bool PARTICLE>
308{
309 T const mass = getVolume() * density;
310 Vector<S,3> mofi;
311 mofi[0] = ( moments(0., 2., 0.) + moments(0., 0., 2.) ) * density;
312 mofi[1] = ( moments(2., 0., 0.) + moments(0., 0., 2.) ) * density;
313 mofi[2] = ( moments(0., 2., 0.) + moments(2., 0., 0.) ) * density;
314 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
315}
316
317template <typename T, typename S, bool PARTICLE>
319{
320 return (std::tgamma(arg1)*std::tgamma(arg2)) / std::tgamma(arg1+arg2);
321}
322
323template <typename T, typename S, bool PARTICLE>
325{
326 S ex1 = 2./_ind.getExponent1();
327 S ex2 = 2./_ind.getExponent2();
328 S tmp1 = 2./(p+q+2.);
329 S tmp2 = util::pow(_ind.getXHalfAxis(), p+1.) * util::pow(_ind.getYHalfAxis(), q+1.) * util::pow(_ind.getZHalfAxis(), r+1.) * ex1 * ex2;
330 S tmp3 = beta( (r+1.)*(ex1/2.), (p+q+2.)*(ex2/2.)+1. ) * beta( (q+1.)*(ex2/2.), (p+1.)*(ex2/2.) );
331 return tmp1 * tmp2 * tmp3;
332}
333
334template <typename T, typename S, bool PARTICLE>
336{
337 return _ind.surfaceNormal(pos, meshSize);
338}
339
340template <typename T, typename S, bool PARTICLE>
342{
343 // counter-clockwise rotation by _theta=-theta around the center of mass
344 Vector<S,3> p;
345 if constexpr(!PARTICLE) {
346 // counter-clockwise rotation by _theta=-theta around the current position of the center of mass & translation
347 p = util::executeRotation<S,3,true>(input, this->_rotMat, this->getPos());
348 }
349 else {
350 p = input;
351 }
352 return _ind.signedDistance(p + _ind.getCenter());
353}
354
355template <typename T, typename S, bool PARTICLE>
357{
358 Vector<T,3> pos(0.);
359 Vector<T,9> rotMatrix = {1, 0, 0, 0, 1, 0, 0, 0, 1};
360 if constexpr (!PARTICLE) {
361 pos = this->getPos();
362 rotMatrix = this->getRotationMatrix();
363 }
364
365 //1.Calculate distance between point and center of unrotated indicator
366 T xDist = input[0] - pos[0];
367 T yDist = input[1] - pos[1];
368 T zDist = input[2] - pos[2];
369
370 //2.Calculate point projected to rotated indicator
371 // counter-clockwise rotation by _theta=-theta around center
372 T x = pos[0] + rotMatrix[0]*xDist + rotMatrix[3]*yDist + rotMatrix[6]*zDist;
373 T y = pos[1] + rotMatrix[1]*xDist + rotMatrix[4]*yDist + rotMatrix[7]*zDist;
374 T z = pos[2] + rotMatrix[2]*xDist + rotMatrix[5]*yDist + rotMatrix[8]*zDist;
375
376 T a = util::pow ( util::abs( (x-pos[0]) / _ind.getXHalfAxis() ), _ind.getExponent1() );
377 T b = util::pow ( util::abs( (y-pos[1]) / _ind.getYHalfAxis() ), _ind.getExponent1() );
378 T c = util::pow ( util::abs( (z-pos[2]) / _ind.getZHalfAxis() ), _ind.getExponent2() );
379 T ab = util::pow( a+b, _ind.getExponent2()/_ind.getExponent1() );
380
381 if ( (ab+c) <= 1. ) {
382 output[0] = 1.;
383 return true;
384 }
385
386 output[0] = 0.;
387 return false;
388}
389
390
391//Constructor: SmoothIndicatorSphere3D
392template <typename T, typename S, bool PARTICLE>
394 : SmoothIndicatorSphere3D(ind.getCenter(), ind.getRadius(), epsilon)
395{ }
396
397template <typename T, typename S, bool PARTICLE>
399 : _ind(center, radius)
400{
401 this->_epsilon = epsilon;
402 if constexpr (!PARTICLE) {
403 this->_pos = center;
404 }
405
406 this->_circumRadius = radius + 0.5*epsilon;
407 if constexpr (!PARTICLE) {
408 this->_myMin = {
409 this->_pos[0] - this->getCircumRadius(),
410 this->_pos[1] - this->getCircumRadius(),
411 this->_pos[2] - this->getCircumRadius()
412 };
413 this->_myMax = {
414 this->_pos[0] + this->getCircumRadius(),
415 this->_pos[1] + this->getCircumRadius(),
416 this->_pos[2] + this->getCircumRadius()
417 };
418 this->_theta = Vector<T,3>(0.,0.,0.);
419 this->init();
420 }
421}
422
423template <typename T, typename S, bool PARTICLE>
427
428template <typename T, typename S, bool PARTICLE>
430{
431 return 4./3.*M_PI*util::pow(_ind.getRadius(), 3);
432}
433
434template <typename T, typename S, bool PARTICLE>
436{
437 T const radius = _ind.getRadius();
438 T const radius2 = radius*radius;
439 T const mass = getVolume()*density;
440 Vector<S,3> mofi;
441 mofi[0] = 2./5.*mass*radius2;
442 mofi[1] = 2./5.*mass*radius2;
443 mofi[2] = 2./5.*mass*radius2;
444 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
445}
446
447template <typename T, typename S, bool PARTICLE>
449{
450 return _ind.surfaceNormal(pos, meshSize);
451}
452
453template <typename T, typename S, bool PARTICLE>
455{
456 // only translation necessary
457 Vector<S,3> dist = input + _ind.getCenter();
458 if constexpr (!PARTICLE) {
459 dist -= this->_pos;
460 }
461 return _ind.signedDistance(dist);
462}
463
464
465template <typename T, typename S, bool PARTICLE>
467{
468 this->_circumRadius = util::sqrt(_ind.getRadius()*_ind.getRadius()+(0.5*length)*(0.5*length))+0.5*this->getEpsilon();
469 if constexpr (!PARTICLE) {
470 this->_myMin = {
471 this->_pos[0] - this->getCircumRadius(),
472 this->_pos[1] - this->getCircumRadius(),
473 this->_pos[2] - this->getCircumRadius()
474 };
475 this->_myMax = {
476 this->_pos[0] + this->getCircumRadius(),
477 this->_pos[1] + this->getCircumRadius(),
478 this->_pos[2] + this->getCircumRadius()
479 };
480 this->init();
481 }
482}
483
484template <typename T, typename S, bool PARTICLE>
488
489template <typename T, typename S, bool PARTICLE>
491 : SmoothIndicatorCylinder3D(ind.getCenter1(), ind.getCenter2(), ind.getRadius(), epsilon, theta)
492{ }
493
494template <typename T, typename S, bool PARTICLE>
496 : _ind(center1, center2, radius)
497{
498 this->_epsilon = epsilon;
499 if constexpr (!PARTICLE) {
500 this->_pos = 0.5 * (_ind.getCenter1() + _ind.getCenter2());
501 this->_theta = util::degreeToRadian(theta);
502 }
503 Vector<T,3> dist = _ind.getCenter2() - _ind.getCenter1();
504 S const length = norm(dist);
505 if constexpr (!PARTICLE) {
506 initIndicatorCylinder3D(this->_theta, length);
507 }
508 else {
509 initIndicatorCylinder3D(Vector<T,3>(0.), length);
510 }
511
512}
513
514template <typename T, typename S, bool PARTICLE>
516 : SmoothIndicatorCylinder3D(center-.5*height*normalize(normal), center+.5*height*normalize(normal), radius, epsilon, theta)
517{ }
518
519template <typename T, typename S, bool PARTICLE>
521{
522 const Vector<T,3> dist = _ind.getCenter2() - _ind.getCenter1();
523 S const length = norm(dist);
524 return M_PI*_ind.getRadius()*_ind.getRadius()*length;
525}
526
527template <typename T, typename S, bool PARTICLE>
529{
530 Vector<T,3> dist = _ind.getCenter2() - _ind.getCenter1();
531 S const length = norm(dist);
532 T const radius2 = _ind.getRadius() * _ind.getRadius();
533 T const mass = getVolume()*density;
534 Vector<S,3> mofi;
535 mofi[0] = 0.5*mass*radius2;
536 mofi[1] = 1/12.*mass*(length*length+3.*radius2);
537 mofi[2] = 1/12.*mass*(length*length+3.*radius2);
538 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
539}
540
541template <typename T, typename S, bool PARTICLE>
543{
544 return _ind.surfaceNormal(pos, meshSize);
545}
546
547template <typename T, typename S, bool PARTICLE>
549{
550 Vector<S,3> p;
551 if constexpr(!PARTICLE) {
552 // counter-clockwise rotation by _theta=-theta around the current position of the center of mass & translation
553 p = util::executeRotation<S,3,true>(input, this->_rotMat, this->getPos());
554 }
555 else {
556 p = input;
557 }
558
559 // moving to indicator coordinate system by adding start position coordinate
560 return _ind.signedDistance(p + 0.5 * (_ind.getCenter2() + _ind.getCenter1()));
561}
562
563
564template <typename T, typename S, bool PARTICLE>
566 :SmoothIndicatorCone3D(ind.getCenter1(), ind.getCenter2(), ind.getRadius1(), ind.getRadius2(), epsilon, theta)
567{ }
568
569template <typename T, typename S, bool PARTICLE>
571 :_ind(center1, center2, radius1, radius2)
572{
573 this->_epsilon = epsilon;
574 _startPos = this->calcCenterOfMass();
575
576 if constexpr (!PARTICLE) {
577 this->_pos = _startPos;
578 this->_theta = util::degreeToRadian(theta);
579 }
580
581 Vector<T,3> dist = _ind.getCenter2() - _ind.getCenter1();
582 S const length = norm(dist);
583 initIndicatorCone3D(theta, length);
584}
585
586template <typename T, typename S, bool PARTICLE>
590
591// TODO: Add Moment of inertia for truncated cone
592template <typename T, typename S, bool PARTICLE>
594{
595 const T _radiusA = _ind.getRadius1();
596 const T _radiusB = _ind.getRadius2();
597
598 if (_radiusA >= _radiusB) {
599 this->_circumRadius = util::sqrt(_radiusA*_radiusA+(0.5*length)*(0.5*length))+0.5*this->getEpsilon();
600 }
601 else {
602 this->_circumRadius = util::sqrt(_radiusB*_radiusB+(0.5*length)*(0.5*length))+0.5*this->getEpsilon();
603 }
604
605 if constexpr (!PARTICLE) {
606 this->_myMin = {
607 this->_pos[0] - this->getCircumRadius(),
608 this->_pos[1] - this->getCircumRadius(),
609 this->_pos[2] - this->getCircumRadius()
610 };
611 this->_myMax = {
612 this->_pos[0] + this->getCircumRadius(),
613 this->_pos[1] + this->getCircumRadius(),
614 this->_pos[2] + this->getCircumRadius()
615 };
616
617 this->init();
618 }
619}
620
621template <typename T, typename S, bool PARTICLE>
623{
624 const Vector<T,3> dist = _ind.getCenter2() - _ind.getCenter1();
625 S const length = norm(dist);
626 return (1/3.)*M_PI*length* (_ind.getRadius1()*_ind.getRadius1()
627 +_ind.getRadius1()*_ind.getRadius2()
628 +_ind.getRadius2()*_ind.getRadius2());
629}
630
631template <typename T, typename S, bool PARTICLE>
633{
634 const T _radiusA = _ind.getRadius1();
635 const T _radiusB = _ind.getRadius2();
636
637 Vector<T,3> dist = _ind.getCenter2() - _ind.getCenter1();
638 S const length = norm(dist);
639
640 const T mass = getVolume()*density;
641 Vector<S,3> mofi;
642
643 //TODO: check for correctness
644 //TODO: Add check that orientation fits or give a warning
645 // This is only valid if the same orientation is chosen. If A and B are not chosen according to this definiton, the calculation will be wrong.
646 T topRadius = _radiusA;
647 T baseRadius = _radiusB;
648 if (_radiusA > _radiusB) {
649 topRadius = _radiusB;
650 baseRadius = _radiusA;
651 }
652 mofi[0] = 3/10.*mass*(util::pow(baseRadius,5) - util::pow(topRadius,5))/(util::pow(baseRadius,3) - util::pow(topRadius,3));
653 mofi[1] = 3/20.*mass*( (util::pow(baseRadius-topRadius, 2) + 4*length*length) * (util::pow(baseRadius,5) - util::pow(topRadius,5)) )
654 / (util::pow(baseRadius-topRadius,3) * (baseRadius*baseRadius+baseRadius*topRadius+topRadius*topRadius));
655 mofi[2] = mofi[1];
656 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
657}
658
659template <typename T, typename S, bool PARTICLE>
661{
662 T topRadius, baseRadius;
663 Vector<T,3> centerTop, centerBase;
664
665 if (_ind.getRadius1() < _ind.getRadius2()) {
666 topRadius = _ind.getRadius1();
667 baseRadius = _ind.getRadius2();
668 centerTop = _ind.getCenter1();
669 centerBase = _ind.getCenter2();
670 }
671 else if (_ind.getRadius1() > _ind.getRadius2()) {
672 topRadius = _ind.getRadius2();
673 baseRadius = _ind.getRadius1();
674 centerTop = _ind.getCenter2();
675 centerBase = _ind.getCenter1();
676 }
677 else {
678 std::cerr << "Error calculating a cone's center of mass." << std::endl;
679 assert(false);
680 }
681
682 const T height = norm(centerTop - centerBase);
683 const T centerOfMassHeight = 0.25*height * (baseRadius*baseRadius + 2*baseRadius*topRadius + 3*topRadius*topRadius)
684 / (baseRadius*baseRadius + baseRadius*topRadius + topRadius*topRadius);
685 return centerBase + normalize(centerTop-centerBase) * centerOfMassHeight;
686}
687
688template <typename T, typename S, bool PARTICLE>
690{
691 return _ind.surfaceNormal(pos, meshSize);
692}
693
694template <typename T, typename S, bool PARTICLE>
696{
697 // counter-clockwise rotation by _theta=-theta around the current position of the center of mass
698 Vector<S,3> p;
699 if constexpr(!PARTICLE) {
700 // counter-clockwise rotation by _theta=-theta around the current position of the center of mass & translation
701 p = util::executeRotation<S,3,true>(input, this->_rotMat, this->getPos());
702 }
703 else {
704 p = input;
705 }
706
707 // moving to indicator coordinate system by adding start position coordinate
708 return _ind.signedDistance(p + _startPos);
709}
710
711
712//TODO: TO Be Repaired
713//TODO: Check for consitency
714template <typename T, typename S, bool PARTICLE>
716 std::shared_ptr<IndicatorF3D<T>> indPtr,
717 Vector<T,3> pos,
718 T epsilon,
719 Vector<T,3> theta)
720 : _indPtr(indPtr),
721 _latticeSpacing(latticeSpacing),
722 _center(3)
723{
724 OstreamManager clout(std::cout,"createIndicatorCustom3D");
725 this->_name = "custom3D";
726 this->_epsilon = epsilon;
727 if constexpr (!PARTICLE) {
728 this->_pos = pos; // global position of the local center
729 this->_theta = util::degreeToRadian(theta);
730 this->init();
731 }
732
733 initBlockData(*indPtr);
734
735 // calculate mass and centerpoint for rotation
736 calcCenter();
737 // calculate min and max from circumRadius
738 calcCircumRadius();
739}
740
741template <typename T, typename S, bool PARTICLE>
743{
744 OstreamManager clout(std::cout,"createIndicatorCustom3D");
745
746 // initialize temporary values
747 Vector<int,3> blockDataSize;
748 Vector<int,3> blockDataPadding;
749 for (unsigned iD=0; iD<3; ++iD) {
750 blockDataSize[iD] = util::max(
751 util::ceil( (ind.getMax()[iD] - ind.getMin()[iD]) / _latticeSpacing ), 1);
752 // Add a padding so that the distance can be cached in the vicinity of the geometry
753 blockDataPadding[iD] = 2*util::ceil(0.2*blockDataSize[iD]);
754 blockDataSize[iD] += blockDataPadding[iD];
755 }
756
757 // create blockData containing signed distance information
758 _cuboid = Cuboid3D<T>(PhysR<T,3>(0.), _latticeSpacing, blockDataSize);
759 this->_blockData.reset(new BlockData<3,T,BaseType<T>>(_cuboid));
760 int iX[3];
761 for (iX[0]=0; iX[0] < this->_blockData->getNx(); ++iX[0]) {
762 for (iX[1]=0; iX[1] < this->_blockData->getNy(); ++iX[1]) {
763 for (iX[2]=0; iX[2] < this->_blockData->getNz(); ++iX[2]) {
764 Vector<T,3> input;
765 for (unsigned iD=0; iD<3; ++iD) {
766 input[iD] = (iX[iD]-blockDataPadding[iD]/2)*_latticeSpacing+ind.getMin()[iD];
767 }
768 this->_blockData->get(iX) = ind.signedDistance(input);
769 }
770 }
771 }
772
773 this->_cacheFunctor = std::make_unique<BlockDataF3D<T,BaseType<T>>>(*(this->_blockData));
774 this->_interpolateCache = std::make_unique<AnalyticalFfromBlockF3D<T,T>>(*(this->_cacheFunctor), _cuboid);
775}
776
777template <typename T, typename S, bool PARTICLE>
778void SmoothIndicatorCustom3D<T,S,PARTICLE>::calcCenter()
779{
780 // TODO check again for correctness of center due to smooth boundary and coordinate system
781 unsigned nCells = 0;
782 int input[3];
783 this->_center = PhysR<T,3>(0.);
784 for (input[0] = 0; input[0] < this->_blockData->getNx(); ++input[0]) {
785 for (input[1] = 0; input[1] < this->_blockData->getNy(); ++input[1]) {
786 for (input[2] = 0; input[2] < this->_blockData->getNz(); ++input[2]) {
787 if (regardCell(input)) {
788 // Always use real boundary as in other geometries too
789 this->_center[0] += this->_latticeSpacing*input[0];
790 this->_center[1] += this->_latticeSpacing*input[1];
791 this->_center[2] += this->_latticeSpacing*input[2];
792 ++nCells;
793 }
794 }
795 }
796 }
797 this->_center *= 1./nCells;
798}
799
800template <typename T, typename S, bool PARTICLE>
802{
803 return _volume;
804}
805
806template <typename T, typename S, bool PARTICLE>
808{
809 // TODO - calculation
810 T cuboidMofi = util::pow(this->_latticeSpacing, 2)/ 6.0; // Single cuboid mofi at center of gravity
811 unsigned nCells = 0;
812 Vector<T,3> mofi = {T(0), T(0), T(0)};
813 T dx, dy, dz;
814 int input[3];
815 for (input[0] = 0; input[0] < this->_blockData->getNx(); ++input[0]) {
816 dx = util::abs(this->_latticeSpacing*input[0] - this->_center[0]);
817 for (input[1] = 0; input[1] < this->_blockData->getNy(); ++input[1]) {
818 dy = util::abs(this->_latticeSpacing*input[1] - this->_center[1]);
819 for (input[2] = 0; input[2] < this->_blockData->getNz(); ++input[2]) {
820 if (regardCell(input)) {
821 dz = util::abs(this->_latticeSpacing*input[2] - this->_center[2]);
822 mofi[0] += (dy*dy+dz*dz+cuboidMofi);
823 mofi[1] += (dx*dx+dz*dz+cuboidMofi);
824 mofi[2] += (dx*dx+dy*dy+cuboidMofi);
825 ++nCells;
826 }
827 }
828 }
829 }
830 _volume = nCells * util::pow(_latticeSpacing,3);
831 const T mass = rhoP * _volume;
832 const T cuboidMass = mass/nCells;
833 mofi *= cuboidMass;
834
835 return Vector<T,4>(mofi[0], mofi[1], mofi[2], mass);
836}
837
838
839template <typename T, typename S, bool PARTICLE>
841{
842 Vector<T,3> min(std::numeric_limits<olb::BaseType<T>>::max());
843 Vector<T,3> max(-std::numeric_limits<olb::BaseType<T>>::max());
844 Vector<T,3> distance;
845 T maxDistance{0};
846
847 int input[3];
848 for (input[0] = 0; input[0] < this->_blockData->getNx(); ++input[0]) {
849 distance[0] = this->_latticeSpacing * input[0] - this->_center[0];
850 for (input[1] = 0; input[1] < this->_blockData->getNy(); ++input[1]) {
851 distance[1] = this->_latticeSpacing * input[1] - this->_center[1];
852 for (input[2] = 0; input[2] < this->_blockData->getNz(); ++input[2]) {
853 distance[2] = this->_latticeSpacing * input[2] - this->_center[2];
854 if (regardCell(input)) {
855 if constexpr (!PARTICLE) {
856 for (unsigned iD=0; iD<3; ++iD) {
857 min[iD] = util::min(distance[iD], min[iD]);
858 max[iD] = util::max(distance[iD], max[iD]);
859 }
860 }
861 maxDistance = util::max(norm(distance), maxDistance);
862 }
863 }
864 }
865 }
866
867 if constexpr (!PARTICLE) {
868 min -= Vector<T,3>(0.5 * this->_epsilon + _latticeSpacing);
869 max += Vector<T,3>(0.5 * this->_epsilon + _latticeSpacing);
870 this->_myMin = this->_pos + min;
871 this->_myMax = this->_pos + max;
872 }
873
874 this->_circumRadius = maxDistance + T{0.5} * (this->_epsilon + util::sqrt(3) * _latticeSpacing);
875}
876
877template <typename T, typename S, bool PARTICLE>
882
883template <typename T, typename S, bool PARTICLE>
885{
886 return _indPtr->surfaceNormal(pos, meshSize);
887}
888
889template <typename T, typename S, bool PARTICLE>
891 std::function<Vector<S,3>(const Vector<S,3>&)> transformPos )
892{
893 return _indPtr->surfaceNormal( pos, meshSize, transformPos );
894}
895
896template <typename T, typename S, bool PARTICLE>
898{
899 PhysR<T,3> position = input;
900 if constexpr (!PARTICLE) {
901 // translation, counter-clockwise rotation by _theta=-theta around (0/0) and movement from rotation center to local center
902 position = util::executeRotation<T,3,true>(input, this->_rotMat, this->getPos());
903 }
904 // The block data originates in (0,0,0) therefore we translate the input position which is relative to center of mass
905 const PhysR<T,3> positionInCache = this->_center + position;
906
907 T signedDistance(0.);
908 if(_interpolateCache->operator()(&signedDistance, positionInCache.data())) {
909 return signedDistance;
910 }
911
912 // If all points were outside return an estimation instead
913 LatticeR<3> latticePosition;
914 PhysR<T,3> extraDistance;
915 for(unsigned iDim=0; iDim<3; ++iDim) {
916 latticePosition[iDim] = util::round( positionInCache[iDim] / this->_latticeSpacing );
917 latticePosition[iDim] = util::max(0, latticePosition[iDim]);
918 latticePosition[iDim] = util::min(this->_blockData->getExtent()[iDim] - 1, latticePosition[iDim]);
919 // The extra distance is always positive because it must be outside the geometry
920 extraDistance[iDim] = util::abs(_latticeSpacing * latticePosition[iDim] - positionInCache[iDim]);
921 }
922 return this->_blockData->get(latticePosition.data()) + norm(extraDistance);
923}
924
925template <typename T, typename S, bool PARTICLE>
927{
928 return this->_blockData->get(input) < std::numeric_limits<T>::epsilon();
929}
930
931template <typename T, typename S, bool PARTICLE>
933{
934 PhysR<T,3> pos(input[0], input[1], input[2]);
935 if constexpr(!PARTICLE) {
936 if(norm(this->getPos() - pos) > this->_circumRadius) {
937 output[0] = T{0};
938 return false;
939 }
940 pos = util::executeRotation<S,3,true>(pos, this->_rotMat, this->getPos());
941 }
942 if(norm(pos) < this->_circumRadius) {
944 }
945 output[0] = T{0};
946 return false;
947}
948
949//Factored-Indicator for spherical boundary layer:
950template <typename T, typename S, bool PARTICLE>
952 : _radius(radius), _factor(factor)
953{
954 this->_epsilon = epsilon;
955 if constexpr (!PARTICLE) {
956 this->_pos = center;
957 }
958
959 this->_circumRadius = radius + 0.5*epsilon;
960 if constexpr (!PARTICLE) {
961 this->_myMin = {center[0] - this->getCircumRadius(), center[1] - this->getCircumRadius(), center[2] - this->getCircumRadius()};
962 this->_myMax = {center[0] + this->getCircumRadius(), center[1] + this->getCircumRadius(), center[2] + this->getCircumRadius()};
963 this->init();
964 }
965}
966
967template <typename T, typename S, bool PARTICLE>
969{
970 T mass = 4/3*M_PI*_radius*_radius*_radius*density;
971 Vector<S,3> mofi;
972 mofi[0] = 2./5.*mass*_radius*_radius;
973 mofi[1] = 2./5.*mass*_radius*_radius;
974 mofi[2] = 2./5.*mass*_radius*_radius;
975 return Vector<S,4>(mofi[0], mofi[1], mofi[2], mass);
976}
977
978// returns true if x is inside the sphere
979template <typename T, typename S, bool PARTICLE>
981{
982 double distToCenter2 = util::pow(this->getPos()[0]-input[0], 2) +
983 util::pow(this->getPos()[1]-input[1], 2) +
984 util::pow(this->getPos()[2]-input[2], 2);
985 /*double d = util::sqrt(distToCenter2) - this->_radius + this->getEpsilon()/2;
986
987 if(d <= 0){
988 output[0] = T(this->_factor);
989 return true;
990 }
991 else if(d > 0 && d <= this->getEpsilon()){
992 output[0] = T(- this->_factor*(d-this->getEpsilon())/this->getEpsilon());
993 return true;
994 }
995 else{
996 output[0] = 0;
997 return false;
998 }*/
999
1000 double d = util::sqrt(distToCenter2) - this->_radius;
1001 output[0] = T(this->_factor*(1.-tanh(d/this->getEpsilon()))/2.);
1002 return true;
1003}
1004
1005} // namespace olb
1006
1007#endif
#define M_PI
indicator function for a 3d frustum
indicator function for a 3d-cuboid, parallel to the planes x=0, y=0, z=0.
S const getxLength() const
indicator function for a 3d-cylinder
indicator function for an ellipsoid
IndicatorF3D is an application from .
virtual Vector< S, 3 > & getMax()
virtual Vector< S, 3 > & getMin()
virtual S signedDistance(const Vector< S, 3 > &input)
Returns signed distance to the nearest point on the indicator surface.
indicator function for a 3D-sphere
indicator function for a super ellipsoid
class for marking output with some text
implements a smooth particle cone in 3D with an _epsilon sector
const S signedDistance(const PhysR< S, 3 > input) override
SmoothIndicatorCone3D(IndicatorCone3D< S > &indPtr, S epsilon, Vector< S, 3 > theta=Vector< S, 3 >(0., 0., 0.))
IndicatorCone3D< S > & getIndicator()
Vector< S, 4 > calcMofiAndMass(const S density) override
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
Vector< S, 3 > calcCenterOfMass() override
implements a smooth particle cuboid in 3D with an _epsilon sector.
Vector< S, 4 > calcMofiAndMass(const S density) override
SmoothIndicatorCuboid3D(IndicatorCuboid3D< S > &ind, S epsilon, Vector< S, 3 > theta=Vector< S, 3 >(0., 0., 0.))
const S signedDistance(const PhysR< S, 3 > input) override
IndicatorCuboid3D< S > & getIndicator()
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
SmoothIndicatorCustom3D(T latticeSpacing, std::shared_ptr< IndicatorF3D< T > > indPtr, Vector< T, 3 > pos, T epsilon, Vector< T, 3 > theta=Vector< T, 3 >(0.))
const S signedDistance(const PhysR< S, 3 > input) override
bool operator()(T output[], const S input[]) override
Vector< T, 4 > calcMofiAndMass(T rhoP) override
implements a smooth particle cylinder in 3D with an _epsilon sector.
const S signedDistance(const PhysR< S, 3 > input) override
SmoothIndicatorCylinder3D(IndicatorCylinder3D< S > &ind, S epsilon, Vector< S, 3 > theta=Vector< S, 3 >(0., 0., 0.))
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
Vector< S, 4 > calcMofiAndMass(const S density) override
IndicatorCylinder3D< S > & getIndicator()
implements a smooth particle ellipsoid in 3D with an _epsilon sector.
Vector< S, 4 > calcMofiAndMass(const S density) override
const S signedDistance(const PhysR< S, 3 > input) override
IndicatorEllipsoid3D< S > & getIndicator()
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
bool operator()(T output[], const S input[]) override
SmoothIndicatorEllipsoid3D(IndicatorEllipsoid3D< S > &ind, S epsilon, Vector< S, 3 > theta=Vector< S, 3 >(0., 0., 0.))
SmoothIndicatorFactoredCircle3D(Vector< S, 3 > center, S radius, S epsilon, S density=0, Vector< S, 3 > vel=Vector< S, 3 >(0., 0., 0.), S omega=0, S factor=1.)
bool operator()(T output[], const S input[]) override
Vector< S, 4 > calcMofiAndMass(const S density) override
implements a smooth sphere in 3D with an _epsilon sector
SmoothIndicatorSphere3D(IndicatorSphere3D< S > &ind, S epsilon)
const S signedDistance(const PhysR< S, 3 > input) override
IndicatorSphere3D< S > & getIndicator()
Vector< S, 4 > calcMofiAndMass(const S density) override
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
implements a smooth particle super-ellipsoid in 3D. The epsilon sector is currently missing.
SmoothIndicatorSuperEllipsoid3D(IndicatorSuperEllipsoid3D< S > &ind, S epsilon, Vector< S, 3 > theta=Vector< S, 3 >(0., 0., 0.))
const S signedDistance(const PhysR< S, 3 > input) override
IndicatorSuperEllipsoid3D< S > & getIndicator()
Vector< S, 3 > surfaceNormal(const Vector< S, 3 > &pos, const S meshSize) override
bool operator()(T output[], const S input[]) override
Vector< S, 4 > calcMofiAndMass(const S density) override
Plain old scalar vector.
Definition vector.h:47
constexpr const T * data() const any_platform
Definition vector.h:161
Pack< T > min(Pack< T > rhs, Pack< T > lhs)
Definition 256.h:406
Pack< T > max(Pack< T > rhs, Pack< T > lhs)
Definition 256.h:416
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
ADf< T, DIM > abs(const ADf< T, DIM > &a)
Definition aDiff.h:1019
ADf< T, DIM > ceil(const ADf< T, DIM > &a)
Definition aDiff.h:900
cpu::simd::Pack< T > min(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:124
ADf< T, DIM > round(const ADf< T, DIM > &a)
Definition aDiff.h:928
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
decltype(Vector< decltype(util::sqrt(T())), D >()) degreeToRadian(const Vector< T, D > &angle)
cpu::simd::Pack< T > pow(cpu::simd::Pack< T > base, cpu::simd::Pack< T > exp)
Definition pack.h:112
Top level namespace for all of OpenLB.
typename util::BaseTypeHelper< T >::type BaseType
Definition baseType.h:59
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
constexpr Vector< T, D > normalize(const ScalarVector< T, D, IMPL > &a, T scale=T{1})
Definition vector.h:245