7#ifndef DGINTERPOLATION_H_
8#define DGINTERPOLATION_H_
97namespace interpolation {
155 mTerm(1, AT_,
"Gauss-Lobatto needs at least two nodes!");
158 MFloat polyLast1, polyLast2, derivLast1, derivLast2, deriv;
165 for(
MInt k = 2; k <= Nmax; k++) {
166 poly = (F2 * k - F1) / k * x * polyLast1 - (k - F1) / k * polyLast2;
167 deriv = derivLast2 + (F2 * k - F1) * polyLast1;
168 polyLast2 = polyLast1;
170 derivLast2 = derivLast1;
177 polyNp1 = (F2 * k - F1) / k * x * poly - (k - F1) / k * polyLast2;
178 derivNp1 = derivLast2 + (F2 * k - F1) * polyLast1;
180 q = polyNp1 - polyLast2;
181 qDeriv = derivNp1 - derivLast2;
201 ASSERT(Nmax > 0,
"Number of nodes must be greater than zero!");
204 const MInt noNodes = Nmax + 1;
205 std::fill_n(&nodes[0], noNodes, F0);
206 std::fill_n(&wInt[0], noNodes, F0);
213 const MFloat tol = F4 * MFloatEps;
214 const MInt noIterations = 10;
224 wInt[0] = F2 / (Nmax * (Nmax + F1));
226 wInt[Nmax] = wInt[0];
228 for(
MInt j = 1; j < (Nmax + 1) / 2; j++) {
230 nodes[j] = -cos((j + F1B4) * PI / Nmax - F3B8 / Nmax / PI * F1 / (j + F1B4));
234 for(
MInt k = 0; k < noIterations; k++) {
235 calcQandL(Nmax, nodes[j], q, qDeriv, poly);
236 const MFloat delta = -q / qDeriv;
240 if(fabs(delta) <= tol * fabs(nodes[j])) {
246 calcQandL(Nmax, nodes[j], q, qDeriv, poly);
247 wInt[j] = F2 / (Nmax * (Nmax + F1) * poly * poly);
250 nodes[Nmax - j] = -nodes[j];
251 wInt[Nmax - j] = wInt[j];
259 nodes[Nmax / 2] = F0;
260 wInt[Nmax / 2] = F2 / (Nmax * (Nmax + F1) * poly * poly);
280 const MInt noNodes = Nmax + 1;
281 std::fill_n(&weights[0], noNodes, F1);
284 for(
MInt j = 1; j < noNodes; j++) {
285 for(
MInt k = 0; k < j; k++) {
286 weights[k] = weights[k] * (nodes[k] - nodes[j]);
287 weights[j] = weights[j] * (nodes[j] - nodes[k]);
292 for(
MInt j = 0; j < noNodes; j++) {
293 weights[j] = F1 / weights[j];
319 const MInt noNodes = Nmax + 1;
323 for(
MInt j = 0; j < noNodes; j++) {
324 if(
approx(x, nodes[j], MFloatEps)) {
327 MFloat t = wBary[j] / (x - nodes[j]);
328 numerator += t * values[j];
332 return numerator / denominator;
354 const MInt noNodes = polyDeg + 1;
355 std::fill_n(&polynomials[0], noNodes, F0);
359 for(
MInt j = 0; j < noNodes; j++) {
360 if(
approx(x, nodes[j], MFloatEps)) {
370 for(
MInt j = 0; j < noNodes; j++) {
371 t = wBary[j] / (x - nodes[j]);
375 for(
MInt j = 0; j < noNodes; j++) {
376 polynomials[j] = polynomials[j] / s;
398 const MInt noNodes = polyDeg + 1;
403 for(
MInt j = 0; j < noNodes; j++) {
404 Lhat[j] = Lhat[j] / wInt[j];
408#ifdef CALC_POLY_DERIV_SORTING
429#ifdef CALC_POLY_DERIV_SORTING
430 const MInt noNodes = Nmax + 1;
432 std::vector<MFloat> column(noNodes);
437 for(
MInt i = 0; i < noNodes; i++) {
438 for(
MInt j = 0; j < noNodes; j++) {
440 D(i, j) = wBary[j] / wBary[i] * F1 / (nodes[i] - nodes[j]);
447 for(
MInt j = 0; j < noNodes; j++) {
448 D(i, i) -= column[j];
454 const MInt noNodes = Nmax + 1;
460 for(
MInt i = 0; i < noNodes; i++) {
461 for(
MInt j = 0; j < noNodes; j++) {
463 D(i, j) = wBary[j] / wBary[i] * F1 / (nodes[i] - nodes[j]);
492 const MInt noNodes = Nmax + 1;
499 for(
MInt j = 0; j < noNodes; j++) {
500 for(
MInt n = 0; n < noNodes; n++) {
501 Dhat(j, n) = -Dhat(j, n) * wInt[n] / wInt[j];
527template <MInt nDim, MInt noVariables>
530 const MInt noNodes1D,
531 const MFloat*
const LFaceN,
532 const MFloat*
const LFaceP,
533 MFloat*
const destination) {
536 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
537 const MFloatTensor src(
const_cast<MFloat*
>(source), noNodes1D, noNodes1D, noNodes1D3, noVariables);
538 MFloatTensor dest(destination, noNodes1D, noNodes1D3, noVariables);
541 std::fill_n(destination, noNodes1D * noNodes1D3 * noVariables, F0);
549 for(
MInt i = 0; i < noNodes1D; i++) {
550 for(
MInt j = 0; j < noNodes1D; j++) {
551 for(
MInt k = 0; k < noNodes1D3; k++) {
552 for(
MInt l = 0; l < noVariables; l++) {
553 dest(j, k, l) += src(i, j, k, l) * LFaceN[i];
560 for(
MInt i = 0; i < noNodes1D; i++) {
561 for(
MInt j = 0; j < noNodes1D; j++) {
562 for(
MInt k = 0; k < noNodes1D3; k++) {
563 for(
MInt l = 0; l < noVariables; l++) {
564 dest(j, k, l) += src(i, j, k, l) * LFaceP[i];
571 for(
MInt i = 0; i < noNodes1D; i++) {
572 for(
MInt j = 0; j < noNodes1D; j++) {
573 for(
MInt k = 0; k < noNodes1D3; k++) {
574 for(
MInt l = 0; l < noVariables; l++) {
575 dest(i, k, l) += src(i, j, k, l) * LFaceN[j];
582 for(
MInt i = 0; i < noNodes1D; i++) {
583 for(
MInt j = 0; j < noNodes1D; j++) {
584 for(
MInt k = 0; k < noNodes1D3; k++) {
585 for(
MInt l = 0; l < noVariables; l++) {
586 dest(i, k, l) += src(i, j, k, l) * LFaceP[j];
593 for(
MInt i = 0; i < noNodes1D; i++) {
594 for(
MInt j = 0; j < noNodes1D; j++) {
595 for(
MInt k = 0; k < noNodes1D; k++) {
596 for(
MInt l = 0; l < noVariables; l++) {
597 dest(i, j, l) += src(i, j, k, l) * LFaceN[k];
604 for(
MInt i = 0; i < noNodes1D; i++) {
605 for(
MInt j = 0; j < noNodes1D; j++) {
606 for(
MInt k = 0; k < noNodes1D; k++) {
607 for(
MInt l = 0; l < noVariables; l++) {
608 dest(i, j, l) += src(i, j, k, l) * LFaceP[k];
615 mTerm(1, AT_,
"Bad face id.");
639template <MInt nDim, MInt noVariables,
class T,
class U>
643 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
644 const MFloatTensor src(&source[0], noNodes1D, noNodes1D, noNodes1D3, noVariables);
645 MFloatTensor dest(&destination[0], noNodes1D, noNodes1D3, noVariables);
653 for(
MInt j = 0; j < noNodes1D; j++) {
654 for(
MInt k = 0; k < noNodes1D3; k++) {
655 for(
MInt l = 0; l < noVariables; l++) {
656 dest(j, k, l) = src(0, j, k, l);
662 for(
MInt j = 0; j < noNodes1D; j++) {
663 for(
MInt k = 0; k < noNodes1D3; k++) {
664 for(
MInt l = 0; l < noVariables; l++) {
665 dest(j, k, l) = src(noNodes1D - 1, j, k, l);
671 for(
MInt i = 0; i < noNodes1D; i++) {
672 for(
MInt k = 0; k < noNodes1D3; k++) {
673 for(
MInt l = 0; l < noVariables; l++) {
674 dest(i, k, l) = src(i, 0, k, l);
680 for(
MInt i = 0; i < noNodes1D; i++) {
681 for(
MInt k = 0; k < noNodes1D3; k++) {
682 for(
MInt l = 0; l < noVariables; l++) {
683 dest(i, k, l) = src(i, noNodes1D - 1, k, l);
689 for(
MInt i = 0; i < noNodes1D; i++) {
690 for(
MInt j = 0; j < noNodes1D; j++) {
691 for(
MInt l = 0; l < noVariables; l++) {
692 dest(i, j, l) = src(i, j, 0, l);
698 for(
MInt i = 0; i < noNodes1D; i++) {
699 for(
MInt j = 0; j < noNodes1D; j++) {
700 for(
MInt l = 0; l < noVariables; l++) {
701 dest(i, j, l) = src(i, j, noNodes1D - 1, l);
707 mTerm(1, AT_,
"Bad face id.");
728template <
class T,
class U,
class V,
class W>
730 const V wBary, W vandermonde) {
733 MFloatMatrix vdm(&vandermonde[0], noNodesOut, noNodesIn);
735 for(
MInt k = 0; k < noNodesOut; k++) {
736 MBool rowHasMatch =
false;
737 for(
MInt j = 0; j < noNodesIn; j++) {
739 if(
approx(nodesOut[k], nodesIn[j], MFloatEps)) {
745 if(rowHasMatch ==
false) {
747 for(
MInt j = 0; j < noNodesIn; j++) {
748 MFloat t = wBary[j] / (nodesOut[k] - nodesIn[j]);
752 for(
MInt j = 0; j < noNodesIn; j++) {
753 vdm(k, j) = vdm(k, j) / s;
776template <MInt nDim,
class T,
class U,
class V>
779 const MInt noNodesIn1D = noNodesIn;
780 const MInt noNodesIn1D2 = (nDim == 2 || nDim == 3) ? noNodesIn1D : 1;
781 const MInt noNodesIn1D3 = (nDim == 3) ? noNodesIn1D : 1;
782 const MInt noNodesOut1D = noNodesOut;
783 const MInt noNodesOut1D2 = (nDim == 2 || nDim == 3) ? noNodesOut1D : 1;
784 const MInt noNodesOut1D3 = (nDim == 3) ? noNodesOut1D : 1;
785 const MFloatTensor src(&source[0], noNodesIn, noNodesIn1D2, noNodesIn1D3, noVariables);
786 MFloatTensor dest(&destination[0], noNodesOut, noNodesOut1D2, noNodesOut1D3, noVariables);
787 const MFloatMatrix vdm(&vandermonde[0], noNodesOut, noNodesIn);
791 MFloat* buf1Ptr =
nullptr;
792 MFloat* buf2Ptr =
nullptr;
796 buf1Ptr = &destination[0];
801 buffer1.
resize(noNodesOut, noNodesIn1D2, noNodesIn1D3, noVariables);
802 buf1Ptr = &buffer1[0];
803 buf2Ptr = &destination[0];
807 buffer1.
resize(noNodesOut, noNodesIn1D2, noNodesIn1D3, noVariables);
808 buffer2.
resize(noNodesOut, noNodesOut, noNodesIn, noVariables);
809 buf1Ptr = &buffer1[0];
810 buf2Ptr = &buffer2[0];
814 mTerm(1, AT_,
"Bad dimension - must be 1, 2 or 3.");
816 MFloatTensor buf1(buf1Ptr, noNodesOut, noNodesIn1D2, noNodesIn1D3, noVariables);
820 for(
MInt i = 0; i < noNodesOut1D; i++) {
821 for(
MInt j = 0; j < noNodesIn1D2; j++) {
822 for(
MInt k = 0; k < noNodesIn1D3; k++) {
823 for(
MInt ii = 0; ii < noNodesIn1D; ii++) {
824 for(
MInt l = 0; l < noVariables; l++) {
825 buf1(i, j, k, l) += vdm(i, ii) * src(ii, j, k, l);
833 IF_CONSTEXPR(nDim == 1) {
return; }
835 MFloatTensor buf2(buf2Ptr, noNodesOut, noNodesOut1D2, noNodesIn1D3, noVariables);
839 IF_CONSTEXPR(nDim == 2 || nDim == 3) {
841 for(
MInt i = 0; i < noNodesOut1D; i++) {
842 for(
MInt j = 0; j < noNodesOut1D; j++) {
843 for(
MInt k = 0; k < noNodesIn1D3; k++) {
844 for(
MInt jj = 0; jj < noNodesIn1D; jj++) {
845 for(
MInt l = 0; l < noVariables; l++) {
846 buf2(i, j, k, l) += vdm(j, jj) * buf1(i, jj, k, l);
855 IF_CONSTEXPR(nDim == 3) {
857 for(
MInt i = 0; i < noNodesOut1D; i++) {
858 for(
MInt j = 0; j < noNodesOut1D; j++) {
859 for(
MInt k = 0; k < noNodesOut1D; k++) {
860 for(
MInt kk = 0; kk < noNodesIn1D; kk++) {
861 for(
MInt l = 0; l < noVariables; l++) {
862 dest(i, j, k, l) += vdm(k, kk) * buf2(i, j, kk, l);
Class stores precalculated values for interpolation & integration on the reference interval [-1,...
MFloatVector m_LhatFace[2]
~DgInterpolation()
Destructor clears all member variables.
void init(const MInt polyDeg, const DgPolynomialType polyType, const MInt noNodes, const DgIntegrationMethod intMethod, const MBool sbpMode, const MString sbpOperator)
Sets the member variables and calls the appropriate functions to calculate the nodes and weights etc.
DgInterpolation()
Default constructor only sets default values for member variables.
void initInterpolation(const MInt polyDeg, const DgPolynomialType polyType, const MInt noNodes, const DgIntegrationMethod intMethod, const MBool sbpMode, const MString sbpOperator)
Sets the member variables neccessary for the interpolation between sets of nodes.
void transpose()
Transposes the first two dimensions (i.e. acting as if the tensor is a matrix).
void set(const T &value)
Initializes tensor to constant value.
size_type resize(size_type n0, size_type n1=1, size_type n2=1, size_type n3=1, size_type n4=1)
Deletes the old data structure and creates a new one with the requested dimensions.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MBool approx(const T &, const U &, const T)
std::basic_string< char > MString
void calcLegendreGaussLobattoNodesAndWeights(MInt Nmax, MFloat *nodes, MFloat *wInt)
Calculate the Gauss-Lobatto integration nodes and weight for the Legendre polynomials on the interval...
void calcQandL(MInt Nmax, MFloat x, MFloat &q, MFloat &qDeriv, MFloat &poly)
Auxiliary function (only used by calcLegendreGaussLobattoNodesAndWeights())
void calcLagrangeInterpolatingPolynomials(const MFloat x, const MInt polyDeg, const MFloat *nodes, const MFloat *wBary, MFloat *polynomials)
Calculates the values of the Lagrangian polynomials l_j for a given point x in [-1,...
void calcPolynomialInterpolationMatrix(MInt noNodesIn, const T nodesIn, MInt noNodesOut, const U nodesOut, const V wBary, W vandermonde)
Calculate the polynomial interpolation matrix (Vandermonde) to interpolate from one set of nodes to a...
MFloat getLagrangeInterpolation(MFloat x, MInt Nmax, const MFloat *nodes, const MFloat *values, const MFloat *wBary)
Calculates the interpolated value at point x given a set of nodes, values, and weights.
void calcBarycentricWeights(MInt Nmax, const MFloat *nodes, MFloat *weights)
Calculates the barycentric weights for Lagrange interpolation at thei specified nodes.
void calcLhat(const MFloat x, const MInt polyDeg, const MFloat *nodes, const MFloat *wInt, const MFloat *wBary, MFloat *Lhat)
Calculates the Lagrange polynomials evaluated at point x in [-1,1] and pre-divides them by the integr...
void calcPolynomialDerivativeMatrix(MInt Nmax, const MFloat *nodes, const MFloat *wBary, MFloat *derivMatrix)
Calculates the first derivative approximation matrix.
void calcLegendreGaussNodesAndWeights(MInt Nmax, MFloat *nodes, MFloat *wInt)
Calculate the Gauss integration nodes and weight for the Legendre polynomials on the interval [-1,...
void prolongToFaceGauss(const MFloat *const source, const MInt faceId, const MInt noNodes1D, const MFloat *const LFaceN, const MFloat *const LFaceP, MFloat *const destination)
Extrapolates ("prolongs") the Gauss node values of an element to a given face.
MBool ascendingAbsVal(MFloat i, MFloat j)
void calcDhat(MInt Nmax, const MFloat *nodes, const MFloat *wInt, const MFloat *wBary, MFloat *dhatMatrix)
Calculates the polynomial derivative matrix and normalizes it using the integration weights.
void prolongToFaceGaussLobatto(const T source, const MInt faceId, const MInt noNodes1D, U destination)
Extrapolates ("prolongs") the Gauss-Lobatto node values of an element to a given face.
void calcLegendrePolyAndDeriv(MInt Nmax, MFloat x, MFloat *polynomial, MFloat *derivative)
Evaluates the Legendre polynomial and its derivative of degree Nmax at point x.
void interpolateNodes(const T source, U vandermonde, MInt noNodesIn, MInt noNodesOut, MInt noVariables, V destination)
void calculateLegendrePolyAndDeriv(MInt Nmax, MFloat x, MFloat *polynomial, MFloat *derivative)
Evaluates the Legendre polynomial and its derivative of degree Nmax at point x.
void calculateLegendreGaussNodesAndWeights(MInt Nmax, MFloat *nodes, MFloat *wInt)
Calculate the Gauss integration nodes and weight for the Legendre polynomials on the interval [-1,...
Namespace for auxiliary functions/classes.