Exemplo n.º 1
0
        /// <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);
            }
        }