/// <summary> /// Evaluates the vector-valued anti-derivatives defining the /// moment-fitting basis (cf. <see cref="lambdaBasis"/>) in each node /// of all cells in the given range /// </summary> /// <param name="i0"> /// First cell in range /// </param> /// <param name="length"> /// Number of cells /// </param> /// <returns> /// The values of <see cref="lambdaBasis"/> in each node /// <list type="bullet"> /// <item>1st index: Node index</item> /// <item>2nd index: Basis function index</item> /// <item>3rd index: Spatial dimension</item> /// </list> /// </returns> /// <remarks> /// This method does not evaluate a Lambda which is constant since the /// derivative of such function is zero. As a result, the integral over /// this function is zero, too, which makes it useless for the /// construction of a quadrature rule /// </remarks> /// <param name="NS"> /// Nodes at which to evaluate. /// </param> private MultidimensionalArray EvaluateLambdas(int cell, NodeSet NS) { int D = LevelSetData.GridDat.SpatialDimension; Debug.Assert( lambdaBasis.Count % D == 0, "Number of polynomials in basis should be divisible by D = " + D); int noOfLambdas = lambdaBasis.Count / D; int noOfNodes = NS.NoOfNodes; if (RestrictNodes) { AffineTrafo trafo = trafos[localCellIndex2SubgridIndex[cell]]; AffineTrafo inverse = trafo.Invert(); NS = new NodeSet(RefElement, inverse.Transform(NS)); NS.LockForever(); MultidimensionalArray lambdaValues = lambdaBasis.Values.GetValues(NS); lambdaValues = lambdaValues.ResizeShallow(noOfNodes, noOfLambdas, D); for (int i = 0; i < noOfNodes; i++) { for (int j = 0; j < noOfLambdas; j++) { for (int d = 0; d < D; d++) { // Bounding box transformation is assumed to just a // stretching, i.e. off-diagonals are zero lambdaValues[i, j, d] *= trafo.Matrix[d, d]; } } } return(lambdaValues); } else { MultidimensionalArray lambdaValues = lambdaBasis.Values.GetValues(NS); return(lambdaValues.ResizeShallow(noOfNodes, noOfLambdas, D)); } }
/// <summary> /// Non-vectorized reference implementation of /// <see cref="GetOptimizedRule(int, AffineTrafo, NodeSet, double[,], int)"/> /// </summary> /// <param name="cell"></param> /// <param name="trafo"></param> /// <param name="nodes"></param> /// <param name="quadResults"></param> /// <param name="order"></param> /// <returns></returns> private QuadRule GetOptimizedRule(int cell, AffineTrafo trafo, NodeSet nodes, double[,] quadResults, int order) { int maxLambdaDegree = order + 1; int noOfLambdas = GetNumberOfLambdas(maxLambdaDegree); int noOfNodes = nodes.GetLength(0); // Leading dimension of B (rhs); required by DGELSY int LDB = Math.Max(noOfLambdas, noOfNodes); double[] rhs = new double[LDB]; AffineTrafo inverseTrafo = trafo.Invert(); NodeSet trafoNodes = new NodeSet(RefElement, inverseTrafo.Transform(nodes)); trafoNodes.LockForever(); Basis basis = new Basis(LevelSetData.GridDat, order); MultidimensionalArray basisValues = basis.Evaluate(trafoNodes); int iSubGrid = localCellIndex2SubgridIndex[cell]; for (int k = 0; k < noOfLambdas; k++) { rhs[k] += quadResults[iSubGrid, k]; } LAPACK.F77_LAPACK.DGELSY(noOfLambdas, noOfNodes, basisValues.Storage, rhs, 1, RCOND); QuadRule optimizedRule = new QuadRule() { Nodes = nodes, Weights = MultidimensionalArray.Create(noOfNodes), OrderOfPrecision = order }; for (int j = 0; j < noOfNodes; j++) { optimizedRule.Weights[j] = rhs[j]; } return(optimizedRule); }