OpenLB 1.8.1
Loading...
Searching...
No Matches
frameChangeF3D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2013, 2015 Gilles Zahnd, Mathias J. Krause
4 * Marie-Luise Maier
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23*/
24
25#ifndef FRAME_CHANGE_F_3D_HH
26#define FRAME_CHANGE_F_3D_HH
27
28#include<cmath>
29#include <random>
30
31#include "frameChangeF3D.h"
32#include "frameChangeF2D.h"
33#include "core/superLattice.h"
34#include "dynamics/lbm.h" // for computation of lattice rho and velocity
35#include "utilities/vectorHelpers.h" // for normalize
37
38#ifndef M_PI
39#define M_PI 3.14159265358979323846
40#endif
41
42namespace olb {
43
44
45template <typename T>
46RotatingLinear3D<T>::RotatingLinear3D(std::vector<T> axisPoint_,
47 std::vector<T> axisDirection_, T w_, T scale_)
48 : AnalyticalF3D<T,T>(3), axisPoint(axisPoint_), axisDirection(axisDirection_),
49 w(w_), scale(scale_) { }
50
51
52template <typename T>
53bool RotatingLinear3D<T>::operator()(T output[], const T x[])
54{
55 output[0] = (axisDirection[1]*(x[2]-axisPoint[2]) - axisDirection[2]*(x[1]-axisPoint[1]))*w*scale;
56 output[1] = (axisDirection[2]*(x[0]-axisPoint[0]) - axisDirection[0]*(x[2]-axisPoint[2]))*w*scale;
57 output[2] = (axisDirection[0]*(x[1]-axisPoint[1]) - axisDirection[1]*(x[0]-axisPoint[0]))*w*scale;
58 return true;
59}
60
61
62
63template <typename T>
65 std::vector<T> axisDirection_, T w_, T ri_, T ro_, T scale_)
66 : AnalyticalF3D<T,T>(3), axisPoint(axisPoint_), axisDirection(axisDirection_),
67 w(w_), ri(ri_), ro(ro_), scale(scale_) { }
68
69
70template <typename T>
71bool RotatingLinearAnnulus3D<T>::operator()(T output[], const T x[])
72{
73
74 if ( (util::sqrt((x[0]-axisPoint[0])*(x[0]-axisPoint[0])+(x[1]-axisPoint[1])*(x[1]-axisPoint[1])) < ri) || (util::sqrt((x[0]-axisPoint[0])*(x[0]-axisPoint[0])+(x[1]-axisPoint[1])*(x[1]-axisPoint[1])) >= ro) ) {
75 output[0] = 0.;
76 output[1] = 0.;
77 output[2] = 0.;
78 }
79 else {
80 T L[3];
81 T si[3];
82 T so[3];
83 int sign1 = 1;
84 int sign2 = 1;
85 if ( (axisDirection[2] && (x[0] == axisPoint[0])) || (axisDirection[1] && (x[2] == axisPoint[2])) || (axisDirection[0] && (x[1] == axisPoint[1])) ) {
86 int sign = 1;
87 if ( (axisDirection[2] && (x[1] < axisPoint[1])) || (axisDirection[1] && (x[0] < axisPoint[0])) || (axisDirection[0] && (x[2] < axisPoint[2])) ) {
88 sign = -1;
89 }
90 //Compute point of intersection between the inner cylinder and the line between axisPoint and x
91 si[0] = axisDirection[0]*x[0] + axisDirection[1]*(axisPoint[0]+sign*ri) + axisDirection[2]*x[0];
92 si[1] = axisDirection[0]*x[1] + axisDirection[1]*x[1] + axisDirection[2]*(axisPoint[1]+sign*ri);
93 si[2] = axisDirection[0]*(axisPoint[2]+sign*ri) + axisDirection[1]*x[2] + axisDirection[2]*x[2];
94 //Compute point of intersection between the outer cylinder and the line between axisPoint and x
95 so[0] = axisDirection[0]*x[0] + axisDirection[1]*(axisPoint[0]+sign*ro) + axisDirection[2]*x[0];
96 so[1] = axisDirection[0]*x[1] + axisDirection[1]*x[1] + axisDirection[2]*(axisPoint[1]+sign*ro);
97 so[2] = axisDirection[0]*(axisPoint[2]+sign*ro) + axisDirection[1]*x[2] + axisDirection[2]*x[2];
98 }
99 else {
100 T alpha;
101 //which quadrant
102 if ( (axisDirection[2] && (x[0] < axisPoint[0])) || (axisDirection[1] && (x[2] < axisPoint[2])) || (axisDirection[0] && (x[1] < axisPoint[1])) ) {
103 sign1 = -1;
104 }
105 if ( (axisDirection[2] && (x[1] < axisPoint[1])) || (axisDirection[1] && (x[0] < axisPoint[0])) || (axisDirection[0] && (x[2] < axisPoint[2])) ) {
106 sign2 = -1;
107 }
108 alpha = util::atan( ( sign2*(axisDirection[0]*(x[2]-axisPoint[2]) + axisDirection[1]*(x[0]-axisPoint[0]) + axisDirection[2]*(x[1]-axisPoint[1]) ) ) / \
109 (sign1*(axisDirection[0]*(x[1]-axisPoint[1]) + axisDirection[1]*(x[2]-axisPoint[2]) + axisDirection[2]*(x[0]-axisPoint[0]))) );
110 si[0] = axisDirection[0]*x[0] + axisDirection[1]*sign2*util::sin(alpha)*ri + axisDirection[2]*sign1*util::cos(alpha)*ri;
111 si[1] = axisDirection[0]*sign1*util::cos(alpha)*ri + axisDirection[1]*x[1] + axisDirection[2]*sign2*util::sin(alpha)*ri;
112 si[2] = axisDirection[0]*sign2*util::sin(alpha)*ri + axisDirection[1]*sign1*util::cos(alpha)*ri + axisDirection[2]*x[2];
113 so[0] = axisDirection[0]*x[0] + axisDirection[1]*sign2*util::sin(alpha)*ro + axisDirection[2]*sign1*util::cos(alpha)*ro;
114 so[1] = axisDirection[0]*sign1*util::cos(alpha)*ro + axisDirection[1]*x[1] + axisDirection[2]*sign2*util::sin(alpha)*ro;
115 so[2] = axisDirection[0]*sign2*util::sin(alpha)*ro + axisDirection[1]*sign1*util::cos(alpha)*ro + axisDirection[2]*x[2];
116 }
117
118 //Compute difference of intersections in all directions
119 L[0] = so[0]-si[0];
120 L[1] = so[1]-si[1];
121 L[2] = so[2]-si[2];
122 bool b0 = (L[0] == 0.);
123 bool b1 = (L[1] == 0.);
124 bool b2 = (L[2] == 0.);
125
126 output[0] = ((axisDirection[1]*(axisPoint[2]-si[2]) - axisDirection[2]*(axisPoint[1]-si[1])) *
127 (1 - (axisDirection[1]*(x[2]-si[2])/(L[2]+b2) + axisDirection[2]*(x[1]-si[1])/(L[1]+b1))) )*w*scale;
128 output[1] = ((axisDirection[2]*(axisPoint[0]-si[0]) - axisDirection[0]*(axisPoint[2]-si[2])) *
129 (1 - (axisDirection[2]*(x[0]-si[0])/(L[0]+b0) + axisDirection[0]*(x[2]-si[2])/(L[2]+b2))) )*w*scale;
130 output[2] = ((axisDirection[0]*(axisPoint[1]-si[1]) - axisDirection[1]*(axisPoint[0]-si[0])) *
131 (1 - (axisDirection[0]*(x[1]-si[1])/(L[1]+b1) + axisDirection[1]*(x[0]-si[0])/(L[0]+b0))) )*w*scale;
132
133 }
134 return true;
135}
136
137template <typename T>
139 std::vector<T> axisDirection_, T w_, T scale_, T additive_)
140 : AnalyticalF3D<T,T>(1), w(w_), scale(scale_), additive(additive_)
141{
142 axisPoint.resize(3);
143 axisDirection.resize(3);
144 for (int i = 0; i < 3; ++i) {
145 axisPoint[i] = axisPoint_[i];
146 axisDirection[i] = axisDirection_[i];
147 }
148}
149
150
151template <typename T>
152bool RotatingQuadratic1D<T>::operator()(T output[], const T x[])
153{
154 T radiusSquared = ((x[1]-axisPoint[1])*(x[1]-axisPoint[1])
155 +(x[2]-axisPoint[2])*(x[2]-axisPoint[2]))*axisDirection[0]
156 + ((x[0]-axisPoint[0])*(x[0]-axisPoint[0])
157 +(x[2]-axisPoint[2])*(x[2]-axisPoint[2]))*axisDirection[1]
158 + ((x[1]-axisPoint[1])*(x[1]-axisPoint[1])
159 +(x[0]-axisPoint[0])*(x[0]-axisPoint[0]))*axisDirection[2];
160 output[0] = scale*w*w/2*radiusSquared+additive;
161 return true;
162}
163
164
165template <typename T>
167 T maxVelocity, T radius, T n, T scale)
168 : AnalyticalF3D<T,T>(3), _center(center), _normal(util::normalize(normal)),
169 _radius(radius), _maxVelocity(maxVelocity), _n(n), _scale(scale) { }
170
171template <typename T>
172CirclePowerLaw3D<T>::CirclePowerLaw3D(T center0, T center1, T center2, T normal0, T normal1, T normal2, T radius, T maxVelocity, T n, T scale )
173 : AnalyticalF3D<T,T>(3), _radius(radius), _maxVelocity(maxVelocity), _n(n), _scale(scale)
174{
175// _center.push_back(center0);
176 _center[0] = center0;
177 _center[1] = center1;
178 _center[2] = center2;
179 std::vector<T> normalTmp;
180 normalTmp.push_back(normal0);
181 normalTmp.push_back(normal1);
182 normalTmp.push_back(normal2 );
183 _normal = normalTmp;
184}
185
186template <typename T>
188 int material, T maxVelocity, T n, T distance2Wall, T scale)
189 : AnalyticalF3D<T,T>(3), _maxVelocity(maxVelocity), _n(n), _scale(scale)
190{
191 _center = superGeometry.getStatistics().getCenterPhysR(material);
192 std::vector<T> normalTmp;
193 normalTmp.push_back(superGeometry.getStatistics().computeDiscreteNormal(material)[0]);
194 normalTmp.push_back(superGeometry.getStatistics().computeDiscreteNormal(material)[1]);
195 normalTmp.push_back(superGeometry.getStatistics().computeDiscreteNormal(material)[2]);
196 _normal = util::normalize(normalTmp);
197
198 // div. by 2 since one of the discrete redius directions is always 0 while the two other are not
199 _radius = T(distance2Wall);
200 for (int iD = 0; iD < 3; iD++) {
201 _radius += superGeometry.getStatistics().getPhysRadius(material)[iD]/2.;
202 }
203}
204
205template <typename T>
206CirclePowerLaw3D<T>::CirclePowerLaw3D(bool useMeanVelocity, std::vector<T> axisPoint, std::vector<T> axisDirection, T Velocity, T radius, T n, T scale)
207 : CirclePowerLaw3D<T>(axisPoint, axisDirection, Velocity, radius, n, scale)
208{
209 if (useMeanVelocity) {
210 _maxVelocity = (2. + (1. + n)/n)/((1. + n)/n * util::pow(1.,(2. + (1. + n)/n))) * Velocity;
211 }
212}
213
214template <typename T>
215CirclePowerLaw3D<T>::CirclePowerLaw3D(bool useMeanVelocity, T center0, T center1, T center2, T normal0, T normal1, T normal2, T radius, T Velocity, T n, T scale)
216 : CirclePowerLaw3D<T>(center0, center1, center2, normal0, normal1, normal2, radius, Velocity, n, scale)
217{
218 if (useMeanVelocity) {
219 _maxVelocity = (2. + (1. + n)/n)/((1. + n)/n * util::pow(1.,(2. + (1. + n)/n))) * Velocity;
220 }
221}
222
223template <typename T>
224CirclePowerLaw3D<T>::CirclePowerLaw3D(bool useMeanVelocity, SuperGeometry<T,3>& superGeometry, int material, T Velocity, T n, T distance2Wall, T scale)
225 : CirclePowerLaw3D<T>(superGeometry, material, Velocity, n, distance2Wall, scale)
226{
227 if (useMeanVelocity) {
228 _maxVelocity = (2. + (1. + n)/n)/((1. + n)/n * util::pow(1.,(2. + (1. + n)/n))) * Velocity;
229 }
230}
231
232template <typename T>
233bool CirclePowerLaw3D<T>::operator()(T output[], const T x[])
234{
235 output[0] = _scale*_maxVelocity*_normal[0]*(1.-util::pow(util::sqrt((x[1]-_center[1])*(x[1]-_center[1])+(x[2]-_center[2])*(x[2]-_center[2]))/_radius, (_n + 1.)/_n));
236 output[1] = _scale*_maxVelocity*_normal[1]*(1.-util::pow(util::sqrt((x[0]-_center[0])*(x[0]-_center[0])+(x[2]-_center[2])*(x[2]-_center[2]))/_radius, (_n + 1.)/_n));
237 output[2] = _scale*_maxVelocity*_normal[2]*(1.-util::pow(util::sqrt((x[1]-_center[1])*(x[1]-_center[1])+(x[0]-_center[0])*(x[0]-_center[0]))/_radius, (_n + 1.)/_n));
238 return true;
239}
240
241template <typename T>
242CirclePowerLawTurbulent3D<T>::CirclePowerLawTurbulent3D(std::vector<T> center, std::vector<T> normal,
243 T maxVelocity, T radius, T n, T turbulenceIntensity, T scale)
244 : CirclePowerLaw3D<T>(center, normal, maxVelocity, radius, n, scale), _turbulenceIntensity(turbulenceIntensity), _generator(_rd()), _dist(0.0, 1.0) { }
245
246template <typename T>
247CirclePowerLawTurbulent3D<T>::CirclePowerLawTurbulent3D(T center0, T center1, T center2, T normal0,
248 T normal1, T normal2, T radius, T maxVelocity, T n, T turbulenceIntensity, T scale)
249 : CirclePowerLaw3D<T>(center0, center1, center2, normal0, normal1, normal2, radius, maxVelocity, n, scale), _turbulenceIntensity(turbulenceIntensity), _generator(_rd()), _dist(0.0, 1.0) { }
250
251template <typename T>
253 int material, T maxVelocity, T distance2Wall, T n, T turbulenceIntensity, T scale)
254 : CirclePowerLaw3D<T>(superGeometry, material, maxVelocity, n, distance2Wall, scale), _turbulenceIntensity(turbulenceIntensity), _generator(_rd()), _dist(0.0, 1.0) { }
255
256template <typename T>
257CirclePowerLawTurbulent3D<T>::CirclePowerLawTurbulent3D(bool useMeanVelocity, std::vector<T> axisPoint, std::vector<T> axisDirection, T Velocity, T radius, T n, T turbulenceIntensity, T scale)
258 : CirclePowerLawTurbulent3D(axisPoint, axisDirection, Velocity, radius, n, turbulenceIntensity, scale)
259{
260 if (useMeanVelocity) {
261 this->_maxVelocity = ((1. + 1./n) * (2. + 1./n)) / 2. * Velocity;
262 }
263}
264template <typename T>
265CirclePowerLawTurbulent3D<T>::CirclePowerLawTurbulent3D(bool useMeanVelocity, T center0, T center1, T center2, T normal0, T normal1, T normal2, T radius, T Velocity, T n, T turbulenceIntensity, T scale)
266 : CirclePowerLawTurbulent3D(center0, center1, center2, normal0, normal1, normal2, radius, Velocity, n, turbulenceIntensity, scale)
267{
268 if (useMeanVelocity) {
269 this->_maxVelocity = ((1. + 1./n) * (2. + 1./n)) / 2. * Velocity;
270 }
271}
272
273template <typename T>
274CirclePowerLawTurbulent3D<T>::CirclePowerLawTurbulent3D(bool useMeanVelocity, SuperGeometry<T,3>& superGeometry, int material, T Velocity, T distance2Wall, T n, T turbulenceIntensity, T scale)
275 : CirclePowerLawTurbulent3D(superGeometry, material, Velocity, n, turbulenceIntensity, distance2Wall, scale)
276{
277 if (useMeanVelocity) {
278 this->_maxVelocity = ((1. + 1./n) * (2. + 1./n)) / 2. * Velocity;
279 }
280}
281
282template <typename T>
283bool CirclePowerLawTurbulent3D<T>::operator()(T output[], const T x[])
284{
285 T meanVelocity = this->_maxVelocity * 2.0 / ((1. + 1./this->_n) * (2. + 1./this->_n));
286
287 if ( 1.-util::sqrt((x[1]-this->_center[1])*(x[1]-this->_center[1])+(x[2]-this->_center[2])*(x[2]-this->_center[2]))/this->_radius < 0.) {
288 output[0] = T();
289 }
290 else {
291 output[0] = this->_scale*this->_maxVelocity*this->_normal[0]*
292 (util::pow(1.-util::sqrt((x[1]-this->_center[1])*(x[1]-this->_center[1])+(x[2]-this->_center[2])*(x[2]-this->_center[2]))/this->_radius, 1./this->_n));
293 output[0] += _dist(_generator) * _turbulenceIntensity * meanVelocity;
294 }
295 if ( 1.-util::sqrt((x[0]-this->_center[0])*(x[0]-this->_center[0])+(x[2]-this->_center[2])*(x[2]-this->_center[2]))/this->_radius < 0.) {
296 output[1] = T();
297 }
298 else {
299 output[1] = this->_scale*this->_maxVelocity*this->_normal[1]*
300 (util::pow(1.-util::sqrt((x[0]-this->_center[0])*(x[0]-this->_center[0])+(x[2]-this->_center[2])*(x[2]-this->_center[2]))/this->_radius, 1./this->_n));
301 output[1] += _dist(_generator) * _turbulenceIntensity * meanVelocity;
302 }
303 if ( 1.-util::sqrt((x[1]-this->_center[1])*(x[1]-this->_center[1])+(x[0]-this->_center[0])*(x[0]-this->_center[0]))/this->_radius < 0.) {
304 output[2] = T();
305 }
306 else {
307 output[2] = this->_scale*this->_maxVelocity*this->_normal[2]*
308 (util::pow(1.-util::sqrt((x[1]-this->_center[1])*(x[1]-this->_center[1])+(x[0]-this->_center[0])*(x[0]-this->_center[0]))/this->_radius, 1./this->_n));
309 output[2] += _dist(_generator) * _turbulenceIntensity * meanVelocity;
310 }
311
312 return true;
313}
314
315template <typename T>
317 T radius, T cassonViscosity, T pressureDrop, T yieldStress, T scale)
318 : AnalyticalF3D<T,T>(3), _center(center), _normal(util::normalize(normal)),
319 _radius(radius), _cassonViscosity(cassonViscosity), _pressureDrop(pressureDrop), _yieldStress(yieldStress), _scale(scale) { }
320
321template <typename T>
322bool CircleCasson3D<T>::operator()(T output[], const T x[])
323{
324 T r_c = _yieldStress / (_pressureDrop / 2.);
325 T r[3];
326 r[0] = util::sqrt((x[1]-_center[1])*(x[1]-_center[1])+(x[2]-_center[2])*(x[2]-_center[2]));
327 r[1] = util::sqrt((x[0]-_center[0])*(x[0]-_center[0])+(x[2]-_center[2])*(x[2]-_center[2]));
328 r[2] = util::sqrt((x[1]-_center[1])*(x[1]-_center[1])+(x[0]-_center[0])*(x[0]-_center[0]));
329
330 T preFac = 1. / _cassonViscosity;
331 for (std::size_t d = 0; d < 3; ++d) {
332 if (r[d] < r_c) {
333 r[d] = r_c;
334 }
335 output[d] =_scale * _normal[d] * preFac * ((_radius*_radius - r[d]*r[d])*_pressureDrop / 4.0 +
336 _yieldStress * (_radius - util::abs(r[d])) - (4.0 / (3.0*util::sqrt(2.0))) * util::sqrt(_pressureDrop*_yieldStress) * (util::sqrt(util::pow(_radius, 3.0))
337 - util::sqrt(util::pow(util::abs(r[d]), 3.0))));
338 }
339 return true;
340}
341
342template <typename T>
343CirclePoiseuille3D<T>::CirclePoiseuille3D(std::vector<T> center, std::vector<T> normal,
344 T maxVelocity, T radius, T scale)
345 : CirclePowerLaw3D<T>(center, normal, maxVelocity, radius, 1., scale) { }
346
347template <typename T>
348CirclePoiseuille3D<T>::CirclePoiseuille3D(T center0, T center1, T center2, T normal0,
349 T normal1, T normal2, T radius, T maxVelocity, T scale)
350 : CirclePowerLaw3D<T>(center0, center1, center2, normal0, normal1, normal2, radius, maxVelocity, 1., scale) { }
351
352template <typename T>
354 int material, T maxVelocity, T distance2Wall, T scale)
355 : CirclePowerLaw3D<T>(superGeometry, material, maxVelocity, 1., distance2Wall, scale) { }
356
357template <typename T>
358CirclePoiseuille3D<T>::CirclePoiseuille3D(bool useMeanVelocity, std::vector<T> axisPoint, std::vector<T> axisDirection, T Velocity, T radius, T scale)
359 : CirclePoiseuille3D(axisPoint, axisDirection, Velocity, radius, scale)
360{
361 if (useMeanVelocity) {
362 this->_maxVelocity = 2. * Velocity;
363 }
364}
365
366template <typename T>
367CirclePoiseuille3D<T>::CirclePoiseuille3D(bool useMeanVelocity, T center0, T center1, T center2, T normal0, T normal1, T normal2, T radius, T Velocity, T scale)
368 : CirclePoiseuille3D(center0, center1, center2, normal0, normal1, normal2, radius, Velocity, scale)
369{
370 if (useMeanVelocity) {
371 this->_maxVelocity = 2. * Velocity;
372 }
373}
374
375template <typename T>
376CirclePoiseuille3D<T>::CirclePoiseuille3D(bool useMeanVelocity, SuperGeometry<T,3>& superGeometry, int material, T Velocity, T distance2Wall, T scale)
377 : CirclePoiseuille3D(superGeometry, material, Velocity, distance2Wall, scale)
378{
379 if (useMeanVelocity) {
380 this->_maxVelocity = 2. * Velocity;
381 }
382}
383
384template < typename T,typename DESCRIPTOR>
386{
387 lengthY = ly;
388 lengthZ = ly;
389 maxVelocity = converter.getCharPhysVelocity();
390 this->getName() = "CirclePoiseuilleStrainRate3D";
391}
392
393
394template < typename T,typename DESCRIPTOR>
396{
397 T y = input[1];
398 T z = input[2];
399
400 T DuDx = T();
401 T DuDy = (T) maxVelocity*(-2.*(y-(lengthY))/((lengthY)*(lengthY)));
402 T DuDz = (T) maxVelocity*(-2.*(z-(lengthZ))/((lengthZ)*(lengthZ)));
403 T DvDx = T();
404 T DvDy = T();
405 T DvDz = T();
406 T DwDx = T();
407 T DwDy = T();
408 T DwDz = T();
409
410 output[0] = (DuDx + DuDx)/2.;
411 output[1] = (DuDy + DvDx)/2.;
412 output[2] = (DuDz + DwDx)/2.;
413 output[3] = (DvDx + DuDy)/2.;
414 output[4] = (DvDy + DvDy)/2.;
415 output[5] = (DvDz + DwDy)/2.;
416 output[6] = (DwDx + DuDz)/2.;
417 output[7] = (DwDy + DvDz)/2.;
418 output[8] = (DwDz + DwDz)/2.;
419
420 return true;
421};
422
423
424
425
426template <typename T>
428 olb::Vector<T, 3>& x2_, std::vector<T>& maxVelocity_)
429 : AnalyticalF3D<T,T>(3), clout(std::cout,"RectanglePoiseille3D"), x0(x0_), x1(x1_),
430 x2(x2_), maxVelocity(maxVelocity_) { }
431
432
433template <typename T>
435 int material_, std::vector<T>& maxVelocity_, T offsetX, T offsetY, T offsetZ)
436 : AnalyticalF3D<T,T>(3), clout(std::cout, "RectanglePoiseuille3D"), maxVelocity(maxVelocity_)
437{
438 olb::Vector<T, 3> min = superGeometry_.getStatistics().getMinPhysR(material_);
439 olb::Vector<T, 3> max = superGeometry_.getStatistics().getMaxPhysR(material_);
440 // set three corners of the plane, move by offset to land on the v=0
441 // boundary and adapt certain values depending on the orthogonal axis to get
442 // different points
443 x0 = min;
444 x1 = min;
445 x2 = min;
446 if ( util::nearZero(max[0]-min[0]) ) { // orthogonal to x-axis
447 x0[1] -= offsetY;
448 x0[2] -= offsetZ;
449 x1[1] -= offsetY;
450 x1[2] -= offsetZ;
451 x2[1] -= offsetY;
452 x2[2] -= offsetZ;
453
454 x1[1] = max[1] + offsetY;
455 x2[2] = max[2] + offsetZ;
456 }
457 else if ( util::nearZero(max[1]-min[1]) ) { // orthogonal to y-axis
458 x0[0] -= offsetX;
459 x0[2] -= offsetZ;
460 x1[0] -= offsetX;
461 x1[2] -= offsetZ;
462 x2[0] -= offsetX;
463 x2[2] -= offsetZ;
464
465 x1[0] = max[0] + offsetX;
466 x2[2] = max[2] + offsetZ;
467 }
468 else if ( util::nearZero(max[2]-min[2]) ) { // orthogonal to z-axis
469 x0[0] -= offsetX;
470 x0[1] -= offsetY;
471 x1[0] -= offsetX;
472 x1[1] -= offsetY;
473 x2[0] -= offsetX;
474 x2[1] -= offsetY;
475
476 x1[0] = max[0] + offsetX;
477 x2[1] = max[1] + offsetY;
478 }
479 else {
480 clout << "Error: constructor from material number works only for axis-orthogonal planes" << std::endl;
481 }
482}
483
484
485template <typename T>
486bool RectanglePoiseuille3D<T>::operator()(T output[], const T x[])
487{
488 std::vector<T> velocity(3,T());
489
490 // create plane normals and supports, (E1,E2) and (E3,E4) are parallel
491 std::vector<std::vector<T> > n(4,std::vector<T>(3,0)); // normal vectors
492 std::vector<std::vector<T> > s(4,std::vector<T>(3,0)); // support vectors
493 for (int iD = 0; iD < 3; iD++) {
494 n[0][iD] = x1[iD] - x0[iD];
495 n[1][iD] = -x1[iD] + x0[iD];
496 n[2][iD] = x2[iD] - x0[iD];
497 n[3][iD] = -x2[iD] + x0[iD];
498 s[0][iD] = x0[iD];
499 s[1][iD] = x1[iD];
500 s[2][iD] = x0[iD];
501 s[3][iD] = x2[iD];
502 }
503 for (int iP = 0; iP < 4; iP++) {
504 n[iP] = util::normalize(n[iP]);
505 }
506
507 // determine plane coefficients in the coordinate equation E_i: Ax+By+Cz+D=0
508 // given form: (x-s)*n=0 => A=n1, B=n2, C=n3, D=-(s1n1+s2n2+s3n3)
509 std::vector<T> A(4,0);
510 std::vector<T> B(4,0);
511 std::vector<T> C(4,0);
512 std::vector<T> D(4,0);
513
514 for (int iP = 0; iP < 4; iP++) {
515 A[iP] = n[iP][0];
516 B[iP] = n[iP][1];
517 C[iP] = n[iP][2];
518 D[iP] = -(s[iP][0]*n[iP][0] + s[iP][1]*n[iP][1] + s[iP][2]*n[iP][2]);
519 }
520
521 // determine distance to the walls by formula
522 std::vector<T> d(4,0);
523 T aabbcc(0);
524 for (int iP = 0; iP < 4; iP++) {
525 aabbcc = A[iP]*A[iP] + B[iP]*B[iP] + C[iP]*C[iP];
526 d[iP] = util::fabs(A[iP]*x[0]+B[iP]*x[1]+C[iP]*x[2]+D[iP])*util::pow(aabbcc,-0.5);
527 }
528
529 // length and width of the rectangle
530 std::vector<T> l(2,0);
531 l[0] = d[0] + d[1];
532 l[1] = d[2] + d[3];
533
534 T positionFactor = 16.*d[0]/l[0]*d[1]/l[0]*d[2]/l[1]*d[3]/l[1]; // between 0 and 1
535
536 output[0] = maxVelocity[0]*positionFactor;
537 output[1] = maxVelocity[1]*positionFactor;
538 output[2] = maxVelocity[2]*positionFactor;
539 return true;
540}
541
542//Trigonometric version TODO: to be unified( etc. plane calculation )
543template <typename T>
545 std::vector<T>& x2_, std::vector<T>& maxVelocity_, int numOfPolynoms_)
546 : AnalyticalF3D<T,T>(3), clout(std::cout,"RectangleTrigonometricPoiseille3D"), x0(x0_), x1(x1_),
547 x2(x2_), maxVelocity(maxVelocity_), numOfPolynoms(numOfPolynoms_)
548{
550}
551
552
553template <typename T>
555 int material_, std::vector<T>& maxVelocity_, T offsetX, T offsetY, T offsetZ, int numOfPolynoms_)
556 : AnalyticalF3D<T,T>(3), clout(std::cout, "RectangleTrigonometricPoiseuille3D"), maxVelocity(maxVelocity_),
557 numOfPolynoms(numOfPolynoms_)
558{
559 std::vector<T> min = superGeometry_.getStatistics().getMinPhysR(material_);
560 std::vector<T> max = superGeometry_.getStatistics().getMaxPhysR(material_);
561 // set three corners of the plane, move by offset to land on the v=0
562 // boundary and adapt certain values depending on the orthogonal axis to get
563 // different points
564 x0 = min;
565 x1 = min;
566 x2 = min;
567 if ( util::nearZero(max[0]-min[0]) ) { // orthogonal to x-axis
568 x0[1] -= offsetY;
569 x0[2] -= offsetZ;
570 x1[1] -= offsetY;
571 x1[2] -= offsetZ;
572 x2[1] -= offsetY;
573 x2[2] -= offsetZ;
574
575 x1[1] = max[1] + offsetY;
576 x2[2] = max[2] + offsetZ;
577 }
578 else if ( util::nearZero(max[1]-min[1]) ) { // orthogonal to y-axis
579 x0[0] -= offsetX;
580 x0[2] -= offsetZ;
581 x1[0] -= offsetX;
582 x1[2] -= offsetZ;
583 x2[0] -= offsetX;
584 x2[2] -= offsetZ;
585
586 x1[0] = max[0] + offsetX;
587 x2[2] = max[2] + offsetZ;
588 }
589 else if ( util::nearZero(max[2]-min[2]) ) { // orthogonal to z-axis
590 x0[0] -= offsetX;
591 x0[1] -= offsetY;
592 x1[0] -= offsetX;
593 x1[1] -= offsetY;
594 x2[0] -= offsetX;
595 x2[1] -= offsetY;
596
597 x1[0] = max[0] + offsetX;
598 x2[1] = max[1] + offsetY;
599 }
600 else {
601 clout << "Error: constructor from material number works only for axis-orthogonal planes" << std::endl;
602 }
604}
605
606
607template <typename T>
609{
610 //2006_Bruus_Lecture Theoretical microfluidics
611 T sumMax = 0;
612 T sumAvg = 0;
613 for (int i=1; i<=numOfPolynoms; ++i) { //TODO: higher polynoms still to be tested
614 T n = i*2-1; //Creating only odd indices
615 T A = util::sin(n*M_PI*0.5);
616 T max = (1./util::pow(n,3)) * (1.-(1 / util::cosh(n*M_PI / 2 ))) * A;
617 //TODO: only for y,z=1 //TODO: Maximum calculation needs to be adapted for different edge ratios
618 T avg = 2. * A * A * (n*M_PI-2*util::tanh(n*M_PI*0.5)) / (util::pow(n,5)*M_PI*M_PI);
619 sumMax += max;
620 sumAvg += avg;
621 }
622 profilePeak = sumMax;
623 profileRatioAvgToPeak = sumAvg / sumMax;
624}
625
626
627template <typename T>
629{
630 return profilePeak;
631}
632
633template <typename T>
635{
636 return profileRatioAvgToPeak;
637}
638
639template <typename T> //TODO: for now only works in x direction!
641{
642 OstreamManager clout( std::cout,"RectPois" ); //TODO: to be removed
643
644 // create plane normals and supports, (E1,E2) and (E3,E4) are parallel
645 std::vector<std::vector<T> > n(4,std::vector<T>(3,0)); // normal vectors
646 std::vector<std::vector<T> > s(4,std::vector<T>(3,0)); // support vectors
647 for (int iD = 0; iD < 3; iD++) {
648 n[0][iD] = x1[iD] - x0[iD];
649 n[1][iD] = -x1[iD] + x0[iD];
650 n[2][iD] = x2[iD] - x0[iD];
651 n[3][iD] = -x2[iD] + x0[iD];
652 s[0][iD] = x0[iD];
653 s[1][iD] = x1[iD];
654 s[2][iD] = x0[iD];
655 s[3][iD] = x2[iD];
656 }
657 for (int iP = 0; iP < 4; iP++) {
658 n[iP] = util::normalize(n[iP]);
659 }
660
661 // determine plane coefficients in the coordinate equation E_i: Ax+By+Cz+D=0
662 // given form: (x-s)*n=0 => A=n1, B=n2, C=n3, D=-(s1n1+s2n2+s3n3)
663 std::vector<T> A(4,0);
664 std::vector<T> B(4,0);
665 std::vector<T> C(4,0);
666 std::vector<T> D(4,0);
667
668 for (int iP = 0; iP < 4; iP++) {
669 A[iP] = n[iP][0];
670 B[iP] = n[iP][1];
671 C[iP] = n[iP][2];
672 D[iP] = -(s[iP][0]*n[iP][0] + s[iP][1]*n[iP][1] + s[iP][2]*n[iP][2]);
673 }
674
675 // determine distance to the walls by formula
676 std::vector<T> d(4,0);
677 T aabbcc(0);
678 for (int iP = 0; iP < 4; iP++) {
679 aabbcc = A[iP]*A[iP] + B[iP]*B[iP] + C[iP]*C[iP];
680 d[iP] = util::fabs(A[iP]*x[0]+B[iP]*x[1]+C[iP]*x[2]+D[iP])*util::pow(aabbcc,-0.5);
681 }
682
683 // length and width of the rectangle
684 std::vector<T> l(2,0);
685 l[0] = d[0] + d[1] ;
686 l[1] = d[2] + d[3] ;
687
688 std::vector<T> dl(2,0);
689 dl[0] = d[0] / l[0];
690 dl[1] = d[2] / l[1];
691
692 //Polynomial creation for odd indices (2i-i) from:
693 //2006_Bruus_Lecture Theoretical microfluidics
694 T sumPoly = 0;
695 for (int i=1; i<=numOfPolynoms; ++i) { //TODO: higher polynoms still to be tested
696 T n = i*2-1;
697 T poly = (1./util::pow(n,3)) * (1.-(util::cosh(n*M_PI*(dl[0]-0.5)) / util::cosh(n*M_PI/ (2) ))) * util::sin(n*M_PI*dl[1]);
698 sumPoly += poly;
699 }
700
701 output[0] = maxVelocity[0] * ( sumPoly / profilePeak);
702 output[1] = maxVelocity[1] * ( sumPoly / profilePeak);
703 output[2] = maxVelocity[2] * ( sumPoly / profilePeak);
704 return true;
705}
706
707
708template <typename T>
709EllipticPoiseuille3D<T>::EllipticPoiseuille3D(std::vector<T> center, T a, T b, T maxVel)
710 : AnalyticalF3D<T,T>(3), clout(std::cout, "EllipticPoiseuille3D"), _center(center),
711 _a2(a*a), _b2(b*b), _maxVel(maxVel) { }
712
713
714template <typename T>
715bool EllipticPoiseuille3D<T>::operator()(T output[], const T x[])
716{
717 T cosOmega2 = util::pow(x[0]-_center[0],2.)/(util::pow(x[0]-_center[0],2.)+util::pow(x[1]-_center[1],2.));
718 T rad2 = _a2*_b2 /((_b2-_a2)*cosOmega2 + _a2) ;
719 T x2 = (util::pow(x[0]-_center[0],2.)+util::pow(x[1]-_center[1],2.))/rad2;
720
721 // clout << _center[0] << " " << _center[1] << " " << x[0] << " " << x[1] << " " << util::sqrt(rad2) << " " << util::sqrt(util::pow(x[0]-_center[0],2.)+util::pow(x[1]-_center[1],2.)) << " " << x2 << std::endl;
722
723 output[0] = 0.;
724 output[1] = 0.;
725 output[2] = _maxVel*(-x2+1);
726 if ( util::nearZero(_center[0]-x[0]) && util::nearZero(_center[1]-x[1]) ) {
727 output[2] = _maxVel;
728 }
729 return true;
730}
731
732
733template <typename T>
734AnalyticalPorousVelocity3D<T>::AnalyticalPorousVelocity3D(SuperGeometry<T,3>& superGeometry, int material, T K_, T mu_, T gradP_, T radius_, T eps_)
735 : AnalyticalF3D<T,T>(3), K(K_), mu(mu_), gradP(gradP_), radius(radius_), eps(eps_)
736{
737 this->getName() = "AnalyticalPorousVelocity3D";
738
739 center = superGeometry.getStatistics().getCenterPhysR(material);
740 std::vector<T> normalTmp;
741 normalTmp.push_back(superGeometry.getStatistics().computeDiscreteNormal(material)[0]);
742 normalTmp.push_back(superGeometry.getStatistics().computeDiscreteNormal(material)[1]);
743 normalTmp.push_back(superGeometry.getStatistics().computeDiscreteNormal(material)[2]);
744 normal = util::normalize(normalTmp);
745
746};
747
748
749template <typename T>
751{
752 T uMax = K / mu*gradP*(1. - 1./(util::cosh((util::sqrt(1./K))*radius)));
753
754 return uMax/eps;
755};
756
757
758template <typename T>
759bool AnalyticalPorousVelocity3D<T>::operator()(T output[], const T x[])
760{
761 T dist[3] = {};
762 dist[0] = normal[0]*util::sqrt((x[1]-center[1])*(x[1]-center[1])+(x[2]-center[2])*(x[2]-center[2]));
763 dist[1] = normal[1]*util::sqrt((x[0]-center[0])*(x[0]-center[0])+(x[2]-center[2])*(x[2]-center[2]));
764 dist[2] = normal[2]*util::sqrt((x[1]-center[1])*(x[1]-center[1])+(x[0]-center[0])*(x[0]-center[0]));
765
766 output[0] = K / mu*gradP*(1. - (util::cosh((util::sqrt(1./K))*(dist[0])))/(util::cosh((util::sqrt(1./K))*radius)));
767 output[1] = K / mu*gradP*(1. - (util::cosh((util::sqrt(1./K))*(dist[1])))/(util::cosh((util::sqrt(1./K))*radius)));
768 output[2] = K / mu*gradP*(1. - (util::cosh((util::sqrt(1./K))*(dist[2])))/(util::cosh((util::sqrt(1./K))*radius)));
769
770 output[0] *= normal[0]/eps;
771 output[1] *= normal[1]/eps;
772 output[2] *= normal[2]/eps;
773
774 return true;
775};
776
777
778
780
781
782// constructor defines _referenceVector to obtain angle between 2 vectors,
783// vector x has to be turned by angle in mathematical positive sense depending
784// to _orientation to lie over _referenceVector
785template<typename T, typename S>
787 std::vector<T> referenceVector, std::vector<T> orientation)
788 : AnalyticalF3D<T, S>(1),
789 _referenceVector(referenceVector),
790 _orientation(orientation)
791{
792 this->getName() = "const";
793}
794
795// operator returns angle between vectors x and _referenceVector
796template<typename T, typename S>
797bool AngleBetweenVectors3D<T, S>::operator()(T output[], const S x[])
798{
799 Vector<T, 3> n_x;
800 Vector<T, 3> orientation(_orientation);
801 T angle = T(0);
802
803 if ( util::nearZero(x[0]) && util::nearZero(x[1]) && util::nearZero(x[2]) ) {
804 // if (util::abs(x[0]) + util::abs(x[1]) + util::abs(x[2]) == T()) {
805 output[0] = angle; // angle = 0
806 return true;
807 }
808 else {
809 //Vector<S, 3> x_tmp(x); // check construction
810 n_x[0] = x[0];
811 n_x[1] = x[1];
812 n_x[2] = x[2];
813 n_x = normalize(n_x);
814 }
815
816 Vector<T, 3> n_ref(_referenceVector);
817 n_ref = normalize(n_ref);
818 Vector<T, 3> cross = crossProduct3D(n_x, n_ref);
819 T n_dot = n_x * n_ref;
820
821
822 if ( util::nearZero(cross*orientation) ) {
823 // std::cout<< "orientation in same plane as x and refvector" << std::endl;
824 }
825 // angle = Pi, if n_x, n_ref opposite
826 if ( util::nearZero(n_x[0]+n_ref[0]) && util::nearZero(n_x[1]+n_ref[1]) && util::nearZero(n_x[2]+n_ref[2]) ) {
827 angle = util::acos(-1);
828 }
829 // angle = 0, if n_x, n_ref equal
830 else if ( util::nearZero(n_x[0]-n_ref[0]) && util::nearZero(n_x[1]-n_ref[1]) && util::nearZero(n_x[2]-n_ref[2]) ) {
831 angle = T();
832 }
833 // angle in (0,Pi) or (Pi,2Pi), if n_x, n_ref not opposite or equal
834 else {
835 Vector<T, 3> n_cross(cross);
836 n_cross = normalize(n_cross);
837 T normal = norm(cross);
838 Vector<T, 3> n_orient;
839
840 if ( !util::nearZero(norm(orientation)) ) {
841 n_orient = orientation;
842 n_orient = normalize(n_orient);
843 }
844 else {
845 std::cout << "orientation vector does not fit" << std::endl;
846 }
847 if ((cross * orientation) > T()) {
848 angle = 2*M_PI - util::atan2(normal, n_dot);
849 }
850 if ((cross * orientation) < T()) {
851 angle = util::atan2(normal, n_dot);
852 }
853 }
854 output[0] = angle;
855 return true;
856}
857
858
859// constructor to obtain rotation util::round an _rotAxisDirection with angle _alpha
860// and _origin
861template<typename T, typename S>
863 olb::Vector<T, 3> rotAxisDirection, T alpha)
864 : AnalyticalF3D<T, S>(3),
865 _origin(origin),
866 _rotAxisDirection(rotAxisDirection),
867 _alpha(alpha)
868{
869 this->getName() = "const";
870}
871
872// operator returns coordinates of the resulting point after rotation of x
873// with _alpha in math positive sense to _rotAxisDirection through _origin
874template<typename T, typename S>
875bool RotationRoundAxis3D<T, S>::operator()(T output[], const S x[])
876{
877 Vector<T, 3> n(_rotAxisDirection);
878 if ( !util::nearZero(norm(n)) && norm(n) > 0 ) {
879 //std::cout<< "Rotation axis: " << _rotAxisDirection[0] << " " << _rotAxisDirection[1] << " " << _rotAxisDirection[2] << std::endl;
880 n = normalize(n);
881 // translation
882 Vector<T, 3> x_tmp;
883 for (int i = 0; i < 3; ++i) {
884 x_tmp[i] = x[i] - _origin[i];
885 }
886 // rotation
887 output[0] = (n[0]*n[0]*(1 - util::cos(_alpha)) + util::cos(_alpha)) * x_tmp[0]
888 + (n[0]*n[1]*(1 - util::cos(_alpha)) - n[2]*util::sin(_alpha))*x_tmp[1]
889 + (n[0]*n[2]*(1 - util::cos(_alpha)) + n[1]*util::sin(_alpha))*x_tmp[2]
890 + _origin[0];
891
892 output[1] = (n[1]*n[0]*(1 - util::cos(_alpha)) + n[2]*util::sin(_alpha))*x_tmp[0]
893 + (n[1]*n[1]*(1 - util::cos(_alpha)) + util::cos(_alpha))*x_tmp[1]
894 + (n[1]*n[2]*(1 - util::cos(_alpha)) - n[0]*util::sin(_alpha))*x_tmp[2]
895 + _origin[1];
896
897 output[2] = (n[2]*n[0]*(1 - util::cos(_alpha)) - n[1]*util::sin(_alpha))*x_tmp[0]
898 + (n[2]*n[1]*(1 - util::cos(_alpha)) + n[0]*util::sin(_alpha))*x_tmp[1]
899 + (n[2]*n[2]*(1 - util::cos(_alpha)) + util::cos(_alpha))*x_tmp[2]
900 + _origin[2];
901 return true;
902 }
903 else {
904 //std::cout<< "Axis is null or NaN" <<std::endl;
905 for (int j=0; j<3; j++) {
906 output[j] = x[j];
907 }
908 return true;
909 }
910}
911
912
914
915
916// constructor to obtain Cartesian coordinates of cylindrical coordinates,
917// the z-axis direction equals the axis direction of the cylinder
918// with _cylinderOrigin
919template<typename T, typename S>
921 std::vector<T> cylinderOrigin)
922 : AnalyticalF3D<T, S>(3),
923 _cylinderOrigin(cylinderOrigin)
924{
925 this->getName() = "CylinderToCartesian3D";
926}
927
928// operator returns Cartesian coordinates of cylindrical coordinates,
929// input is x[0] = radius, x[1] = phi, x[2] = z
930template<typename T, typename S>
931bool CylinderToCartesian3D<T, S>::operator()(T output[], const S x[])
932{
933 PolarToCartesian2D<T, S> pol2cart(_cylinderOrigin);
934 pol2cart(output,x);
935 output[2] = x[2];
936 return true;
937}
938
939
940// constructor to obtain cylindrical coordinates of Cartesian coordinates
941template<typename T, typename S>
943 olb::Vector<T, 3> cartesianOrigin, T& angle, olb::Vector<T, 3> orientation)
944 : AnalyticalF3D<T, S>(3),
945 _cartesianOrigin(cartesianOrigin),
946 _orientation(orientation)
947{
948 // rotation with angle to (0,0,1)
949 std::vector<T> origin(3,T());
950 T e3[3]= {T(),T(),T()};
951 e3[2] = T(1);
952 RotationRoundAxis3D<T, S> rotRAxis(origin, orientation, angle);
953 T tmp[3] = {T(),T(),T()};
954 rotRAxis(tmp, e3);
955
956 std::vector<T> htmp(tmp,tmp+3);
957 _axisDirection = htmp;
958}
959
960// constructor to obtain cylindrical coordinates of Cartesian coordinates
961template<typename T, typename S>
963 olb::Vector<T, 3> cartesianOrigin, olb::Vector<T, 3> axisDirection,
964 olb::Vector<T, 3> orientation)
965 : AnalyticalF3D<T, S>(3),
966 _cartesianOrigin(cartesianOrigin),
967 _axisDirection(axisDirection),
968 _orientation(orientation)
969{
970 this->getName() = "const";
971}
972
973// constructor to obtain cylindrical coordinates of Cartesian coordinates
974template<typename T, typename S>
976 T cartesianOriginX, T cartesianOriginY, T cartesianOriginZ,
977 T axisDirectionX, T axisDirectionY, T axisDirectionZ,
978 T orientationX, T orientationY, T orientationZ)
979 : AnalyticalF3D<T, S>(3)
980{
981 _cartesianOrigin[0] = cartesianOriginX;
982 _cartesianOrigin[1] = cartesianOriginY;
983 _cartesianOrigin[2] = cartesianOriginZ;
984
985 _axisDirection[0] = axisDirectionX;
986 _axisDirection[1] = axisDirectionY;
987 _axisDirection[2] = axisDirectionZ;
988
989 _orientation[0] = orientationX;
990 _orientation[1] = orientationY;
991 _orientation[2] = orientationZ;
992}
993
994// operator returns cylindrical coordinates, output[0] = radius(>= 0),
995// output[1] = phi in [0, 2Pi), output[2] = z
996template<typename T, typename S>
997bool CartesianToCylinder3D<T, S>::operator()(T output[], const S x[])
998{
999 T x_rot[3] = {T(),T(),T()};
1000 x_rot[0] = x[0];
1001 x_rot[1] = x[1];
1002 x_rot[2] = x[2];
1003// T x_rot[3] = {x[0], x[1], x[2]};
1004 Vector<T, 3> e3(T(),T(), T(1));
1005 Vector<T, 3> axisDirection(_axisDirection);
1006 Vector<T, 3> orientation(_orientation);
1007
1008 Vector<T, 3> normal = crossProduct3D(axisDirection, e3);
1009 Vector<T, 3> normalAxisDir(axisDirection);
1010 normalAxisDir = normalize(normalAxisDir);
1011
1012 // if axis has to be rotated
1013 if (!( util::nearZero(normalAxisDir[0]) && util::nearZero(normalAxisDir[1]) && util::nearZero(normalAxisDir[2]-1) )) {
1014
1015 if ( !util::nearZero(norm(orientation)) ) {
1016 normal = orientation; // if _orientation = 0,0,0 -> segm. fault
1017 }
1019 T tmp[3] = {T(),T(),T()};
1020 tmp[0] = axisDirection[0];
1021 tmp[1] = axisDirection[1];
1022 tmp[2] = axisDirection[2];
1023 T alpha[1] = {T()};
1024 angle(alpha, tmp);
1025
1026 // rotation with angle alpha to (0,0,1)
1027 RotationRoundAxis3D<T, S> rotRAxis(_cartesianOrigin, util::fromVector3(normal), -alpha[0]);
1028 rotRAxis(x_rot, x);
1029 }
1030 CartesianToPolar2D<T, S> car2pol(_cartesianOrigin, util::fromVector3(e3), _orientation);
1031 T x_rot_help[2] = {T(),T()};
1032 x_rot_help[0] = x_rot[0];
1033 x_rot_help[1] = x_rot[1];
1034
1035 T output_help[2] = {T(),T()};
1036 car2pol(output_help, x_rot_help);
1037
1038 output[0] = output_help[0];
1039 output[1] = output_help[1];
1040 output[2] = x_rot[2] - _cartesianOrigin[2];
1041 return true; // output[0] = radius, output[1] = phi, output[2] = z
1042}
1043
1044// Read only access to _axisDirection
1045template<typename T, typename S>
1047{
1048 return _axisDirection;
1049}
1050
1051// Read and write access to _axisDirection
1052template<typename T, typename S>
1054{
1055 return _axisDirection;
1056}
1057
1058// Read only access to _catesianOrigin
1059template<typename T, typename S>
1061{
1062 return _cartesianOrigin;
1063}
1064
1065// Read and write access to _catesianOrigin
1066template<typename T, typename S>
1068{
1069 return _cartesianOrigin;
1070}
1071
1072// Read and write access to _axisDirection using angle
1073template<typename T, typename S>
1075{
1076 std::vector<T> Null(3,T());
1077 T e3[3] = {T(),T(),T()};
1078 e3[2] = T(1);
1079
1080 RotationRoundAxis3D<T, S> rotRAxis(Null, _orientation, angle);
1081 T tmp[3] = {T(),T(),T()};
1082 rotRAxis(tmp,e3);
1083 for (int i=0; i<3; ++i) {
1084 _axisDirection[i] = tmp[i];
1085 }
1086}
1087
1088
1090
1091
1092// constructor to obtain spherical coordinates of Cartesian coordinates
1093template<typename T, typename S>
1095//std::vector<T> sphericalOrigin)
1096 : AnalyticalF3D<T, S>(3) //, _sphericalOrigin(sphericalOrigin)
1097{
1098 this->getName() = "const";
1099}
1100
1101// operator returns Cartesian coordinates of spherical coordinates
1102// (x[0] = radius, x[1] = phi, x[2] = theta)
1103// phi in x-y-plane, theta in x-z-plane, z axis as orientation
1104template<typename T, typename S>
1105bool SphericalToCartesian3D<T, S>::operator()(T output[], const S x[])
1106{
1107 output[0] = x[0]*util::sin(x[2])*util::cos(x[1]);
1108 output[1] = x[0]*util::sin(x[2])*util::sin(x[1]);
1109 output[2] = x[0]*util::cos(x[2]);
1110 return true;
1111}
1112
1113
1114template<typename T, typename S>
1116 std::vector<T> cartesianOrigin, std::vector<T> axisDirection)
1117 : AnalyticalF3D<T, S>(3),
1118 _cartesianOrigin(cartesianOrigin),
1119 _axisDirection(axisDirection)
1120{
1121 this->getName() = "const";
1122}
1123
1124// operator returns spherical coordinates output[0] = radius(>= 0),
1125// output[1] = phi in [0, 2Pi), output[2] = theta in [0, Pi]
1126template<typename T, typename S>
1127bool CartesianToSpherical3D<T, S>::operator()(T output[], const S x[])
1128{
1129 T x_rot[3] = {T(),T(),T()};
1130 x_rot[0] = x[0];
1131 x_rot[1] = x[1];
1132 x_rot[2] = x[2];
1133
1134 Vector<T,3> axisDirection(_axisDirection);
1135 Vector<T,3> e3(T(), T(), T(1));
1136 Vector<T,3> normal = crossProduct3D(axisDirection,e3);
1137
1138 Vector<T,3> normalAxisDir = axisDirection;
1139 normalAxisDir = normalize(normalAxisDir);
1140 Vector<T,3> cross;
1141 // if axis has to be rotated
1142 if ( !( util::nearZero(normalAxisDir[0]) && util::nearZero(normalAxisDir[1]) && util::nearZero(normalAxisDir[2]-1) ) ) {
1144 T tmp[3] = {T(),T(),T()};
1145 for (int i=0; i<3; ++i) {
1146 tmp[i] = axisDirection[i];
1147 }
1148 T alpha[1] = {T(0)};
1149 angle(alpha,tmp);
1150 // cross is rotation axis
1151 cross = crossProduct3D(e3, axisDirection);
1152 // rotation with angle alpha to (0,0,1)
1153 RotationRoundAxis3D<T, S> rotRAxis(_cartesianOrigin, util::fromVector3(normal), -alpha[0]);
1154 rotRAxis(x_rot,x);
1155 }
1156
1157 CartesianToPolar2D<T, S> car2pol(_cartesianOrigin, util::fromVector3(e3), util::fromVector3(cross));
1158 // y[0] = car2pol(x_rot)[0];
1159 Vector<T, 3> difference;
1160
1161 for (int i=0; i<3; ++i) {
1162 difference[i] = x_rot[i] - _cartesianOrigin[i];
1163 }
1164
1165 T distance = T();
1166 for (int i = 0; i <= 2; ++i) {
1167 distance += difference[i]*difference[i];
1168 }
1169 distance = util::sqrt(distance);
1170
1171 car2pol(output, x_rot);
1172 output[0] = distance;
1173 output[2] = util::acos(difference[2]/output[0]); // angle between z-axis and r-vector
1174
1175 return true; // output[0] = radius, output[1] = phi, output[2] = theta
1176}
1177
1178
1180
1181
1187template<typename T, typename S>
1189 CartesianToCylinder3D<T, S>& car2cyl, T length, T radWire, T cutoff, T Mw, T Mp,
1190 T radParticle, T mu0)
1191 : AnalyticalF3D<T, S>(3),
1192 _car2cyl(car2cyl),
1193 _length(length),
1194 _radWire(radWire),
1195 _cutoff(cutoff),
1196 _Mw(Mw),
1197 _Mp(Mp),
1198 _radParticle(radParticle),
1199 _mu0(mu0)
1200{
1201 // Field direction H_0 parallel to fluid flow direction, if not: *(-1)
1203}
1204
1205template<typename T, typename S>
1207{
1208
1209 Vector<T, 3> magneticForcePolar;
1210 T outputTmp[3] = {T(), T(), T()};
1211 Vector<T, 3> normalAxis(_car2cyl.getAxisDirection());
1212 normalAxis = normalize(normalAxis);
1213
1214 Vector<T, 3> relPosition;
1215 relPosition[0] = (x[0] - _car2cyl.getCartesianOrigin()[0]);
1216 relPosition[1] = (x[1] - _car2cyl.getCartesianOrigin()[1]);
1217 relPosition[2] = (x[2] - _car2cyl.getCartesianOrigin()[2]);
1218
1219 T tmp[3] = {T(),T(),T()};
1220 _car2cyl(tmp,x);
1221 T rad = tmp[0];
1222 T phi = tmp[1];
1223
1224 T test = relPosition * normalAxis;
1225
1226 if ( (rad > _radWire && rad <= _cutoff*_radWire) &&
1227 (T(0) <= test && test <= _length) ) {
1228
1229 magneticForcePolar[0] = _factor/util::pow(rad, 3)
1230 *(util::pow(_radWire, 2)/util::pow(rad, 2) + util::cos(2*phi));
1231 magneticForcePolar[1] = _factor/util::pow(rad, 3)*util::sin(2*phi);
1232
1233 // changes radial and angular force components to cartesian components.
1234 outputTmp[0] = magneticForcePolar[0]*util::cos(phi)
1235 - magneticForcePolar[1]*util::sin(phi);
1236 outputTmp[1] = magneticForcePolar[0]*util::sin(phi)
1237 + magneticForcePolar[1]*util::cos(phi);
1238
1239 // if not in standard axis direction
1240 if ( !( util::nearZero(normalAxis[0]) && util::nearZero(normalAxis[1]) && util::nearZero(normalAxis[2]-1) ) ) {
1241 Vector<T, 3> e3(T(), T(), T(1));
1242 Vector<T, 3> orientation =
1243 crossProduct3D(Vector<T,3>(_car2cyl.getAxisDirection()),e3);
1244
1246 T alpha[1] = {T()};
1247 T tmp2[3] = {T(),T(),T()};
1248 for (int i = 0; i<3; ++i) {
1249 tmp2[i] = _car2cyl.getAxisDirection()[i];
1250 }
1251 angle(alpha,tmp2);
1252
1253 std::vector<T> origin(3, T());
1254 RotationRoundAxis3D<T, S> rotRAxis(origin, util::fromVector3(orientation), alpha[0]);
1255 rotRAxis(output,outputTmp);
1256 }
1257 else {
1258 output[0] = outputTmp[0];
1259 output[1] = outputTmp[1];
1260 output[2] = T();
1261 }
1262 }
1263 else {
1264 output[0] = outputTmp[0];
1265 output[1] = outputTmp[1];
1266 output[2] = outputTmp[1];
1267 }
1268 return true;
1269}
1270
1271template<typename T, typename S>
1273 CartesianToCylinder3D<T, S>& car2cyl, T length, T radWire, T cutoff, T Mw
1274)
1275 : AnalyticalF3D<T, S>(3),
1276 _car2cyl(car2cyl),
1277 _length(length),
1278 _radWire(radWire),
1279 _cutoff(cutoff),
1280 _Mw(Mw)
1281{
1282 // Field direction H_0 parallel to fluid flow direction, if not: *(-1)
1283 _factor = - _Mw * util::pow(_radWire, 2);
1284}
1285
1286template<typename T, typename S>
1288{
1289
1290 Vector<T, 3> magneticFieldPolar;
1291 T outputTmp[3] = {T(), T(), T()};
1292 Vector<T, 3> normalAxis(_car2cyl.getAxisDirection());
1293 normalAxis = normalize(normalAxis);
1294
1295 Vector<T, 3> relPosition;
1296 relPosition[0] = (x[0] - _car2cyl.getCartesianOrigin()[0]);
1297 relPosition[1] = (x[1] - _car2cyl.getCartesianOrigin()[1]);
1298 relPosition[2] = (x[2] - _car2cyl.getCartesianOrigin()[2]);
1299
1300 T tmp[3] = {T(), T(), T()};
1301 _car2cyl(tmp, x);
1302 T rad = tmp[0];
1303 T phi = tmp[1];
1304
1305 T test = relPosition * normalAxis;
1306
1307 if ( (rad > _radWire && rad <= _cutoff * _radWire) &&
1308 (T(0) <= test && test <= _length) ) {
1309
1310 magneticFieldPolar[0] = _factor / util::pow(rad, 2)
1311 * (util::cos(phi));
1312 magneticFieldPolar[1] = _factor / util::pow(rad, 2) * util::sin(phi);
1313
1314 // changes radial and angular force components to cartesian components.
1315 outputTmp[0] = magneticFieldPolar[0] * util::cos(phi)
1316 - magneticFieldPolar[1] * util::sin(phi);
1317 outputTmp[1] = magneticFieldPolar[0] * util::sin(phi)
1318 + magneticFieldPolar[1] * util::cos(phi);
1319
1320 // if not in standard axis direction
1321 if ( !( util::nearZero(normalAxis[0]) && util::nearZero(normalAxis[1]) && util::nearZero(normalAxis[2] - 1) ) ) {
1322 Vector<T, 3> e3(T(), T(), T(1));
1323 Vector<T, 3> orientation =
1324 crossProduct3D(Vector<T, 3>(_car2cyl.getAxisDirection()), e3);
1325
1327 T alpha[1] = {T()};
1328 T tmp2[3] = {T(), T(), T()};
1329 for (int i = 0; i < 3; ++i) {
1330 tmp2[i] = _car2cyl.getAxisDirection()[i];
1331 }
1332 angle(alpha, tmp2);
1333
1334 std::vector<T> origin(3, T());
1335 RotationRoundAxis3D<T, S> rotRAxis(origin, util::fromVector3(orientation), alpha[0]);
1336 rotRAxis(output, outputTmp);
1337 }
1338 else {
1339 output[0] = outputTmp[0];
1340 output[1] = outputTmp[1];
1341 output[2] = T();
1342 }
1343 }
1344 else {
1345 output[0] = outputTmp[0];
1346 output[1] = outputTmp[1];
1347 output[2] = outputTmp[1];
1348 }
1349
1350 return true;
1351}
1352
1353
1354} // end namespace olb
1355
1356#endif
#define M_PI
AnalyticalF are applications from DD to XD, where X is set by the constructor.
AnalyticalPorousVelocity3D(SuperGeometry< T, 3 > &superGeometry, int material, T K_, T mu_, T gradP_, T radius_, T eps_=T(1))
bool operator()(T output[], const T input[]) override
This class calculates the angle alpha between vector _referenceVector and any other vector x.
AngleBetweenVectors3D(std::vector< T > referenceVector, std::vector< T > orientation)
constructor defines _referenceVector and _orientation
bool operator()(T output[], const S x[]) override
operator writes angle between x and _referenceVector inro output field
This class converts Cartesian coordinates of point x to cylindrical coordinates wrote into output fie...
olb::Vector< T, 3 > const & getAxisDirection() const
Read only access to _axisDirection.
olb::Vector< T, 3 > _cartesianOrigin
origin of the Cartesian coordinate system
olb::Vector< T, 3 > const & getCartesianOrigin() const
Read only access to _catesianOrigin.
bool operator()(T output[], const S x[]) override
operator writes cylindrical coordinates of Cartesian point x into output field, output[0] = radius ( ...
CartesianToCylinder3D(olb::Vector< T, 3 > cartesianOrigin, T &angle, olb::Vector< T, 3 > orientation={T(1), T(), T()})
olb::Vector< T, 3 > _axisDirection
direction of the axis along which the cylindrical coordinates are calculated
void setAngle(T angle)
Read and write access to _axisDirection using angle.
olb::Vector< T, 3 > _orientation
direction to know orientation for math positive to obtain angle phi of Cartesian point x
This class converts Cartesian coordinates of point x to polar coordinates wrote into output field (ou...
bool operator()(T output[], const S x[]) override
operator writes shperical coordinates of Cartesian point x into output field, output[0] = radius ( >=...
CartesianToSpherical3D(std::vector< T > cartesianOrigin, std::vector< T > axisDirection)
bool operator()(T output[], const T x[]) override
CircleCasson3D(olb::Vector< T, 3 > axisPoint, std::vector< T > axisDirection, T radius, T cassonViscosity, T pressureDrop, T yieldStress, T scale=1.0)
Velocity profile for util::round pipes and a laminar flow of a Newtonian fluid: u(r)=u_max*(1-(r/R)^2...
CirclePoiseuille3D(std::vector< T > axisPoint, std::vector< T > axisDirection, T maxVelocity, T radius, T scale=T(1))
bool operator()(T output[], const T input[]) override
CirclePoiseuilleStrainRate3D(UnitConverter< T, DESCRIPTOR > const &converter, T ly)
This functor returns a quadratic Poiseuille profile for use with a pipe with util::round cross-sectio...
std::vector< T > _normal
bool operator()(T output[], const T x[]) override
olb::Vector< T, 3 > _center
CirclePowerLaw3D(olb::Vector< T, 3 > axisPoint, std::vector< T > axisDirection, T maxVelocity, T radius, T n, T scale=T(1))
Velocity profile for util::round pipes and turbulent flows: u(r)=u_max*(1-r/R)^(1/n) The exponent n c...
CirclePowerLawTurbulent3D(std::vector< T > axisPoint_, std::vector< T > axisDirection, T maxVelocity, T radius, T n=7, T turbulenceIntensity=0.05, T scale=T(1))
bool operator()(T output[], const T x[]) override
bool operator()(T output[], const S x[]) override
operator writes Cartesian coordinates of cylinder coordinates x[0] = radius >= 0, x[1] = phi in [0,...
CylinderToCartesian3D(std::vector< T > cylinderOrigin)
constructor defines _cylinderOrigin
EllipticPoiseuille3D(std::vector< T > center, T a, T b, T maxVel)
bool operator()(T output[], const T x[]) override
std::string & getName()
read and write access to name
Definition genericF.hh:51
T _factor
factor = mu0*4/3.*PI*radParticle^3*_Mp*radWire^2/r^3
MagneticFieldFromCylinder3D(CartesianToCylinder3D< T, S > &car2cyl, T length, T radWire, T cutoff, T Mw)
bool operator()(T output[], const S x[]) override
operator writes the magnetic force in a point x util::round a cylindrical wire into output field
T _Mw
saturation magnetization wire, linear scaling factor
T _factor
factor = mu0*4/3.*PI*radParticle^3*_Mp*radWire^2/r^3
T _radParticle
particle radius, cubic scaling factor
T _Mw
saturation magnetization wire, linear scaling factor
MagneticForceFromCylinder3D(CartesianToCylinder3D< T, S > &car2cyl, T length, T radWire, T cutoff, T Mw, T Mp=T(1), T radParticle=T(1), T mu0=4 *3.14159265e-7)
Magnetic field that creates magnetization in wire has to be orthogonal to the wire.
bool operator()(T output[], const S x[]) override
operator writes the magnetic force in a point x util::round a cylindrical wire into output field
T _Mp
magnetization particle, linear scaling factor
T _mu0
permeability constant, linear scaling factor
class for marking output with some text
This class converts polar coordinates of point x (x[0] = radius, x[1] = phi) to Cartesian coordinates...
RectanglePoiseuille3D(olb::Vector< T, 3 > &x0_, olb::Vector< T, 3 > &x1_, olb::Vector< T, 3 > &x2_, std::vector< T > &maxVelocity_)
bool operator()(T output[], const T x[]) override
RectangleTrigonometricPoiseuille3D(std::vector< T > &x0_, std::vector< T > &x1_, std::vector< T > &x2_, std::vector< T > &maxVelocity, int numOfPolynoms_=1)
bool operator()(T output[], const T x[]) override
RotatingLinear3D(std::vector< T > axisPoint_, std::vector< T > axisDirection_, T w_, T scale_=1)
bool operator()(T output[], const T x[]) override
RotatingLinearAnnulus3D(std::vector< T > axisPoint_, std::vector< T > axisDirection_, T w_, T ri_, T ro_, T scale_=1)
bool operator()(T output[], const T x[])
RotatingQuadratic1D(std::vector< T > axisPoint_, std::vector< T > axisDirection_, T w_, T scale_=1, T additive_=0)
std::vector< T > axisPoint
std::vector< T > axisDirection
bool operator()(T output[], const T x[]) override
This class saves coordinates of the resulting point after rotation in the output field.
RotationRoundAxis3D(olb::Vector< T, 3 > origin, olb::Vector< T, 3 > rotAxisDirection, T alpha)
constructor defines _rotAxisDirection, _alpha and _origin
bool operator()(T output[], const S x[]) override
operator writes coordinates of the resulting point after rotation of x by angle _alpha in math positi...
bool operator()(T output[], const S x[]) override
operator writes spherical coordinates of Cartesian coordinates of x (x[0] = radius,...
Representation of a statistic for a parallel 2D geometry.
SuperGeometryStatistics< T, D > & getStatistics()
Returns the statistics object.
Conversion between physical and lattice units, as well as discretization.
constexpr T getCharPhysVelocity() const
return characteristic velocity in physical units
Plain old scalar vector.
This file contains two different classes of functors, in the FIRST part.
This file contains two different classes of functors, in the FIRST part.
ADf< T, DIM > abs(const ADf< T, DIM > &a)
Definition aDiff.h:1019
Expr sqrt(Expr x)
Definition expr.cpp:225
std::vector< T > fromVector3(const Vector< T, 3 > &vec)
ADf< T, DIM > atan2(const T &y, const ADf< T, DIM > &x)
Definition aDiff.h:623
ADf< T, DIM > sin(const ADf< T, DIM > &a)
Definition aDiff.h:569
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
ADf< T, DIM > cosh(const ADf< T, DIM > &a)
Definition aDiff.h:657
Vector< T, D > normalize(const Vector< T, D > &a)
Expr fabs(Expr x)
Definition expr.cpp:230
ADf< T, DIM > acos(const ADf< T, DIM > &a)
Definition aDiff.h:605
bool nearZero(T a) any_platform
return true if a is close to zero
Definition util.h:402
ADf< T, DIM > tanh(const ADf< T, DIM > &a)
Definition aDiff.h:663
ADf< T, DIM > atan(const ADf< T, DIM > &a)
Definition aDiff.h:614
ADf< T, DIM > cos(const ADf< T, DIM > &a)
Definition aDiff.h:578
Top level namespace for all of OpenLB.
constexpr T max(const ScalarVector< T, D, IMPL > &v)
Definition vector.h:466
constexpr T norm(const ScalarVector< T, D, IMPL > &a) any_platform
Euclidean vector norm.
constexpr Vector< T, 3 > crossProduct3D(const ScalarVector< T, 3, IMPL > &a, const ScalarVector< T, 3, IMPL_ > &b) any_platform
Definition vector.h:263
constexpr Vector< T, D > normalize(const ScalarVector< T, D, IMPL > &a, T scale=T{1})
Definition vector.h:284
Representation of a parallel 2D geometry – header file.