Beispiel #1
0
        /// <summary>
        /// Set up all outputs (live, console and file) prior to the model run
        /// </summary>
        /// <param name="numTimeSteps">The number of time steps in the model run</param>
        /// <param name="ecosystemModelGrid">The model grid</param>
        /// <param name="outputFilesSuffix">The suffix to be applied to all output files</param>
        public void SetupOutputs(uint numTimeSteps, ModelGrid ecosystemModelGrid, string outputFilesSuffix)
        {
            Console.WriteLine("Setting up global outputs...\n");

            // Set the suffix for all output files
            _OutputSuffix = outputFilesSuffix + "_Global";

            // Create an SDS object to hold total abundance and biomass data
            BasicOutput = SDSCreator.CreateSDS("netCDF", "BasicOutputs" + _OutputSuffix, _OutputPath);

            // Create vector to hold the values of the time dimension
            TimeSteps = new float[numTimeSteps + 1];

            // Set the first value to be -1 (this will hold initial outputs)
            TimeSteps[0] = 0;

            // Fill other values from 0 (this will hold outputs during the model run)
            for (int i = 1; i < numTimeSteps + 1; i++)
            {
                TimeSteps[i] = i;
            }

            // Add basic variables to the output file, dimensioned by time
            string[] TimeDimension = { "Time step" };
            DataConverter.AddVariable(BasicOutput, "Total living biomass", "Kg / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Organic matter pool", "Kg / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Respiratory CO2 pool", "Kg / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Number of cohorts extinct", "", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Number of cohorts produced", "", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Number of cohorts combined", "", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Number of cohorts in model", "", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);
            DataConverter.AddVariable(BasicOutput, "Number of stocks in model", "", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps);

            this.FileName = _OutputPath + "BasicOutputs" + _OutputSuffix + ".nc";
        }
Beispiel #2
0
        /// <summary>
        /// Set up the predation tracker
        /// </summary>_
        /// <param name="numTimeSteps">The total number of timesteps for this simulation</param>
        /// <param name="cellIndices">List of indices of active cells in the model grid</param>
        /// <param name="massFlowsFilename">Filename for outputs of the flows of mass between predators and prey</param>
        /// <param name="cohortDefinitions">The functional group definitions for cohorts in the model</param>
        /// <param name="missingValue">The missing value to be used in the output file</param>
        /// <param name="outputFileSuffix">The suffix to be applied to the output file</param>
        /// <param name="outputPath">The path to write the output file to</param>
        /// <param name="trackerMassBins">The mass bin handler containing the mass bins to be used for predation tracking</param>
        /// <param name="cellIndex">The index of the current cell in the list of all cells to run the model for</param>
        public PredationTracker(uint numTimeSteps,
                                List <uint[]> cellIndices,
                                string massFlowsFilename,
                                FunctionalGroupDefinitions cohortDefinitions,
                                double missingValue,
                                string outputFileSuffix,
                                string outputPath, MassBinsHandler trackerMassBins, int cellIndex)
        {
            // Assign the missing value
            _MissingValue = missingValue;

            // Get the mass bins to use for the predation tracker and the number of mass bins that this correpsonds to
            _MassBins    = trackerMassBins.GetSpecifiedMassBins();
            _NumMassBins = trackerMassBins.NumMassBins;

            // Initialise the array to hold data on mass flows between mass bins
            _MassFlows = new double[_NumMassBins, _NumMassBins];

            // Define the model time steps to be used in the output file
            float[] TimeSteps = new float[numTimeSteps];
            for (int i = 1; i <= numTimeSteps; i++)
            {
                TimeSteps[i - 1] = i;
            }

            // 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
            MassFlowsDataSet = SDSCreator.CreateSDS("netCDF", massFlowsFilename + outputFileSuffix + "_Cell" + cellIndex, outputPath);

            // Define the dimensions to be used in the predation tracker output file
            string[] dimensions = { "Predator mass bin", "Prey mass bin", "Time steps" };

            // Add the mass flow variable to the predation tracker
            DataConverter.AddVariable(MassFlowsDataSet, "Log mass (g)", 3, dimensions, _MissingValue, _MassBins, _MassBins, TimeSteps);
        }
        /// <summary>
        /// Constructor for the global NPP tracker: sets up the output file and the data arrays
        /// </summary>
        /// <param name="outputPath">Path to the file to output NPP data to</param>
        /// <param name="numLats">The number of cells latitudinally in the NPP output grid</param>
        /// <param name="numLons">The number of cells longitudinally in the NPP output grid</param>
        /// <param name="lats">The latitudes of cells in the grid to output</param>
        /// <param name="lons">The longitudes of cells in the grid to output</param>
        /// <param name="latCellSize">The latitudinal cell size of the grid to output</param>
        /// <param name="lonCellSize">The longitudinal cell size of the grid to output</param>
        /// <param name="numTimeSteps">The number of time steps to output NPP data for</param>
        public GlobalNPPTracker(string outputPath, int numLats, int numLons, float[] lats, float[] lons, float latCellSize, float lonCellSize,
                                int numTimeSteps, int numStocks)
        {
            _NumLats = numLats;
            _NumLons = numLons;

            // Initialise the data converter
            DataConverter = new ArraySDSConvert();

            // Initialise the SDS object creator
            SDSCreator = new CreateSDSObject();

            // Create an SDS object to hold NPP data
            NPPOutput = SDSCreator.CreateSDS("netCDF", "NPPOutput", outputPath);
            // Create an SDS object to hold total abundance and biomass data
            HANPPOutput = SDSCreator.CreateSDS("netCDF", "HANPPOutput", outputPath);

            // Create vector to hold the values of the time dimension
            float[] TimeSteps = new float[numTimeSteps];

            // Fill other values from 0 (this will hold outputs during the model run)
            for (int i = 0; i < numTimeSteps; i++)
            {
                TimeSteps[i] = i;
            }

            // Declare vectors for geographical dimension data
            float[] outLats = new float[numLats];
            float[] outLons = new float[numLons];

            // Populate the dimension variable vectors with cell centre latitude and longitudes
            for (int i = 0; i < numLats; i++)
            {
                outLats[i] = lats[i] + (latCellSize / 2);
            }

            for (int jj = 0; jj < numLons; jj++)
            {
                outLons[jj] = lons[jj] + (lonCellSize / 2);
            }

            // Add output variables that are dimensioned geographically and temporally to grid output file
            string[] GeographicalDimensions = { "Latitude", "Longitude", "Time step" };
            for (int ii = 0; ii < numStocks; ii++)
            {
                DataConverter.AddVariable(NPPOutput, "NPP_" + ii.ToString(), 3, GeographicalDimensions, -9999.0, outLats, outLons, TimeSteps);
                DataConverter.AddVariable(HANPPOutput, "HANPP_" + ii.ToString(), 3, GeographicalDimensions, -9999.0, outLats, outLons, TimeSteps);
            }

            NPP   = new double[numLats, numLons, numStocks];
            HANPP = new double[numLats, numLons, numStocks];

            for (int ii = 0; ii < numLats; ii++)
            {
                for (int jj = 0; jj < numLons; jj++)
                {
                    for (int kk = 0; kk < numStocks; kk++)
                    {
                        NPP[ii, jj, kk]   = -9999.0;
                        HANPP[ii, jj, kk] = -9999.0;
                    }
                }
            }

            this.FileName = outputPath + "NPPOutput.nc";
        }
        public void OutputCurrentModelState(ModelGrid currentModelGrid, FunctionalGroupDefinitions functionalGroupHandler, List <uint[]> cellIndices, uint currentTimestep, int maximumNumberOfCohorts, string filename)
        {
            float[] Latitude = currentModelGrid.Lats;

            float[] Longitude = currentModelGrid.Lons;

            float[] CohortFunctionalGroup = new float[functionalGroupHandler.GetNumberOfFunctionalGroups()];
            for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++)
            {
                CohortFunctionalGroup[fg] = fg;
            }

            int CellCohortNumber = 0;
            GridCellCohortHandler CellCohorts;

            for (int cellIndex = 0; cellIndex < cellIndices.Count; cellIndex++)
            {
                CellCohorts = currentModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]);
                for (int i = 0; i < CellCohorts.Count; i++)
                {
                    if (CellCohorts[i].Count > CellCohortNumber)
                    {
                        CellCohortNumber = CellCohorts[i].Count;
                    }
                }
            }

            int MaxNumberCohorts = Math.Max(CellCohortNumber, maximumNumberOfCohorts);

            float[] Cohort = new float[MaxNumberCohorts];
            for (int c = 0; c < Cohort.Length; c++)
            {
                Cohort[c] = c;
            }

            //Define an array for stock functional group - there are only three currently
            float[] StockFunctionalGroup = new float[] { 1, 2, 3 };

            //Define an array for index of stocks - there is only one currently
            float[] Stock = new float[] { 1 };

            string Filename = filename + "_" + currentTimestep.ToString() + Simulation.ToString();

            StateOutput = SDSCreator.CreateSDS("netCDF", Filename, _OutputPath);

            //Define the cohort properties for output
            string[] CohortProperties = new string[]
            { "JuvenileMass", "AdultMass", "IndividualBodyMass", "IndividualReproductivePotentialMass", "CohortAbundance",
              "BirthTimeStep", "MaturityTimeStep", "LogOptimalPreyBodySizeRatio",
              "MaximumAchievedBodyMass", "Merged", "TrophicIndex", "ProportionTimeActive" };

            //define the dimensions for cohort outputs
            string[] dims = new string[] { "Latitude", "Longitude", "Cohort Functional Group", "Cohort" };

            // Add the variables for each cohort property
            // Then calculate the state for this property and put the data to this variable
            foreach (string v in CohortProperties)
            {
                DataConverter.AddVariable(StateOutput, "Cohort" + v, 4,
                                          dims, currentModelGrid.GlobalMissingValue, Latitude,
                                          Longitude, CohortFunctionalGroup, Cohort);

                StateOutput.PutData <double[, , , ]>("Cohort" + v,
                                                     CalculateCurrentCohortState(currentModelGrid, v, Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length, cellIndices));

                StateOutput.Commit();
            }

            //Define the stock properties for output
            string[] StockProperties = new string[] { "IndividualBodyMass", "TotalBiomass" };


            //define the dimensions for cohort outputs
            dims = new string[] { "Latitude", "Longitude", "Stock Functional Group", "Stock" };

            // Add the variables for each stock property
            // Then calculate the state for this property and put the data to this variable
            foreach (string v in StockProperties)
            {
                DataConverter.AddVariable(StateOutput, "Stock" + v, 4,
                                          dims, currentModelGrid.GlobalMissingValue, Latitude,
                                          Longitude, StockFunctionalGroup, Stock);

                StateOutput.PutData <double[, , , ]>("Stock" + v,
                                                     CalculateCurrentStockState(currentModelGrid, v, Latitude.Length, Longitude.Length, StockFunctionalGroup.Length, Stock.Length, cellIndices));

                StateOutput.Commit();
            }

            //Close this data set
            StateOutput.Dispose();
        }
        /// <summary>
        /// Set up the predation tracker
        /// </summary>_
        /// <param name="numTimeSteps">The total number of timesteps for this simulation</param>
        /// <param name="cellIndices">List of indices of active cells in the model grid</param>
        /// <param name="massFlowsFilename">Filename for outputs of the flows of mass between predators and prey</param>
        /// <param name="cohortDefinitions">The functional group definitions for cohorts in the model</param>
        /// <param name="missingValue">The missing value to be used in the output file</param>
        /// <param name="outputFileSuffix">The suffix to be applied to the output file</param>
        /// <param name="outputPath">The path to write the output file to</param>
        /// <param name="trackerMassBins">The mass bin handler containing the mass bins to be used for predation tracking</param>
        /// <param name="cellIndex">The index of the current cell in the list of all cells to run the model for</param>
        public PredationTracker(uint numTimeSteps,
            List<uint[]> cellIndices,
            string massFlowsFilename,
            FunctionalGroupDefinitions cohortDefinitions,
            double missingValue,
            string outputFileSuffix,
            string outputPath, MassBinsHandler trackerMassBins, int cellIndex)
        {
            // Assign the missing value
            _MissingValue = missingValue;

            // Get the mass bins to use for the predation tracker and the number of mass bins that this correpsonds to
            _MassBins = trackerMassBins.GetSpecifiedMassBins();
            _NumMassBins = trackerMassBins.NumMassBins;

            // Initialise the array to hold data on mass flows between mass bins
            _MassFlows = new double[_NumMassBins, _NumMassBins];

            // Define the model time steps to be used in the output file
            float[] TimeSteps = new float[numTimeSteps];
            for (int i = 1; i <= numTimeSteps; i++)
            {
                TimeSteps[i - 1] = i;
            }

            // 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
            MassFlowsDataSet = SDSCreator.CreateSDS("netCDF", massFlowsFilename + outputFileSuffix + "_Cell" + cellIndex, outputPath);

            // Define the dimensions to be used in the predation tracker output file
            string[] dimensions = { "Predator mass bin", "Prey mass bin", "Time steps" };

            // Add the mass flow variable to the predation tracker
            DataConverter.AddVariable(MassFlowsDataSet, "Log mass (g)", 3, dimensions, _MissingValue, _MassBins, _MassBins, TimeSteps);
        }
        /// <summary>
        /// Constructor for the global NPP tracker: sets up the output file and the data arrays
        /// </summary>
        /// <param name="outputPath">Path to the file to output NPP data to</param>
        /// <param name="numLats">The number of cells latitudinally in the NPP output grid</param>
        /// <param name="numLons">The number of cells longitudinally in the NPP output grid</param>
        /// <param name="lats">The latitudes of cells in the grid to output</param>
        /// <param name="lons">The longitudes of cells in the grid to output</param>
        /// <param name="latCellSize">The latitudinal cell size of the grid to output</param>
        /// <param name="lonCellSize">The longitudinal cell size of the grid to output</param>
        /// <param name="numTimeSteps">The number of time steps to output NPP data for</param>
        public GlobalNPPTracker(string outputPath, int numLats, int numLons, float[] lats, float[] lons, float latCellSize, float lonCellSize,
            int numTimeSteps, int numStocks)
        {
            _NumLats = numLats;
            _NumLons = numLons;

            // Initialise the data converter
            DataConverter = new ArraySDSConvert();

            // Initialise the SDS object creator
            SDSCreator = new CreateSDSObject();

            // Create an SDS object to hold NPP data
            NPPOutput = SDSCreator.CreateSDS("netCDF", "NPPOutput", outputPath);
            // Create an SDS object to hold total abundance and biomass data
            HANPPOutput = SDSCreator.CreateSDS("netCDF", "HANPPOutput", outputPath);

            // Create vector to hold the values of the time dimension
            float[] TimeSteps = new float[numTimeSteps];

            // Fill other values from 0 (this will hold outputs during the model run)
            for (int i = 0; i < numTimeSteps; i++)
            {
                TimeSteps[i] = i;
            }

            // Declare vectors for geographical dimension data
            float[] outLats = new float[numLats];
            float[] outLons = new float[numLons];

            // Populate the dimension variable vectors with cell centre latitude and longitudes
            for (int i = 0; i < numLats; i++)
            {
                outLats[i] = lats[i] + (latCellSize / 2);
            }

            for (int jj = 0; jj < numLons; jj++)
            {
                outLons[jj] = lons[jj] + (lonCellSize / 2);
            }

            // Add output variables that are dimensioned geographically and temporally to grid output file
            string[] GeographicalDimensions = { "Latitude", "Longitude", "Time step" };
            for (int ii = 0; ii < numStocks; ii++)
            {
                DataConverter.AddVariable(NPPOutput, "NPP_" + ii.ToString(), 3, GeographicalDimensions, -9999.0, outLats, outLons, TimeSteps);
                DataConverter.AddVariable(HANPPOutput, "HANPP_" + ii.ToString(), 3, GeographicalDimensions, -9999.0, outLats, outLons, TimeSteps);
            }

            NPP = new double[numLats, numLons, numStocks];
            HANPP = new double[numLats, numLons, numStocks];

            for (int ii = 0; ii < numLats; ii++)
            {
                for (int jj = 0; jj < numLons; jj++)
                {
                    for (int kk = 0; kk < numStocks; kk++)
                    {
                        NPP[ii, jj, kk] = -9999.0;
                        HANPP[ii, jj, kk] = -9999.0;
                    }
                }

            }

            this.FileName = outputPath + "NPPOutput.nc";
        }
