/// <summary> /// Loads a time-step from the database into previously allocated /// DG-fields (<paramref name="PreAllocatedFields"/>). /// </summary> public void LoadFieldData(ITimestepInfo info, IGridData grdDat, IEnumerable <DGField> PreAllocatedFields) { using (var tr = new FuncTrace()) { DGField[] Fields = PreAllocatedFields.ToArray(); // enforce 'evaluation' of the enum (in the case it is some delayed linq-expr). List <DGField> FieldsFlatten = new List <DGField>(); TimestepInfo.FlattenHierarchy(FieldsFlatten, Fields); foreach (var f in FieldsFlatten) { if (!Fields.Contains(f, (a, b) => object.ReferenceEquals(a, b))) { throw new ArgumentException("Unable to load timestep: field '" + f.Identification + "', which is required by at least one of the given fields, must also be contained in the given list of fields.", "PreAllocatedFields"); } } // Load data vector // ================ var partition = grdDat.CellPartitioning; var DataVec = this.Driver.LoadVector <CellFieldDataSet>(info.StorageID, ref partition); // Permute data vector // =================== var SortedDataVec = new CellFieldDataSet[DataVec.Count]; { // tau is the GlobalID-permutation that we have for the loaded vector // sigma is the current GlobalID-permutation of the grid var sigma = grdDat.CurrentGlobalIdPermutation; var tau = new Permutation(DataVec.Select(cd => cd.GlobalID).ToArray(), csMPI.Raw._COMM.WORLD); // compute resorting permutation Permutation invSigma = sigma.Invert(); Permutation Resorting = invSigma * tau; tau = null; invSigma = null; // put dg coordinates into right order Resorting.ApplyToVector(DataVec, SortedDataVec); } // Load the fields // =============== HashSet <object> loadedObjects = new HashSet <object>(ReferenceComparer.Instance); foreach (var Field in Fields) { Field.LoadData(info, SortedDataVec, loadedObjects); } } }
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> /// Apply the resorting (only mesh redistribution between MPI processors, no mesh adaptation) /// </summary> public void Resort(Permutation r, IGridData NewGrid) { using (new FuncTrace()) { this.GridAdaptation = false; this.Resorting = r; this.InverseResorting = r.Invert(); m_OldGrid = null; m_OldTracker = null; m_NewGrid = NewGrid; m_newJ = m_NewGrid.iLogicalCells.NoOfLocalUpdatedCells; // fix the sequence in which we serialize/de-serialize fields string[] FieldNames = this.m_oldDGFieldData.Keys.ToArray(); int NoFields = FieldNames.Length; // format data for serialization double[][] oldFieldsData = new double[m_oldJ][]; { double[][][] oldFields = FieldNames.Select(rstring => this.m_oldDGFieldData[rstring]).ToArray(); for (int j = 0; j < m_oldJ; j++) { int Ntot = 0; for (int iF = 0; iF < NoFields; iF++) { Ntot += oldFields[iF][j].Length; } double[] data_j = new double[Ntot + NoFields]; int cnt = 0; for (int iF = 0; iF < NoFields; iF++) { double[] data_iF_j = oldFields[iF][j]; int Nj = data_iF_j.Length; data_j[cnt] = Nj; cnt++; for (int n = 0; n < Nj; n++) { data_j[cnt] = data_iF_j[n]; cnt++; } } oldFieldsData[j] = data_j; } oldFields = null; m_oldDGFieldData = null; } // redistribute data double[][] newFieldsData = new double[m_newJ][]; { Resorting.ApplyToVector(oldFieldsData, newFieldsData, m_NewGrid.CellPartitioning); oldFieldsData = null; Debug.Assert(newFieldsData.Length == m_newJ); } // re-format re-distributed data m_newDGFieldData_OnlyRedist = new Dictionary <string, double[][]>(); { double[][][] newFields = new double[FieldNames.Length][][]; for (int iF = 0; iF < NoFields; iF++) { newFields[iF] = new double[m_newJ][]; } for (int j = 0; j < m_newJ; j++) { double[] data_j = newFieldsData[j]; int cnt = 0; for (int iF = 0; iF < NoFields; iF++) { int Nj = (int)data_j[cnt]; cnt++; double[] data_iF_j = new double[Nj]; for (int n = 0; n < Nj; n++) { data_iF_j[n] = data_j[cnt]; cnt++; } newFields[iF][j] = data_iF_j; } Debug.Assert(cnt == data_j.Length); } for (int iF = 0; iF < NoFields; iF++) { m_newDGFieldData_OnlyRedist.Add(FieldNames[iF], newFields[iF]); } } } }