/// <summary>
        /// Run this
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="order"></param>
        void CalculateComboQuadRuleSet(ExecutionMask mask, int order)
        {
            comboRule.order = order;
            rulez[0].Clear();
            rulez[1].Clear();
            //Find quadrature nodes and weights in each cell/chunk
#if LOG_TIME
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
#endif
            foreach (Chunk chunk in mask)
            {
                foreach (int cell in chunk.Elements)
                {
                    QuadRule[] sayeRule = comboRule.ComboEvaluate(cell);
                    ChunkRulePair <QuadRule> sayePair_volume  = new ChunkRulePair <QuadRule>(Chunk.GetSingleElementChunk(cell), sayeRule[0]);
                    ChunkRulePair <QuadRule> sayePair_surface = new ChunkRulePair <QuadRule>(Chunk.GetSingleElementChunk(cell), sayeRule[1]);
                    rulez[0].Add(sayePair_volume);
                    rulez[1].Add(sayePair_surface);
                }
            }
#if LOG_TIME
            stopWatch.Stop();
            long ts = stopWatch.ElapsedMilliseconds;
            Console.WriteLine("Calculated combo cutcell rule : {0}ms", ts);
#endif
        }
示例#2
0
        /*
         * /// <summary>
         * /// initialized by the constructor to avoid MPI-deadlocks;
         * /// </summary>
         * Dictionary<RefElement, EdgeMask> m_Subgrid4Kref_AllEdges = new Dictionary<RefElement, EdgeMask>();
         */

        //LevelSetTracker lsTrk {
        //    get {
        //        return XDGSpaceMetrics.Tracker;
        //    }
        //}


        public EdgeQuadratureScheme Get_SurfaceElement_EdgeQuadScheme(SpeciesId sp)
        {
            if (!this.SpeciesList.Contains(sp))
            {
                throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported.");
            }

            //var allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(this.m_CutCellSubgrid_InnerEdges);

            var innerCutCellEdges    = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().InnerEdgesMask;
            var boundaryCutCellEdges = ExecutionMask.Intersect(this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().BoundaryEdgesMask, this.XDGSpaceMetrics.GridDat.BoundaryEdges);
            var allRelevantEdges     = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(ExecutionMask.Union(innerCutCellEdges, boundaryCutCellEdges));

            //EdgeMask AggEdges = this.CellAgglomeration != null ? this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges : null;
            //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0)
            //    allRelevantEdges = allRelevantEdges.Except(AggEdges);


            var edgeQrIns = new EdgeQuadratureScheme(false, allRelevantEdges);

            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);

                    var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetSurfaceElement_BoundaryRuleFactory(iLevSet, Kref);

                    edgeQrIns.AddFactory(factory, cutEdges);
                }
            }

            return(edgeQrIns);
        }
            public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
            {
                if (!RuleStatus.initialized || order != RuleStatus.order)
                {
#if LOG_ACTIONS
                    Console.WriteLine("Initialize {0} \n", quadMode);
#endif
                    return(InitializeRule(mask, order));
                }
                else
                {
                    switch (RuleStatus.RecalculationMode)
                    {
                    case Mode.CalculateOnceAfterInstantiation:
#if LOG_ACTIONS
                        Console.WriteLine("Reusing {0} \n", quadMode);
#endif
                        return(UseExistingRule(mask));

                    //break;
                    case Mode.RecalculateOnEveryVolumeCall:
                        if (quadMode == QuadratureType.Volume)
                        {
#if LOG_ACTIONS
                            Console.WriteLine("Recalcing {0} \n", quadMode);
#endif
                            return(InitializeRule(mask, order));
                        }
                        else
                        {
#if LOG_ACTIONS
                            Console.WriteLine("Reusing {0} \n", quadMode);
#endif
                            return(UseExistingRule(mask));
                        }

                    //break;
                    case Mode.RecalculateOnEverySurfaceCall:
                        if (quadMode == QuadratureType.Surface)
                        {
#if LOG_ACTIONS
                            Console.WriteLine("Recalcing {0} \n", quadMode);
#endif
                            return(InitializeRule(mask, order));
                        }
                        else
                        {
#if LOG_ACTIONS
                            Console.WriteLine("Reusing {0} \n", quadMode);
#endif
                            return(UseExistingRule(mask));
                        }

                    //break;
                    default:
                        throw new NotImplementedException();
                        //break;
                    }
                }
            }
            IEnumerable <IChunkRulePair <QuadRule> > UseExistingRule(ExecutionMask subMask)
            {
                if (subMask.Equals(RuleStatus.initialMask))
                {
                    return(rule);
                }
                //If not, filter rules to fit subMask
                else
                {
                    Debug.Assert(subMask.IsSubMaskOf(RuleStatus.initialMask));
                    List <IChunkRulePair <QuadRule> > subRulez = new List <IChunkRulePair <QuadRule> >(subMask.Count());

                    IEnumerator <int> initialMask_enum = RuleStatus.initialMask.GetItemEnumerator();
                    int      i = 0;
                    BitArray subMask_bitmask = subMask.GetBitMask();
                    while (initialMask_enum.MoveNext())
                    {
                        if (subMask_bitmask[initialMask_enum.Current])
                        {
                            subRulez.Add(rule.ElementAt(i));
                        }
                        ++i;
                    }
                    return(subRulez);
                }
            }
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            rule.order = order;
            var result = new List <ChunkRulePair <QuadRule> >();


#if LOG_TIME
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
#endif
            //Find quadrature nodes and weights in each cell/chunk
            foreach (Chunk chunk in mask)
            {
                foreach (int cell in chunk.Elements)
                {
                    QuadRule sayeRule = rule.Evaluate(cell);
                    ChunkRulePair <QuadRule> sayePair = new ChunkRulePair <QuadRule>(Chunk.GetSingleElementChunk(cell), sayeRule);
                    result.Add(sayePair);
                }
            }
#if LOG_TIME
            stopWatch.Stop();
            long ts = stopWatch.ElapsedMilliseconds;
            Console.WriteLine("Calculated cutcell rule : {0}ms", ts);
#endif
            return(result);
        }
示例#6
0
        /// <summary>
        /// Estimates the distance below which we consider an element (i.e.,
        /// cell or edge) cut. This is important in the case of curved
        /// interfaces.
        /// </summary>
        /// <param name="element">
        /// The element (edge or cell) in question.
        /// </param>
        /// <param name="mask">
        /// The mask containing the given element <paramref name="element"/>.
        /// </param>
        /// <returns>
        /// The minimal distance below which consider element
        /// <paramref name="element"/> cut.
        /// </returns>
        /// <remarks>
        /// Uses different estimates depending on the element type. The case of
        /// edges is straightforward (since we don't have enough information to
        /// do something sophisticated). For cells, we use a modified version of
        /// a formular given by MinGibou2007:
        /// \f$
        /// \max |\Phi(v)| \leq 0.5 * \mathrm{Lip}(\Phi) h_\mathrm{max}.
        /// \f$
        /// In particular, we assume that the Lipschitz constant is close to 1
        /// which is true if the level set is signed distance. A more
        /// sophisticated method would evaluate the gradients at the vertices
        /// in order to estimate the Lipschitz constant, but this would be less
        /// efficient.
        /// </remarks>
        private double EstimateMinDistance(int element, ExecutionMask mask)
        {
            double minDistance = double.NaN;

            if (mask is CellMask)
            {
                // Assume norm of gradient \approx 1
                // -> Lipschitz constant is in the order of 1
                double hMaxEdge    = -1.0;
                int[]  cells2Edges = gridData.Cells.Cells2Edges[element];
                for (int e = 0; e < cells2Edges.Length; e++)
                {
                    int edgeIndex = Math.Abs(cells2Edges[e]) - 1;
                    hMaxEdge = Math.Max(gridData.Edges.h_max_Edge[edgeIndex], hMaxEdge);
                }
                minDistance = 0.5 * hMaxEdge;
            }
            else if (mask is EdgeMask)
            {
                //minDistance = 0.5 * gridData.Edges.h_max_Edge[element];
                minDistance = 1.0 * gridData.Edges.h_max_Edge[element];
            }
            else
            {
                throw new NotImplementedException("Unknown mask type");
            }

            return(minDistance);
        }
        /// <summary>
        /// construction of the quadrature rule.
        /// </summary>
        public IEnumerable <IChunkRulePair <DoubleEdgeQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }


            var orgQr = this.RefElement.GetQuadratureRule(order);
            var dblQr = new DoubleEdgeQuadRule();

            dblQr.OrderOfPrecision = orgQr.OrderOfPrecision;
            int L = orgQr.NoOfNodes;
            int D = orgQr.Nodes.GetLength(1);

            dblQr.Median  = L;
            dblQr.Nodes   = new NodeSet(this.RefElement, L * 2, D);
            dblQr.Weights = MultidimensionalArray.Create(L * 2);
            dblQr.Nodes.SetSubArray(orgQr.Nodes, new int[] { 0, 0 }, new int[] { L - 1, D - 1 });
            dblQr.Nodes.SetSubArray(orgQr.Nodes, new int[] { L, 0 }, new int[] { 2 * L - 1, D - 1 });
            dblQr.Weights.SetSubArray(orgQr.Weights, new int[] { 0 }, new int[] { L - 1 });
            dblQr.Weights.SetSubArray(orgQr.Weights, new int[] { L }, new int[] { 2 * L - 1 });
            dblQr.Nodes.LockForever();

            return(mask.Select(chunk => new ChunkRulePair <DoubleEdgeQuadRule>(chunk, dblQr)));
        }
        public IEnumerable <IChunkRulePair <CellBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            using (var tr = new FuncTrace()) {
                if (mask != null && mask is CellMask == false)
                {
                    throw new ArgumentException("Cell mask required", "mask");
                }
                if (mask.MaskType != MaskType.Geometrical)
                {
                    throw new ArgumentException("Expecting a geometrical mask.");
                }


                Stopwatch totalTimer        = new Stopwatch();
                Stopwatch projectionTimer   = new Stopwatch();
                Stopwatch optimizationTimer = new Stopwatch();

                totalTimer.Start();
                if (order != currentOrder)
                {
                    cache.Clear();
                    SwitchOrder(order);
                }

                var result = new List <ChunkRulePair <CellBoundaryQuadRule> >(mask.NoOfItemsLocally);
                foreach (Chunk chunk in mask)
                {
                    for (int i = 0; i < chunk.Len; i++)
                    {
                        int cell = chunk.i0 + i;

                        if (cache.ContainsKey(cell))
                        {
                            result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                           Chunk.GetSingleElementChunk(cell),
                                           cache[cell]));
                            continue;
                        }

                        optimizationTimer.Start();
                        CellBoundaryQuadRule optimizedRule = GetOptimizedRule(chunk.i0 + i, order);
                        optimizationTimer.Stop();

                        cache.Add(cell, optimizedRule);
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                       Chunk.GetSingleElementChunk(i + chunk.i0), optimizedRule));
                    }
                }
                totalTimer.Stop();

                double totalTicks             = (double)totalTimer.ElapsedTicks;
                double percentageProjection   = Math.Round(projectionTimer.ElapsedTicks / totalTicks * 100, 2);
                double percentageOptimization = Math.Round(optimizationTimer.ElapsedTicks / totalTicks * 100, 2);
                tr.Info("Percentage spent on projection to surface: " + percentageProjection.ToString(NumberFormatInfo.InvariantInfo) + "%");
                tr.Info("Percentage spent on optimization: " + percentageOptimization.ToString(NumberFormatInfo.InvariantInfo) + "%");

                return(result);
            }
        }
 IEnumerable <IChunkRulePair <QuadRule> > InitializeRule(ExecutionMask subMask, int Order)
 {
     ComboRuleEvaluator(subMask, Order);
     RuleStatus.order       = Order;
     RuleStatus.initialMask = subMask;
     RuleStatus.initialized = true;
     return(rule);
 }