Beispiel #7
0
        public void SetupOutputs(ModelGrid ecosystemModelGrid, string outputFilesSuffix, uint numTimeSteps,
                                 FunctionalGroupDefinitions cohortFunctionalGroupDefinitions, FunctionalGroupDefinitions
                                 stockFunctionalGroupDefinitions)
        {
            // Create an SDS object to hold grid outputs
            GridOutput = SDSCreator.CreateSDS("netCDF", "GridOutputs" + outputFilesSuffix, _OutputPath);

            // Initilalise trait-based outputs
            InitialiseTraitBasedOutputs(cohortFunctionalGroupDefinitions, stockFunctionalGroupDefinitions);

            // Create vector to hold the values of the time dimension
            TimeSteps = new float[numTimeSteps + 1];

            // Set the first value to be 0 (this will hold initial outputs)
            TimeSteps[0] = 0;

            // Fill other values from 0 (this will hold outputs during the model run)
            for (int i = 1; i < numTimeSteps + 1; i++)
            {
                TimeSteps[i] = i;
            }

            // Declare vectors for geographical dimension data
            float[] outLats = new float[ecosystemModelGrid.NumLatCells];
            float[] outLons = new float[ecosystemModelGrid.NumLonCells];

            // Populate the dimension variable vectors with cell centre latitude and longitudes
            for (int i = 0; i < ecosystemModelGrid.NumLatCells; i++)
            {
                outLats[i] = ecosystemModelGrid.Lats[i] + (ecosystemModelGrid.LatCellSize / 2);
            }

            for (int jj = 0; jj < ecosystemModelGrid.NumLonCells; jj++)
            {
                outLons[jj] = ecosystemModelGrid.Lons[jj] + (ecosystemModelGrid.LonCellSize / 2);
            }

            //GridOutputArray = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells, numTimeSteps];

            // Add output variables that are dimensioned geographically and temporally to grid output file
            string[] GeographicalDimensions = { "Latitude", "Longitude", "Time step" };
            DataConverter.AddVariable(GridOutput, "Biomass density", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
            DataConverter.AddVariable(GridOutput, "Abundance density", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);

            // Initialise the arrays that will be used for the grid-based outputs
            LogBiomassDensityGridCohorts   = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            LogBiomassDensityGridStocks    = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            LogBiomassDensityGrid          = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            LogAbundanceDensityGridCohorts = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];

            FrostDays     = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            FracEvergreen = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            Realm         = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            HANPP         = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
            Temperature   = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];

            // Temporary outputs for checking plant model
            DataConverter.AddVariable(GridOutput, "Fraction year frost", 3, GeographicalDimensions, ecosystemModelGrid.GlobalMissingValue, outLats, outLons, TimeSteps);
            DataConverter.AddVariable(GridOutput, "Fraction evergreen", 3, GeographicalDimensions, ecosystemModelGrid.GlobalMissingValue, outLats, outLons, TimeSteps);
            DataConverter.AddVariable(GridOutput, "Realm", 3, GeographicalDimensions, ecosystemModelGrid.GlobalMissingValue, outLats, outLons, TimeSteps);
            DataConverter.AddVariable(GridOutput, "HANPP", 3, GeographicalDimensions, ecosystemModelGrid.GlobalMissingValue, outLats, outLons, TimeSteps);
            DataConverter.AddVariable(GridOutput, "Temperature", 3, GeographicalDimensions, ecosystemModelGrid.GlobalMissingValue, outLats, outLons, TimeSteps);

            // Set up outputs for medium or high output levels
            if ((ModelOutputDetail == OutputDetailLevel.Medium) || (ModelOutputDetail == OutputDetailLevel.High))
            {
                double[,] temp = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                foreach (string TraitValue in CohortTraitIndices.Keys)
                {
                    BiomassDensityGrid.Add(TraitValue, temp);
                    DataConverter.AddVariable(GridOutput, TraitValue + "biomass density", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    AbundanceDensityGrid.Add(TraitValue, temp);
                    DataConverter.AddVariable(GridOutput, TraitValue + "abundance density", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                }

                foreach (string TraitValue in StockTraitIndices.Keys)
                {
                    BiomassDensityGrid.Add(TraitValue, temp);
                    DataConverter.AddVariable(GridOutput, TraitValue + "biomass density", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                }


                if (OutputMetrics)
                {
                    double[,] MTL = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Mean Trophic Level", MTL);

                    double[,] TE = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Trophic Evenness", TE);

                    double[,] BE = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Biomass Evenness", BE);

                    double[,] FR = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Functional Richness", FR);

                    double[,] RFE = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Rao Functional Evenness", RFE);

                    double[,] BR = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Biomass Richness", BR);

                    double[,] TR = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Trophic Richness", TR);

                    double[,] Bmax = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Max Bodymass", Bmax);

                    double[,] Bmin = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Min Bodymass", Bmin);

                    double[,] TImax = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Max Trophic Index", TImax);

                    double[,] TImin = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Min Trophic Index", TImin);

                    double[,] ArithMean = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Arithmetic Mean Bodymass", ArithMean);

                    double[,] GeomMean = new double[ecosystemModelGrid.NumLatCells, ecosystemModelGrid.NumLonCells];
                    MetricsGrid.Add("Geometric Mean Bodymass", GeomMean);

                    DataConverter.AddVariable(GridOutput, "Mean Trophic Level", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Trophic Evenness", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Biomass Evenness", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Functional Richness", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Rao Functional Evenness", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Biomass Richness", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Trophic Richness", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Max Bodymass", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Min Bodymass", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Max Trophic Index", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Min Trophic Index", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Arithmetic Mean Bodymass", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                    DataConverter.AddVariable(GridOutput, "Geometric Mean Bodymass", 3, GeographicalDimensions, 0, outLats, outLons, TimeSteps);
                }
            }
        }
        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();
        }
        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();
        }