/// <summary> /// Adds a one-dimensional variable to the specified SDS object with floating point dimension data /// </summary> /// <param name="SDSObject">A reference to an SDS object</param> /// <param name="variableName">The name of the variable to create</param> /// <param name="units">Units of the data</param> /// <param name="numDimensions">The number of dimensions for the new variable</param> /// <param name="namesDimensions">A vector of names of the dimensions for the variable</param> /// <param name="missingValue">The missing value to apply to the new variable</param> /// <param name="dimension1Data">A vector of values of the first dimension</param> public void AddVariable(DataSet SDSObject, string variableName, string units, int numDimensions, string[] namesDimensions, double missingValue, float[] dimension1Data) { //If the wrong number of dimension names have been provided, then return error if (namesDimensions.Length != numDimensions) Debug.Fail("Error: you have provided the wrong number of dimension names"); //Since this overload method deals with one-dimensional variables, return an error if this is not the case if (numDimensions != 1) Debug.Fail("Error: you have provided data for the wrong number of dimensions"); //If the variable already exists in the SDS, then take no action, otherwise create new variable if (SDSObject.Variables.Contains(variableName)) { Console.WriteLine("SDS object already contains a variable with that name. Skipping..."); } else { //For each dimension, if it already exists in the SDS then take no action, otherwise create a new variable and populate it with the provided data if (SDSObject.Variables.Contains(namesDimensions[0])) { } else { SDSObject.AddVariable<float>(namesDimensions[0], dimension1Data, namesDimensions[0]); } //If the variable is the same as one of the entered dimensions, then take no action, otherwise create the new variable and populate it with missing values if (SDSObject.Variables.Contains(variableName)) { } else { //Create array of missing values of the correct dimensions double[] tempOutData = new double[dimension1Data.Length]; for (int ii = 0; ii < dimension1Data.Length; ii++) { tempOutData[ii] = missingValue; } //Add variable to SDS var testOut = SDSObject.Add<double[]>(variableName, units, missingValue, tempOutData, namesDimensions); //Metadata required by SDS testOut.Metadata["DisplayName"] = variableName; testOut.Metadata["MissingValue"] = missingValue; //Commit changes SDSObject.Commit(); } } }
public void Init(string constructionString) { dataSet = DataSet.Create(constructionString); //Инициализируем DataSet Variable X = dataSet.AddVariable<double>("X", "x"); Variable Y = dataSet.AddVariable<double>("Y", "y"); Variable Z = dataSet.AddVariable<double>("Z", "z"); time = dataSet.AddVariable<double>("Time", "t"); u = dataSet.AddVariable<double>("U velocity", "x", "y", "z", "t"); v = dataSet.AddVariable<double>("V velocity", "x", "y", "z", "t"); w = dataSet.AddVariable<double>("W velocity", "x", "y", "z", "t"); T = dataSet.AddVariable<double>("Temperature", "x", "y", "z", "t"); div = dataSet.AddVariable<double>("Divergence", "x", "y", "z", "t"); double[] wArr = new double[modellingParams.Nx]; for (int i = 0; i < modellingParams.Nx; i++) { wArr[i] = i * modellingParams.Dx; } X.PutData(wArr); wArr = new double[modellingParams.Ny]; for (int i = 0; i < modellingParams.Ny; i++) { wArr[i] = i * modellingParams.Dy; } Y.PutData(wArr); wArr = new double[modellingParams.Nz]; for (int i = 0; i < modellingParams.Nz; i++) { wArr[i] = i * modellingParams.Dz; } Z.PutData(wArr); //Инициализируем рассчетный модуль для слоя начальными условиями solver = new LayerSolver(prevData, modellingParams); u.Append(prevData.U.ToArray(), "t"); v.Append(prevData.V.ToArray(), "t"); w.Append(prevData.W.ToArray(), "t"); T.Append(prevData.T.ToArray(), "t"); div.Append(prevData.Div.ToArray(), "t"); time.PutData(new double[1] { 0 }); dataSet.Commit(); }
/// <summary> /// Creates and adds the variable as an axis to the coordinate system and related data set. /// </summary> /// <param name="name">Name of the new variable.</param> /// <param name="dims">Names of dimensions the variable depends on.</param> /// <typeparam name="DataType">Data type of the axis.</typeparam> /// <returns>The variable just created and added as an axis.</returns> internal Variable <DataType> AddAxis <DataType>(string name, params string[] dims) { if (committed) { throw new NotSupportedException("Coordinate system cannot be changed after committing."); } if (axes.Contains(name)) { throw new Exception("The coordinate system already contains an axis with the same name."); } Variable <DataType> var = sds.AddVariable <DataType>(name, dims); return(AddAxis(var)); }
public void SolveAll(string ctorString) { //dataSet = ProxyDataSet.Open("msds:nc?file=../../../temp.nc"); dataSet = ProxyDataSet.Open("msds:memory"); //Инициализируем DataSet Variable X = dataSet.AddVariable<double>("X", "x"); Variable Y = dataSet.AddVariable<double>("Y", "y"); Variable Z = dataSet.AddVariable<double>("Z", "z"); Variable time = dataSet.AddVariable<double>("Time", "t"); Variable u = dataSet.AddVariable<double>("U velocity", "x", "y", "z", "t"); Variable v = dataSet.AddVariable<double>("V velocity", "x", "y", "z", "t"); Variable w = dataSet.AddVariable<double>("W velocity", "x", "y", "z", "t"); Variable T = dataSet.AddVariable<double>("Temperature", "x", "y", "z", "t"); Variable div = dataSet.AddVariable<double>("Divergence", "x", "y", "z", "t"); dataSet.Commit(); double[] wArr = new double[modellingParams.Nx]; for (int i = 0; i < modellingParams.Nx; i++) { wArr[i] = i * modellingParams.Dx; } X.PutData(wArr); wArr = new double[modellingParams.Ny]; for (int i = 0; i < modellingParams.Ny; i++) { wArr[i] = i * modellingParams.Dy; } Y.PutData(wArr); wArr = new double[modellingParams.Nz]; for (int i = 0; i < modellingParams.Nz; i++) { wArr[i] = i * modellingParams.Dz; } Z.PutData(wArr); //Инициализируем рассчетный модуль для слоя начальными условиями LayerSolver solver = new LayerSolver(prevData, modellingParams); u.Append(prevData.U.ToArray(), "t"); v.Append(prevData.V.ToArray(), "t"); w.Append(prevData.W.ToArray(), "t"); T.Append(prevData.T.ToArray(), "t"); div.Append(prevData.Div.ToArray(), "t"); time.PutData(new double[1] { 0 }); dataSet.Commit(); //Основной рассчет for (int i = 1; i < modellingParams.Nt; i++) { LayerData result = solver.Solve(true); //Кладем данные в DataSet u.Append(result.U.ToArray(), "t"); v.Append(result.V.ToArray(), "t"); w.Append(result.W.ToArray(), "t"); T.Append(result.T.ToArray(), "t"); div.Append(result.Div.ToArray(), "t"); time.Append(new double[1] { (double)i / modellingParams.Nt }); dataSet.Commit(); //Переходим на следующий слой solver = new LayerSolver(prevData, result, modellingParams); prevData = result; double temp = 0; int count = 0; for (int ii = 1; ii < result.Width; ii++) { for (int jj = 1; jj < result.Height; jj++) { for (int kk = 1; kk < result.Thickness; kk++) { temp += result.Div[ii, jj, kk]; count++; } } } temp = temp / count * modellingParams.Dx * modellingParams.Dy * modellingParams.Dz; Console.WriteLine((double)i / modellingParams.Nt * 100 + "% Error = " + temp); } dataSet.Commit(); }
/// <summary> /// Extract an array of values from a state variable in a model grid and add to a two-dimensional variable in an SDS object /// </summary> /// <param name="ecosystemModelGrid">The model grid to extract data from</param> /// <param name="cellIndices">List of indices of active cells in the model grid</param> /// <param name="gridVariableName">The name of the state variable in the model grid</param> /// <param name="traitValue">The trait value of the functional groups to get data for</param> /// <param name="variableType">The type of the state variable: 'stock' or 'cohort'</param> /// <param name="outputVariableName">The name of the variable to write to</param> /// <param name="SDSObject">The SDS object to write to</param> /// <param name="functionalGroupHandler">The functional group handler corresponding to cohorts or stocks</param> /// <param name="initialisation">The Madingley Model initialisation</param> public void Array2DToSDS2D(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, string gridVariableName, string traitValue, string variableType, string outputVariableName, DataSet SDSObject, FunctionalGroupDefinitions functionalGroupHandler, MadingleyModelInitialisation initialisation) { // Get the missing value from the model grid double MissingValue = ecosystemModelGrid.GlobalMissingValue; // create an array to hold the data to output double[,] dataToConvert = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells]; // generate arrays to hold latitudes and longitudes float[] lats = new float[ecosystemModelGrid.NumLatCells]; float[] lons = new float[ecosystemModelGrid.NumLonCells]; // Populate arrays of latitudes and longitudes, converting from bottom left cell references as used in the model grid // to cell centre references as required by SDS for (uint ii = 0; ii < ecosystemModelGrid.NumLatCells; ii++) { lats[ii] = ecosystemModelGrid.Lats[ii] + (ecosystemModelGrid.LatCellSize / 2); } for (uint jj = 0; jj < ecosystemModelGrid.NumLonCells; jj++) { lons[jj] = ecosystemModelGrid.Lons[jj] + (ecosystemModelGrid.LonCellSize / 2); } // Get the required data from the model grid dataToConvert = ecosystemModelGrid.GetStateVariableGrid(gridVariableName, traitValue, functionalGroupHandler.AllFunctionalGroupsIndex, cellIndices, variableType, initialisation); // If not already contained in the SDS, add the dimension information (geographic coordinates) if (SDSObject.Variables.Contains("Latitude")) { } else { SDSObject.AddVariable<float>("Latitude", lats, "Lat"); } if (SDSObject.Variables.Contains("Longitude")) { } else { SDSObject.AddVariable<float>("Longitude", lons, "Lon"); } // If the SDS object already contains the output variable, then add the data. Otherwise, define the variable and then add the data if (SDSObject.Variables.Contains(outputVariableName)) { SDSObject.PutData<double[,]>(outputVariableName, dataToConvert); // Commit the changes SDSObject.Commit(); } else { // Set up the dimensions and add the gridded data string[] dimensions = { "Lat", "Lon" }; var DataGrid = SDSObject.AddVariable<double>(outputVariableName, dataToConvert, dimensions); // Add appropriate metadata (including missing values) DataGrid.Metadata["DisplayName"] = outputVariableName; DataGrid.Metadata["MissingValue"] = (double)MissingValue; // Commit changes to update data set SDSObject.Commit(); } }
/// <summary> /// Adds a geographical array of values to a two-dimensional variable in an SDS object /// </summary> /// <param name="dataToConvert">The array of values to add</param> /// <param name="ouputVariableName">The name of the variable to write to</param> /// <param name="lats">The values of the latitude dimension variable</param> /// <param name="lons">The values of the longitude dimension variable</param> /// <param name="missingValue">The value used for missing data</param> /// <param name="SDSObject">The SDS object to write to</param> public void Array2DToSDS2D(double[,] dataToConvert, string ouputVariableName, float[] lats, float[] lons, double missingValue, DataSet SDSObject) { // If not already contained in the SDS, add the dimension information (geographic coordinates) if (SDSObject.Variables.Contains("Latitude")) { } else { SDSObject.AddVariable<float>("Latitude", lats, "Lat"); } if (SDSObject.Variables.Contains("Longitude")) { } else { SDSObject.AddVariable<float>("Longitude", lons, "Lon"); } // If the SDS object contains the variable to write to, then simply add the data, otherwise add a new variable and then add the data if (SDSObject.Variables.Contains(ouputVariableName)) { // Add the data SDSObject.PutData<double[,]>(ouputVariableName, dataToConvert); // Commit the changes SDSObject.Commit(); } else { // Set up the dimensions and add the gridded data string[] dimensions = { "Lat", "Lon" }; var DataGrid = SDSObject.AddVariable<double>(ouputVariableName, dataToConvert, dimensions); // Add appropriate metadata (including missing values) DataGrid.Metadata["DisplayName"] = ouputVariableName; DataGrid.Metadata["MissingValue"] = (double)missingValue; // Commit changes to update data set SDSObject.Commit(); } }
/// <summary> /// Adds a vector of double values to a one-dimensional variable in an SDS object /// </summary> /// <param name="dataToConvert">The vector of values to add</param> /// <param name="outputVariableName">The name of the variable to write to</param> /// <param name="dimensionName">The name of the dimension variable of the output variable</param> /// <param name="dimensionValues">The values of the dimension variable</param> /// <param name="missingValue">The value used for missing data</param> /// <param name="SDSObject">The SDS object to write to</param> public void VectorToSDS1D(double[] dataToConvert, string outputVariableName, string dimensionName, float[] dimensionValues, double missingValue, DataSet SDSObject) { // If not already contained in the SDS object, add the dimension variable if (SDSObject.Variables.Contains(dimensionName)) { } else { SDSObject.AddVariable<float>(dimensionName, dimensionValues, dimensionName); } // If not already contained in the SDS object, add the output variable if (SDSObject.Variables.Contains(outputVariableName)) { SDSObject.PutData<double[]>(outputVariableName, dataToConvert); SDSObject.Commit(); } else { // Set up the dimensions and add the gridded data string[] dimensions = { dimensionName }; var DataGrid = SDSObject.AddVariable<double>(outputVariableName, dataToConvert, dimensions); // Add appropriate metadata (including missing values) DataGrid.Metadata["DisplayName"] = outputVariableName; DataGrid.Metadata["MissingValue"] = (double)missingValue; // Commit changes SDSObject.Commit(); } }
public void WriteFeedingInteractions(uint timestep) { int nrows = FeedingInteractionsMatrixPredation.GetLength(0); int ncols = FeedingInteractionsMatrixPredation.GetLength(1); int MaxLengthPredation = 0; for (int i = 0; i < nrows; i++) { for (int j = 0; j < ncols; j++) { if (FeedingInteractionsMatrixPredation[i, j].Count > MaxLengthPredation) MaxLengthPredation = FeedingInteractionsMatrixPredation[i, j].Count; } } double[, ,] FGIndicesPredation = new double[nrows, ncols, MaxLengthPredation]; double[, ,] FGIndicesHerbivory = new double[nrows, ncols, 2]; double[, ,] CIndicesPredation = new double[nrows, ncols, MaxLengthPredation]; double[, ,] CIndicesHerbivory = new double[nrows, ncols, 2]; double[, ,] BiomassAssimilatedPredation = new double[nrows, ncols, MaxLengthPredation]; double[, ,] BiomassAssimilatedHerbivory = new double[nrows, ncols, 2]; double[, ,] BiomassIngestedPredation = new double[nrows, ncols, MaxLengthPredation]; double[, ,] BiomassIngestedHerbivory = new double[nrows, ncols, 2]; float[] FGIndices = new float[nrows]; float[] CIndices = new float[ncols]; float[] PredationIndices = new float[MaxLengthPredation]; float[] HerbivoryIndices = new float[2] {0,1}; for (int i = 0; i < nrows; i++) { FGIndices[i] = i; } for (int i = 0; i < ncols; i++) { CIndices[i] = i; } for (int i = 0; i < MaxLengthPredation; i++) { PredationIndices[i] = i; } for (int f = 0; f < nrows; f++) { for (int c = 0; c < ncols; c++) { //Populate output data matrices for predation feeding events for (int i = 0; i < FeedingInteractionsMatrixPredation[f, c].Count; i++) { FGIndicesPredation[f, c, i] = Convert.ToDouble(FeedingInteractionsMatrixPredation[f, c].ElementAt(i).Item1); CIndicesPredation[f, c, i] = Convert.ToDouble(FeedingInteractionsMatrixPredation[f, c].ElementAt(i).Item2); BiomassAssimilatedPredation[f, c, i] = (FeedingInteractionsMatrixPredation[f, c].ElementAt(i).Item3); BiomassIngestedPredation[f, c, i] = (FeedingInteractionsMatrixPredation[f, c].ElementAt(i).Item4); } //Populate output data matrices for herbivory feeding events for (int i = 0; i < FeedingInteractionsMatrixHerbivory[f,c].Count; i++) { FGIndicesHerbivory[f, c, i] = Convert.ToDouble(FeedingInteractionsMatrixHerbivory[f, c].ElementAt(i).Item1); CIndicesHerbivory[f, c, i] = Convert.ToDouble(FeedingInteractionsMatrixHerbivory[f, c].ElementAt(i).Item2); BiomassAssimilatedHerbivory[f, c, i] = (FeedingInteractionsMatrixHerbivory[f, c].ElementAt(i).Item3); BiomassIngestedHerbivory[f, c, i] = (FeedingInteractionsMatrixHerbivory[f, c].ElementAt(i).Item4); } } } // Initialise the data converter DataConverter = new ArraySDSConvert(); // Initialise the SDS object creator SDSCreator = new CreateSDSObject(); // Create an SDS object to hold the predation tracker data _FeedingInteractionsDS = SDSCreator.CreateSDS("netCDF", _Filename + _OutputFileSuffix + timestep, _OutputPath); string[] PredationDimensions = new string[3] {"Functional Group Indices","Cohort Indices","Predation Interaction Dimension"}; string[] HerbivoryDimensions = new string[3] { "Functional Group Indices", "Cohort Indices", "Herbivory Interaction Dimension" }; string[] PredD1 = new string [1] { PredationDimensions[0] }; string[] PredD2 = new string[1] { PredationDimensions[1] }; string[] PredD3 = new string[1] { PredationDimensions[2] }; string[] HerbD3 = new string[1] { HerbivoryDimensions[2] }; DataConverter.AddVariable(_FeedingInteractionsDS, PredationDimensions[0], "index", 1, PredD1, _MV, FGIndices); DataConverter.AddVariable(_FeedingInteractionsDS, PredationDimensions[1], "index", 1, PredD2, _MV, CIndices); DataConverter.AddVariable(_FeedingInteractionsDS, PredationDimensions[2], "index", 1, PredD3, _MV, PredationIndices); DataConverter.AddVariable(_FeedingInteractionsDS, HerbivoryDimensions[2], "index", 1, HerbD3, _MV, HerbivoryIndices); /*DataConverter.AddVariable(_FeedingInteractionsDS, "Predation Interactions Functional Groups", 3, PredationDimensions, _MV, FGIndices, CIndices, PredationIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Predation Interactions Cohort Index", 3, PredationDimensions, _MV, FGIndices, CIndices, PredationIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Predation Interactions Biomass Assimilated", 3, PredationDimensions, _MV, FGIndices, CIndices, PredationIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Predation Interactions Biomass Ingested", 3, PredationDimensions, _MV, FGIndices, CIndices, PredationIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Herbivory Interactions Functional Groups", 3, HerbivoryDimensions, _MV, FGIndices, CIndices, HerbivoryIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Herbivory Interactions Stock Index", 3, HerbivoryDimensions, _MV, FGIndices, CIndices, HerbivoryIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Herbivory Interactions Biomass Assimilated", 3, HerbivoryDimensions, _MV, FGIndices, CIndices, HerbivoryIndices); DataConverter.AddVariable(_FeedingInteractionsDS, "Herbivory Interactions Biomass Ingested", 3, HerbivoryDimensions, _MV, FGIndices, CIndices, HerbivoryIndices);*/ //Add variable to SDS var FGIPredOut = _FeedingInteractionsDS.AddVariable<double>("Predation Interactions Functional Groups", FGIndicesPredation, PredationDimensions); FGIPredOut.Metadata["DisplayName"] = "Predation Interactions Functional Groups"; FGIPredOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var CIPredOut = _FeedingInteractionsDS.AddVariable<double>("Predation Interactions Cohort Index", CIndicesPredation, PredationDimensions); CIPredOut.Metadata["DisplayName"] = "Predation Interactions Cohort Index"; CIPredOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var BAPredOut = _FeedingInteractionsDS.AddVariable<double>("Predation Interactions Biomass Assimilated", BiomassAssimilatedPredation, PredationDimensions); BAPredOut.Metadata["DisplayName"] = "Predation Interactions Biomass Assimilated"; BAPredOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var BIPredOut = _FeedingInteractionsDS.AddVariable<double>("Predation Interactions Biomass Ingested", BiomassIngestedPredation, PredationDimensions); BIPredOut.Metadata["DisplayName"] = "Predation Interactions Biomass Ingested"; BIPredOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var FGIHerbOut = _FeedingInteractionsDS.AddVariable<double>("Herbivory Interactions Functional Groups", FGIndicesHerbivory, HerbivoryDimensions); FGIHerbOut.Metadata["DisplayName"] = "Herbivory Interactions Functional Groups"; FGIHerbOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var CIHerbOut = _FeedingInteractionsDS.AddVariable<double>("Herbivory Interactions Cohort Index", CIndicesHerbivory, HerbivoryDimensions); CIHerbOut.Metadata["DisplayName"] = "Herbivory Interactions Cohort Index"; CIHerbOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var BAHerbOut = _FeedingInteractionsDS.AddVariable<double>("Herbivory Interactions Biomass Assimilated", BiomassAssimilatedHerbivory, HerbivoryDimensions); BAHerbOut.Metadata["DisplayName"] = "Herbivory Interactions Biomass Assimilated"; BAHerbOut.Metadata["MissingValue"] = _MV; //Add variable to SDS var BIHerbOut = _FeedingInteractionsDS.AddVariable<double>("Herbivory Interactions Biomass Ingested", BiomassIngestedHerbivory, HerbivoryDimensions); BIHerbOut.Metadata["DisplayName"] = "Herbivory Interactions Biomass Ingested"; BIHerbOut.Metadata["MissingValue"] = _MV; //Commit changes _FeedingInteractionsDS.Commit(); }
/// <summary> /// Copies given dataset into another dataset. /// </summary> /// <param name="src">Original dataset to copy.</param> /// <param name="dst">Destination dataset.</param> /// <param name="updater">Delegate accepting update progressm notifications.</param> /// <returns>New instance of <see cref="DataSet"/> class.</returns> /// <remarks> /// This method splits the original dataser into parts and therefore is able /// to clone very large datasets not fitting to memory. /// </remarks> public static DataSet Clone(DataSet src, DataSet dst, ProgressUpdater updater) { if (src == null) throw new ArgumentNullException("src"); if (dst == null) throw new ArgumentNullException("dst"); if (dst.IsReadOnly) throw new NotSupportedException("Destination DataSet is read-only"); // Maximum memory capacity in bytes ulong N = 200 * 1024 * 1024; // Estimated size of a single string in bytes int sizeofString = 100 * 1024; /*********************************************************************************** * Preparing output ***********************************************************************************/ bool isAutoCommit = dst.IsAutocommitEnabled; try { dst.IsAutocommitEnabled = false; DataSetSchema srcSchema = src.GetSchema(); Dictionary<int, int> IDs = new Dictionary<int, int>(); // Creating empty variables and copying global metadata and scalar variables if (updater != null) updater(0, "Creating structure and copying global metadata and scalar variables..."); VariableSchema globalMetadataVar = null; foreach (VariableSchema v in srcSchema.Variables) { if (v.ID == DataSet.GlobalMetadataVariableID) { globalMetadataVar = v; continue; } Variable t = dst.AddVariable(v.TypeOfData, v.Name, null, v.Dimensions.AsNamesArray()); IDs.Add(v.ID, t.ID); foreach (var attr in v.Metadata) t.Metadata[attr.Key] = attr.Value; if (t.Rank == 0) // scalar t.PutData(src.Variables.GetByID(v.ID).GetData()); } if (globalMetadataVar != null) { // Copying global metadata foreach (var attr in globalMetadataVar.Metadata) dst.Metadata[attr.Key] = attr.Value; } dst.Commit(); // Console.Out.WriteLine("Done.\n"); /*********************************************************************************** * Adjusting dimensions deltas ***********************************************************************************/ Dimension[] srcDims = srcSchema.GetDimensions(); Dictionary<string, int> deltas = new Dictionary<string, int>(srcDims.Length); foreach (var d in srcDims) deltas[d.Name] = d.Length; // Console.Out.WriteLine("Total memory capacity: " + (N / 1024.0 / 1024.0).ToString("F2") + " Mb"); ulong totalSize; do { totalSize = 0; foreach (var var in srcSchema.Variables) { if (var.Rank == 0) continue; // scalar int typeSize = SizeOf(var.TypeOfData, sizeofString); ulong count = 0; foreach (var vdim in var.Dimensions) { int dimDelta = deltas[vdim.Name]; if (count == 0) count = (ulong)dimDelta; else count *= (ulong)dimDelta; } totalSize += (ulong)typeSize * count; } if (totalSize > N) { string maxDim = null; int max = int.MinValue; foreach (var dim in deltas) if (dim.Value > max) { max = dim.Value; maxDim = dim.Key; } if (maxDim == null || max <= 1) throw new NotSupportedException("Cannot copy the DataSet: it is too large to be copied entirely by the utility for the provided memory capacity"); deltas[maxDim] = max >> 1; } } while (totalSize > N); // Printing deltas if (updater != null) updater(0, String.Format("Deltas for the dimensions adjusted (max iteration capacity: " + (totalSize / 1024.0 / 1024.0).ToString("F2") + " Mb)")); /*********************************************************************************** * Copying data ***********************************************************************************/ // Console.WriteLine(); if (updater != null) updater(0, "Copying data ..."); Dictionary<int, int[]> origins = new Dictionary<int, int[]>(srcSchema.Variables.Length); Dictionary<int, int[]> shapes = new Dictionary<int, int[]>(srcSchema.Variables.Length); List<VariableSchema> copyVars = srcSchema.Variables.Where(vs => (vs.Rank > 0 && vs.ID != DataSet.GlobalMetadataVariableID)).ToList(); Dictionary<string, int> dimOrigin = new Dictionary<string, int>(srcDims.Length); foreach (var d in srcDims) dimOrigin[d.Name] = 0; Array.Sort(srcDims, (d1, d2) => d1.Length - d2.Length); int totalDims = srcDims.Length; do { // for each variable: for (int varIndex = copyVars.Count; --varIndex >= 0; ) { VariableSchema var = copyVars[varIndex]; bool hasChanged = false; // Getting its origin int[] origin; if (!origins.TryGetValue(var.ID, out origin)) { origin = new int[var.Rank]; origins[var.ID] = origin; hasChanged = true; } // Getting its shape int[] shape; if (!shapes.TryGetValue(var.ID, out shape)) { shape = new int[var.Rank]; for (int i = 0; i < var.Dimensions.Count; i++) shape[i] = deltas[var.Dimensions[i].Name]; shapes.Add(var.ID, shape); } // Updating origin for the variable: if (!hasChanged) for (int i = 0; i < shape.Length; i++) { int o = dimOrigin[var.Dimensions[i].Name]; if (origin[i] != o) { hasChanged = true; origin[i] = o; } } if (!hasChanged) // this block is already copied continue; bool doCopy = false; bool shapeUpdated = false; for (int i = 0; i < shape.Length; i++) { int s = origin[i] + shape[i]; int len = var.Dimensions[i].Length; if (s > len) { if (!shapeUpdated) { shapeUpdated = true; shape = (int[])shape.Clone(); } shape[i] = len - origin[i]; } if (shape[i] > 0) doCopy = true; } if (doCopy) { Array data = src.Variables.GetByID(var.ID).GetData(origin, shape); // Compute real size here for strings dst.Variables.GetByID(IDs[var.ID]).PutData(origin, data); } else // variable is copied { copyVars.RemoveAt(varIndex); } } dst.Commit(); // Updating dimensions origin bool isOver = true; for (int i = 0; i < totalDims; i++) { Dimension dim = srcDims[i]; int origin = dimOrigin[dim.Name] + deltas[dim.Name]; if (origin < dim.Length) { dimOrigin[dim.Name] = origin; isOver = false; // Progress indicator if (i == totalDims - 1) { double perc = (double)origin / dim.Length * 100.0; if (updater != null) updater(perc, "Copying data ..."); } break; } dimOrigin[dim.Name] = 0; } if (isOver) break; } while (copyVars.Count > 0); if (updater != null) updater(100.0, "Done."); } finally { dst.IsAutocommitEnabled = isAutoCommit; } return dst; }