示例#10
0
        /// <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 (mask.MaskType != MaskType.Geometrical)
                {
                    throw new ArgumentException("Expecting a geometrical mask.");
                }

                int      noOfEdges      = LevelSetData.GridDat.Grid.RefElements[0].NoOfFaces;
                CellMask tmpLogicalMask = new CellMask(mask.GridData, mask.GetBitMask(), MaskType.Logical);
#if DEBUG
                CellMask differingCells = tmpLogicalMask.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 {0} are not in the CutCellMaks of this tracker.", differingCells.GetSummary());
                }
#endif

                subGrid = new SubGrid(tmpLogicalMask);
                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);
            }
        }
示例#11
0
        /// <summary>
        /// Uses <see cref="Grid.RefElement.GetQuadratureRule"/> to create a quad rule
        /// (i.e., the quad rule is the same for all elements of
        /// <paramref name="mask"/>)
        /// </summary>
        /// <param name="mask">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <param name="order">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <returns>
        /// <see cref="Grid.RefElement.GetQuadratureRule"/>
        /// </returns>
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            QuadRule rule = RefElement.GetQuadratureRule(order);

            Debug.Assert(rule.Nodes.IsLocked, "Error: non-locked quad rule from reference element.");
            Debug.Assert(object.ReferenceEquals(rule.Nodes.RefElement, RefElement), "Error: quad rule from reference element has not the right reference elment assigned.");

            return(mask.Select(chunk => new ChunkRulePair <QuadRule>(chunk, rule)));
        }
示例#12
0
            public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
            {
                if (!(mask is CellMask))
                {
                    throw new ArgumentException("Expecting a cell mask.");
                }
                if (mask.MaskType != MaskType.Geometrical)
                {
                    throw new ArgumentException("Expecting a geometrical mask.");
                }

#if DEBUG
                if (mask.Except(m_Owner.MaxGrid).NoOfItemsLocally > 0)
                {
                    throw new NotSupportedException("'mask' must be a subset of the cut cells, for my reference element.");
                }
#endif
                if (!Rules.ContainsKey(order))
                {
                    m_Owner.GetQuadRuleSet_Internal(order);
                }

                if (mask.NoOfItemsLocally == m_Owner.MaxGrid.NoOfItemsLocally)
                {
                    // aggressive
                    return(Rules[order]);
                }
                else
                {
                    var Rule = Rules[order];

                    SubGrid S          = new SubGrid((CellMask)mask);
                    var     jsub2jcell = S.SubgridIndex2LocalCellIndex;
                    var     Ret        = new ChunkRulePair <QuadRule> [S.LocalNoOfCells_WithExternal];

                    int L = Ret.Length, H = Rule.Length;
                    int h = 0;
                    for (int jsub = 0; jsub < L; jsub++)
                    {
                        int jCell = jsub2jcell[jsub];

                        Debug.Assert(Rule[h].Chunk.Len == 1);

                        while (jCell > Rule[h].Chunk.i0)
                        {
                            h++;
                        }

                        Debug.Assert(jCell == Rule[h].Chunk.i0);
                        Ret[jsub] = Rule[h];
                    }

                    return(Ret);
                }
            }
示例#13
0
        /// <summary>
        /// Returns the quad rule supplied to the constructor for every
        /// single chunk in <paramref name="mask"/>.
        /// </summary>
        /// <param name="mask">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <param name="order">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <returns>
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </returns>
        public IEnumerable <IChunkRulePair <T> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            var result   = new List <IChunkRulePair <T> >(mask.Count());
            var quadRule = m_qr;

            foreach (Chunk chunk in mask)
            {
                result.Add(new ChunkRulePair <T>(chunk, quadRule));
            }
            return(result);
        }
示例#14
0
 public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
 {
     if (!ruleStatus.Initialized || order != ruleStatus.Order)
     {
         InitializeRule(order);
         return(UseExistingRule(mask));
     }
     else
     {
         return(UseExistingRule(mask));
     }
 }
示例#15
0
        /// <summary>
        /// Uses <see cref="Grid.RefElement.GetQuadratureRule"/> to create a quad rule
        /// (i.e., the quad rule is the same for all elements of
        /// <paramref name="mask"/>)
        /// </summary>
        /// <param name="mask">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <param name="order">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <returns>
        /// <see cref="Grid.RefElement.GetQuadratureRule"/>
        /// </returns>
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }

            QuadRule rule = RefElement.GetQuadratureRule(order);

            Debug.Assert(rule.Nodes.IsLocked, "Error: non-locked quad rule from reference element.");
            Debug.Assert(object.ReferenceEquals(rule.Nodes.RefElement, RefElement), "Error: quad rule from reference element has not the right reference elment assigned.");

            return(mask.Select(chunk => new ChunkRulePair <QuadRule>(chunk, rule)));
        }
示例#16
0
        /// <summary>
        /// Returns the quad rule supplied to the constructor for every
        /// single chunk in <paramref name="mask"/>.
        /// </summary>
        /// <param name="mask">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <param name="order">
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </param>
        /// <returns>
        /// <see cref="IQuadRuleFactory{QuadRule}.GetQuadRuleSet"/>
        /// </returns>
        public IEnumerable <IChunkRulePair <T> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }

            var result   = new List <IChunkRulePair <T> >(mask.Count());
            var quadRule = m_qr;

            foreach (Chunk chunk in mask)
            {
                result.Add(new ChunkRulePair <T>(chunk, quadRule));
            }
            return(result);
        }
示例#17
0
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }
            var baseSet = baseFactory.GetQuadRuleSet(mask, order);

            var result = new List <ChunkRulePair <QuadRule> >();

            foreach (var chunkRulePair in baseSet)
            {
                MultidimensionalArray levelSetValues = tracker.DataHistories[levSetIndex].Current.GetLevSetValues(
                    chunkRulePair.Rule.Nodes, chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len);
                MultidimensionalArray gradientValues = tracker.DataHistories[levSetIndex].Current.GetLevelSetGradients(
                    chunkRulePair.Rule.Nodes, chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len);

                foreach (int cell in chunkRulePair.Chunk.Elements)
                {
                    QuadRule rule = chunkRulePair.Rule.CloneAs();

                    for (int i = 0; i < rule.NoOfNodes; i++)
                    {
                        rule.Weights[i] *= polynomial.Evaluate(levelSetValues[cell - chunkRulePair.Chunk.i0, i], width);

                        // Scale by the norm of the gradient in order to be on
                        // the safe side with non-signed-distance functions
                        double norm = 0.0;
                        for (int j = 0; j < RefElement.SpatialDimension; j++)
                        {
                            int index = cell - chunkRulePair.Chunk.i0;
                            norm += gradientValues[index, i, j] * gradientValues[index, i, j];
                        }
                        rule.Weights[i] *= Math.Sqrt(norm);
                    }

                    result.Add(new ChunkRulePair <QuadRule>(
                                   Chunk.GetSingleElementChunk(cell), rule));
                }
            }

            return(result);
        }
示例#18
0
        /// <summary>
        /// Constructs the <see cref="ExecutionMask"/> of the appropriate type
        /// containing all cells/edges with reference element <paramref name="E"/>
        /// </summary>
        /// <param name="E"></param>
        /// <param name="g"></param>
        /// <returns></returns>
        TDomain GetDomainForRefElement(Grid.RefElements.RefElement E, IGridData g)
        {
            ExecutionMask em = null;

            if (typeof(TDomain) == typeof(EdgeMask) || typeof(TDomain).IsSubclassOf(typeof(EdgeMask)))
            {
                em = g.iLogicalEdges.GetEdges4RefElement(E);
            }
            else if (typeof(TDomain) == typeof(CellMask) || typeof(TDomain).IsSubclassOf(typeof(CellMask)))
            {
                em = g.iLogicalCells.GetCells4Refelement(E);
            }
            else
            {
                throw new NotImplementedException();
            }


            return((TDomain)(em));
        }
