예제 #1
0
        private void WriteVolumeNodes(StreamWriter log, IQuadRuleFactory <QuadRule> ruleFactory, int order, SubGrid subGrid, ITestCase testCase, int selectedCell = -1)
        {
            foreach (var chunkRulePair in ruleFactory.GetQuadRuleSet(subGrid.VolumeMask, order))
            {
                foreach (int cell in chunkRulePair.Chunk.Elements)
                {
                    QuadRule rule = chunkRulePair.Rule;

                    MultidimensionalArray globalVertices = MultidimensionalArray.Create(
                        1, rule.NoOfNodes, Grid.SpatialDimension);
                    MultidimensionalArray metrics = levelSetTracker.DataHistories[0].Current.GetLevelSetNormalReferenceToPhysicalMetrics(
                        rule.Nodes, cell, 1);
                    GridData.TransformLocal2Global(rule.Nodes, cell, 1, globalVertices, 0);

                    if (selectedCell >= 0 && cell != selectedCell)
                    {
                        continue;
                    }

                    for (int k = 0; k < rule.NoOfNodes; k++)
                    {
                        double weight = rule.Weights[k];

                        if (testCase is ISurfaceTestCase)
                        {
                            // Use to get correct HMF weights in reference coordinate
                            // system (surface weights are already divided by $metrics
                            // to save this step in actual quadrature)
                            //weight *= metrics[0, k];
                        }

                        if (Grid.SpatialDimension == 2)
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                Math.Round(weight, 2).ToString(formatInfo));
                        }
                        else
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                globalVertices[0, k, 2].ToString(formatInfo),
                                weight.ToString(formatInfo));
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Creates a new composite quadrature rules of minimal order
        /// <paramref name="order"/> from a single quadrature rule factory and
        /// an associated domain of integration.
        /// </summary>
        /// <typeparam name="TDomain">
        /// The type of the domain to be integrated over.
        /// </typeparam>
        /// <param name="ruleFactory">
        /// The quadrature rule factory to be used to create the quadrature
        /// rules for the given domain.
        /// </param>
        /// <param name="order">
        /// The minimal order of the quadrature rules to be used. See
        /// <see cref="IQuadRuleFactory{T}.GetQuadRuleSet"/>.
        /// </param>
        /// <param name="domain">
        /// The domain to be integrated over.
        /// </param>
        /// <returns>
        /// A composite rule containing the quadrature rules associated with
        /// all elements of the given domain.
        /// </returns>
        /// <remarks>
        /// The main specialty about the resulting composite rule is that the
        /// implementation guarantees that the sets of nodes and weights
        /// associated to the respective quadrature rules share the <b>same</b>
        /// objects of their contents are equal. This is allows for the
        /// optimization of the execution of the quadrature itself.
        /// </remarks>
        public static CompositeQuadRule <TQuadRule> Create <TDomain>(
            IQuadRuleFactory <TQuadRule> ruleFactory, int order, TDomain domain)
            where TDomain : ExecutionMask
        {
            CompositeQuadRule <TQuadRule> compositeRule = new CompositeQuadRule <TQuadRule>();
            // BEWARE: This check may cause nasty trouble in parallel runs
            // where a domain is only present on some domains and has thus been
            // removed by Björn
            //if (domain.NoOfItemsLocally == 0) {
            //    return compositeRule;
            //}
            var ruleSet = ruleFactory.GetQuadRuleSet(domain, order);

            var nodes    = new List <NodeSet>();
            var nodesMap = new Dictionary <MultidimensionalArray, int>();

            var weights    = new List <MultidimensionalArray>();
            var weightsMap = new Dictionary <MultidimensionalArray, int>();

            foreach (var chunkRulePair in ruleSet)
            {
                Chunk     chunk = chunkRulePair.Chunk;
                TQuadRule rule  = chunkRulePair.Rule;

                Debug.Assert(rule.Nodes.IsLocked, "Error in quadrature rule creation: factory delivered some rule non-locked node set.");

                int iNode;
                if (!nodesMap.TryGetValue(rule.Nodes, out iNode))
                {
                    // nodes must be added
                    nodes.Add(rule.Nodes);
                    iNode = nodes.Count - 1;
                    nodesMap.Add(rule.Nodes, iNode);
                }

                int iWeight;
                if (!weightsMap.TryGetValue(rule.Weights, out iWeight))
                {
                    // weights must be added
                    weights.Add(rule.Weights);
                    iWeight = weights.Count - 1;
                    weightsMap.Add(rule.Weights, iWeight);
                }

                // Make sure arrays are not only equal but identical (i.e.,
                // reference equals)
                rule.Nodes   = nodes[iNode];
                rule.Weights = weights[iWeight];

                compositeRule.chunkRulePairs.Add(
                    new ChunkRulePair <TQuadRule>(chunk, rule));
            }

            return(compositeRule);
        }
예제 #3
0
        private void WriteSurfaceNodes(StreamWriter log, IQuadRuleFactory <QuadRule> ruleFactory, int order, SubGrid subGrid)
        {
            var edgeRules = ruleFactory.GetQuadRuleSet(
                levelSetTracker.Regions.GetCutCellSubGrid().AllEdgesMask, order);

            foreach (var chunkRulePair in edgeRules)
            {
                foreach (int edge in chunkRulePair.Chunk.Elements)
                {
                    QuadRule rule = chunkRulePair.Rule;

                    int cell = GridData.iGeomEdges.CellIndices[edge, 0];

                    NodeSet volumeVertices = new NodeSet(
                        GridData.iGeomCells.GetRefElement(cell),
                        rule.NoOfNodes, Grid.SpatialDimension);
                    Grid.RefElements[0].TransformFaceCoordinates(
                        GridData.iGeomEdges.FaceIndices[edge, 0], rule.Nodes, volumeVertices);
                    volumeVertices.LockForever();

                    MultidimensionalArray globalVertices = MultidimensionalArray.Create(
                        1, rule.NoOfNodes, Grid.SpatialDimension);
                    GridData.TransformLocal2Global(volumeVertices, cell, 1, globalVertices, 0);
                    for (int k = 0; k < rule.NoOfNodes; k++)
                    {
                        if (Grid.SpatialDimension == 2)
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                rule.Weights[k].ToString(formatInfo));
                        }
                        else
                        {
                            log.WriteLine(
                                "{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
                                cell,
                                k,
                                globalVertices[0, k, 0].ToString(formatInfo),
                                globalVertices[0, k, 1].ToString(formatInfo),
                                globalVertices[0, k, 2].ToString(formatInfo),
                                rule.Weights[k].ToString(formatInfo));
                        }
                    }
                }
            }
        }
