Ejemplo n.º 1
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);
        }