示例#19
0
            public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
            {
                if (mask.MaskType != MaskType.Geometrical)
                {
                    throw new ArgumentException("Expecting a geometrical mask.");
                }

                QuadRule fullRule = RefElement.GetQuadratureRule(order);
                int      L1       = fullRule.NoOfNodes;
                int      D        = fullRule.SpatialDim;

                var otherRule = m_orgrule.GetQuadRuleSet(mask, order);
                var ret       = new List <IChunkRulePair <QuadRule> >(otherRule.Count());

                foreach (var x in otherRule)
                {
                    Chunk    chk = x.Chunk;
                    QuadRule qr  = x.Rule;
                    int      L2  = qr.NoOfNodes;

                    Debug.Assert(qr.SpatialDim == fullRule.SpatialDim);

                    QuadRule compQr = new QuadRule();
                    compQr.OrderOfPrecision = qr.OrderOfPrecision;

                    compQr.Nodes   = new NodeSet(this.RefElement, L1 + L2, D);
                    compQr.Weights = MultidimensionalArray.Create(L1 + L2);


                    compQr.Nodes.SetSubArray(fullRule.Nodes, new int[] { 0, 0 }, new int[] { L1 - 1, D - 1 });
                    compQr.Weights.SetSubArray(fullRule.Weights, new int[] { 0 }, new int[] { L1 - 1 });
                    compQr.Nodes.SetSubArray(qr.Nodes, new int[] { L1, 0 }, new int[] { L1 + L2 - 1, D - 1 });
                    compQr.Weights.AccSubArray(-1, qr.Weights, new int[] { L1 }, new int[] { L1 + L2 - 1 });

                    compQr.Nodes.LockForever();

                    ret.Add(new ChunkRulePair <QuadRule>(chk, compQr));
                }

                return(ret);
            }
示例#20
0
        /// <summary>
        /// Constructs the <see cref="ExecutionMask"/> of the appropriate type
        /// containing all cells/edges with reference element <paramref name="E"/>
        /// </summary>
        /// <param name="E"></param>
        /// <param name="g"></param>
        /// <returns></returns>
        TDomain GetDomainForRefElement(RefElement E, IGridData g)
        {
            ExecutionMask em = null;

            if (typeof(TDomain) == typeof(EdgeMask) || typeof(TDomain).IsSubclassOf(typeof(EdgeMask)))
            {
                em = g.iGeomEdges.GetEdges4RefElement(E);
            }
            else if (typeof(TDomain) == typeof(CellMask) || typeof(TDomain).IsSubclassOf(typeof(CellMask)))
            {
                em = g.iGeomCells.GetCells4Refelement(E);
            }
            else
            {
                throw new NotImplementedException();
            }

            if (em.MaskType != MaskType.Geometrical)
            {
                throw new ApplicationException();
            }

            return((TDomain)(em));
        }
示例#21
0
        IEnumerable <IChunkRulePair <QuadRule> > IQuadRuleFactory <QuadRule> .GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }

            var    ret = new List <IChunkRulePair <QuadRule> >();
            double R   = RADIUS[iLevSet];

            foreach (var chunk in mask)
            {
                for (int jCell = chunk.i0; jCell < chunk.JE; jCell++)
                {
                    double alpha_0, alpha_1;
                    FindAngles(jCell, RADIUS[this.iLevSet], _Context, out alpha_0, out alpha_1);

                    if (alpha_0 == alpha_1)
                    {
                        QuadRule emptyRule = new QuadRule();
                        emptyRule.Nodes            = new NodeSet(this.RefElement, new double[1, 2]);
                        emptyRule.Weights          = MultidimensionalArray.Create(1);
                        emptyRule.OrderOfPrecision = 123;
                        ret.Add(new ChunkRulePair <QuadRule>(new Chunk()
                        {
                            i0 = jCell, Len = 1
                        }, emptyRule));
                    }
                    else
                    {
                        var da1Drule = this.RefElement.FaceRefElement.GetBruteForceQuadRule(8, order);

                        QuadRule Bogenrule = new QuadRule();

                        var GlobNodes = MultidimensionalArray.Create(da1Drule.NoOfNodes, 2);
                        var LocNodes  = MultidimensionalArray.Create(1, da1Drule.NoOfNodes, 2);
                        Bogenrule.Nodes = new NodeSet(this.RefElement, da1Drule.NoOfNodes, 2);

                        for (int k = 0; k < da1Drule.NoOfNodes; k++)
                        {
                            double beta  = da1Drule.Nodes[k, 0];
                            double alpha = alpha_0 + (beta + 1) * 0.5 * (alpha_1 - alpha_0);

                            GlobNodes[k, 0] = R * Math.Cos(alpha);
                            GlobNodes[k, 1] = R * Math.Sin(alpha);

                            if (Position != null)
                            {
                                GlobNodes[k, 0] += Position[0];
                                GlobNodes[k, 1] += Position[1];
                            }
                        }
                        _Context.TransformGlobal2Local(GlobNodes, LocNodes, jCell, 1, 0);
                        Bogenrule.Nodes.Set(LocNodes.ExtractSubArrayShallow(0, -1, -1));

                        var GlobCenter = MultidimensionalArray.Create(1, 2);
                        var LocCenter  = MultidimensionalArray.Create(1, 1, 2);
                        _Context.TransformGlobal2Local(GlobCenter, LocCenter, jCell, 1, 0);

                        //double RR = Math.Sqrt((LocNodes[0, 0, 0] - LocCenter[0, 0, 0]).Pow2() + (LocNodes[0, 0, 1] - LocCenter[0, 0, 1]).Pow2());


                        //double metric = (R*(alpha_1 - alpha_0)/2.0)/_Context.ChefBasis.Scaling[jCell];
                        double metric = (R * (alpha_1 - alpha_0) / 2.0) / _Context.Cells.JacobiDet[jCell];
                        //double metric = R;
                        Bogenrule.OrderOfPrecision = 123;
                        Bogenrule.Weights          = da1Drule.Weights.CloneAs();
                        Bogenrule.Weights.Scale(metric);
                        Bogenrule.Nodes.LockForever();

                        ret.Add(new ChunkRulePair <QuadRule>(new Chunk()
                        {
                            i0 = jCell, Len = 1
                        }, Bogenrule));
                        //*/

                        /*
                         * var da1Drule = this.RefElement.FaceRefElement.GetBruteForceQuadRule(8, order);
                         *
                         * QuadRule PswsLin = new QuadRule();
                         *
                         * var GlobNodes = MultidimensionalArray.Create(da1Drule.NoOfNodes, 2);
                         * var LocNodes = MultidimensionalArray.Create(1, da1Drule.NoOfNodes, 2);
                         * PswsLin.Nodes = new NodeSet(this.RefElement, da1Drule.NoOfNodes, 2);
                         *
                         * double x0 = Math.Cos(alpha_0) * R;
                         * double y0 = Math.Sin(alpha_0) * R;
                         * double x1 = Math.Cos(alpha_1) * R;
                         * double y1 = Math.Sin(alpha_1) * R;
                         * double dist = Math.Sqrt((x1 - x0).Pow2() + (y1 - y0).Pow2());
                         *
                         * for(int k = 0; k < da1Drule.NoOfNodes; k++) {
                         *  double beta = da1Drule.Nodes[k, 0];
                         *  //double alpha = alpha_0 + (beta + 1) * 0.5 * (alpha_1 - alpha_0);
                         *
                         *  //GlobNodes[k, 0] = R * Math.Cos(alpha);
                         *  //GlobNodes[k, 1] = R * Math.Sin(alpha);
                         *
                         *  double a = 0.5*(beta + 1);
                         *  GlobNodes[k, 0] = x0*(1 - a) + x1*a;
                         *  GlobNodes[k, 1] = y0 * (1 - a) + y1 * a;
                         *
                         * }
                         * _Context.TransformGlobal2Local(GlobNodes, LocNodes, jCell, 1, 0);
                         * PswsLin.Nodes.Set(LocNodes.ExtractSubArrayShallow(0, -1, -1));
                         *
                         * var GlobCenter = MultidimensionalArray.Create(1, 2);
                         * var LocCenter = MultidimensionalArray.Create(1, 1, 2);
                         * _Context.TransformGlobal2Local(GlobCenter, LocCenter, jCell, 1, 0);
                         *
                         * //double RR = Math.Sqrt((LocNodes[0, 0, 0] - LocCenter[0, 0, 0]).Pow2() + (LocNodes[0, 0, 1] - LocCenter[0, 0, 1]).Pow2());
                         *
                         *
                         * //double metric = (R*(alpha_1 - alpha_0)/2.0)/_Context.ChefBasis.Scaling[jCell];
                         * double metric = (dist / 2.0) / _Context.Cells.JacobiDet[jCell];
                         * //double metric = R;
                         * PswsLin.OrderOfPrecision = 123;
                         * PswsLin.Weights = da1Drule.Weights.CloneAs();
                         * PswsLin.Weights.Scale(metric);
                         * PswsLin.Nodes.LockForever();
                         *
                         * ret.Add(new ChunkRulePair<QuadRule>(new Chunk() { i0 = jCell, Len = 1 }, PswsLin));
                         */
                    }
                }
            }

            return(ret);
        }