예제 #4
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);
        }
예제 #5
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);
            }
        /// <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);
            }
        }
예제 #7
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);
        }
예제 #8
0
        public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (mask.MaskType != MaskType.Geometrical)
            {
                throw new ArgumentException("Expecting a geometrical mask.");
            }

            var standardVolumeRules = baseFactory.GetQuadRuleSet(mask, order);
            var pointRules          = rootFactory.GetQuadRuleSet(mask, order);

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

            foreach (var chunkRulePair in standardVolumeRules)
            {
                foreach (int cell in chunkRulePair.Chunk.Elements)
                {
                    QuadRule standardRule = chunkRulePair.Rule;

                    var pointRule = pointRules.Single(pair => pair.Chunk.i0 <= cell && pair.Chunk.JE > cell).Rule;
                    MultidimensionalArray gradientsAtRoots = tracker.DataHistories[0].Current.GetLevelSetGradients(pointRule.Nodes, cell, 1);

                    QuadRule modifiedRule;
                    switch (pointRule.NoOfNodes)
                    {
                    case 0:
                    case 1: {
                        // Cell not really cut
                        MultidimensionalArray levelSetValue = tracker.DataHistories[0].Current.GetLevSetValues(
                            new NodeSet(RefElement, new double[2]), cell, 1);
                        if (Math.Sign(levelSetValue.Storage[0]) < 0)
                        {
                            // Cell is completely void
                            QuadRule emptyRule = QuadRule.CreateEmpty(RefElement, 1, 2);
                            emptyRule.Nodes.LockForever();
                            modifiedRule = emptyRule;
                        }
                        else
                        {
                            // Cell is completely non-void
                            modifiedRule = standardRule;
                        }
                    }
                    break;

                    case 2: {
                        double a, b, c;
                        GetLevelSetApproximationCofficients(cell, pointRule.Nodes.GetRow(0), pointRule.Nodes.GetRow(1), out a, out b, out c);
                        double[] eqcv = Heqpol_coefficients(a, b, c);

                        modifiedRule = standardRule.CloneAs();
                        for (int i = 0; i < modifiedRule.NoOfNodes; i++)
                        {
                            double x = modifiedRule.Nodes[i, 0];
                            double y = modifiedRule.Nodes[i, 1];
                            // double[] v = new double[] {
                            //     1.0, x, x * x, y, x * y, y * y };
                            double v = eqcv[0] + eqcv[1] * x + eqcv[2] * x * x
                                       + eqcv[3] * y + eqcv[4] * x * y + eqcv[5] * y * y;

                            modifiedRule.Weights[i] *= v;
                        }

                        modifiedRule.Nodes.LockForever();
                    }
                    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, do the equivalent polynomial thing
                        double a, b, c;
                        GetLevelSetApproximationCofficients(cell, orderedRoots[0], orderedRoots[1], out a, out b, out c);
                        double[] eqcv1 = Heqpol_coefficients(a, b, c);

                        GetLevelSetApproximationCofficients(cell, orderedRoots[2], orderedRoots[3], out a, out b, out c);
                        double[] eqcv2 = Heqpol_coefficients(a, b, c);

                        modifiedRule = standardRule.CloneAs();
                        for (int i = 0; i < modifiedRule.NoOfNodes; i++)
                        {
                            double x = modifiedRule.Nodes[i, 0];
                            double y = modifiedRule.Nodes[i, 1];
                            // double[] v = new double[] {
                            //     1.0, x, x * x, y, x * y, y * y };
                            double v1 = eqcv1[0] + eqcv1[1] * x + eqcv1[2] * x * x
                                        + eqcv1[3] * y + eqcv1[4] * x * y + eqcv1[5] * y * y;
                            double v2 = eqcv2[0] + eqcv2[1] * x + eqcv2[2] * x * x
                                        + eqcv2[3] * y + eqcv2[4] * x * y + eqcv2[5] * y * y;

                            modifiedRule.Weights[i] *= v1 * v2;
                        }
                    }
                    break;

                    default:
                        throw new NotImplementedException();
                    }

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

            return(result);
        }
