public EdgeMask GetEdges4RefElement(RefElement Kref)
            {
                if (m_Edges4RefElement == null)
                {
                    m_Edges4RefElement = new EdgeMask[this.EdgeRefElements.Length];
                }

                int iKref = this.EdgeRefElements.IndexOf(Kref, (a, b) => object.ReferenceEquals(a, b));

                if (m_Edges4RefElement[iKref] == null)
                {
                    EdgeMask parrEdg = m_Owner.ParentGrid.iGeomEdges.GetEdges4RefElement(Kref);
                    EdgeMask thisAll = EdgeMask.GetFullMask(this.m_Owner, MaskType.Geometrical);
                    if (parrEdg.MaskType != MaskType.Geometrical)
                    {
                        throw new ApplicationException("expecting a geometrical mask");
                    }
                    if (thisAll.MaskType != MaskType.Geometrical)
                    {
                        throw new ApplicationException("expecting a geometrical mask");
                    }

                    BitArray parrBitmask = parrEdg.GetBitMask().CloneAs();
                    BitArray thisBitMask = thisAll.GetBitMask();
                    Debug.Assert(parrBitmask.Length == thisBitMask.Length);

                    BitArray intersect = parrBitmask.And(thisBitMask);
                    Debug.Assert(object.ReferenceEquals(intersect, parrBitmask));

                    m_Edges4RefElement[iKref] = new EdgeMask(m_Owner, intersect, MaskType.Geometrical);
                }

                return(m_Edges4RefElement[iKref]);
            }
예제 #2
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)));
        }