示例#22
0
        /// <summary>
        /// Constructs the adapted subdivisions for all cells in
        /// <paramref name="mask"/>. The size of each chunk will be exactly one
        /// since, in general, we cannot expect subsequent cells to have the
        /// same subdivisions.
        /// </summary>
        /// <param name="mask">
        /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/>
        /// </param>
        /// <returns>
        /// The subdivisions for all elements in <paramref name="mask"/>,
        /// </returns>
        public IEnumerable <KeyValuePair <Chunk, IEnumerable <SubdivisionNode> > > GetSubdivisionNodes(ExecutionMask mask)
        {
            using (new FuncTrace()) {
                foreach (int iElement in mask.ItemEnum)  // loop over all cells/edges in mask

                {
                    this.subdivisionTree.ResetToSavePoint();

                    double minDistance = EstimateMinDistance(iElement, mask);

                    NestedVertexSet currentSet = baseVertexSet;
                    for (int i = 0; i < maxDivisions; i++)
                    {
                        if (currentSet.NumberOfLocalVertices == 0)
                        {
                            // No new vertices were added during last subdivision
                            break;
                        }

                        int     cell;
                        NodeSet vertices = GetVertices(iElement, currentSet, mask, out cell);

                        MultidimensionalArray levelSetValues = LevelSetData.GetLevSetValues(vertices, cell, 1);

                        subdivisionTree.ReadDistances(levelSetValues.ExtractSubArrayShallow(0, -1));

                        currentSet = new NestedVertexSet(currentSet);
                        subdivisionTree.Subdivide(
                            currentSet,
                            true,
                            minDistance / Math.Pow(2.0, i));
                    }

                    // Finally, read level set values in leaves (needed by IsCut)
                    {
                        int     cell;
                        NodeSet vertices = GetVertices(iElement, currentSet, mask, out cell);
                        if (vertices != null)
                        {
                            MultidimensionalArray levelSetValues = LevelSetData.GetLevSetValues(vertices, cell, 1);

                            subdivisionTree.ReadDistances(levelSetValues.ExtractSubArrayShallow(0, -1));
                        }
                    }

                    yield return(new KeyValuePair <Chunk, IEnumerable <SubdivisionNode> >(
                                     new Chunk()
                    {
                        i0 = iElement,
                        Len = 1
                    },
                                     subdivisionTree.Leaves));
                }
            }
        }
        /// <summary>
        /// produces an edge quadrature rule
        /// </summary>
        /// <param name="mask">an edge mask</param>
        /// <param name="order">desired order</param>
        /// <returns></returns>
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            // init & checks
            // =============

            if (!(mask is EdgeMask))
            {
                throw new ArgumentException("Expecting an edge mask.");
            }
#if DEBUG
            var maskBitMask = mask.GetBitMask();
#endif

            var      Edg2Cel     = this.grd.iGeomEdges.CellIndices;
            var      Edg2Fac     = this.grd.iGeomEdges.FaceIndices;
            int      J           = this.grd.Cells.NoOfLocalUpdatedCells;
            QuadRule DefaultRule = this.RefElement.GetQuadratureRule(order);;

            int myIKrfeEdge = this.grd.Edges.EdgeRefElements.IndexOf(this.RefElement, (a, b) => object.ReferenceEquals(a, b));
            if (myIKrfeEdge < 0)
            {
                throw new ApplicationException("fatal error");
            }


            int[] EdgeIndices = mask.ItemEnum.ToArray();
            int   NoEdg       = EdgeIndices.Length;

            // return value
            ChunkRulePair <QuadRule>[] Ret = new ChunkRulePair <QuadRule> [NoEdg];

            // find cells
            // ==========

            BitArray CellBitMask   = new BitArray(J);
            int[]    Cells         = new int[NoEdg]; // mapping: Edge Index --> Cell Index (both geometrical)
            int[]    Faces         = new int[NoEdg]; // mapping: Edge Index --> Face
            BitArray MaxDomainMask = m_maxDomain.GetBitMask();
            {
                for (int i = 0; i < NoEdg; i++)
                {
                    int iEdge = EdgeIndices[i];
                    if (this.grd.Edges.GetRefElementIndex(iEdge) != myIKrfeEdge)
                    {
                        throw new ArgumentException("illegal edge mask");
                    }

                    if (!(grd.Edges.IsEdgeConformalWithCell1(iEdge) || grd.Edges.IsEdgeConformalWithCell2(iEdge)))
                    {
                        throw new NotSupportedException("For an edge that is not conformal with at least one cell, no edge rule can be created from a cell boundary rule.");
                    }

                    int  jCell0 = Edg2Cel[iEdge, 0];
                    int  jCell1 = Edg2Cel[iEdge, 1];
                    bool conf0  = grd.Edges.IsEdgeConformalWithCell1(iEdge);
                    bool conf1  = grd.Edges.IsEdgeConformalWithCell2(iEdge);


                    // this gives no errors for surface elements in 3D
                    bool Allow0 = MaxDomainMask[jCell0];
                    bool Allow1 = (jCell1 >= 0 && jCell1 < J) ? MaxDomainMask[jCell1] : false;


                    // //this is required for MPI parallel calculations
                    //bool Allow0 = true;// AllowedCells[jCell0];
                    //bool Allow1 = (jCell1 >= 0 && jCell1 < J);// ? AllowedCells[jCell1] : false;

                    if (!Allow0 && !Allow1)
                    {
                        // fallback onto default rule, if allowed

                        //if (this.m_DefaultRuleFallbackAllowed) {
                        //    Cells[i] = -1; // by a negative index, we mark that we take the default rule
                        //    Faces[i] = -1;
                        //    Ret[i] = new ChunkRulePair<QuadRule>(Chunk.GetSingleElementChunk(EdgeIndices[i]), DefaultRule);


                        //} else {
                        throw new ArgumentException("unable to find a cell from which the edge rule can be taken.");
                        //}
                    }
                    else
                    {
                        Debug.Assert(Allow0 || Allow1);

                        if (conf0 && Allow0)
                        {
                            // cell 0 is allowed and conformal:
                            // take this, it won't get better

                            CellBitMask[jCell0] = true;
                            Faces[i]            = Edg2Fac[iEdge, 0];
                            Cells[i]            = jCell0;
                        }
                        else if (conf1 && Allow1)
                        {
                            // cell 1 is allowed and conformal:
                            // take this, it won't get better

                            CellBitMask[jCell1] = true;
                            Faces[i]            = Edg2Fac[iEdge, 1];
                            Cells[i]            = jCell1;
                        }
                        else if (Allow0)
                        {
                            // cell 0 is allowed, but NOT conformal

                            CellBitMask[jCell0] = true;
                            Faces[i]            = -Edg2Fac[iEdge, 0]; // by a negative index, we mark a non-conformal edge
                            Cells[i]            = jCell0;
                        }
                        else if (Allow1)
                        {
                            // cell 1 is allowed, but NOT conformal

                            CellBitMask[jCell1] = true;
                            Faces[i]            = -Edg2Fac[iEdge, 1]; // by a negative index, we mark a non-conformal edge
                            Cells[i]            = jCell1;
                        }
                    }
                }
            }


            // get cell boundary rule
            // ======================
            var CellMask = new CellMask(this.grd, CellBitMask);


            IChunkRulePair <CellBoundaryQuadRule>[] cellBndRule = this.m_cellBndQF.GetQuadRuleSet(CellMask, order).ToArray();
            int[] jCell2PairIdx = new int[J];
            for (int i = 0; i < cellBndRule.Length; i++)
            {
                var chk = cellBndRule[i].Chunk;
                for (int jCell = chk.JE - 1; jCell >= chk.i0; jCell--)
                {
                    jCell2PairIdx[jCell] = i + 555;
                }
            }

            int[] iChunk = new int[NoEdg]; // which chunk for which edge?
            for (int i = 0; i < NoEdg; i++)
            {
                if (Cells[i] >= 0)
                {
                    iChunk[i] = jCell2PairIdx[Cells[i]] - 555;
                }
                else
                {
                    iChunk[i] = int.MinValue;
                }
            }

            // build rule
            // ==========
            {
                for (int i = 0; i < NoEdg; i++)   // loop over edges
                //if (MaxDomainMask[Cells[i]] == false)
                //    Debugger.Break();

                //if (Cells[i] >= 0) {
                {
                    var      CellBndR = cellBndRule[iChunk[i]].Rule;
                    QuadRule qrEdge   = null;

                    if (Faces[i] >= 0)
                    {
                        qrEdge = this.CombineQr(null, CellBndR, Faces[i]);
                    }
                    else
                    {
                        throw new NotSupportedException("currently no support for non-conformal edges.");
                    }

                    qrEdge.Nodes.LockForever();
                    qrEdge.Weights.LockForever();
                    Ret[i] = new ChunkRulePair <QuadRule>(Chunk.GetSingleElementChunk(EdgeIndices[i]), qrEdge);
                    //} else {
                    //    Debug.Assert(Ret[i] != null);
                    //}
                }
            }


            // return
            // ======

#if DEBUG
            for (int i = 0; i < Ret.Length; i++)
            {
                Chunk c = Ret[i].Chunk;
                for (int e = c.i0; e < c.JE; e++)
                {
                    Debug.Assert(maskBitMask[e] == true);
                }
            }