예제 #9
0
        /// <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 <DoubleEdgeQuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
        {
            if (!(mask is EdgeMask))
            {
                throw new ArgumentException();
            }

            EdgeMask edgMask = mask as EdgeMask;
            var      ret     = new Dictionary <Chunk, DoubleEdgeQuadRule>(mask.NoOfItemsLocally);

#if DEBUG
            var EdgesOfInterest = edgMask.GetBitMask();
            var EdgeTouched     = (BitArray)EdgesOfInterest.Clone();
#endif

            WeightInbalance = 0.0;

            // find all cells that are 'touched' by the edge mask
            // --------------------------------------------------
            int      J            = grd.NoOfLocalUpdatedCells;
            BitArray TouchedCells = new BitArray(J, false);

            var Edg2Cell = grd.Edges;

            int chunkCnt = 0;
            foreach (var chnk in mask)
            {
                int EE = chnk.JE;
                for (int e = chnk.i0; e < EE; e++)
                {
                    int j1 = Edg2Cell[e, 0], j2 = Edg2Cell[e, 1];
                    TouchedCells[j1] = true;
                    if (j2 >= 0)
                    {
                        TouchedCells[j2] = true;
                    }


                    Chunk singleEdgeChunk;
                    singleEdgeChunk.i0  = e;
                    singleEdgeChunk.Len = 1;

                    ret.Add(singleEdgeChunk, null);
                }
                chunkCnt++;
            }


            CellMask celMask = (new CellMask(grd, TouchedCells));

            // 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.Simplex;
            int NoOfFaces  = volSplx.NoOfEdges;
            var Cells2Edge = grd.LocalCellIndexToEdges;

            foreach (var kv in cellBndRule)   // loop over cell chunks (in the cell boundary rule)...
            {
                Chunk chk = kv.Chunk;
                CellBoundaryQuadRule qr = kv.Rule;

                int JE = chk.JE;
                for (int j = chk.i0; j < JE; j++)   // loop over all cells in chunk...
                {
                    Debug.Assert(qr.NumbersOfNodesPerEdge.Length == NoOfFaces);

                    for (int e = 0; e < NoOfFaces; e++)   // loop over faces of cell...

                    //if (qr.NumbersOfNodesPerEdge[e] <= 0)
                    //    // no contribution from this edge
                    //    continue;



                    {
                        int iEdge = Math.Abs(Cells2Edge[j, e]) - 1;

                        Chunk singleEdgeChunk = Chunk.GetSingleElementChunk(iEdge);

                        DoubleEdgeQuadRule 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.Simplex.Vertices;
                            MultidimensionalArray _vtx = MultidimensionalArray.Create(vtx.GetLength(0), vtx.GetLength(1));
                            _vtx.SetA2d(vtx);
                            var VolSimplex = m_cellBndQF.Simplex;

                            var RefCoord  = MultidimensionalArray.Create(vtx.GetLength(0), vtx.GetLength(1) + 1);
                            var PhysCoord = MultidimensionalArray.Create(1, vtx.GetLength(0), vtx.GetLength(1) + 1);

                            VolSimplex.EdgeToVolumeCoordinates(e, _vtx, RefCoord);
                            grd.TransformLocal2Global(RefCoord, PhysCoord, j, 1, 0);
#endif

                            qrEdge = CombineQr(qrEdge, qr, e, j);

                            Debug.Assert(qrEdge != null);
                            ret[singleEdgeChunk] = qrEdge;
                        }
                        else
                        {
                            // nop: the edge is not in the 'edgMask'!
                            continue;
                        }
                    }
                }
            }

#if DEBUG
            for (int i = EdgeTouched.Length - 1; i >= 0; i--)
            {
                Debug.Assert(EdgeTouched[i] == false);
            }
#endif

            return(ret.Select(p => new ChunkRulePair <DoubleEdgeQuadRule>(p.Key, p.Value)));
        }