7#ifndef MAIA_PARTICLELIB_H
8#define MAIA_PARTICLELIB_H
14template <MInt nDim,
class SysEqn>
41 typename std::vector<typename std::vector<LPTSpherical<nDim>>::iterator>
subDomain;
46 typename std::vector<typename std::vector<LPTEllipsoidal<nDim>>::iterator>
subDomain;
78 if(i.m_partId == j.m_partId) {
79 return i.m_position[0] < j.m_position[0];
81 return (i.m_partId < j.m_partId);
88 static MBool compare(
const T& i,
const T& j) {
return (i.m_diameter < j.m_diameter); }
94 static MBool compare(
const T& i,
const T& j) {
return (i.m_diameter > j.m_diameter); }
100 static MBool compare(
const T& i,
const T& j) {
return (i.m_temperature > j.m_temperature); }
106 static MBool compare(
const T& i,
const T& j) {
return (i.m_partId < j.m_partId); }
114 static MBool compare(
const T& i,
const T& j) {
return (i.m_cellId < j.m_cellId); }
121 if(i.cellId == j.cellId) {
122 return (i.partId < j.partId);
124 return (i.cellId < j.cellId);
151 for(
MInt count = 0; count < length; ++count) {
152 returnValue +=
a[count] *
b[count];
162 for(
MInt count = 0; count < length; ++count) {
163 result[count] = -now[count];
166 for(
MInt count = 0; count < length; ++count) {
167 result[count] = now[count];
172 MFloat angle = acos(dotP);
173 MFloat sint1 = sin(angle * (1 - time));
174 MFloat sint = sin(angle * time);
176 for(
MInt count = 0; count < length; ++count) {
177 result[count] = (before[count] * sint1 + result[count] * sint) / sinA;
180 for(
MInt count = 0; count < length; ++count) {
181 result[count] = before[count] * (F1 - time) + result[count] * time;
198 for(
MInt i = 0; i < 3; i++) {
199 for(
MInt j = 0; j < 3; j++) {
200 temp[i][j] = right[i][j];
205 for(
MInt i = 0; i < 3; i++) {
206 for(
MInt j = 0; j < 3; j++) {
207 for(
MInt k = 0; k < 3; k++) {
208 right[i][j] += left[i][k] * temp[k][j];
224 for(
MInt i = 0; i < 3; i++) {
225 for(
MInt j = 0; j < 3; j++) {
226 temp[i][j] = left[i][j];
231 for(
MInt i = 0; i < 3; i++) {
232 for(
MInt j = 0; j < 3; j++) {
233 for(
MInt k = 0; k < 3; k++) {
234 left[i][j] += temp[i][k] * right[k][j];
253 const MInt dist, std::mt19937_64& PRNG,
const MFloat distCoeff = 0.0,
254 const MFloat nozzleAngle = 0.0) {
263 const MFloat correctedOpeningAngle = openingAngle - 2.0 * nozzleAngle;
265 std::copy_n(coneAxis, 3, ¢erAxis[0]);
270 normal_distribution<MFloat> distAngle(0, distCoeff * correctedOpeningAngle);
273 distedAngle = distAngle(PRNG);
275 }
while(distedAngle > correctedOpeningAngle);
278 distedAngle = correctedOpeningAngle;
282 const MFloat coneAngleRad = (distedAngle / 360) * M_PI;
284 ASSERT(abs(coneAxis[0]) > std::numeric_limits<MFloat>::epsilon()
285 || abs(coneAxis[1]) > std::numeric_limits<MFloat>::epsilon()
286 || abs(coneAxis[2]) > std::numeric_limits<MFloat>::epsilon(),
287 "ERROR: ConeAxis cannot be Zero!");
288 ASSERT(openingAngle <= 360,
"ERROR: Opening angle cannot be larger than 360 degrees!");
296 if(abs(centerAxis[0]) > 0.0) {
297 v1[0] = 1.0 / centerAxis[0];
298 }
else if(abs(centerAxis[1]) > 0.0) {
299 v1[1] = 1.0 / centerAxis[1];
301 v1[2] = 1.0 / centerAxis[2];
304 if(abs(coneAxis[0]) < std::numeric_limits<MFloat>::epsilon()) {
306 }
else if(abs(coneAxis[1]) < std::numeric_limits<MFloat>::epsilon()) {
308 }
else if(abs(coneAxis[2]) < std::numeric_limits<MFloat>::epsilon()) {
314 std::copy_n(&v1[0], 3, &temp[0]);
325 uniform_real_distribution<MFloat> dist0_2Pi(0, 2 * M_PI);
330 uniform_real_distribution<MFloat> randAngle(cos(coneAngleRad), 1);
333 MFloat omega = coneAngleRad;
339 phi = dist0_2Pi(PRNG);
343 omega = acos(randAngle(PRNG));
349 vec[0] = sin(omega) * (cos(phi) * v1[0] + sin(phi) * v2[0]) + cos(omega) * centerAxis[0];
350 vec[1] = sin(omega) * (cos(phi) * v1[1] + sin(phi) * v2[1]) + cos(omega) * centerAxis[1];
351 vec[2] = sin(omega) * (cos(phi) * v1[2] + sin(phi) * v2[2]) + cos(omega) * centerAxis[2];
356 vec[0] = tan(omega) * (cos(phi) * v1[0] + sin(phi) * v2[0]) + centerAxis[0];
357 vec[1] = tan(omega) * (cos(phi) * v1[1] + sin(phi) * v2[1]) + centerAxis[1];
358 vec[2] = tan(omega) * (cos(phi) * v1[2] + sin(phi) * v2[2]) + centerAxis[2];
384 std::mt19937_64& PRNG) {
386 std::copy_n(normalDirection, 3, ¢erAxis[0]);
397 if(std::abs(centerAxis[0]) > 0.0) {
398 v1[0] = 1.0 / centerAxis[0];
399 }
else if(std::abs(centerAxis[1]) > 0.0) {
400 v1[1] = 1.0 / centerAxis[1];
402 v1[2] = 1.0 / centerAxis[2];
405 if(std::abs(normalDirection[0]) < std::numeric_limits<MFloat>::epsilon()) {
407 }
else if(std::abs(normalDirection[1]) < std::numeric_limits<MFloat>::epsilon()) {
409 }
else if(std::abs(normalDirection[2]) < std::numeric_limits<MFloat>::epsilon()) {
414 std::copy_n(&v1[0], 3, &temp[0]);
428 std::uniform_real_distribution<MFloat> dist0_2Pi(0, 2 * M_PI);
430 std::uniform_real_distribution<MFloat> randRadius(0, 1);
439 phi = dist0_2Pi(PRNG);
442 radius = randRadius(PRNG);
445 vec[0] = 0.5 * diameter * radius * (cos(phi) * v1[0] + sin(phi) * v2[0]);
446 vec[1] = 0.5 * diameter * radius * (cos(phi) * v1[1] + sin(phi) * v2[1]);
447 vec[2] = 0.5 * diameter * radius * (cos(phi) * v1[2] + sin(phi) * v2[2]);
460 std::mt19937_64& PRNG,
const MInt circleSplit = 1,
const MInt splitNo = 0) {
462 std::copy_n(normalDirection, 3, ¢erAxis[0]);
473 if(std::abs(centerAxis[0]) > 0.0) {
474 v1[0] = 1.0 / centerAxis[0];
475 }
else if(std::abs(centerAxis[1]) > 0.0) {
476 v1[1] = 1.0 / centerAxis[1];
478 v1[2] = 1.0 / centerAxis[2];
481 if(std::abs(normalDirection[0]) < std::numeric_limits<MFloat>::epsilon()) {
483 }
else if(std::abs(normalDirection[1]) < std::numeric_limits<MFloat>::epsilon()) {
485 }
else if(std::abs(normalDirection[2]) < std::numeric_limits<MFloat>::epsilon()) {
490 std::copy_n(&v1[0], 3, &temp[0]);
502 const MFloat splitCircle = (2.0 * M_PI /
static_cast<MFloat>(circleSplit));
505 std::uniform_real_distribution<MFloat> dist0_2Pi(splitCircle * splitNo, splitCircle * (splitNo + 1));
512 phi = dist0_2Pi(PRNG);
516 vec[0] = 0.5 * diameter * (cos(phi) * v1[0] + sin(phi) * v2[0]);
517 vec[1] = 0.5 * diameter * (cos(phi) * v1[1] + sin(phi) * v2[1]);
518 vec[2] = 0.5 * diameter * (cos(phi) * v1[2] + sin(phi) * v2[2]);
530 std::copy_n(normalDirection, 3, ¢erAxis[0]);
541 if(std::abs(centerAxis[0]) > 0.0) {
542 v1[0] = 1.0 / centerAxis[0];
543 }
else if(std::abs(centerAxis[1]) > 0.0) {
544 v1[1] = 1.0 / centerAxis[1];
546 v1[2] = 1.0 / centerAxis[2];
549 if(std::abs(normalDirection[0]) < std::numeric_limits<MFloat>::epsilon()) {
551 }
else if(std::abs(normalDirection[1]) < std::numeric_limits<MFloat>::epsilon()) {
553 }
else if(std::abs(normalDirection[2]) < std::numeric_limits<MFloat>::epsilon()) {
558 std::copy_n(&v1[0], 3, &temp[0]);
570 vec[0] = 0.5 * diameter * (cos(phi) * v1[0] + sin(phi) * v2[0]);
571 vec[1] = 0.5 * diameter * (cos(phi) * v1[1] + sin(phi) * v2[1]);
572 vec[2] = 0.5 * diameter * (cos(phi) * v1[2] + sin(phi) * v2[2]);
585 std::mt19937_64& PRNG) {
586 const MFloat K = 1.0 - exp(-pow((max - min) / mean, spread));
588 std::uniform_real_distribution<MFloat> uni(0.0, 1.0);
589 const MFloat x = uni(PRNG);
591 return min + mean * pow(-log(1.0 - x * K), 1.0 / spread);
602 std::uniform_real_distribution<MFloat> uni(0.0, 1.0);
603 const MFloat x = uni(PRNG);
605 return 4 / sqrt(M_PI) *
POW2(x) / x_mean * exp(-
POW2(x / x_mean));
BitsetType::reference isInvalid()
static MBool compare(const T &i, const T &j)
static MBool compare(const T &i, const MInt j)
static MBool compare(const MInt i, const T &j)
static MBool compare(const T &i, const T &j)
static MBool compare(const T &i, const T &j)
static MBool compare(const T &i, const T &j)
static MBool compare(const T &i, const T &j)
static MBool compare(const T &i, const T &j)
static MBool compare(const T &i, const T &j)
@ PART_EMITT_DIST_GAUSSIAN
constexpr Real POW2(const Real x)
typename std::vector< LPTSpherical< nDim > >::iterator partListIterator
void slerp(const MFloat *before, const MFloat *now, const MFloat time, MFloat *result, const MInt length)
MBool activeParticle(const LPTSpherical< nDim > &particle)
MFloat NTDistribution(const MFloat x_mean, std::mt19937_64 &PRNG)
void matrixMultiplyLeft(MFloat left[3][3], MFloat right[3][3])
Matrix multiplication; matrix right is changed and contains the result.
MFloat scalarProduct(const MFloat *a, const MFloat *b, const MInt length)
typename std::vector< LPTSpherical< nDim > >::const_iterator partListIteratorConst
MBool inactiveParticle(const LPTSpherical< nDim > &particle)
typename std::vector< LPTEllipsoidal< nDim > >::const_iterator ellipsListIteratorConst
void randomPointInCircle(MFloat *vec, const MFloat *normalDirection, const MFloat diameter, std::mt19937_64 &PRNG)
void randomPointOnCircle(MFloat *vec, const MFloat *normalDirection, const MFloat diameter, std::mt19937_64 &PRNG, const MInt circleSplit=1, const MInt splitNo=0)
MInt randomVectorInCone(MFloat *vec, const MFloat *coneAxis, const MFloat length, const MFloat openingAngle, const MInt dist, std::mt19937_64 &PRNG, const MFloat distCoeff=0.0, const MFloat nozzleAngle=0.0)
Generate a random vector in a cone defined by its opening angle.
MBool activeEllipsoid(const LPTEllipsoidal< nDim > &particle)
void matrixMultiplyRight(MFloat left[3][3], MFloat right[3][3])
Matrix multiplication; matrix left is changed and contains the result.
MFloat rosinRammler(const MFloat min, const MFloat mean, const MFloat max, const MFloat spread, std::mt19937_64 &PRNG)
void pointOnCircle(MFloat *vec, const MFloat *normalDirection, const MFloat diameter, MFloat phi)
typename std::vector< LPTEllipsoidal< nDim > >::iterator ellipsListIterator
MBool inactiveEllipsoid(const LPTEllipsoidal< nDim > &particle)
void cross(const T *const u, const T *const v, T *const c)
void normalize(std::array< T, N > &u)
Namespace for auxiliary functions/classes.
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
std::vector< typename std::vector< LPTEllipsoidal< nDim > >::iterator > subDomain
std::vector< typename std::vector< LPTSpherical< nDim > >::iterator > subDomain