#endif

            return(Ret);

            /*
             *
             * var EdgesThatConcernMe = grd.Edges.Edges4RefElement[m_cellBndQF.RefElement.FaceSimplex];
             * EdgeMask edgMask = (mask as EdgeMask).Intersect(EdgesThatConcernMe);
             *
             * var ret = new Dictionary<Chunk, QuadRule>(mask.NoOfItemsLocally);
             #if DEBUG
             * var EdgesOfInterest = edgMask.GetBitMask();
             * var EdgeTouched = (BitArray)EdgesOfInterest.Clone();
             *
             * edgMask.ToTxtFile("Edges-" + grd.MyRank + ".csv", false);
             #endif
             *
             *
             * WeightInbalance = 0.0;
             *
             * // find all cells that are 'touched' by the edge mask
             * // --------------------------------------------------
             * int J = grd.Cells.NoOfLocalUpdatedCells;
             * BitArray TouchedCells = new BitArray(J, false);
             *
             * var Edg2Cell = grd.Edges.CellIndices;
             *
             * int chunkCnt = 0;
             * foreach (var chnk in mask) {
             *  int EE = chnk.JE;
             *  for (int e = chnk.i0; e < EE; e++) {
             *      if (!(grd.Edges.IsEdgeConformalwithCell1(e) || grd.Edges.IsEdgeConformalwithCell2(e))) {
             *          throw new NotSupportedException("For an edge that is not conformal with at least one cell, no edge rule can be created from a cell boundary rule.");
             *      }
             *
             *      int j1 = Edg2Cell[e, 0], j2 = Edg2Cell[e, 1];
             *      TouchedCells[j1] = true;
             *      if (j2 >= 0 && j2 < J)
             *          TouchedCells[j2] = true;
             *
             *
             *      Chunk singleEdgeChunk;
             *      singleEdgeChunk.i0 = e;
             *      singleEdgeChunk.Len = 1;
             *
             *      ret.Add(singleEdgeChunk, null);
             *  }
             *  chunkCnt++;
             * }
             *
             * CellMask celMask = new CellMask(grd, TouchedCells);
             * celMask.ToTxtFile("CellsU-" + grd.MyRank + ".csv", false);
             * celMask = celMask.Intersect(m_maxDomain);
             * celMask.ToTxtFile("Cells-" + grd.MyRank + ".csv", false);
             *
             * // create cell boundary rule!
             * IEnumerable<IChunkRulePair<CellBoundaryQuadRule>> cellBndRule = m_cellBndQF.GetQuadRuleSet(celMask, order);
             *
             * //// do MPI communication (get rules for external cells)
             * //{
             * //    int size, rank;
             * //    csMPI.Raw.Comm_Rank(csMPI.Raw._COMM.WORLD, out rank);
             * //    csMPI.Raw.Comm_Size(csMPI.Raw._COMM.WORLD, out size);
             *
             * //    if (size > 1)
             * //        throw new NotSupportedException("currently no MPI support");
             * //}
             *
             * // assign the cell boundary rule to edges
             * // --------------------------------------
             * var volSplx = m_cellBndQF.RefElement;
             * int NoOfFaces = volSplx.NoOfFaces;
             * var Cells2Edge = grd.Cells.Cells2Edges;
             * var FaceIndices = grd.Edges.FaceIndices;
             *
             * int cnt = -1;
             * foreach (var kv in cellBndRule) { // loop over cell chunks (in the cell boundary rule)...
             *  Chunk chk = kv.Chunk;
             *  CellBoundaryQuadRule qr = kv.Rule;
             *  cnt++;
             *
             *  int JE = chk.JE;
             *  for (int j = chk.i0; j < JE; j++) { // loop over all cells in chunk...
             *      Debug.Assert(qr.NumbersOfNodesPerFace.Length == NoOfFaces);
             *      var Cells2Edge_j = Cells2Edge[j];
             *
             *      for (int _e = Cells2Edge_j.Length - 1; _e >= 0; _e--) { // loop over all edges of cell...
             *
             *          //if (qr.NumbersOfNodesPerEdge[e] <= 0)
             *          //    // no contribution from this edge
             *          //    continue;
             *
             *          bool isInCell = Cells2Edge_j[_e] >= 0;
             *          int iEdge = Math.Abs(Cells2Edge_j[_e]) - 1;
             *          int iFace = FaceIndices[iEdge, isInCell ? 0 : 1];
             *
             *          if (isInCell) {
             *              if (!grd.Edges.IsEdgeConformalwithCell1(iEdge))
             *                  // we already tested that at least one cell is conformal with the edge,
             *                  // so it is safe to drop this face
             *                  continue;
             *          } else {
             *              if (!grd.Edges.IsEdgeConformalwithCell2(iEdge))
             *                  // we already tested that at least one cell is conformal with the edge,
             *                  // so it is safe to drop this face
             *                  continue;
             *          }
             *
             *
             *          Chunk singleEdgeChunk = Chunk.GetSingleElementChunk(iEdge);
             *
             *          QuadRule qrEdge;
             *          if (ret.TryGetValue(singleEdgeChunk, out qrEdge)) {
             *              // we are interested in this edge!
             *
             #if DEBUG
             *              Debug.Assert(EdgesOfInterest[iEdge] == true);
             *              EdgeTouched[iEdge] = false;
             *
             *              var vtx = this.RefElement.Vertices;
             *              MultidimensionalArray _vtx = MultidimensionalArray.Create(vtx.GetLength(0), vtx.GetLength(1));
             *              _vtx.Set(vtx);
             *
             *              var RefCoord = MultidimensionalArray.Create(vtx.GetLength(0), vtx.GetLength(1) + 1);
             *              var PhysCoord = MultidimensionalArray.Create(1, vtx.GetLength(0), vtx.GetLength(1) + 1);
             *
             *              volSplx.TransformFaceCoordinates(iFace, _vtx, RefCoord);
             *              grd.TransformLocal2Global(RefCoord, PhysCoord, j, 1, 0);
             *
             #endif
             *
             *              qrEdge = CombineQr(qrEdge, qr, iFace, j);
             *
             *              Debug.Assert(qrEdge != null);
             *              ret[singleEdgeChunk] = qrEdge;
             *          } else {
             *              // nop: the edge is not in the 'edgMask'!
             *              continue;
             *          }
             *      }
             *
             *  }
             * }
             *
             #if DEBUG
             * (new EdgeMask(this.grd, EdgeTouched)).ToTxtFile("failedEdges-" + grd.MyRank + ".csv", false);
             *
             * for (int i = EdgeTouched.Length - 1; i >= 0; i--)
             *  Debug.Assert(EdgeTouched[i] == false);
             #endif
             *
             * return ret.Select(p => new ChunkRulePair<QuadRule>(p.Key, p.Value));
             */
        }
示例#24
0
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask == null)
            {
                mask = EdgeMask.GetFullMask(tracker.Ctx.GridDat);
            }

            if (mask is EdgeMask == false)
            {
                throw new Exception();
            }

            QuadRule baseRule = lineSimplex.GetQuadratureRule(order);
            int      D        = tracker.Ctx.Grid.GridSimplex.SpatialDimension;

            var result = new List <ChunkRulePair <QuadRule> >(mask.NoOfItemsLocally);

            foreach (Chunk chunk in mask)
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    List <double[]> nodes            = new List <double[]>();
                    List <double>   weights          = new List <double>();
                    int[]           noOfNodesPerEdge = new int[referenceLineSegments.Length];

                    int edge = i + chunk.i0;

                    // Always choose 'left' edge
                    int cell      = tracker.Ctx.GridDat.Edges[edge, 0];
                    int localEdge = tracker.Ctx.GridDat.EdgeIndices[edge, 0];

                    LineSegment referenceSegment = referenceLineSegments[localEdge];
                    double[]    roots            = referenceSegment.GetRoots(tracker.LevelSets[levSetIndex], cell);

                    LineSegment[] subSegments = referenceSegment.Split(roots);

                    for (int k = 0; k < subSegments.Length; k++)
                    {
                        for (int m = 0; m < baseRule.NoOfNodes; m++)
                        {
                            // Base rule _always_ is a line rule, thus Nodes[*, _0_]
                            double[] point = subSegments[k].GetPointOnSegment(baseRule.Nodes[m, 0]);

                            uint lh = tracker.Ctx.NSC.LockNodeSetFamily(
                                tracker.Ctx.NSC.CreateContainer(
                                    MultidimensionalArray.CreateWrapper(point, 1, D), -1.0));
                            MultidimensionalArray levelSetValue = tracker.GetLevSetValues(levSetIndex, 0, cell, 1);
                            tracker.Ctx.NSC.UnlockNodeSetFamily(lh);

                            // Only positive volume
                            if (levelSetValue[0, 0] <= 0.0)
                            {
                                continue;
                            }

                            weights.Add(baseRule.Weights[m] * subSegments[k].Length / referenceSegment.Length);
                            nodes.Add(point);
                        }
                    }

                    if (weights.Count == 0)
                    {
                        continue;
                    }

                    MultidimensionalArray localNodes = MultidimensionalArray.Create(nodes.Count, D);
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            localNodes[j, d] = nodes[j][d];
                        }
                    }

                    MultidimensionalArray localEdgeNodes = MultidimensionalArray.Create(nodes.Count, 1);
                    tracker.Ctx.Grid.GridSimplex.VolumeToEdgeCoordinates(localEdge, localNodes, localEdgeNodes);

                    QuadRule subdividedRule = new QuadRule()
                    {
                        OrderOfPrecision = order,
                        Weights          = MultidimensionalArray.Create(weights.Count),
                        Nodes            = localEdgeNodes.CloneAs()
                    };
                    subdividedRule.Weights.SetV(weights, -1);

                    result.Add(new ChunkRulePair <QuadRule>(
                                   Chunk.GetSingleElementChunk(edge), subdividedRule));
                }
            }

            return(result);
        }
