/// <summary> /// Uses a moment-fitting basis of order <paramref name="order"/> for /// determining optimal weights of a quadrature rule for a sub-region /// of each cell in the given <paramref name="mask"/>. /// </summary> /// <param name="mask"> /// Cells for which rules shall be created /// </param> /// <param name="nodes">Integration nodes</param> /// <param name="quadResults"> /// Integration results for each function in the /// <see cref="lambdaBasis"/> /// </param> /// <param name="order"> /// Desired order of the moment-fitting system. Assuming that /// <see cref="surfaceRuleFactory"/> integrates the basis /// polynomials exactly over the zero iso-contour (which it usually /// doesn't), the resulting quadrature rules will be exact up to this /// order. /// </param> /// <returns> /// A set of quadrature rules /// </returns> private QuadRule[] GetOptimizedRules(CellMask mask, NodeSet nodes, double[,] quadResults, int order) { using (var tr = new FuncTrace()) { int maxLambdaDegree = order + 1; int noOfLambdas = GetNumberOfLambdas(maxLambdaDegree); int noOfNodes = nodes.GetLength(0); QuadRule[] optimizedRules = new QuadRule[mask.NoOfItemsLocally]; if (mask.NoOfItemsLocally == 0) { return(optimizedRules); } // Leading dimension of B (rhs); required by DGELSY int LDB = Math.Max(noOfLambdas, noOfNodes); double[] rhs = new double[LDB * mask.NoOfItemsLocally]; Basis basis = new Basis(LevelSetData.GridDat, order); MultidimensionalArray basisValues = basis.Evaluate(nodes); int n = 0; foreach (Chunk chunk in mask) { foreach (int cell in chunk.Elements) { int iSubGrid = localCellIndex2SubgridIndex[cell]; for (int k = 0; k < noOfLambdas; k++) { rhs[n * LDB + k] += quadResults[iSubGrid, k]; } n++; } } double[] matrix; if (basisValues.IsContinious) { matrix = basisValues.Storage; } else { matrix = new double[basisValues.Length]; basisValues.CopyTo(matrix, true, 0); } LAPACK.F77_LAPACK.DGELSY(noOfLambdas, noOfNodes, matrix, rhs, mask.NoOfItemsLocally, RCOND); n = 0; foreach (Chunk chunk in mask) { foreach (int cell in chunk.Elements) { optimizedRules[n] = new QuadRule() { Nodes = nodes, Weights = MultidimensionalArray.Create(noOfNodes), OrderOfPrecision = order }; for (int j = 0; j < noOfNodes; j++) { optimizedRules[n].Weights[j] = rhs[n * LDB + j]; } double max = optimizedRules[n].Weights.Max(d => d.Abs()); if (max > 2.0 * RefElement.Volume) { tr.Info(String.Format( "Warning: Abnormally large integration weight detected" + " for level set volume integral in cell {0}" + " (|w| = {1}). This may indicate a loss of" + " integration accuracy.", cell, max)); } n++; } } return(optimizedRules); } }