73template <MInt nDim,
typename T,
typename U>
74inline T*
vecAdd(T*
const result,
const U*
const a) {
75 std::transform(
a,
a + nDim, result, result, std::plus<T>());
78template <
MInt nDim,
typename T,
typename U,
typename... Ts>
79inline T*
vecAdd(T*
const result,
const U*
const a,
const Ts...
b) {
80 std::transform(
a,
a + nDim, result, vecAdd<nDim>(result,
b...), std::plus<T>());
85template <
MInt nDim,
typename T,
typename... Ts>
86inline void vecAvg(T*
const M,
const Ts*
const... args) {
87 std::fill_n(M, nDim, 0.0);
88 maia::math::vecAdd<nDim>(M, args...);
89 constexpr std::size_t n =
sizeof...(Ts);
90 std::transform(M, M + nDim, M, std::bind(std::multiplies<T>(), std::placeholders::_1, 1.0 / n));
101inline void cross(
const T*
const u,
const T*
const v, T*
const c) {
102 c[0] = u[1] * v[2] - v[1] * u[2];
103 c[1] = u[2] * v[0] - v[2] * u[0];
104 c[2] = u[0] * v[1] - v[0] * u[1];
113inline std::array<T, 3>
cross(
const std::array<T, 3>& u,
const std::array<T, 3>& v) {
114 std::array<T, 3> result;
115 cross(&u[0], &v[0], &result[0]);
120inline T
cross(
const std::array<T, 2>& u,
const std::array<T, 2>& v) {
121 return u[0] * v[1] - u[1] * v[0];
130inline T*
cross(
const T (&u)[3],
const T (&v)[3]) {
132 cross(&u[0], &v[0], &result[0]);
137inline T
cross(
const T (&u)[2],
const T (&v)[2]) {
138 return u[0] * v[1] - u[1] * v[0];
147template <
typename T, std::
size_t N>
149 static_assert(N > 1,
"ERROR: Invalid norm call!");
152 return std::sqrt(u[0] * u[0] + u[1] * u[1]);
155 return std::sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
157 return std::sqrt(std::accumulate(u.begin(), u.end(), 0.0, [](
const MFloat&
a,
const T&
b) { return a + b * b; }));
168 ASSERT(N > 1,
"ERROR: Invalid norm call!");
171 return std::sqrt(u[0] * u[0] + u[1] * u[1]);
174 return std::sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
178 for(
MInt i = 0; i < N; i++) {
182 return std::sqrt(tmp);
190template <
typename T, std::
size_t N>
206 std::for_each(u.begin(), u.end(), [
inverse](T&
a) { a *= inverse; });
230 for(
MInt i = 0; i < N; i++) {
241template <
typename T, std::
size_t N>
242inline std::array<T, N>
normalized(
const std::array<T, N>& u) {
243 std::array<T, N> n(u);
250 IF_CONSTEXPR(nDim == 2) {
return sqrt(
POW2(
a[0] -
b[0]) +
POW2(
a[1] -
b[1])); }
251 IF_CONSTEXPR(nDim == 3) {
return sqrt(
POW2(
a[0] -
b[0]) +
POW2(
a[1] -
b[1]) +
POW2(
a[2] -
b[2])); }
281 for(
MInt i = 0; i < dim; i++) {
282 for(
MInt j = 0; j < dim; j++) {
288 for(
MInt i = 0; i < dim; i++) {
289 for(
MInt j = 0; j < dim; j++) {
290 for(
MInt k = 0; k < dim; k++) {
291 result(i, j) += m1(i, k) * m2(k, j);
301 if(m1_m != m2_n)
mTerm(1, AT_,
"Dimension of matrix multiplication does not match!!!");
303 for(
MInt i = 0; i < m1_n; i++) {
304 for(
MInt j = 0; j < m2_m; j++) {
310 for(
MInt i = 0; i < m1_n; i++) {
311 for(
MInt j = 0; j < m2_m; j++) {
312 for(
MInt k = 0; k < m1_m; k++) {
313 result(i, j) += m1(i, k) * m2(k, j);
321 for(
MInt i = 0; i < dim1; i++) {
322 for(
MInt j = 0; j < dim2; j++) {
323 result(i, j) = m1(i, j) + m2(i, j);
330 for(
MInt i = 0; i < dim1; i++) {
331 for(
MInt j = 0; j < dim2; j++) {
332 ret_val += m(i, j) * m(i, j);
352 const MFloat p1 = 1.0, p2 = -0.1098628627e-2, p3 = 0.2734510407e-4, p4 = -0.2073370639e-5, p5 = 0.2093887211e-6,
353 q1 = -0.1562499995e-1, q2 = 0.1430488765e-3, q3 = -0.6911147651e-5, q4 = 0.7621095161e-6,
354 q5 = -0.9349451520e-7, r1 = 57568490574.0, r2 = -13362590354.0, r3 = 651619640.7, r4 = -11214424.18,
355 r5 = 77392.33017, r6 = -184.9052456, s1 = 57568490411.0, s2 = 1029532985.0, s3 = 9494680.718,
356 s4 = 59272.64853, s5 = 267.8532712, s6 = 1.0;
357 MFloat ax, fr, fs, z, fp, fq1, xx,
y, tmp;
359 if(
approx(x, 0.0, std::numeric_limits<MFloat>::epsilon())) {
366 fr = r1 +
y * (r2 +
y * (r3 +
y * (r4 +
y * (r5 +
y * r6))));
367 fs = s1 +
y * (s2 +
y * (s3 +
y * (s4 +
y * (s5 +
y * s6))));
372 xx = ax - 0.785398164;
373 fp = p1 +
y * (p2 +
y * (p3 +
y * (p4 +
y * p5)));
374 fq1 = q1 +
y * (q2 +
y * (q3 +
y * (q4 +
y * q5)));
375 tmp = std::sqrt(0.636619772 / ax) * (fp * cos(xx) - z * fq1 * sin(xx));
389 const MFloat p1 = 1.0, p2 = 0.183105e-2, p3 = -0.3516396496e-4, p4 = 0.2457520174e-5, p5 = -0.240337019e-6,
390 p6 = 0.636619772, q1 = 0.04687499995, q2 = -0.2002690873e-3, q3 = 0.8449199096e-5, q4 = -0.88228987e-6,
391 q5 = 0.105787412e-6, r1 = 72362614232.0, r2 = -7895059235.0, r3 = 242396853.1, r4 = -2972611.439,
392 r5 = 15704.48260, r6 = -30.16036606, s1 = 144725228442.0, s2 = 2300535178.0, s3 = 18583304.74,
393 s4 = 99447.43394, s5 = 376.9991397, s6 = 1.0;
395 MFloat ax, fr, fs,
y, z, fp, fq1, xx, tmp;
400 fr = r1 +
y * (r2 +
y * (r3 +
y * (r4 +
y * (r5 +
y * r6))));
401 fs = s1 +
y * (s2 +
y * (s3 +
y * (s4 +
y * (s5 +
y * s6))));
406 xx = ax - 2.35619491;
407 fp = p1 +
y * (p2 +
y * (p3 +
y * (p4 +
y * p5)));
408 fq1 = q1 +
y * (q2 +
y * (q3 +
y * (q4 +
y * q5)));
409 tmp = sqrt(p6 / ax) * (cos(xx) * fp - z * sin(xx) * fq1) * (x < 0.0 ? -fabs(s6) : fabs(s6));
422 mTerm(1, AT_,
"invalid order");
429 const MFloat darg = PIB2 / 90;
431 arg = std::fmod(std::abs(arg), F2 * PI);
443 const auto lowerInd =
static_cast<MInt>(arg / darg);
444 const MFloat lowerVal = FTRIG[lowerInd];
445 const MFloat higherVal = FTRIG[lowerInd + 1];
446 const MFloat deltaArg = arg - lowerInd * darg;
447 const MFloat fac = deltaArg / darg;
449 return (lowerVal * (F1 - fac) + higherVal * fac) * SIGN;
463 for(
MInt i = 0; i < (dim - 1); ++i) {
465 for(
MInt j = i; j < dim; ++j) {
473 for(
MInt j = 0; j < dim; ++j) {
484 cross(qA, qB, &crossProduct[0]);
486 const MFloat dot = std::inner_product(qA, &qA[3], qB, 0.0);
488 for(
MInt n = 0; n < 3; n++) {
489 qC[n] = qA[3] * qB[n] + qB[3] * qA[n] + crossProduct[n];
491 qC[3] = qA[3] * qB[3] - dot;
496 return (T(0) < val) - (val < T(0));
507 const MFloat mu2 = Strouhal * F2 * PI;
511 const MInt maxNoCycles = 20;
512 for(
MInt cycle = maxNoCycles; cycle > 0; cycle--) {
513 if(cad >= 4 * PI * cycle) {
514 cad = cad - 4 * PI * cycle;
517 cad = cad * 180 / PI;
522 ASSERT(mode == 1,
"Incorrect mode!");
523 cad = cad + offset * PI / 180;
534 R(0, 0) = q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3];
535 R(1, 1) = q[0] * q[0] - q[1] * q[1] + q[2] * q[2] - q[3] * q[3];
536 R(2, 2) = q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3];
538 R(0, 1) = F2 * (q[1] * q[2] + q[0] * q[3]);
539 R(0, 2) = F2 * (q[1] * q[3] - q[0] * q[2]);
540 R(1, 0) = F2 * (q[1] * q[2] - q[0] * q[3]);
541 R(1, 2) = F2 * (q[2] * q[3] + q[0] * q[1]);
542 R(2, 0) = F2 * (q[1] * q[3] + q[0] * q[2]);
543 R(2, 1) = F2 * (q[2] * q[3] - q[0] * q[1]);
551 quaternion[0] = cos(F1B2 * rotation[1]) * cos(F1B2 * (rotation[2] + rotation[0]));
552 quaternion[1] = sin(F1B2 * rotation[1]) * sin(F1B2 * (rotation[2] - rotation[0]));
553 quaternion[2] = sin(F1B2 * rotation[1]) * cos(F1B2 * (rotation[2] - rotation[0]));
554 quaternion[3] = cos(F1B2 * rotation[1]) * sin(F1B2 * (rotation[2] + rotation[0]));
565 c[i] += A(i, j) *
b[j];
578 c[i] += A(j, i) *
b[j];
596 for(
MInt i = 0; i < n; i++) {
597 for(
MInt j = 0; j < n; j++) {
609 maximum = fabs(
a[s][s]);
612 for(
MInt i = s + 1; i < n; i++) {
613 if(fabs(
a[i][s]) > maximum) {
614 maximum = fabs(
a[i][s]);
619 if(maximum < epsilon) {
624 std::cerr <<
"Error in matrix inverse computation " << s <<
" " <<
a[s][s] << std::endl;
625 for(
MInt i = 0; i < n; i++) {
626 for(
MInt j = 0; j < n; j++) {
627 std::cerr <<
a[i][j] <<
" ";
629 std::cerr << std::endl;
632 std::cerr <<
"Error in matrix inverse computation " << std::endl;
640 for(
MInt j = s; j < 2 * n; j++) {
642 a[s][j] =
a[pRow][j];
649 for(
MInt j = s; j < 2 * n; j++) {
650 a[s][j] =
a[s][j] / f;
654 for(
MInt i = 0; i < n; i++) {
657 for(
MInt j = s; j < 2 * n; j++) {
658 a[i][j] += f *
a[s][j];
666 std::cerr <<
"Error 2 in inverse matrix computation" << std::endl;
672 for(
MInt i = 0; i < n; i++) {
673 for(
MInt j = 0; j < n; j++) {
674 ainv[i][j] =
a[i][n + j];
687 for(
MInt j = start; j < end; j++) {
723 for(
MInt i = 1; i < size; i++) {
725 if(
a[i] !=
a[i - 1]) {
730 for(
MInt k = i; k < size - 1; k++) {
765 }
else if(Nmax == 1) {
769 MFloat polyLast1, polyLast2, derivLast1, derivLast2;
778 for(
MInt k = 2; k <= Nmax; k++) {
779 poly = (F2 * k - F1) / k * x * polyLast1 - (k - F1) / k * polyLast2;
780 deriv = derivLast2 + (F2 * k - F1) * polyLast1;
781 polyLast2 = polyLast1;
783 derivLast2 = derivLast1;
810 const MInt noNodes = Nmax + 1;
811 std::fill_n(&nodes[0], noNodes, F0);
812 std::fill_n(&wInt[0], noNodes, F0);
816 const MFloat tol = F4 * MFloatEps;
817 const MInt noIterations = 10;
823 }
else if(Nmax == 1) {
824 nodes[0] = -sqrt(F1B3);
826 nodes[1] = -nodes[0];
830 for(
MInt j = 0; j < (Nmax + 1) / 2; j++) {
832 nodes[j] = -cos((F2 * j + F1) / (F2 * Nmax + F2) * PI);
837 for(
MInt k = 0; k < noIterations; k++) {
839 MFloat delta = -poly / deriv;
843 if(fabs(delta) <= tol * fabs(nodes[j])) {
850 wInt[j] = F2 / ((1 - nodes[j] * nodes[j]) * deriv * deriv);
853 nodes[Nmax - j] = -nodes[j];
854 wInt[Nmax - j] = wInt[j];
863 nodes[Nmax / 2] = F0;
864 wInt[Nmax / 2] = F2 / (deriv * deriv);
883#define MAIA_TRANSITION_FUNCTION 2
887#if MAIA_TRANSITION_FUNCTION == 0
888 return (r < r1) ? F0 : F1;
889#elif MAIA_TRANSITION_FUNCTION == 1
891#elif MAIA_TRANSITION_FUNCTION == 2
892 return POW2(R) * (3.0 - 2.0 * R);
893#elif MAIA_TRANSITION_FUNCTION == 3
894 return POW3(R) * (10.0 + R * (6.0 * R - 15.0));
895#elif MAIA_TRANSITION_FUNCTION == 4
896 return POW3(R) * (6.0 + R * (2.0 * R - 7.0));
897#elif MAIA_TRANSITION_FUNCTION == 5
898 return F1B2 * (F1 + sin(PI * (F3B2 + R)));
904 std::vector<MFloat> linspaced(num);
906 for(
auto i = 0; i < num; i++) {
907 linspaced[i] = start + delta * i;
922 return (angle - std::fmod(angle, azimuthalAngle / 180.0 * PI)) / (azimuthalAngle / 180.0 * PI);
939template <
typename T, std::
size_t N>
941template <
typename T, std::
size_t N>
947void invert(T& A, T& weights, T& AInv,
const MInt m,
const MInt n);
958void solveQR(std::array<std::array<MFloat, nDim>, nDim>& A_, std::array<MFloat, nDim>& b_);
959template <
typename T, std::
size_t N>
960void adjointRow(std::array<std::array<T, N>, N>& m, std::array<T, N>& A,
const MInt r);
962void adjoint1stRow4x4(std::array<std::array<T, 4>, 4>& m, std::array<T, 4>& A);
963template <
typename T, std::
size_t N>
964void adjoint1stRow(std::array<std::array<T, N>, N>& m, std::array<T, N>& A);
This class is a ScratchSpace.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr Real POW3(const Real x)
constexpr Real POW2(const Real x)
MBool approx(const T &, const U &, const T)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
MFloat frobeniusMatrixNorm(MFloatScratchSpace &m, MInt dim1, MInt dim2)
void cross(const T *const u, const T *const v, T *const c)
void adjoint1stRow(std::array< std::array< T, N >, N > &m, std::array< T, N > &A)
MFloat RBF(const MFloat R, const MFloat R0)
radial base function
std::vector< MFloat > svd(MFloat *const A, MFloat *const b, const MInt m, const MInt n, MFloat *const x)
void quickSortImpl(MInt *a, MInt start, MInt end)
MFloat determinant(std::array< T, N > &m)
void multiplySparseMatrixVector(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
void rotation2quaternion(MFloat *rotation, MFloat *quaternion)
T * vecAdd(T *const result, const U *const a)
Linear Algebra.
MFloat distance(const MFloat *a, const MFloat *b)
void adjoint1stRow4x4(std::array< std::array< T, 4 >, 4 > &m, std::array< T, 4 > &A)
void calculateLegendrePolyAndDeriv(MInt Nmax, MFloat x, MFloat *polynomial, MFloat *derivative)
Evaluates the Legendre polynomial and its derivative of degree Nmax at point x.
std::vector< MFloat > linSpace(const MFloat start, const MFloat end, const MInt num)
void matrixVectorProduct(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A*b
void sortEigenVectors(MFloat A[3][3], MFloat w[3])
Sorts the eigenvalues and the associated eigenvectors from large to small.
MFloat besselJ0(MFloat x)
MInt removeDoubleEntries(MInt *a, MInt size)
void invert(MFloat *A, const MInt m, const MInt n)
MFloat besselJ1(MFloat x)
void solveQR(std::array< std::array< MFloat, nDim >, nDim > &A_, std::array< MFloat, nDim > &b_)
void normalize(std::array< T, N > &u)
MFloat frobeniusMatrixNormSquared(MFloatScratchSpace &m, MInt dim1, MInt dim2)
MFloat besselJi(MInt order, MFloat x)
void computeRotationMatrix(MFloatScratchSpace &R, MFloat *q)
rotation matrix co-rotating(~inertial) frame -> body-fixed frame
MFloat deltaFun(const MFloat r, const MFloat r0, const MFloat r1)
void calcEigenVectors(MFloat A[3][3], MFloat Q[3][3], MFloat w[3])
void calculateLegendreGaussNodesAndWeights(MInt Nmax, MFloat *nodes, MFloat *wInt)
Calculate the Gauss integration nodes and weight for the Legendre polynomials on the interval [-1,...
MFloat getSector(MFloat y, MFloat z, MFloat azimuthalAngle)
void solveSparseMatrix(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
MFloat crankAngle(const MFloat time, const MFloat Strouhal, const MFloat offset, const MInt mode)
help-function for engine calculations which returns the crank-angle for a given time,...
void solveSparseMatrixIterative(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
void quickSort(MInt *a, MInt start, MInt end)
MFloat getAngle(MFloat y, MFloat z)
MFloat norm(const std::array< T, N > &u)
std::array< T, N > normalized(const std::array< T, N > &u)
MFloat lincos(MFloat arg)
void addMatrices(MFloatScratchSpace &m1, MFloatScratchSpace &m2, MFloatScratchSpace &result, MInt dim1, MInt dim2)
MInt inverse(MFloat **a, MFloat **ainv, MInt n, const MFloat epsilon)
void multiplyMatricesSq(MFloatScratchSpace &m1, MFloatScratchSpace &m2, MFloatScratchSpace &result, MInt dim)
void multiplyMatrices(MFloatScratchSpace &m1, MFloatScratchSpace &m2, MFloatScratchSpace &result, MInt m1_n, MInt m1_m, MInt m2_n, MInt m2_m)
void vecAvg(T *const M, const Ts *const ... args)
Computes the arithmetic mean of an arbritary number of vectors of dimension nDim and returns it in M.
void calcEigenValues(MFloat A[3][3], MFloat w[3])
void adjointRow(std::array< std::array< T, N >, N > &m, std::array< T, N > &A, const MInt r)
MInt quickSortPartition(MInt *a, MInt start, MInt end)
void quatMult(const MFloat *const qA, const MFloat *const qB, MFloat *const qC)
void solveDenseMatrix(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
MInt invertR(T &A, T &weights, T &AInv, const MInt m, const MInt n)
void matrixVectorProductTranspose(MFloat *c, MFloatScratchSpace &A, MFloat *b)
c=A^t*b
Namespace for auxiliary functions/classes.