示例#25
0
        /// <summary>
        /// Returns a <see cref="CellBoundaryQuadRule"/> for each cell in the
        /// given <paramref name="mask"/>. This rule consists of Gaussian
        /// quadrature rules on each continuous line segment on the edges of a
        /// given cell (where continuous means 'not intersected by the zero
        /// level set'
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public IEnumerable <IChunkRulePair <CellBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (!(mask is CellMask))
            {
                throw new ArgumentException("This works on cell basis, so a volume mask is required.");
            }
            //Console.WriteLine("boundary order: " + order);

            if (mask == null)
            {
                mask = CellMask.GetFullMask(levelSetData.GridDat);
            }

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

            double[] EdgeToVolumeTransformationDeterminants = this.RefElement.FaceTrafoGramianSqrt;

            QuadRule baseRule = lineSimplex.GetQuadratureRule(order);
            int      D        = levelSetData.GridDat.SpatialDimension;
            var      _Cells   = levelSetData.GridDat.Cells;

            var result = new List <ChunkRulePair <CellBoundaryQuadRule> >(mask.NoOfItemsLocally);

            foreach (Chunk chunk in mask)
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    int cell = i + chunk.i0;

                    if (cache.ContainsKey(cell))
                    {
                        Debug.Assert(cache[cell].Nodes.IsLocked, "Quadrule with non-locked nodes in cache.");
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                       Chunk.GetSingleElementChunk(cell), cache[cell]));
                        continue;
                    }

                    List <double[]> nodes            = new List <double[]>();
                    List <double>   weights          = new List <double>();
                    int[]           noOfNodesPerEdge = new int[referenceLineSegments.Length];

                    for (int e = 0; e < referenceLineSegments.Length; e++)
                    {
                        LineSegment referenceSegment = referenceLineSegments[e];
                        int         iKref            = _Cells.GetRefElementIndex(cell);
                        double[]    roots            = referenceSegment.GetRoots(levelSetData.LevelSet, cell, iKref);
                        double      edgeDet          = EdgeToVolumeTransformationDeterminants[e];

                        LineSegment[] subSegments = referenceSegment.Split(roots);

                        for (int k = 0; k < subSegments.Length; k++)
                        {
                            // Evaluate sub segment at center to determine sign
                            NodeSet _point = new NodeSet(this.RefElement, subSegments[k].GetPointOnSegment(0.0));

                            double weightFactor = subSegments[k].Length / referenceSegment.Length;

                            if (weightFactor < 1.0e-14)
                            {
                                // segment has a length of approximately 0.0 => no need to care about it.
                                continue;
                            }

                            weightFactor *= edgeDet;

                            if (jumpType != JumpTypes.Implicit)
                            {
                                //using (tracker.GridDat.NSC.CreateLock(MultidimensionalArray.CreateWrapper(point, 1, D), this.iKref, -1.0)) {
                                MultidimensionalArray levelSetValue = this.levelSetData.GetLevSetValues(_point, cell, 1);

                                switch (jumpType)
                                {
                                case JumpTypes.Heaviside:
                                    if (levelSetValue[0, 0] <= -Tolerance)
                                    {
                                        continue;
                                    }
                                    break;

                                case JumpTypes.OneMinusHeaviside:
                                    if (levelSetValue[0, 0] >= Tolerance)
                                    {
                                        continue;
                                    }
                                    break;

                                case JumpTypes.Sign:
                                    weightFactor *= levelSetValue[0, 0].Sign();
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }
                                //}
                            }

                            for (int m = 0; m < baseRule.NoOfNodes; m++)
                            {
                                // Base rule _always_ is a line rule, thus Nodes[*, _0_]
                                double[] point = subSegments[k].GetPointOnSegment(baseRule.Nodes[m, 0]);

                                weights.Add(weightFactor * baseRule.Weights[m]);
                                nodes.Add(point);

                                noOfNodesPerEdge[e]++;
                            }
                        }
                    }

                    if (weights.Count == 0)
                    {
                        result.Add(new ChunkRulePair <CellBoundaryQuadRule>(Chunk.GetSingleElementChunk(cell), emptyrule));
                        continue;
                    }

                    NodeSet localNodes = new NodeSet(this.RefElement, nodes.Count, D);
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            localNodes[j, d] = nodes[j][d];
                        }
                    }
                    localNodes.LockForever();

                    CellBoundaryQuadRule subdividedRule = new CellBoundaryQuadRule()
                    {
                        OrderOfPrecision      = order,
                        Weights               = MultidimensionalArray.Create(weights.Count),
                        Nodes                 = localNodes,
                        NumbersOfNodesPerFace = noOfNodesPerEdge
                    };
                    subdividedRule.Weights.SetSubVector(weights, -1);

                    cache.Add(cell, subdividedRule);

                    result.Add(new ChunkRulePair <CellBoundaryQuadRule>(
                                   Chunk.GetSingleElementChunk(cell), subdividedRule));
                }
            }

            return(result);
        }
示例#26
0
 /// <summary>
 /// Uses <see cref="SubdivisionNode.NullSubdivisionNode"/> to create an
 /// identity transformation for the given simplex. The chunks of
 /// <paramref name="mask"/> are not altered.
 /// </summary>
 /// <param name="mask">
 /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/>
 /// </param>
 /// <returns>
 /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/>
 /// </returns>
 public IEnumerable <KeyValuePair <Chunk, IEnumerable <SubdivisionNode> > > GetSubdivisionNodes(ExecutionMask mask)
 {
     foreach (Chunk chunk in mask)
     {
         yield return(new KeyValuePair <Chunk, IEnumerable <SubdivisionNode> >(
                          chunk,
                          new SubdivisionNode[] { SubdivisionNode.NullSubdivisionNode(simplex.SpatialDimension) }));
     }
 }
示例#27
0
        /// <summary>
        /// Uses <see cref="Grid.RefElement.SubdivisionTree"/> to create the brute
        /// force subdivision which is the same for all cells. As a result, the
        /// chunks of <paramref name="mask"/> are not altered.
        /// </summary>
        /// <param name="mask">
        /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/>
        /// </param>
        /// <returns>
        /// <see cref="ISubdivisionStrategy.GetSubdivisionNodes"/>
        /// </returns>
        /// <remarks>
        /// Currently, the nodes returned by
        /// <see cref="Grid.RefElement.SubdivisionTree"/> are unnecessarily
        /// boxed by this method. This should be changed by changing the return
        /// type of <see cref="Grid.RefElement.SubdivisionTree"/> at some
        /// point.
        /// </remarks>
        public IEnumerable <KeyValuePair <Chunk, IEnumerable <SubdivisionNode> > > GetSubdivisionNodes(ExecutionMask mask)
        {
            using (new FuncTrace()) {
                RefElement.SubdivisionTreeNode[] leaves = RefElement.GetSubdivisionTree(numberOfSubdivisions).GetLeaves();

                foreach (Chunk chunk in mask)
                {
                    yield return(new KeyValuePair <Chunk, IEnumerable <SubdivisionNode> >(
                                     chunk,
                                     leaves.Select((leave) => new SubdivisionNode(leave.TrafoFromRoot, true))));
                }
            }
        }
