Exemplo n.º 1
0
        /// <summary>
        /// Boundary quadrature for the surface elements, i.e. for each cut background-cell \f$ K_j \f$ a quadrature to approximate
        /// \f[
        ///    \int_{\partial K_j \cap \mathfrak{I} } \ldots \mathrm{dS} .
        /// \f]
        /// </summary>
        public EdgeQuadratureScheme GetEdgeQuadScheme(SpeciesId sp, bool UseDefaultFactories = true, EdgeMask IntegrationDomain = null, int?fixedOrder = null)
        {
            if (!this.SpeciesList.Contains(sp))
            {
                throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported.");
            }


            // determine domain
            // ================
            var allRelevantEdges = GetEdgeMask(sp, IntegrationDomain);

            // create quadrature scheme
            // ========================
            {
                // default rules for all edges:
                EdgeQuadratureScheme edgeQrIns = new EdgeQuadratureScheme(UseDefaultFactories, allRelevantEdges);

                // overwrite with cut-cell-rules in cut-cells:
                foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements)
                {
                    for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++)   // loop over level sets...
                    {
                        EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet).Intersect(allRelevantEdges);
#if DEBUG
                        CellMask difference = cutEdges.GetAdjacentCells(XDGSpaceMetrics.GridDat).Except(XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet));
                        if (difference.Count() > 0)
                        {
                            throw new ArithmeticException("Edges of the Cells" + difference.GetSummary() + " are detected as cut, but these cells are not contained in the cut Cell-Mask of the Level-Set-Tracker");
                        }
#endif


                        var jmp     = IdentifyWing(iLevSet, sp);
                        var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetEdgeRuleFactory(iLevSet, jmp, Kref);
                        edgeQrIns.AddFactoryDomainPair(factory, cutEdges, fixedOrder);
                    }
                }

                return(edgeQrIns);
            }
        }
        /// <summary>
        /// Constructs the quadrature rules all edges of all cells in
        /// <paramref name="mask"/>. For edges that are not intersected by the
        /// zero iso-contour, standard Gaussian quadrature rules of
        /// sufficiently high order will be used.
        /// </summary>
        /// <param name="mask">
        /// Cells for which quadrature rules shall be created
        /// </param>
        /// <param name="order">
        /// Desired order of the moment-fitting system. Assuming that
        /// <see cref="edgeSurfaceRuleFactory"/> 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>
        /// <remarks>
        /// Since the selected level set is generally discontinuous across cell
        /// boundaries, this method does not make use of the fact that
        /// neighboring cells share edges. That is, the optimization will be
        /// performed twice for each inner edge in <paramref name="mask"/>.
        /// </remarks>
        public IEnumerable <IChunkRulePair <CellBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            using (var tr = new FuncTrace()) {
                if (!(mask is CellMask))
                {
                    throw new ArgumentException("CellMask required", "mask");
                }
#if DEBUG
                CellMask differingCells = ((CellMask)mask).Except(this.LevelSetData.Region.GetCutCellMask4LevSet(this.levelSetIndex));
                if (differingCells.NoOfItemsLocally > 0)
                {
                    throw new ArgumentException("The provided mask has to be a sub-set of the cut cells. Cells " + differingCells.GetSummary() + " are not in the CutCellMaks of this tracker.");
                }
#endif


                int noOfEdges = LevelSetData.GridDat.Grid.RefElements[0].NoOfFaces;
                subGrid = new SubGrid((CellMask)mask);
                localCellIndex2SubgridIndex = subGrid.LocalCellIndex2SubgridIndex;

                if (order != lastOrder)
                {
                    cache.Clear();
                    SwitchOrder(order);
                }

                var result = new List <ChunkRulePair <CellBoundaryQuadRule> >(mask.NoOfItemsLocally);
                CellBoundaryQuadRule[] optimizedRules = GetOptimizedRules((CellMask)mask, order);
                int n = 0;
                foreach (Chunk chunk in mask)
                {
                    foreach (int cell in chunk.Elements)
                    {
                        if (cache.ContainsKey(cell))
                        {
                            result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                           Chunk.GetSingleElementChunk(cell), cache[cell]));
                        }
                        else
                        {
                            cache.Add(cell, optimizedRules[n]);
                            result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                           Chunk.GetSingleElementChunk(cell), optimizedRules[n]));
                        }

                        n++;
                    }
                }

                return(result);
            }
        }