/// <summary> /// clone /// </summary> public object Clone() { var ret = new BCElement(); ret.GlobalID = this.GlobalID; ret.TransformationParams = this.TransformationParams.CloneAs(); ret.NodeIndices = this.NodeIndices.CloneAs(); ret.EdgeTag = this.EdgeTag; ret.Type = this.Type; return(ret); }
static bool AreCellsEqual(GridCommons A, GridCommons B) { if (object.ReferenceEquals(A, B)) { return(true); } if ((A == null) != (B == null)) { return(false); } if (A.Cells == null) { throw new ArgumentException(); } int A_NumberOfBcCells = A.NumberOfBcCells; int match = 1; { // load cells of grid B, if required // --------------------------------- Cell[] B_Cells; if (B.Cells == null) { throw new Exception("Cells are not initialized"); } else { B_Cells = B.Cells; } if (A.Cells.Length != B_Cells.Length) { throw new ApplicationException(); } // put the cells of B into the same order as those of A // ---------------------------------------------------- { // tau is the GlobalID-permutation that we have for the loaded vector // sigma is the current GlobalID-permutation of the grid var sigma = new Permutation(A.Cells.Select(cell => cell.GlobalID).ToArray(), csMPI.Raw._COMM.WORLD); var tau = new Permutation(B_Cells.Select(cell => cell.GlobalID).ToArray(), csMPI.Raw._COMM.WORLD); if (sigma.TotalLength != tau.TotalLength) { // should have been checked already throw new ArgumentException(); } // compute resorting permutation Permutation invSigma = sigma.Invert(); Permutation Resorting = invSigma * tau; tau = null; // Werfen wir sie dem GC zum Fraße vor! invSigma = null; // put dg coordinates into right order Resorting.ApplyToVector(B_Cells.CloneAs(), B_Cells); } // compare cells // ------------- for (int j = 0; j < A.Cells.Length; j++) { Cell Ca = A.Cells[j]; Cell Cb = B_Cells[j]; Debug.Assert(Ca.GlobalID == Cb.GlobalID); if (!ArrayTools.ListEquals(Ca.NodeIndices, Cb.NodeIndices, (ia, ib) => ia == ib)) { match = 0; break; } if (Ca.Type != Cb.Type) { match = 0; break; } if (Ca.CellFaceTags != null || Cb.CellFaceTags != null) { CellFaceTag[] CFTA = Ca.CellFaceTags != null ? Ca.CellFaceTags : new CellFaceTag[0]; CellFaceTag[] CFTB = Cb.CellFaceTags != null ? Cb.CellFaceTags : new CellFaceTag[0]; if (CFTA.Length != CFTB.Length) { match = 0; break; } bool setMatch = true; for (int i1 = 0; i1 < CFTA.Length; i1++) { bool b = false; for (int j1 = 0; j1 < CFTB.Length; j1++) { if (CFTA[i1].Equals(CFTB[j1])) { b = true; break; } } if (b == false) { setMatch = false; break; } } if (!setMatch) { match = 0; break; } } double h = Math.Min(Ca.TransformationParams.MindistBetweenRows(), Cb.TransformationParams.MindistBetweenRows()); double L2Dist = Ca.TransformationParams.L2Dist(Cb.TransformationParams); if (L2Dist > h * 1.0e-9) { match = 0; break; } } } if (A_NumberOfBcCells > 0) { BCElement[] B_BcCells; if (B.BcCells == null && !B.BcCellsStorageGuid.Equals(Guid.Empty)) { throw new Exception("Bc Cells are not initialized"); } else { B_BcCells = B.BcCells; } if (A.BcCells.Length != B_BcCells.Length) { throw new ApplicationException("Internal error."); } // put the cells of B into the same order as those of A // ---------------------------------------------------- { long Offset = A.NumberOfCells_l; // tau is the GlobalID-permutation that we have for the loaded vector // sigma is the current GlobalID-permutation of the grid var sigma = new Permutation(A.BcCells.Select(cell => cell.GlobalID - Offset).ToArray(), csMPI.Raw._COMM.WORLD); var tau = new Permutation(B_BcCells.Select(cell => cell.GlobalID - Offset).ToArray(), csMPI.Raw._COMM.WORLD); if (sigma.TotalLength != tau.TotalLength) { // should have been checked already throw new ArgumentException(); } // compute resorting permutation Permutation invSigma = sigma.Invert(); Permutation Resorting = invSigma * tau; tau = null; // Werfen wir sie dem GC zum Fraße vor! invSigma = null; // put dg coordinates into right order Resorting.ApplyToVector(B_BcCells.CloneAs(), B_BcCells); } // compare cells // ------------- for (int j = 0; j < A.BcCells.Length; j++) { BCElement Ca = A.BcCells[j]; BCElement Cb = B_BcCells[j]; Debug.Assert(Ca.GlobalID == Cb.GlobalID); if (!ArrayTools.ListEquals(Ca.NodeIndices, Cb.NodeIndices, (ia, ib) => ia == ib)) { match = 0; break; } if (Ca.Type != Cb.Type) { match = 0; break; } if (Ca.Conformal != Cb.Conformal) { match = 0; break; } if (Ca.EdgeTag != Cb.EdgeTag) { match = 0; break; } if (Ca.NeighCell_GlobalIDs != null || Cb.NeighCell_GlobalIDs != null) { long[] NgA = Ca.NeighCell_GlobalIDs != null ? Ca.NeighCell_GlobalIDs : new long[0]; long[] NgB = Cb.NeighCell_GlobalIDs != null ? Cb.NeighCell_GlobalIDs : new long[0]; if (NgA.Length != NgB.Length) { match = 0; break; } bool setMatch = true; for (int i1 = 0; i1 < NgA.Length; i1++) { bool b = false; for (int j1 = 0; j1 < NgB.Length; j1++) { if (NgA[i1] == NgB[j1]) { b = true; break; } } if (b == false) { setMatch = false; break; } } if (!setMatch) { match = 0; break; } } double h = Math.Min(Ca.TransformationParams.MindistBetweenRows(), Cb.TransformationParams.MindistBetweenRows()); double L2Dist = Ca.TransformationParams.L2Dist(Cb.TransformationParams); if (L2Dist > h * 1.0e-9) { match = 0; break; } } } match = match.MPIMin(); return(match > 0); }
/// <summary> /// Concatenates grids <paramref name="A"/> and <paramref name="B"/> into one data structure. /// </summary> public static GridCommons MergeLogically(GridCommons A, GridCommons B) { GridCommons R = new GridCommons(); R.m_GridGuid = Guid.NewGuid(); //R.BcCellPartitioning; R.m_BcCellPartitioning //R.BcCells; //R.BcCellsStorageGuid; //R.CellPartitioning; //R.Cells; //R.Description; //R.EdgeRefElements; //R.EdgeTagNames; //R.GridGuid; == R.ID; //R.InversePeriodicTrafo on-demand //R.m_ClassNameOfEdgeRefElement //R.m_RefElements; //R.m_EdgeRefElements; ///////////////////////// // merge ref elements ///////////////////////// { R.m_RefElements = A.m_RefElements.CloneAs(); int[] BrefElm = new int[B.m_RefElements.Length]; for (int iKrefB = 0; iKrefB < BrefElm.Length; iKrefB++) { RefElement Kref = B.m_RefElements[iKrefB]; int iKrefBNew = R.m_RefElements.IndexOf(Kref, (a, b) => a.Equals(b)); if (iKrefBNew < 0) { ArrayTools.AddToArray(Kref, ref R.m_RefElements); iKrefBNew = B.m_RefElements.Length - 1; } BrefElm[iKrefB] = iKrefBNew; } R.m_EdgeRefElements = A.m_EdgeRefElements.CloneAs(); int[] BEdgeRefElm = new int[B.m_EdgeRefElements.Length]; for (int iEdgeKrefB = 0; iEdgeKrefB < BEdgeRefElm.Length; iEdgeKrefB++) { RefElement Kref = B.m_EdgeRefElements[iEdgeKrefB]; int iEdgeKrefBNew = R.m_EdgeRefElements.IndexOf(Kref, (a, b) => a.Equals(b)); if (iEdgeKrefBNew < 0) { ArrayTools.AddToArray(Kref, ref R.m_EdgeRefElements); iEdgeKrefBNew = B.m_EdgeRefElements.Length - 1; } BEdgeRefElm[iEdgeKrefB] = iEdgeKrefBNew; } } ////////////////////////////////////////// // merge edge tags & periodic transformations ////////////////////////////////////////// byte[] BNewEdgeTag = new byte[0xff]; // mapping: old edge tag in B (index) => edge tag in R (content) { R.m_PeriodicTrafo.AddRange(A.m_PeriodicTrafo.Select(at => at.CloneAs()).ToArray()); R.m_EdgeTagNames.AddRange(A.m_EdgeTagNames); foreach (var kv in B.m_EdgeTagNames) { byte _EdgeTagB = kv.Key, _NewEdgeTagB; string NameB = kv.Value; if (R.m_EdgeTagNames.ContainsValue(NameB)) { _NewEdgeTagB = R.m_EdgeTagNames.First(kv2 => kv2.Value.Equals(NameB)).Key; } else { _NewEdgeTagB = R.m_EdgeTagNames.Keys.Where(et => et < FIRST_PERIODIC_BC_TAG).Max(); } BNewEdgeTag[_EdgeTagB] = _NewEdgeTagB; } AffineTrafo[] BperiodicTrafo = B.m_PeriodicTrafo.Select(at => at.CloneAs()).ToArray(); for (int i = 0; i < BperiodicTrafo.Length; i++) { var Tr = BperiodicTrafo[i]; int _BEdgeTag = i + FIRST_PERIODIC_BC_TAG; int _BNewEdgeTag; int idxTr = R.m_PeriodicTrafo.IndexOf(Tr, (TrA, TrB) => TrA.ApproximateEquals(TrB)); if (idxTr < 0) { R.m_PeriodicTrafo.Add(Tr); _BNewEdgeTag = R.m_PeriodicTrafo.Count + FIRST_PERIODIC_BC_TAG - 1; R.m_EdgeTagNames.Add((byte)_BNewEdgeTag, B.m_EdgeTagNames[(byte)_BEdgeTag]); } else { _BNewEdgeTag = idxTr + FIRST_PERIODIC_BC_TAG; } BNewEdgeTag[_BEdgeTag] = (byte)_BNewEdgeTag; } } ////////////////////////// // merge cells (logically) ////////////////////////// { int NodeOffset = A.NodePartitioning.TotalLength; long JAglb = A.NumberOfCells_l; long JBglb = B.NumberOfCells_l; long KAglb = A.NoOfBcCells.MPISum(); long KBglb = B.NoOfBcCells.MPISum(); int JA = A.Cells.Length; int JB = B.Cells.Length; R.Cells = new Cell[JA + JB]; int KA = A.NoOfBcCells; int KB = B.NoOfBcCells; R.BcCells = new BCElement[KA + KB]; // check GlobalIds of cells for (int ja = 0; ja < JA; ja++) { Cell CA = A.Cells[ja]; if (CA.GlobalID < 0 || CA.GlobalID >= JAglb) { throw new ArgumentException("Illegal GlobalId in grid A.", "A"); } } for (int jb = 0; jb < JB; jb++) { Cell CB = B.Cells[jb]; if (CB.GlobalID < 0 || CB.GlobalID >= JBglb) { throw new ArgumentException("Illegal GlobalId in grid B.", "B"); } } // check globalIDs of boundary elements for (int ka = 0; ka < KA; ka++) { BCElement BcA = A.BcCells[ka]; if (BcA.GlobalID < JAglb || BcA.GlobalID >= JAglb + KAglb) { throw new ArgumentException("Illegal GlobalId for boundary element in grid A.", "A"); } } for (int kb = 0; kb < KB; kb++) { BCElement BcB = B.BcCells[kb]; if (BcB.GlobalID < JB || BcB.GlobalID >= JBglb + KBglb) { throw new ArgumentException("Illegal GlobalId for boundary element in grid B.", "B"); } } // cells of A: // ----------- for (int ja = 0; ja < JA; ja++) { Cell CA = A.Cells[ja]; R.Cells[ja] = new Cell() { GlobalID = CA.GlobalID, NodeIndices = CA.NodeIndices == null ? null : CA.NodeIndices.CloneAs(), Type = CA.Type, TransformationParams = CA.TransformationParams.CloneAs(), CellFaceTags = CA.CellFaceTags == null ? null : CA.CellFaceTags.Select(tag => new CellFaceTag() { EdgeTag = tag.EdgeTag, FaceIndex = tag.FaceIndex, ConformalNeighborship = tag.ConformalNeighborship, NeighCell_GlobalID = tag.NeighCell_GlobalID < JAglb ? tag.NeighCell_GlobalID : // normal cell tag.NeighCell_GlobalID + JBglb, // boundary element PeriodicInverse = tag.PeriodicInverse }).ToArray() }; Debug.Assert(R.Cells[ja].GlobalID >= 0 && R.Cells[ja].GlobalID < JAglb); if (CA.CellFaceTags != null) { for (int i = 0; i < CA.CellFaceTags.Length; i++) { var cft = R.Cells[ja].CellFaceTags[i]; var orgCft = CA.CellFaceTags[i]; Debug.Assert( (orgCft.NeighCell_GlobalID < JAglb && cft.NeighCell_GlobalID >= 0 && cft.NeighCell_GlobalID < JAglb) || // normall cell (orgCft.NeighCell_GlobalID >= JAglb && cft.NeighCell_GlobalID >= JAglb + JBglb && cft.NeighCell_GlobalID < JAglb + JBglb + KAglb)); // boundary element } } } // cells of B: // ----------- for (int jb = 0; jb < JB; jb++) { Cell CB = B.Cells[jb]; R.Cells[jb + JA] = new Cell() { GlobalID = CB.GlobalID + JAglb, NodeIndices = CB.NodeIndices == null ? null : CB.NodeIndices.Select(idx => idx + NodeOffset).ToArray(), Type = CB.Type, TransformationParams = CB.TransformationParams.CloneAs(), CellFaceTags = CB.CellFaceTags == null ? null : CB.CellFaceTags.Select(tag => new CellFaceTag() { EdgeTag = BNewEdgeTag[tag.EdgeTag], FaceIndex = tag.FaceIndex, ConformalNeighborship = tag.ConformalNeighborship, NeighCell_GlobalID = tag.NeighCell_GlobalID + JAglb, // correct for normal cell and boundary element PeriodicInverse = tag.PeriodicInverse }).ToArray() }; Debug.Assert(R.Cells[jb + JA].GlobalID >= JAglb && R.Cells[jb + JA].GlobalID < JAglb + JBglb); if (CB.CellFaceTags != null) { for (int i = 0; i < CB.CellFaceTags.Length; i++) { var cft = R.Cells[jb + JA].CellFaceTags[i]; var orgCft = CB.CellFaceTags[i]; Debug.Assert( (orgCft.NeighCell_GlobalID < JBglb && cft.NeighCell_GlobalID >= JAglb && cft.NeighCell_GlobalID < JAglb + JBglb) || // normall cell (orgCft.NeighCell_GlobalID >= JBglb && cft.NeighCell_GlobalID >= JAglb + JBglb + KAglb && cft.NeighCell_GlobalID < JAglb + JBglb + KAglb + KBglb)); // boundary element } } } // boundary elements of A: // ----------------------- for (int ka = 0; ka < KA; ka++) { BCElement BcA = A.BcCells[ka]; R.BcCells[ka] = new BCElement() { Conformal = BcA.Conformal, GlobalID = BcA.GlobalID + JBglb, NeighCell_GlobalIDs = BcA.NeighCell_GlobalIDs == null ? null : BcA.NeighCell_GlobalIDs.Select( gidN => gidN < JAglb ? gidN : gidN + JBglb).ToArray(), EdgeTag = BcA.EdgeTag, NodeIndices = BcA.NodeIndices == null ? null : BcA.NodeIndices.CloneAs(), TransformationParams = BcA.TransformationParams.CloneAs(), Type = BcA.Type }; Debug.Assert(R.BcCells[ka].GlobalID >= JAglb + JBglb && R.BcCells[ka].GlobalID < JAglb + JBglb + KAglb); if (BcA.NeighCell_GlobalIDs != null) { for (int i = 0; i < BcA.NeighCell_GlobalIDs.Length; i++) { long Ngid = R.BcCells[ka].NeighCell_GlobalIDs[i]; long orgNgid = BcA.NeighCell_GlobalIDs[i]; Debug.Assert((orgNgid < JAglb && Ngid >= 0 && Ngid < JAglb) || // normall cell (orgNgid >= JAglb && Ngid >= JAglb + JBglb && Ngid < JAglb + JBglb + KAglb)); // boundary element } } } // boundary elements of B: // ----------------------- for (int kb = 0; kb < KB; kb++) { BCElement BcB = A.BcCells[kb]; R.BcCells[kb + KA] = new BCElement() { Conformal = BcB.Conformal, GlobalID = BcB.GlobalID + JAglb, NeighCell_GlobalIDs = BcB.NeighCell_GlobalIDs == null ? null : BcB.NeighCell_GlobalIDs.Select( gidN => gidN < JBglb ? gidN + JAglb : gidN + JAglb).ToArray(), EdgeTag = BNewEdgeTag[BcB.EdgeTag], NodeIndices = BcB.NodeIndices == null ? null : BcB.NodeIndices.Select(idx => idx + NodeOffset).ToArray(), TransformationParams = BcB.TransformationParams.CloneAs(), Type = BcB.Type }; Debug.Assert(R.BcCells[kb].GlobalID >= JAglb + JBglb + KAglb && R.BcCells[kb].GlobalID < JAglb + JBglb + KAglb + KBglb); if (BcB.NeighCell_GlobalIDs != null) { for (int i = 0; i < BcB.NeighCell_GlobalIDs.Length; i++) { long Ngid = R.BcCells[kb + KA].NeighCell_GlobalIDs[i]; long orgNgid = BcB.NeighCell_GlobalIDs[i]; Debug.Assert((orgNgid < JBglb && Ngid >= JAglb && Ngid < JAglb + JBglb) || // normall cell (orgNgid >= JBglb && Ngid >= JAglb + JBglb + KAglb && Ngid < JAglb + JBglb + KAglb + KBglb)); // boundary element } } } } return(R); }