/// <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); } } }
/// <summary> /// Saves a time-step to the database's persistent memory. /// </summary> /// <param name="_tsi">Contains Id etc.</param> public void SaveTimestep(TimestepInfo _tsi) { using (var tr = new FuncTrace()) { if (!(_tsi.ID.Equals(Guid.Empty) && _tsi.StorageID.Equals(Guid.Empty))) { throw new ArgumentException("Timestep is already saved in database"); } var fields = _tsi.Fields.ToArray(); var GridDat = fields[0].GridDat; { List <DGField> FieldsFlatten = new List <DGField>(); TimestepInfo.FlattenHierarchy(FieldsFlatten, fields); foreach (var f in FieldsFlatten) { if (!object.ReferenceEquals(f.GridDat, GridDat)) { throw new ArgumentException("mismatch in GridData object."); } if (!fields.Contains(f, (a, b) => object.ReferenceEquals(a, b))) { // here, we ensure that the 'fields' -- list is complete, i.e. // that the flatten hierarchy contains no field which is not already a memeber of 'fields'. // The purpose is e.g. to prevent saving an XDG field without the required level-set field. throw new ArgumentException( "Unable to save 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.", "_tsi"); } } } // build vector // ============ int J = GridDat.iLogicalCells.NoOfLocalUpdatedCells; var vec = new CellFieldDataSet[J]; var _fields = fields.ToArray(); int NF = _fields.Length; var Permutation = GridDat.CurrentGlobalIdPermutation.Values; for (int j = 0; j < J; j++) { // loop over cells vec[j] = new CellFieldDataSet(); vec[j].GlobalID = Permutation[j]; //vec[j].DGCoordinateData = new CellFieldDataSet.CellFieldData[NF]; for (int idxF = 0; idxF < NF; idxF++) { // loop over fields var field = _fields[idxF]; int N = field.Basis.GetLength(j); double[] Coords = new double[N]; for (int n = 0; n < N; n++) { Coords[n] = field.Coordinates[j, n]; } //vec[j].DGCoordinateData[idxF] = new CellFieldDataSet.CellFieldData() { // Data = Coords //}; vec[j].AppendDGCoordinates(Coords); Debug.Assert(ArrayTools.ListEquals(Coords, vec[j].GetDGCoordinates(idxF))); } } // Save dg coordinates // =================== Guid VectorGuid = Driver.SaveVector(vec); _tsi.StorageID = VectorGuid; // Save state object // ================= _tsi.ID = Guid.NewGuid().MPIBroadcast(0); Exception e = null; if (MyRank == 0) { try { //tsi = new TimestepInfo(physTime, currentSession, TimestepNo, fields, VectorGuid); using (var s = fsDriver.GetTimestepStream(true, _tsi.ID)) { Driver.Serialize(s, _tsi, typeof(TimestepInfo)); s.Close(); } } catch (Exception ee) { e = ee; Console.Error.WriteLine(ee.GetType().Name + " on rank " + MyRank + " saving time-step " + _tsi.TimeStepNumber + ": " + ee.Message); Console.Error.WriteLine(ee.StackTrace); } } e.ExceptionBcast(); // log session // =========== SessionInfo currentSession = (SessionInfo)(_tsi.Session); // hack if (MyRank == 0) { try { currentSession.LogTimeStep(_tsi.ID); } catch (Exception ee) { e = ee; Console.Error.WriteLine(ee.GetType().Name + " on rank " + MyRank + " saving time-step " + _tsi.TimeStepNumber + ": " + ee.Message); Console.Error.WriteLine(ee.StackTrace); } } e.ExceptionBcast(); _tsi.Database = currentSession.Database; } }