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]); }
/// <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))); }