示例#28
0
        /// <summary>
        /// Constructs suitable quadrature rules cells in
        /// <paramref name="mask"/>.
        /// </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="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>
        /// <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 <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            using (var tr = new FuncTrace()) {
                CellMask cellMask = mask as CellMask;
                if (cellMask == null)
                {
                    throw new ArgumentException("Mask must be a volume mask", "mask");
                }

                // Note: This is a parallel call, so do this early to avoid parallel confusion
                localCellIndex2SubgridIndex = new SubGrid(cellMask).LocalCellIndex2SubgridIndex;

                int maxLambdaDegree = order + 1;
                int noOfLambdas     = GetNumberOfLambdas(maxLambdaDegree);
                int noOfEdges       = LevelSetData.GridDat.Grid.RefElements[0].NoOfFaces;
                int D = RefElement.SpatialDimension;

                // Get the basis polynomials and integrate them analytically
                Polynomial[] basePolynomials = RefElement.GetOrthonormalPolynomials(order).ToArray();
                Polynomial[] polynomials     = new Polynomial[basePolynomials.Length * D];
                for (int i = 0; i < basePolynomials.Length; i++)
                {
                    Polynomial p = basePolynomials[i];

                    for (int d = 0; d < D; d++)
                    {
                        Polynomial pNew = p.CloneAs();
                        for (int j = 0; j < p.Coeff.Length; j++)
                        {
                            pNew.Exponents[j, d]++;
                            pNew.Coeff[j] /= pNew.Exponents[j, d];
                            pNew.Coeff[j] /= D; // Make sure divergence is Phi again
                        }
                        polynomials[i * D + d] = pNew;
                    }
                }

                // basePolynomials[i] == div(polynomials[i*D], ... , polynomials[i*D + D - 1])
                lambdaBasis = new PolynomialList(polynomials);


                if (RestrictNodes)
                {
                    trafos = new AffineTrafo[mask.NoOfItemsLocally];

                    foreach (Chunk chunk in mask)
                    {
                        foreach (var cell in chunk.Elements.AsSmartEnumerable())
                        {
                            CellMask singleElementMask = new CellMask(
                                LevelSetData.GridDat, Chunk.GetSingleElementChunk(cell.Value));

                            LineAndPointQuadratureFactory.LineQRF lineFactory = this.edgeRuleFactory as LineAndPointQuadratureFactory.LineQRF;
                            if (lineFactory == null)
                            {
                                throw new Exception();
                            }
                            var lineRule  = lineFactory.GetQuadRuleSet(singleElementMask, order).Single().Rule;
                            var pointRule = lineFactory.m_Owner.GetPointFactory().GetQuadRuleSet(singleElementMask, order).Single().Rule;

                            // Also add point rule points since line rule points
                            // are constructed from Gauss rules that do not include
                            // the end points
                            BoundingBox box = new BoundingBox(lineRule.Nodes);
                            box.AddPoints(pointRule.Nodes);

                            int noOfRoots = pointRule.Nodes.GetLength(0);
                            if (noOfRoots <= 1)
                            {
                                // Cell is considered cut because the level set
                                // is very close, but actually isn't. Note that
                                // we can NOT omit the cell (as in the surface
                                // case) as it will be missing in the list of
                                // uncut cells, i.e. this cell would be ignored
                                // completely
                                trafos[localCellIndex2SubgridIndex[cell.Value]] =
                                    AffineTrafo.Identity(RefElement.SpatialDimension);
                                continue;
                            }
                            else if (noOfRoots == 2)
                            {
                                // Go a bit into the direction of the normal
                                // from the center between the nodes in order
                                // not to miss regions with strong curvature
                                double[] center = box.Min.CloneAs();
                                center.AccV(1.0, box.Max);
                                center.ScaleV(0.5);
                                NodeSet centerNode = new NodeSet(RefElement, center);
                                centerNode.LockForever();

                                MultidimensionalArray normal = LevelSetData.GetLevelSetReferenceNormals(centerNode, cell.Value, 1);
                                MultidimensionalArray dist   = LevelSetData.GetLevSetValues(centerNode, cell.Value, 1);

                                double scaling = Math.Sqrt(LevelSetData.GridDat.Cells.JacobiDet[cell.Value]);

                                double[] newPoint = new double[D];
                                for (int d = 0; d < D; d++)
                                {
                                    newPoint[d] = center[d] - normal[0, 0, d] * dist[0, 0] / scaling;
                                }

                                box.AddPoint(newPoint);

                                // Make sure points stay in box
                                for (int d = 0; d < D; d++)
                                {
                                    box.Min[d] = Math.Max(box.Min[d], -1);
                                    box.Max[d] = Math.Min(box.Max[d], 1);
                                }
                            }

                            MultidimensionalArray preImage = RefElement.Vertices.ExtractSubArrayShallow(
                                new int[] { 0, 0 }, new int[] { D, D - 1 });

                            MultidimensionalArray image = MultidimensionalArray.Create(D + 1, D);
                            image[0, 0] = box.Min[0]; // Top left
                            image[0, 1] = box.Max[1];
                            image[1, 0] = box.Max[0]; // Top right
                            image[1, 1] = box.Max[1];
                            image[2, 0] = box.Min[0]; // Bottom left;
                            image[2, 1] = box.Min[1];

                            AffineTrafo trafo = AffineTrafo.FromPoints(preImage, image);
                            trafos[localCellIndex2SubgridIndex[cell.Value]] = trafo;
                        }
                    }
                }

                LambdaCellBoundaryQuadrature cellBoundaryQuadrature =
                    new LambdaCellBoundaryQuadrature(this, edgeRuleFactory, cellMask);
                cellBoundaryQuadrature.Execute();

                LambdaLevelSetSurfaceQuadrature surfaceQuadrature =
                    new LambdaLevelSetSurfaceQuadrature(this, surfaceRuleFactory, cellMask);
                surfaceQuadrature.Execute();

                // Must happen _after_ all parallel calls (e.g., definition of
                // the sub-grid or quadrature) in order to avoid problems in
                // parallel runs
                if (mask.NoOfItemsLocally == 0)
                {
                    var empty = new ChunkRulePair <QuadRule> [0];
                    return(empty);
                }

                if (cachedRules.ContainsKey(order))
                {
                    order = cachedRules.Keys.Where(cachedOrder => cachedOrder >= order).Min();
                    CellMask cachedMask = new CellMask(mask.GridData, cachedRules[order].Select(p => p.Chunk).ToArray());

                    if (cachedMask.Equals(mask))
                    {
                        return(cachedRules[order]);
                    }
                    else
                    {
                        throw new NotImplementedException(
                                  "Case not yet covered yet in combination with caching; deactivate caching to get rid of this message");
                    }
                }

                double[,] quadResults = cellBoundaryQuadrature.Results;
                foreach (Chunk chunk in mask)
                {
                    for (int i = 0; i < chunk.Len; i++)
                    {
                        int iSubGrid = localCellIndex2SubgridIndex[chunk.i0 + i];

                        switch (jumpType)
                        {
                        case JumpTypes.Heaviside:
                            for (int k = 0; k < noOfLambdas; k++)
                            {
                                quadResults[iSubGrid, k] -= surfaceQuadrature.Results[iSubGrid, k];
                            }
                            break;

                        case JumpTypes.OneMinusHeaviside:
                            for (int k = 0; k < noOfLambdas; k++)
                            {
                                quadResults[iSubGrid, k] += surfaceQuadrature.Results[iSubGrid, k];
                            }
                            break;

                        case JumpTypes.Sign:
                            for (int k = 0; k < noOfLambdas; k++)
                            {
                                quadResults[iSubGrid, k] -= 2.0 * surfaceQuadrature.Results[iSubGrid, k];
                            }
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                }

                BitArray voidCellsArray = new BitArray(LevelSetData.GridDat.Cells.NoOfLocalUpdatedCells);
                BitArray fullCellsArray = new BitArray(LevelSetData.GridDat.Cells.NoOfLocalUpdatedCells);
                foreach (Chunk chunk in cellMask)
                {
                    foreach (var cell in chunk.Elements)
                    {
                        double rhsL2Norm = 0.0;
                        for (int k = 0; k < noOfLambdas; k++)
                        {
                            double entry = quadResults[localCellIndex2SubgridIndex[cell], k];
                            rhsL2Norm += entry * entry;
                        }

                        if (rhsL2Norm < 1e-14)
                        {
                            // All integrals are zero => cell not really cut
                            // (level set is tangent) and fully in void region
                            voidCellsArray[cell] = true;
                            continue;
                        }

                        double l2NormFirstIntegral = quadResults[localCellIndex2SubgridIndex[cell], 0];
                        l2NormFirstIntegral *= l2NormFirstIntegral;
                        double rhsL2NormWithoutFirst = rhsL2Norm - l2NormFirstIntegral;

                        // Beware: This check is only sensible if basis is orthonormal on RefElement!
                        if (rhsL2NormWithoutFirst < 1e-14 &&
                            Math.Abs(l2NormFirstIntegral - RefElement.Volume) < 1e-14)
                        {
                            // All integrals are zero except integral over first integrand
                            // If basis is orthonormal, this implies that cell is uncut and
                            // fully in non-void region since then
                            // \int_K \Phi_i dV = \int_A \Phi_i dV = \delta_{0,i}
                            // However, we have to compare RefElement.Volume since
                            // integration is performed in reference coordinates!
                            fullCellsArray[cell] = true;
                        }
                    }
                }

                var result = new List <ChunkRulePair <QuadRule> >(cellMask.NoOfItemsLocally);

                CellMask emptyCells = new CellMask(LevelSetData.GridDat, voidCellsArray);
                foreach (Chunk chunk in emptyCells)
                {
                    foreach (int cell in chunk.Elements)
                    {
                        QuadRule emptyRule = QuadRule.CreateEmpty(RefElement, 1, RefElement.SpatialDimension);
                        emptyRule.Nodes.LockForever();
                        result.Add(new ChunkRulePair <QuadRule>(
                                       Chunk.GetSingleElementChunk(cell), emptyRule));
                    }
                }

                CellMask fullCells = new CellMask(LevelSetData.GridDat, fullCellsArray);
                foreach (Chunk chunk in fullCells)
                {
                    foreach (int cell in chunk.Elements)
                    {
                        QuadRule fullRule = RefElement.GetQuadratureRule(order);
                        result.Add(new ChunkRulePair <QuadRule>(
                                       Chunk.GetSingleElementChunk(cell), fullRule));
                    }
                }

                CellMask realCutCells = cellMask.Except(emptyCells).Except(fullCells);
                if (RestrictNodes)
                {
                    foreach (Chunk chunk in realCutCells)
                    {
                        foreach (int cell in chunk.Elements)
                        {
                            CellMask singleElementMask = new CellMask(
                                LevelSetData.GridDat, Chunk.GetSingleElementChunk(cell));

                            AffineTrafo trafo = trafos[localCellIndex2SubgridIndex[cell]];
                            Debug.Assert(Math.Abs(trafo.Matrix.Determinant()) > 1e-10);

                            NodeSet nodes       = GetNodes(noOfLambdas).CloneAs();
                            NodeSet mappedNodes = new NodeSet(RefElement, trafo.Transform(nodes));
                            mappedNodes.LockForever();

                            // Remove nodes in negative part
                            MultidimensionalArray levelSetValues  = LevelSetData.GetLevSetValues(mappedNodes, cell, 1);
                            List <int>            nodesToBeCopied = new List <int>(mappedNodes.GetLength(0));
                            for (int n = 0; n < nodes.GetLength(0); n++)
                            {
                                if (levelSetValues[0, n] >= 0.0)
                                {
                                    nodesToBeCopied.Add(n);
                                }
                            }

                            NodeSet reducedNodes = new NodeSet(
                                this.RefElement, nodesToBeCopied.Count, D);
                            for (int n = 0; n < nodesToBeCopied.Count; n++)
                            {
                                for (int d = 0; d < D; d++)
                                {
                                    reducedNodes[n, d] = mappedNodes[nodesToBeCopied[n], d];
                                }
                            }
                            reducedNodes.LockForever();

                            QuadRule optimizedRule = GetOptimizedRule(
                                cell,
                                trafo,
                                reducedNodes,
                                quadResults,
                                order);

                            result.Add(new ChunkRulePair <QuadRule>(
                                           singleElementMask.Single(), optimizedRule));
                        }
                    }
                }
                else
                {
                    // Use same nodes in all cells
                    QuadRule[] optimizedRules = GetOptimizedRules(
                        realCutCells, GetNodes(noOfLambdas), quadResults, order);
                    int ruleIndex = 0;
                    foreach (Chunk chunk in realCutCells)
                    {
                        foreach (var cell in chunk.Elements)
                        {
                            result.Add(new ChunkRulePair <QuadRule>(
                                           Chunk.GetSingleElementChunk(cell), optimizedRules[ruleIndex]));
                            ruleIndex++;
                        }
                    }
                }

                cachedRules[order] = result.OrderBy(p => p.Chunk.i0).ToArray();
                return(cachedRules[order]);
            }
        }
