示例#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);
        }
示例#2
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);
        }
示例#3
0
        /// <summary>
        /// Returns a set of <see cref="CellEdgeBoundaryQuadRule"/>s that
        /// enables the integration over sub-segments of the edges of the edges
        /// of a (three-dimensional) domain. This is obviously only useful if
        /// the integrand has a discontinuity that is aligned with the zero
        /// iso-contour of the level set function.
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public IEnumerable <IChunkRulePair <CellEdgeBoundaryQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask == null)
            {
                mask = CellMask.GetFullMask(this.lsData.GridDat, MaskType.Geometrical);
            }

            if (mask is CellMask == false)
            {
                throw new ArgumentException("Edge mask required", "mask");
            }
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }


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

            QuadRule baseRule        = lineSimplex.GetQuadratureRule(order);
            int      D               = lsData.GridDat.SpatialDimension;
            int      noOfEdges       = lsData.GridDat.Grid.RefElements[0].NoOfFaces;
            int      noOfEdgesOfEdge = RefElement.FaceRefElement.NoOfFaces;

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

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

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

                    List <double[]> nodes   = new List <double[]>();
                    List <double>   weights = new List <double>();

                    if (lsData.GridDat.Cells.Cells2Edges[cell].Length != noOfEdges)
                    {
                        throw new NotImplementedException("Not implemented for hanging nodes");
                    }

                    int[] noOfNodesPerEdge = new int[noOfEdges];
                    int[,] noOfNodesPerEdgeOfEdge = new int[noOfEdges, noOfEdgesOfEdge];
                    for (int e = 0; e < noOfEdges; e++)
                    {
                        int    edge    = Math.Abs(lsData.GridDat.Cells.Cells2Edges[cell][e]) - 1;
                        double edgeDet = lsData.GridDat.Edges.SqrtGramian[edge];

                        for (int ee = 0; ee < noOfEdgesOfEdge; ee++)
                        {
                            LineSegment refSegment    = referenceLineSegments[e, ee];
                            double      edgeOfEdgeDet = RefElement.FaceRefElement.FaceTrafoGramianSqrt[ee];

                            double[]      roots       = refSegment.GetRoots(lsData.LevelSet, cell, 0);
                            LineSegment[] subSegments = refSegment.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 scaling = edgeOfEdgeDet * subSegments[k].Length / refSegment.Length;

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

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

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

                                    case JumpTypes.Sign:
                                        scaling *= 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(baseRule.Weights[m] * scaling);
                                    nodes.Add(point);

                                    noOfNodesPerEdge[e]++;
                                    noOfNodesPerEdgeOfEdge[e, ee]++;
                                }
                            }
                        }
                    }

                    if (weights.Count == 0)
                    {
                        CellEdgeBoundaryQuadRule emptyRule =
                            CellEdgeBoundaryQuadRule.CreateEmpty(1, RefElement);
                        emptyRule.Nodes.LockForever();
                        cache.Add(cell, emptyRule);
                        result.Add(new ChunkRulePair <CellEdgeBoundaryQuadRule>(
                                       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();

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

                    cache.Add(cell, subdividedRule);

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

            return(result);
        }