示例#29
0
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }

            QuadRule baseRule   = Line.Instance.GetQuadratureRule(order);
            var      pointRules = rootFactory.GetQuadRuleSet(mask, order);

            var result = new List <ChunkRulePair <QuadRule> >();

            foreach (Chunk chunk in mask)
            {
                foreach (int cell in chunk.Elements)
                {
                    var pointRule = pointRules.Single(pair => pair.Chunk.i0 <= cell && pair.Chunk.JE > cell).Rule;

                    QuadRule reconstructedRule;
                    switch (pointRule.NoOfNodes)
                    {
                    case 0:
                    case 1:
                        // Cell not really cut
                        reconstructedRule = QuadRule.CreateEmpty(RefElement, 1, 2);
                        break;

                    case 2: {
                        LineSegment linearReconstruction = new LineSegment(
                            RefElement.SpatialDimension,
                            RefElement,
                            pointRule.Nodes.GetRow(0),
                            pointRule.Nodes.GetRow(1));

                        reconstructedRule = QuadRule.CreateEmpty(
                            RefElement, baseRule.NoOfNodes, RefElement.SpatialDimension);
                        for (int i = 0; i < baseRule.NoOfNodes; i++)
                        {
                            reconstructedRule.Weights[i] =
                                baseRule.Weights[i] * linearReconstruction.Length / Line.Instance.Volume;

                            double[] point = linearReconstruction.GetPointOnSegment(baseRule.Nodes[i, 0]);
                            for (int d = 0; d < RefElement.SpatialDimension; d++)
                            {
                                reconstructedRule.Nodes[i, d] = point[d];
                            }
                        }
                    }
                    break;

                    case 4: {
                        // Assume only single interface
                        double[] xCoords  = pointRule.Nodes.GetColumn(0);
                        double   maxXDist = xCoords.Max() - xCoords.Min();

                        double[] yCoords  = pointRule.Nodes.GetColumn(1);
                        double   maxYDist = yCoords.Max() - yCoords.Min();

                        int orderingDirection;
                        if (maxXDist > maxYDist)
                        {
                            orderingDirection = 0;
                        }
                        else
                        {
                            orderingDirection = 1;
                        }

                        double[][] roots = new double[pointRule.NoOfNodes][];
                        for (int i = 0; i < roots.Length; i++)
                        {
                            roots[i] = new double[] { pointRule.Nodes[i, 0], pointRule.Nodes[i, 1] };
                        }
                        var orderedRoots = roots.OrderBy(t => t[orderingDirection]).ToArray();

                        // Now, construct two separate rules
                        LineSegment linearReconstruction1 = new LineSegment(
                            RefElement.SpatialDimension,
                            RefElement,
                            orderedRoots[0],
                            orderedRoots[1]);
                        LineSegment linearReconstruction2 = new LineSegment(
                            RefElement.SpatialDimension,
                            RefElement,
                            orderedRoots[2],
                            orderedRoots[3]);

                        reconstructedRule = QuadRule.CreateEmpty(
                            RefElement, 2 * baseRule.NoOfNodes, RefElement.SpatialDimension);
                        for (int i = 0; i < baseRule.NoOfNodes; i++)
                        {
                            reconstructedRule.Weights[i] =
                                baseRule.Weights[i] * linearReconstruction1.Length / Line.Instance.Volume;

                            double[] point = linearReconstruction1.GetPointOnSegment(baseRule.Nodes[i, 0]);
                            for (int d = 0; d < RefElement.SpatialDimension; d++)
                            {
                                reconstructedRule.Nodes[i, d] = point[d];
                            }

                            int offset = baseRule.NoOfNodes;
                            reconstructedRule.Weights[offset + i] =
                                baseRule.Weights[i] * linearReconstruction2.Length / Line.Instance.Volume;

                            point = linearReconstruction2.GetPointOnSegment(baseRule.Nodes[i, 0]);
                            for (int d = 0; d < RefElement.SpatialDimension; d++)
                            {
                                reconstructedRule.Nodes[offset + i, d] = point[d];
                            }
                        }
                    }
                    break;

                    default:
                        throw new NotImplementedException();
                    }

                    reconstructedRule.Nodes.LockForever();

                    MultidimensionalArray metrics =
                        tracker.DataHistories[0].Current.GetLevelSetNormalReferenceToPhysicalMetrics(reconstructedRule.Nodes, cell, 1);
                    for (int i = 0; i < reconstructedRule.NoOfNodes; i++)
                    {
                        reconstructedRule.Weights[i] /= metrics[0, i];
                    }

                    result.Add(new ChunkRulePair <QuadRule>(
                                   Chunk.GetSingleElementChunk(cell), reconstructedRule));
                }
            }

            return(result);
        }
        /// <summary>
        /// Uses the given edge rule factory to create quadrature rules for
        /// the boundaries of all cells in <paramref name="mask"/>.
        /// </summary>
        /// <param name="mask">
        /// A <b><see cref="CellMask"/></b> containing all cells to be
        /// integrated over.
        /// </param>
        /// <param name="order">
        /// <see cref="IQuadRuleFactory{T}.GetQuadRuleSet"/>
        /// </param>
        /// <returns>
        /// Quadrature rules for the boundary of all cells in
        /// <paramref name="mask"/> in the volume coordinate system.
        /// </returns>
        public IEnumerable <IChunkRulePair <T> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (!(mask is CellMask))
            {
                throw new ArgumentException("Expecting a cell/volume mask.");
            }
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }
            if (!object.ReferenceEquals(this.context, mask.GridData))
            {
                throw new ArgumentException();
            }

            // helper vars
            int D                = this.context.SpatialDimension;
            var CellToEdge       = this.context.iLogicalCells.Cells2Edges;
            var EdgeToCell       = this.context.iLogicalEdges.CellIndices;
            var FaceIndices      = this.context.iGeomEdges.FaceIndices;
            var TrafoIdx         = this.context.iGeomEdges.Edge2CellTrafoIndex;
            var EdgeToCellTrafos = this.context.iGeomEdges.Edge2CellTrafos;
            int NoOfFaces        = RefElement.NoOfFaces;
            var Scalings         = context.iGeomEdges.Edge2CellTrafos_SqrtGramian;
            int J                = this.context.iLogicalCells.NoOfLocalUpdatedCells;

            // output data structure, temporary
            Dictionary <int, T> cellBndRuleMap = new Dictionary <int, T>();

            // Get edge quad rules
            BitArray edgeBitMask = new BitArray(context.iGeomEdges.Count);

            foreach (Chunk chunk in mask)
            {
                foreach (int cell in chunk.Elements)
                {
                    var LocalCellIndexToEdges_cell = CellToEdge[cell];
                    for (int e = LocalCellIndexToEdges_cell.Length - 1; e >= 0; e--)
                    {
                        int edge = Math.Abs(LocalCellIndexToEdges_cell[e]) - 1;
                        edgeBitMask[edge] = true;
                    }
                    cellBndRuleMap.Add(cell, new T()
                    {
                        NumbersOfNodesPerFace = new int[NoOfFaces]
                    });
                }
            }
            IEnumerable <IChunkRulePair <QuadRule> > edgeRuleMap = edgeRuleFactory.GetQuadRuleSet(
                new EdgeMask(context, edgeBitMask, MaskType.Geometrical), order);


            // build cell boundary rule
            var CellBitMask = mask.GetBitMask();

            foreach (var edgeRule in edgeRuleMap)
            {
                QuadRule rule = edgeRule.Rule;
                Debug.Assert(rule.Nodes.GetLength(1) == Math.Max(D - 1, 1));
                int iEdge0 = edgeRule.Chunk.i0;
                int iEdgeE = edgeRule.Chunk.JE;

                for (int iEdge = iEdge0; iEdge < iEdgeE; iEdge++)
                {
                    for (int kk = 0; kk < 2; kk++)   // loop over in and out
                    {
                        int jCell = EdgeToCell[iEdge, kk];
                        if (jCell < 0 || jCell >= J)
                        {
                            continue;
                        }
                        if (!CellBitMask[jCell])
                        {
                            continue;
                        }

                        int    iTrafo = TrafoIdx[iEdge, kk];
                        var    trafo  = EdgeToCellTrafos[iTrafo];
                        int    iFace  = FaceIndices[iEdge, kk];
                        double scl    = Scalings[iTrafo];

                        NodeSet VolumeNodes = new NodeSet(this.RefElement, rule.NoOfNodes, D);
                        trafo.Transform(rule.Nodes, VolumeNodes);
                        VolumeNodes.LockForever();

                        var cellBndRule = cellBndRuleMap[jCell];
                        AddToCellBoundaryRule(cellBndRule, VolumeNodes, rule.Weights, iFace, scl);
                    }
                }
            }


            // return
            // ======
            {
                int[] Cells = cellBndRuleMap.Keys.ToArray();
                Array.Sort(Cells);

                ChunkRulePair <T>[] R = new ChunkRulePair <T> [Cells.Length];
                for (int i = 0; i < R.Length; i++)
                {
                    int jCell = Cells[i];
                    cellBndRuleMap[jCell].Nodes.LockForever();
                    R[i] = new ChunkRulePair <T>(Chunk.GetSingleElementChunk(jCell), cellBndRuleMap[jCell]);
                }


                return(R);
            }
        }