/// <summary> /// Constructor for the autotroph processor: initialises necessary classes /// </summary> public AutotrophProcessor() { _PhytoplanktonConversionRatio = EcologicalParameters.Parameters["AutotrophProcessor.ConvertNPPtoAutotroph.PhytoplanktonConversionRatio"]; // Initialise the utility functions Utilities = new UtilityFunctions(); }
/// <summary> /// Constructor for dispersal: assigns all parameter values /// </summary> public AdvectiveDispersal(string globalModelTimeStepUnit, Boolean DrawRandomly) { InitialiseParatemersAdvectiveDispersal(); // Initialise the utility functions UtilityFunctions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of dispersal to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Initialise the advective dispersal temporal scaling to adjust between time steps appropriately _AdvectionTimeStepsPerModelTimeStep = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, "day") * 24 / _AdvectiveModelTimeStepLengthHours; // Convert velocity from m/s to km/month. Note that if the _TimeUnitImplementation changes, this will also have to change. VelocityUnitConversion = 60 * 60 * 24 * Utilities.ConvertTimeUnits(globalModelTimeStepUnit, "day") * _DeltaT / 1000; // Set the seed for the random number generator RandomNumberGenerator = new NonStaticSimpleRNG(); if (DrawRandomly) { RandomNumberGenerator.SetSeedFromSystemTime(); } else { RandomNumberGenerator.SetSeed(14141); } }
/// <summary> /// Constructor for starvation mortality: assigns all parameter values /// /// </summary> public StarvationMortality(string globalModelTimeStepUnit) { InitialiseParametersStarvationMortality(); // Initialise the utility functions UtilityFunctions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of mortality to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); }
/// <summary> /// Constructor for metabolism: assigns all parameter values /// </summary> public MetabolismEndotherm(string globalModelTimeStepUnit) { // Initialise ecological parameters for metabolism InitialiseMetabolismParameters(); // Initialise the utility functions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of metabolism to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); }
/// <summary> /// Constructor for metabolism: assigns all parameter values /// </summary> public MetabolismHeterotroph(string globalModelTimeStepUnit) { // Initialise ecological parameters for metabolism InitialiseMetabolismParameters(); // Initialise the utility functions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of metabolism to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Set the constant to convert temperature in degrees Celsius to Kelvin _TemperatureUnitsConvert = 273.0; }
/// <summary> /// Constructor for dispersal: assigns all parameter values /// </summary> public DiffusiveDispersal(string globalModelTimeStepUnit, Boolean DrawRandomly) { InitialiseParametersDiffusiveDispersal(); // Initialise the utility functions UtilityFunctions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of dispersal to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Set the seed for the random number generator RandomNumberGenerator = new NonStaticSimpleRNG(); if (DrawRandomly) { RandomNumberGenerator.SetSeedFromSystemTime(); } else { RandomNumberGenerator.SetSeed(14141); } }
/// <summary> /// Assigns all parameter values for repsonsive dispersal /// </summary> public ResponsiveDispersal(string globalModelTimeStepUnit, Boolean DrawRandomly) { InitialiseParametersResponsiveDispersal(); // Initialise the utility functions UtilityFunctions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of dispersal to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Set the seed for the random number generator RandomNumberGenerator = new NonStaticSimpleRNG(); if (DrawRandomly) { RandomNumberGenerator.SetSeedFromSystemTime(); } else { RandomNumberGenerator.SetSeed(14141); } }
/// <summary> /// Constructor for reproduction: assigns all parameter values /// <param name="globalModelTimeStepUnit">The time step of the global model</param> /// <param name="drawRandomly">Indicates whether to draw values randomly</param> /// </summary> public ReproductionBasic(string globalModelTimeStepUnit, Boolean drawRandomly) { // Initialise ecological parameters for reproduction InitialiseReproductionParameters(); // Initialise the utility class UtilityFunctions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of herbivory to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Instantiate the random number generator RandomNumberGenerator = new NonStaticSimpleRNG(); // Set the seed for the random number generator if (drawRandomly) { RandomNumberGenerator.SetSeedFromSystemTime(); } else { RandomNumberGenerator.SetSeed(4000); } }
/// <summary> /// Overloaded constructor for model grid to construct the grid for specific locations /// </summary> /// <param name="minLat">Minimum grid latitude (degrees)</param> /// <param name="minLon">Minimum grid longitude (degrees, currently -180 to 180)</param> /// <param name="maxLat">Maximum grid latitude (degrees)</param> /// <param name="maxLon">Maximum grid longitude (degrees, currently -180 to 180)</param> /// <param name="latCellSize">Latitudinal size of grid cells</param> /// <param name="lonCellSize">Longitudinal size of grid cells</param> /// <param name="cellList">List of indices of active cells in the model grid</param> /// <param name="enviroStack">List of environmental data layers</param> /// <param name="cohortFunctionalGroups">The functional group definitions for cohorts in the model</param> /// <param name="stockFunctionalGroups">The functional group definitions for stocks in the model</param> /// <param name="globalDiagnostics">Global diagnostic variables</param> /// <param name="tracking">Whether process tracking is enabled</param> /// <param name="specificLocations">Whether the model is to be run for specific locations</param> /// <param name="runInParallel">Whether model grid cells will be run in parallel</param> public ModelGrid(float minLat, float minLon, float maxLat, float maxLon, float latCellSize, float lonCellSize, List<uint[]> cellList, SortedList<string, EnviroData> enviroStack, FunctionalGroupDefinitions cohortFunctionalGroups, FunctionalGroupDefinitions stockFunctionalGroups, SortedList<string, double> globalDiagnostics, Boolean tracking, Boolean specificLocations, Boolean runInParallel) { // Add one to the counter of the number of grids. If there is more than one model grid, exit the program with a debug crash. NumGrids = NumGrids + 1; //Debug.Assert(NumGrids < 2, "You have initialised more than one grid on which to apply models. At present, this is not supported"); // Initialise the utility functions Utilities = new UtilityFunctions(); // CURRENTLY DEFINING MODEL CELLS BY BOTTOM LEFT CORNER _MinLatitude = minLat; _MinLongitude = minLon; _MaxLatitude = maxLat; _MaxLongitude = maxLon; _LatCellSize = latCellSize; _LonCellSize = lonCellSize; _GridCellRarefaction = 1; // Check to see if the number of grid cells is an integer Debug.Assert((((_MaxLatitude - _MinLatitude) % _LatCellSize) == 0), "Error: number of grid cells is non-integer: check cell size"); _NumLatCells = (UInt32)((_MaxLatitude - _MinLatitude) / _LatCellSize); _NumLonCells = (UInt32)((_MaxLongitude - _MinLongitude) / _LonCellSize); _Lats = new float[_NumLatCells]; _Lons = new float[_NumLonCells]; // Set up latitude and longitude vectors - lower left for (int ii = 0; ii < _NumLatCells; ii++) { _Lats[ii] = _MinLatitude + ii * _LatCellSize; } for (int jj = 0; jj < _NumLonCells; jj++) { _Lons[jj] = _MinLongitude + jj * _LonCellSize; } // Set up a grid of grid cells InternalGrid = new GridCell[_NumLatCells, _NumLonCells]; // Instantiate the arrays of lists of cohorts to disperse DeltaFunctionalGroupDispersalArray = new List<uint>[_NumLatCells, _NumLonCells]; DeltaCohortNumberDispersalArray = new List<uint>[_NumLatCells, _NumLonCells]; // Instantiate the array of lists of grid cells to disperse those cohorts to DeltaCellToDisperseToArray = new List<uint[]>[_NumLatCells, _NumLonCells]; // Instantiate the arrays of cell entry and exit directions DeltaCellExitDirection = new List<uint>[_NumLatCells, _NumLonCells]; DeltaCellEntryDirection = new List<uint>[_NumLatCells, _NumLonCells]; // An array of lists of cells to which organisms in each cell can disperse to; includes all cells which contribute to the // perimeter list, plus diagonal cells if they are in the same realm CellsForDispersal = new List<uint[]>[_NumLatCells, _NumLonCells]; // An array of lists of directions corresponding to cells which organisms can disperse to CellsForDispersalDirection = new List<uint>[_NumLatCells, _NumLonCells]; Console.WriteLine("Initialising grid cell environment:"); int Count = 0; int NCells = cellList.Count; if (!runInParallel) { // Loop over cells to set up the model grid for (int ii = 0; ii < cellList.Count; ii++) { // Create the grid cell at the specified position InternalGrid[cellList[ii][0], cellList[ii][1]] = new GridCell(_Lats[cellList[ii][0]], cellList[ii][0], _Lons[cellList[ii][1]], cellList[ii][1], latCellSize, lonCellSize, enviroStack, _GlobalMissingValue, cohortFunctionalGroups, stockFunctionalGroups, globalDiagnostics, tracking, specificLocations); if (!specificLocations) { CellsForDispersal[cellList[ii][0], cellList[ii][1]] = new List<uint[]>(); CellsForDispersalDirection[cellList[ii][0], cellList[ii][1]] = new List<uint>(); Count++; Console.Write("\rInitialised {0} of {1}", Count, NCells); } else { Console.Write("\rRow {0} of {1}", ii + 1, NumLatCells / GridCellRarefaction); Console.WriteLine(""); Console.WriteLine(""); } } } else { // Run a parallel loop over rows Parallel.For(0, NCells, ii => { // Create the grid cell at the specified position InternalGrid[cellList[ii][0], cellList[ii][1]] = new GridCell(_Lats[cellList[ii][0]], cellList[ii][0], _Lons[cellList[ii][1]], cellList[ii][1], latCellSize, lonCellSize, enviroStack, _GlobalMissingValue, cohortFunctionalGroups, stockFunctionalGroups, globalDiagnostics, tracking, specificLocations); if (!specificLocations) { CellsForDispersal[cellList[ii][0], cellList[ii][1]] = new List<uint[]>(); CellsForDispersalDirection[cellList[ii][0], cellList[ii][1]] = new List<uint>(); } Count++; Console.Write("\rInitialised {0} of {1}", Count, NCells); } ); } if (!specificLocations) { InterpolateMissingValues(); // Fill in the array of dispersable perimeter lengths for each grid cell CalculatePerimeterLengthsAndCellsDispersableTo(); CellHeightsKm = new double[_Lats.Length]; CellWidthsKm = new double[_Lats.Length]; // Calculate the lengths of widths of grid cells in each latitudinal strip // Assume that we are at the midpoint of each cell when calculating lengths for (int ii = 0; ii < _Lats.Length; ii++) { CellHeightsKm[ii] = Utilities.CalculateLengthOfDegreeLatitude(_Lats[ii] + _LatCellSize / 2) * _LatCellSize; CellWidthsKm[ii] = Utilities.CalculateLengthOfDegreeLongitude(_Lats[ii] + _LatCellSize / 2) * _LonCellSize; } } Console.WriteLine("\n"); }
/// <summary> /// Initializes the ecosystem model /// </summary> /// <param name="initialisation">An instance of the model initialisation class</param> /// <param name="scenarioParameters">The parameters for the scenarios to run</param> /// <param name="scenarioIndex">The index of the scenario being run</param> /// <param name="outputFilesSuffix">The suffix to be applied to all outputs from this model run</param> /// <param name="globalModelTimeStepUnit">The time step unit used in the model</param> /// <param name="simulation">The index of the simulation being run</param> public MadingleyModel(MadingleyModelInitialisation initialisation, ScenarioParameterInitialisation scenarioParameters, int scenarioIndex, string outputFilesSuffix, string globalModelTimeStepUnit, int simulation) { // Assign the properties for this model run AssignModelRunProperties(initialisation, scenarioParameters, scenarioIndex, outputFilesSuffix); // Set up list of global diagnostics SetUpGlobalDiagnosticsList(); // Set up the model grid SetUpModelGrid(initialisation, scenarioParameters, scenarioIndex, simulation); // Set up model outputs SetUpOutputs(initialisation, simulation, scenarioIndex); // Make the initial outputs InitialOutputs(outputFilesSuffix, initialisation, CurrentMonth); // Instance the array of process trackers ProcessTrackers = new ProcessTracker[_CellList.Count]; // Temporary variables Boolean varExists; // Set up process trackers for each grid cell for (int i = 0; i < _CellList.Count; i++) { ProcessTrackers[i] = new ProcessTracker(NumTimeSteps, EcosystemModelGrid.Lats, EcosystemModelGrid.Lons, _CellList, initialisation.ProcessTrackingOutputs, initialisation.TrackProcesses, CohortFunctionalGroupDefinitions, EcosystemModelGrid.GlobalMissingValue, outputFilesSuffix, initialisation.OutputPath, initialisation.ModelMassBins, SpecificLocations, i, initialisation, EcosystemModelGrid.GetEnviroLayer("Realm", 0, _CellList[i][0], _CellList[i][1], out varExists) == 2.0, EcosystemModelGrid.LatCellSize, EcosystemModelGrid.LonCellSize); } // Set up a cross cell process tracker TrackCrossCellProcesses = new CrossCellProcessTracker(initialisation.TrackCrossCellProcesses, "DispersalData", initialisation.OutputPath, outputFilesSuffix); //Set up a global process tracker if (SpecificLocations) initialisation.TrackGlobalProcesses = false; TrackGlobalProcesses = new GlobalProcessTracker(NumTimeSteps, EcosystemModelGrid.Lats, EcosystemModelGrid.Lons, _CellList, initialisation.ProcessTrackingOutputs, initialisation.TrackGlobalProcesses, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, EcosystemModelGrid.GlobalMissingValue, outputFilesSuffix, initialisation.OutputPath, initialisation.ModelMassBins, SpecificLocations, initialisation, EcosystemModelGrid.LatCellSize, EcosystemModelGrid.LonCellSize); //Set-up the instance of OutputModelState WriteModelState = new OutputModelState(initialisation, outputFilesSuffix, simulation); if (SpecificLocations) initialisation.RunRealm = ""; // Record the initial cohorts in the process trackers RecordInitialCohorts(); // Initialise the class for cross-grid-cell ecology MadingleyEcologyCrossGridCell = new EcologyCrossGridCell(); // Initialise the time step timer TimeStepTimer = new StopWatch(); EcologyTimer = new StopWatch(); OutputTimer = new StopWatch(); // Set the global model time step unit _GlobalModelTimeStepUnit = globalModelTimeStepUnit; // Initialise the utility functions Utilities = new UtilityFunctions(); // Initialise the climate change impacts class ClimateChangeSimulator = new ClimateChange(); // Initialise the harvesting impacts class HarvestingSimulator = new Harvesting(EcosystemModelGrid.Lats, EcosystemModelGrid.Lons, (float)EcosystemModelGrid.LatCellSize); }
/// <summary> /// Constructor for a grid cell; creates cell and reads in environmental data /// </summary> /// <param name="latitude">The latitude of the grid cell</param> /// <param name="latIndex">The latitudinal index of the grid cell</param> /// <param name="longitude">The longitude of the grid cell</param> /// <param name="lonIndex">The longitudinal index of the grid cell</param> /// <param name="latCellSize">The latitudinal dimension of the grid cell</param> /// <param name="lonCellSize">The longitudinal dimension of the grid cell</param> /// <param name="dataLayers">A list of environmental data variables in the model</param> /// <param name="missingValue">The missing value to be applied to all data in the grid cell</param> /// <param name="cohortFunctionalGroups">The definitions for cohort functional groups in the model</param> /// <param name="stockFunctionalGroups">The definitions for stock functional groups in the model</param> /// <param name="globalDiagnostics">A list of global diagnostic variables for the model grid</param> /// <param name="tracking">Whether process-tracking is enabled</param> /// <param name="specificLocations">Whether the model is being run for specific locations</param> public GridCell(float latitude, uint latIndex, float longitude, uint lonIndex, float latCellSize, float lonCellSize, SortedList<string, EnviroData> dataLayers, double missingValue, FunctionalGroupDefinitions cohortFunctionalGroups, FunctionalGroupDefinitions stockFunctionalGroups, SortedList<string, double> globalDiagnostics,Boolean tracking, bool specificLocations) { // Boolean to track when environmental data are missing Boolean EnviroMissingValue; // Initialise the utility functions Utilities = new UtilityFunctions(); // Temporary vector for holding initial values of grid cell properties double[] tempVector; // Initialise deltas sorted list _Deltas = new Dictionary<string, Dictionary<string, double>>(); // Initialize delta abundance sorted list with appropriate processes Dictionary<string, double> DeltaAbundance = new Dictionary<string, double>(); DeltaAbundance.Add("mortality", 0.0); // Add delta abundance sorted list to deltas sorted list _Deltas.Add("abundance", DeltaAbundance); // Initialize delta biomass sorted list with appropriate processes Dictionary<string, double> DeltaBiomass = new Dictionary<string, double>(); DeltaBiomass.Add("metabolism", 0.0); DeltaBiomass.Add("predation", 0.0); DeltaBiomass.Add("herbivory", 0.0); DeltaBiomass.Add("reproduction", 0.0); // Add delta biomass sorted list to deltas sorted list _Deltas.Add("biomass", DeltaBiomass); // Initialize delta reproductive biomass vector with appropriate processes Dictionary<string, double> DeltaReproductiveBiomass = new Dictionary<string, double>(); DeltaReproductiveBiomass.Add("reproduction", 0.0); // Add delta reproduction sorted list to deltas sorted list _Deltas.Add("reproductivebiomass", DeltaReproductiveBiomass); // Initialize organic pool delta vector with appropriate processes Dictionary<string, double> DeltaOrganicPool = new Dictionary<string, double>(); DeltaOrganicPool.Add("herbivory", 0.0); DeltaOrganicPool.Add("predation", 0.0); DeltaOrganicPool.Add("mortality", 0.0); // Add delta organic pool sorted list to deltas sorted list _Deltas.Add("organicpool", DeltaOrganicPool); // Initialize respiratory CO2 pool delta vector with appropriate processes Dictionary<string, double> DeltaRespiratoryCO2Pool = new Dictionary<string, double>(); DeltaRespiratoryCO2Pool.Add("metabolism", 0.0); // Add delta respiratory CO2 pool to deltas sorted list _Deltas.Add("respiratoryCO2pool", DeltaRespiratoryCO2Pool); // Set the grid cell values of latitude, longitude and missing value as specified _Latitude = latitude; _Longitude = longitude; // Initialise list of environmental data layer values _CellEnvironment = new SortedList<string, double[]>(); //Add the latitude and longitude tempVector = new double[1]; tempVector[0] = latitude; _CellEnvironment.Add("Latitude", tempVector); tempVector = new double[1]; tempVector[0] = longitude; _CellEnvironment.Add("Longitude", tempVector); // Add an organic matter pool to the cell environment to track organic biomass not held by animals or plants with an initial value of 0 tempVector = new double[1]; tempVector[0] = 0.0; _CellEnvironment.Add("Organic Pool", tempVector); // Add a repsiratory CO2 pool to the cell environment with an initial value of 0 tempVector = new double[1]; tempVector[0] = 0.0; _CellEnvironment.Add("Respiratory CO2 Pool", tempVector); // Add the grid cell area (in km2) to the cell environment with an initial value of 0 tempVector = new double[1]; // Calculate the area of this grid cell tempVector[0] = Utilities.CalculateGridCellArea(latitude, lonCellSize, latCellSize); // Add it to the cell environment _CellEnvironment.Add("Cell Area", tempVector); //Add the latitude and longitude indices tempVector = new double[1]; tempVector[0] = latIndex; _CellEnvironment.Add("LatIndex", tempVector); tempVector = new double[1]; tempVector[0] = lonIndex; _CellEnvironment.Add("LonIndex", tempVector); // Add the missing value of data in the grid cell to the cell environment tempVector = new double[1]; tempVector[0] = missingValue; _CellEnvironment.Add("Missing Value", tempVector); // Loop through environmental data layers and extract values for this grid cell // Also standardise missing values // Loop over variables in the list of environmental data foreach (string LayerName in dataLayers.Keys) { // Initiliase the temporary vector of values to be equal to the number of time intervals in the environmental variable tempVector = new double[dataLayers[LayerName].NumTimes]; // Loop over the time intervals in the environmental variable for (int hh = 0; hh < dataLayers[LayerName].NumTimes; hh++) { // Add the value of the environmental variable at this time interval to the temporary vector tempVector[hh] = dataLayers[LayerName].GetValue(_Latitude, _Longitude, (uint)hh, out EnviroMissingValue,latCellSize,lonCellSize); // If the environmental variable is a missing value, then change the value to equal the standard missing value for this cell if (EnviroMissingValue) tempVector[hh] = missingValue; } // Add the values of the environmental variables to the cell environment, with the name of the variable as the key _CellEnvironment.Add(LayerName, tempVector); } if (_CellEnvironment.ContainsKey("LandSeaMask")) { if (_CellEnvironment["LandSeaMask"][0].CompareTo(0.0) == 0) { if (ContainsData(_CellEnvironment["OceanTemp"], _CellEnvironment["Missing Value"][0])) { //This is a marine cell tempVector = new double[1]; tempVector[0] = 2.0; _CellEnvironment.Add("Realm", tempVector); _CellEnvironment.Add("NPP", _CellEnvironment["OceanNPP"]); _CellEnvironment.Add("DiurnalTemperatureRange", _CellEnvironment["OceanDTR"]); if (_CellEnvironment.ContainsKey("Temperature")) { if(_CellEnvironment.ContainsKey("SST")) { _CellEnvironment["Temperature"] = _CellEnvironment["SST"]; } else { } } else { _CellEnvironment.Add("Temperature", _CellEnvironment["SST"]); } } else { //This is a freshwater cell and in this model formulation is characterised as belonging to the terrestrial realm tempVector = new double[1]; tempVector[0] = 2.0; _CellEnvironment.Add("Realm", tempVector); _CellEnvironment.Add("NPP", _CellEnvironment["LandNPP"]); _CellEnvironment.Add("DiurnalTemperatureRange", _CellEnvironment["LandDTR"]); } } else { //This is a land cell tempVector = new double[1]; tempVector[0] = 1.0; _CellEnvironment.Add("Realm", tempVector); _CellEnvironment.Add("NPP", _CellEnvironment["LandNPP"]); _CellEnvironment.Add("DiurnalTemperatureRange", _CellEnvironment["LandDTR"]); } } else { Debug.Fail("No land sea mask defined - a mask is required to initialise appropriate ecology"); } //Calculate and add the standard deviation of monthly temperature as a measure of seasonality //Also calculate and add the annual mean temperature for this cell tempVector = new double[12]; double[] sdtemp = new double[12]; double[] meantemp = new double[12]; tempVector = _CellEnvironment["Temperature"]; double Average = tempVector.Average(); meantemp[0] = Average; double SumOfSquaresDifferences = tempVector.Select(val => (val - Average) * (val - Average)).Sum(); sdtemp[0] = Math.Sqrt(SumOfSquaresDifferences / tempVector.Length); _CellEnvironment.Add("SDTemperature", sdtemp); _CellEnvironment.Add("AnnualTemperature", meantemp); //Remove unrequired cell environment layers if (_CellEnvironment.ContainsKey("LandNPP")) _CellEnvironment.Remove("LandNPP"); if (_CellEnvironment.ContainsKey("LandDTR")) _CellEnvironment.Remove("LandDTR"); if (_CellEnvironment.ContainsKey("OceanNPP")) _CellEnvironment.Remove("OceanNPP"); if (_CellEnvironment.ContainsKey("OceanDTR")) _CellEnvironment.Remove("OceanDTR"); if (_CellEnvironment.ContainsKey("SST")) _CellEnvironment.Remove("SST"); // CREATE NPP SEASONALITY LAYER _CellEnvironment.Add("Seasonality", CalculateNPPSeasonality(_CellEnvironment["NPP"], _CellEnvironment["Missing Value"][0])); // Calculate other climate variables from temperature and precipitation // Declare an instance of the climate variables calculator ClimateVariablesCalculator CVC = new ClimateVariablesCalculator(); // Calculate the fraction of the year that experiences frost double[] NDF = new double[1]; NDF[0] = CVC.GetNDF(_CellEnvironment["FrostDays"], _CellEnvironment["Temperature"],_CellEnvironment["Missing Value"][0]); _CellEnvironment.Add("Fraction Year Frost", NDF); double[] frostMonthly = new double[12]; frostMonthly[0] = Math.Min(_CellEnvironment["FrostDays"][0] / 31.0, 1.0); frostMonthly[1] = Math.Min(_CellEnvironment["FrostDays"][1] / 28.0, 1.0); frostMonthly[2] = Math.Min(_CellEnvironment["FrostDays"][2] / 31.0, 1.0); frostMonthly[3] = Math.Min(_CellEnvironment["FrostDays"][3] / 30.0, 1.0); frostMonthly[4] = Math.Min(_CellEnvironment["FrostDays"][4] / 31.0, 1.0); frostMonthly[5] = Math.Min(_CellEnvironment["FrostDays"][5] / 30.0, 1.0); frostMonthly[6] = Math.Min(_CellEnvironment["FrostDays"][6] / 31.0, 1.0); frostMonthly[7] = Math.Min(_CellEnvironment["FrostDays"][7] / 31.0, 1.0); frostMonthly[8] = Math.Min(_CellEnvironment["FrostDays"][8] / 30.0, 1.0); frostMonthly[9] = Math.Min(_CellEnvironment["FrostDays"][9] / 31.0, 1.0); frostMonthly[10] = Math.Min(_CellEnvironment["FrostDays"][10] / 30.0, 1.0); frostMonthly[11] = Math.Min(_CellEnvironment["FrostDays"][11] / 31.0, 1.0); _CellEnvironment.Add("Fraction Month Frost", frostMonthly); _CellEnvironment.Remove("FrostDays"); // Calculate AET and the fractional length of the fire season Tuple<double[], double, double> TempTuple = new Tuple<double[], double, double>(new double[12], new double(), new double()); TempTuple = CVC.MonthlyActualEvapotranspirationSoilMoisture(_CellEnvironment["AWC"][0], _CellEnvironment["Precipitation"], _CellEnvironment["Temperature"]); _CellEnvironment.Add("AET", TempTuple.Item1); _CellEnvironment.Add("Fraction Year Fire", new double[1] { TempTuple.Item3 / 360 }); // Designate a breeding season for this grid cell, where a month is considered to be part of the breeding season if its NPP is at // least 80% of the maximum NPP throughout the whole year double[] BreedingSeason = new double[12]; for (int i = 0; i < 12; i++) { if ((_CellEnvironment["Seasonality"][i] / _CellEnvironment["Seasonality"].Max()) > 0.5) { BreedingSeason[i] = 1.0; } else { BreedingSeason[i] = 0.0; } } _CellEnvironment.Add("Breeding Season", BreedingSeason); // Initialise the grid cell cohort and stock handlers _GridCellCohorts = new GridCellCohortHandler(cohortFunctionalGroups.GetNumberOfFunctionalGroups()); _GridCellStocks = new GridCellStockHandler(stockFunctionalGroups.GetNumberOfFunctionalGroups()); }
/// <summary> /// Constructor for human appropriation of autotroph matter /// </summary> public HumanAutotrophMatterAppropriation() { _Utilities = new UtilityFunctions(); }
/// <summary> /// Constructor for herbivory: assigns all parameter values /// </summary> /// <param name="cellArea">The area (in square km) of the grid cell</param> /// <param name="globalModelTimeStepUnit">The time step unit used in the model</param> public RevisedHerbivory(double cellArea, string globalModelTimeStepUnit) { InitialiseParametersHerbivory(); // Initialise the utility functions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of herbivory to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Store the specified cell area in this instance of this herbivory implementation _CellArea = cellArea; _CellAreaHectares = cellArea * 100; }
/// <summary> /// Constructor for model grid: assigns grid properties and initialises the grid cells /// </summary> /// <param name="minLat">Minimum grid latitude (degrees)</param> /// <param name="minLon">Minimum grid longitude (degrees, currently -180 to 180)</param> /// <param name="maxLat">Maximum grid latitude (degrees)</param> /// <param name="maxLon">Maximum grid longitude (degrees, currently -180 to 180)</param> /// <param name="latCellSize">Latitudinal resolution of grid cell</param> /// <param name="lonCellSize">Longitudinal resolution of grid cell</param> /// <param name="cellRarefaction">The rarefaction to be applied to active grid cells in the model</param> /// <param name="enviroStack">Environmental data layers</param> /// <param name="cohortFunctionalGroups">The functional group definitions for cohorts in the model</param> /// <param name="stockFunctionalGroups">The functional group definitions for stocks in the model</param> /// <param name="globalDiagnostics">Global daignostic variables</param> /// <param name="tracking">Whether process-tracking is enabled</param> /// <param name="DrawRandomly">Whether the model is set to use a random draw</param> /// <param name="specificLocations">Whether the model is to be run for specific locations</param> public ModelGrid(float minLat, float minLon,float maxLat,float maxLon,float latCellSize,float lonCellSize, SortedList<string,EnviroData> enviroStack, FunctionalGroupDefinitions cohortFunctionalGroups, FunctionalGroupDefinitions stockFunctionalGroups, SortedList<string, double> globalDiagnostics, Boolean tracking, Boolean DrawRandomly, Boolean specificLocations, string globalModelTimeStepUnit) { // Add one to the counter of the number of grids. If there is more than one model grid, exit the program with a debug crash. NumGrids = NumGrids + 1; //Debug.Assert(NumGrids < 2, "You have initialised more than one grid on which to apply models. At present, this is not supported"); // Initialise the utility functions Utilities = new UtilityFunctions(); // Seed the random number generator // Set the seed for the random number generator RandomNumberGenerator = new NonStaticSimpleRNG(); if (DrawRandomly) { RandomNumberGenerator.SetSeedFromSystemTime(); } else { RandomNumberGenerator.SetSeed(4315); } // CURRENTLY DEFINING MODEL CELLS BY BOTTOM LEFT CORNER _MinLatitude = minLat; _MinLongitude = minLon; _MaxLatitude = maxLat; _MaxLongitude = maxLon; _LatCellSize = latCellSize; _LonCellSize = lonCellSize; // Check to see if the number of grid cells is an integer Debug.Assert((((_MaxLatitude - _MinLatitude) % _LatCellSize) == 0), "Error: number of grid cells is non-integer: check cell size"); _NumLatCells = (UInt32)((_MaxLatitude - _MinLatitude) / _LatCellSize); _NumLonCells = (UInt32)((_MaxLongitude - _MinLongitude) / _LonCellSize); _Lats = new float[_NumLatCells]; _Lons = new float[_NumLonCells]; // Set up latitude and longitude vectors - lower left for (int ii = 0; ii < _NumLatCells; ii++) { _Lats[ii] = _MinLatitude + ii * _LatCellSize; } for (int jj = 0; jj < _NumLonCells; jj++) { _Lons[jj] = _MinLongitude + jj * _LonCellSize; } // Instantiate a grid of grid cells InternalGrid = new GridCell[_NumLatCells, _NumLonCells]; // Instantiate the arrays of lists of cohorts to disperse DeltaFunctionalGroupDispersalArray = new List<uint>[_NumLatCells, _NumLonCells]; DeltaCohortNumberDispersalArray = new List<uint>[_NumLatCells, _NumLonCells]; // Instantiate the array of lists of grid cells to disperse those cohorts to DeltaCellToDisperseToArray = new List<uint[]>[_NumLatCells, _NumLonCells]; // Instantiate the arrays of cell entry and exit directions DeltaCellExitDirection = new List<uint>[_NumLatCells, _NumLonCells]; DeltaCellEntryDirection = new List<uint>[_NumLatCells, _NumLonCells]; // An array of lists of cells to which organisms in each cell can disperse to; includes all cells which contribute to the // perimeter list, plus diagonal cells if they are in the same realm CellsForDispersal = new List<uint[]>[_NumLatCells, _NumLonCells]; // An array of lists of directions corresponding to cells which organisms can disperse to CellsForDispersalDirection = new List<uint>[_NumLatCells, _NumLonCells]; Console.WriteLine("Initialising grid cell environment:"); // Loop through to set up model grid for (int ii = 0; ii < _NumLatCells; ii+=GridCellRarefaction) { for (int jj = 0; jj < _NumLonCells; jj+=GridCellRarefaction) { InternalGrid[ii, jj] = new GridCell(_Lats[ii],(uint)ii, _Lons[jj],(uint)jj, LatCellSize, LonCellSize, enviroStack, GlobalMissingValue, cohortFunctionalGroups, stockFunctionalGroups, globalDiagnostics, tracking, specificLocations,globalModelTimeStepUnit); CellsForDispersal[ii,jj] = new List<uint[]>(); CellsForDispersalDirection[ii, jj] = new List<uint>(); Console.Write("\rRow {0} of {1}", ii+1, NumLatCells/GridCellRarefaction); } } Console.WriteLine(""); Console.WriteLine(""); InterpolateMissingValues(globalModelTimeStepUnit); // Fill in the array of dispersable perimeter lengths for each grid cell CalculatePerimeterLengthsAndCellsDispersableTo(); CellHeightsKm = new double[_Lats.Length]; CellWidthsKm = new double[_Lats.Length]; // Calculate the lengths of widths of grid cells in each latitudinal strip // Assume that we are at the midpoint of each cell when calculating lengths for (int ii = 0; ii < _Lats.Length; ii++) { CellHeightsKm[ii] = Utilities.CalculateLengthOfDegreeLatitude(_Lats[ii] + _LatCellSize / 2) * _LatCellSize; CellWidthsKm[ii] = Utilities.CalculateLengthOfDegreeLongitude(_Lats[ii] + _LatCellSize / 2) * _LonCellSize; } }
/// <summary> /// Constructor for EnviroData /// </summary> /// <param name="fileName">Filename (including extension)</param> /// <param name="dataName">The name of the variable that contains the data within the specified file</param> /// <param name="dataType">Type of data, nc = NetCDF, ascii = ESRI ASCII)</param> /// <param name="dataResolution">The temporal resolution of the environmental variable</param> /// <param name="units">The units of the data</param> /// <todo>Check whether lat/lon or 0/1 are fixed for all NetCDFs</todo> /// <todo>CHECK IF DIMENSIONS HAVE TO BE THE SAME FOR ALL VARIABLES IN A NETCDF AND HOW TO EXTRACT DIMENSIONS FOR A SINGLE VARIABLE IF NECESSARY</todo> /// <todo>Write code to check for equal cell sizes in NetCDFs</todo> public EnviroData(string fileName, string dataName, string dataType, string dataResolution, string units) { // Initialise the utility functions Utilities = new UtilityFunctions(); // Temporary array to hold environmental data double[,] tempDoubleArray; // Temporary vectors to hold dimension data Single[] tempSingleVector; Int32[] tempInt32Vector; Int16[] tempInt16Vector; // Vectors of possible names of the dimension variables to search in the files for string[] LonSearchStrings = new string[] { "lon", "Lon", "longitude", "Longitude", "lons", "Lons", "long", "Long", "longs", "Longs", "longitudes", "Longitudes", "x", "X" }; string[] LatSearchStrings = new string[] { "lat", "Lat", "latitude", "Latitude", "lats", "Lats", "latitudes", "Latitudes", "y", "Y" }; string[] MonthSearchStrings = new string[] { "month", "Month", "months", "Months", "Time", "time" }; //Integer counter for iterating through search strings int kk = 0; // Intialise the list of arrays to hold the values of the environmental data _DataArray = new List<double[,]>(); // Construct the string required to access the file using Scientific Dataset _ReadFileString = "msds:" + dataType + "?file=" + fileName + "&openMode=readOnly"; // Open the data file using Scientific Dataset DataSet internalData = DataSet.Open(_ReadFileString); // Store the specified units _Units = units; // Switch based on the tempeoral resolution and data type switch (dataResolution) { case "year": switch (dataType) { case "esriasciigrid": // Extract the number of latidudinal and longitudinal cells in the file _NumLats = (uint)internalData.Dimensions["x"].Length; _NumLons = (uint)internalData.Dimensions["y"].Length; // Set number of time intervals equal to 1 _NumTimes = 1; // Initialise the vector of time steps with length 1 _Times = new double[1]; // Assign the single value of the time step dimension to be equal to 1 _Times[0] = 1; // Get the value used for missing data in this environmental variable _MissingValue = internalData.GetAttr<double>(1, "NODATA_value"); // Get the latitudinal and longitudinal sizes of grid cells _LatStep = internalData.GetAttr<double>(1, "cellsize"); _LonStep = _LatStep; // Get longitudinal 'x' and latitudinal 'y' corners of the bottom left of the data grid _LatMin = internalData.GetAttr<double>(1, "yllcorner"); _LonMin = internalData.GetAttr<double>(1, "xllcorner"); // Create vectors holding the latitudes and longitudes of the bottom-left corners of the grid cells _Lats = new double[NumLats]; for (int ii = 0; ii < NumLats; ii++) { _Lats[NumLats - 1 - ii] = LatMin + ii * _LatStep; } _Lons = new double[NumLons]; for (int ii = 0; ii < NumLons; ii++) { _Lons[ii] = LonMin + ii * _LonStep; } //Fill in the two-dimensional environmental data array // Note: currently assumes Lats (x), Lons (y) in SDS - this is different to ESRI ASCII tempDoubleArray = new double[NumLats, NumLons]; tempDoubleArray = internalData.GetData<double[,]>(dataName); _DataArray.Add(tempDoubleArray); break; case "nc": // Loop over possible names for the latitude dimension until a match in the data file is found kk = 0; while ((kk < LatSearchStrings.Length) && (!internalData.Variables.Contains(LatSearchStrings[kk]))) kk++; // If a match for the latitude dimension has been found then read in the data, otherwise throw an error if (kk < LatSearchStrings.Length) { // Get number of latitudinal cells in the file _NumLats = (uint)internalData.Dimensions[LatSearchStrings[kk]].Length; // Read in the values of the latitude dimension from the file // Check which format the latitude dimension data are in; if unrecognized, then throw an error if (internalData.Variables[LatSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "single") { // Read the latitude dimension data to a temporary vector tempSingleVector = internalData.GetData<Single[]>(LatSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Lats = new double[tempSingleVector.Length]; for (int jj = 0; jj < tempSingleVector.Length; jj++) { _Lats[jj] = (double)tempSingleVector[jj]; } } else if (internalData.Variables[LatSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "double") { // Read the dimension data directly into the vector of dimension values _Lats = internalData.GetData<double[]>(LatSearchStrings[kk]); } else { // Data format unrecognized, so throw an error Debug.Fail("Unrecognized data format for latitude dimension"); } } else { // Didn't find a plausible match for latitude dimension data, so throw an error Debug.Fail("Cannot find any variables that look like latitude dimensions"); } // Loop over possible names for the latitude dimension until a match in the data file is found kk = 0; while ((kk < LonSearchStrings.Length) && (!internalData.Variables.Contains(LonSearchStrings[kk]))) kk++; // If a match for the longitude dimension has been found then read in the data, otherwise throw an error if (kk < LonSearchStrings.Length) { // Get number of longitudinal cells in the file _NumLons = (uint)internalData.Dimensions[LonSearchStrings[kk]].Length; // Read in the values of the longitude dimension from the file // Check which format the longitude dimension data are in; if unrecognized, then throw an error if (internalData.Variables[LonSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "single") { // Read the longitude dimension data to a temporary vector tempSingleVector = internalData.GetData<Single[]>(LonSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Lons = new double[tempSingleVector.Length]; for (int jj = 0; jj < tempSingleVector.Length; jj++) { _Lons[jj] = (double)tempSingleVector[jj]; } } else if (internalData.Variables[LonSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "double") { // Read the dimension data directly into the vector of dimension values _Lons = internalData.GetData<double[]>(LonSearchStrings[kk]); } else { // Data format unrecognized, so throw an error Debug.Fail("Unrecognized data format for longitude dimension"); } } else { // Didn't find a plausible match for longitude dimension data, so throw an error Debug.Fail("Cannot find any variables that look like longitude dimensions"); } // Set number of time intervals equal to 1 _NumTimes = 1; // Initialise the vector of time steps with length 1 _Times = new double[1]; // Assign the single value of the time step dimension to be equal to 1 _Times[0] = 1; // Get the latitudinal and longitudinal sizes of grid cells _LatStep = (_Lats[1] - _Lats[0]); _LonStep = (_Lons[1] - _Lons[0]); // Convert vectors of latitude and longutiude dimension data from cell-centre references to bottom-left references //if LatStep is positive then subtract the step to convert to the bottom left corner of the cell, // else if LatStep is negative, then need to add the step to convert to the bottom left for (int ii = 0; ii < _Lats.Length; ii++) { _Lats[ii] = (_LatStep.CompareTo(0.0) > 0) ? _Lats[ii] - (_LatStep / 2) : _Lats[ii] + (_LatStep / 2); } for (int jj = 0; jj < _Lons.Length; jj++) { _Lons[jj] = (_LonStep.CompareTo(0.0) > 0) ? _Lons[jj] - (_LonStep / 2) : _Lons[jj] + (_LonStep / 2); } // Check whether latitudes and longitudes are inverted in the NetCDF file bool LatInverted = (_Lats[1] < _Lats[0]); bool LongInverted = (_Lons[1] < _Lons[0]); // Run method to read in the environmental data and the dimension data from the NetCDF EnvironmentListFromNetCDF(internalData, dataName, LatInverted, LongInverted); // Get longitudinal 'x' and latitudinal 'y' corners of the bottom left of the data grid _LatMin = _Lats[0]; _LonMin = _Lons[0]; break; default: // Data type not recognized, so throw an error Debug.Fail("Data type not supported"); break; } break; case "month": switch (dataType) { case "esriasciigrid": // This combination does not work in the model, so throw an error Debug.Fail("Variables at monthly temporal resolution must be stored as three-dimensional NetCDFs"); break; case "nc": // Loop over possible names for the latitude dimension until a match in the data file is found kk = 0; while ((kk < LatSearchStrings.Length) && (!internalData.Variables.Contains(LatSearchStrings[kk]))) kk++; // If a match for the latitude dimension has been found then read in the data, otherwise throw an error if (kk < LatSearchStrings.Length) { // Get number of latitudinal cells in the file _NumLats = (uint)internalData.Dimensions[LatSearchStrings[kk]].Length; // Read in the values of the latitude dimension from the file // Check which format the latitude dimension data are in; if unrecognized, then throw an error if (internalData.Variables[LatSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "single") { // Read the latitude dimension data to a temporary vector tempSingleVector = internalData.GetData<Single[]>(LatSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Lats = new double[tempSingleVector.Length]; for (int jj = 0; jj < tempSingleVector.Length; jj++) { _Lats[jj] = (double)tempSingleVector[jj]; } } else if (internalData.Variables[LatSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "double") { // Read the dimension data directly into the vector of dimension values _Lats = internalData.GetData<double[]>(LatSearchStrings[kk]); } else { // Data format unrecognized, so throw an error Debug.Fail("Unrecognized data format for latitude dimension"); } } else { // Didn't find a plausible match for latitude dimension data, so throw an error Debug.Fail("Cannot find any variables that look like latitude dimensions"); } // Loop over possible names for the latitude dimension until a match in the data file is found kk = 0; while ((kk < LonSearchStrings.Length) && (!internalData.Variables.Contains(LonSearchStrings[kk]))) kk++; // If a match for the longitude dimension has been found then read in the data, otherwise throw an error if (kk < LonSearchStrings.Length) { // Get number of longitudinal cells in the file _NumLons = (uint)internalData.Dimensions[LonSearchStrings[kk]].Length; // Read in the values of the longitude dimension from the file // Check which format the longitude dimension data are in; if unrecognized, then throw an error if (internalData.Variables[LonSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "single") { // Read the longitude dimension data to a temporary vector tempSingleVector = internalData.GetData<Single[]>(LonSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Lons = new double[tempSingleVector.Length]; for (int jj = 0; jj < tempSingleVector.Length; jj++) { _Lons[jj] = (double)tempSingleVector[jj]; } } else if (internalData.Variables[LonSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "double") { // Read the dimension data directly into the vector of dimension values _Lons = internalData.GetData<double[]>(LonSearchStrings[kk]); } else { // Data format unrecognized, so throw an error Debug.Fail("Unrecognized data format for longitude dimension"); } } else { // Didn't find a plausible match for longitude dimension data, so throw an error Debug.Fail("Cannot find any variables that look like longitude dimensions"); } // Loop over possible names for the monthly temporal dimension until a match in the data file is found kk = 0; while ((kk < MonthSearchStrings.Length) && (!internalData.Variables.Contains(MonthSearchStrings[kk]))) kk++; // Of a match for the monthly temporal dimension has been found then read in the data, otherwise thrown an error if (internalData.Variables.Contains(MonthSearchStrings[kk])) { // Get the number of months in the temporal dimension _NumTimes = (uint)internalData.Dimensions[MonthSearchStrings[kk]].Length; // Check that the number of months is 12 Debug.Assert(_NumTimes == 12, "Number of time intervals in an environmental data file with specified monthly temporal resolution is not equal to 12"); // Read in the values of the temporal dimension from the file // Check which format the temporal dimension data are in; if unrecognized, then throw an error if (internalData.Variables[MonthSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "single") { // Read the temporal dimension data to a temporary vector tempSingleVector = internalData.GetData<Single[]>(MonthSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Times = new double[_NumTimes]; for (int hh = 0; hh < tempSingleVector.Length; hh++) { _Times[hh] = (double)tempSingleVector[hh]; } } else if (internalData.Variables[MonthSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "double") { // Read the dimension data directly into the vector of dimension values _Times = internalData.GetData<double[]>(MonthSearchStrings[kk]); } else if (internalData.Variables[MonthSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "int32") { // Read the temporal dimension data to a temporary vector tempInt32Vector = internalData.GetData<Int32[]>(MonthSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Times = new double[_NumTimes]; for (int hh = 0; hh < tempInt32Vector.Length; hh++) { _Times[hh] = (double)tempInt32Vector[hh]; } } else if (internalData.Variables[MonthSearchStrings[kk]].TypeOfData.Name.ToString().ToLower() == "int16") { // Read the temporal dimension data to a temporary vector tempInt16Vector = internalData.GetData<Int16[]>(MonthSearchStrings[kk]); // Convert the dimension data to double format and add to the vector of dimension values _Times = new double[_NumTimes]; for (int hh = 0; hh < tempInt16Vector.Length; hh++) { _Times[hh] = (double)tempInt16Vector[hh]; } } else { // Data format unrecognized, so throw an error Debug.Fail("Unrecognized data format for time dimension"); } } else { // Didn't find a plausible match for temporal dimension data, so throw an error Debug.Fail("Cannot find any variables that look like a monthly temporal dimension"); } // Convert the values of the time dimension to equal integers between 1 and 12 (the format currently recognized by the model) for (int hh = 0; hh < _NumTimes; hh++) { if (_Times[hh] != hh + 1) _Times[hh] = hh + 1; } // Get the latitudinal and longitudinal sizes of grid cells _LatStep = (_Lats[1] - _Lats[0]); _LonStep = (_Lons[1] - _Lons[0]); // Convert vectors of latitude and longutiude dimension data from cell-centre references to bottom-left references for (int ii = 0; ii < _Lats.Length; ii++) { _Lats[ii] = _Lats[ii] - (_LatStep / 2); } for (int jj = 0; jj < _Lons.Length; jj++) { _Lons[jj] = _Lons[jj] - (_LonStep / 2); } // Check whether latitudes and longitudes are inverted in the NetCDF file bool LatInverted = (_Lats[1] < _Lats[0]); bool LongInverted = (_Lons[1] < _Lons[0]); // Run method to read in the environmental data and the dimension data from the NetCDF EnvironmentListFromNetCDF3D(internalData, dataName, LatInverted, LongInverted); // Get longitudinal 'x' and latitudinal 'y' corners of the bottom left of the data grid _LatMin = _Lats[0]; _LonMin = _Lons[0]; break; default: // Data type not recognized, so throw an error Debug.Fail("Data type not supported"); break; } break; default: // The model currently only supports variables with temporal resolution 'year' or 'month', so throw an error Debug.Fail("Temporal resolution not supported"); break; } // Check to see whether the environmental variable has longitude values from 0 to 360, instead of -180 to 180 (which the model currently recognizes) if (_LonMin + (_NumLons * _LonStep) > 180.0) { // Convert the longitude values to be -180 to 180, instead of 0 to 360 Utilities.ConvertToM180To180(_Lons); // Update the minimum longitude value accordingly _LonMin = _Lons.Min(); } // Update the variable keeping track of the number of environmental data layers _NumEnviroLayers = _NumEnviroLayers + 1; //Close the environmental data file internalData.Dispose(); }
/// <summary> /// Overloaded constructor to fetch climate information from the cloud using FetchClimate for specific locations /// </summary> /// <param name="dataName">Name of the the climate variable to be fetched</param> /// <param name="dataResolution">Time resolution requested</param> /// <param name="latMin">Bottom latitude</param> /// <param name="lonMin">Leftmost longitude</param> /// <param name="latMax">Maximum latitude</param> /// <param name="lonMax">Maximum longitude</param> /// <param name="cellSize">Size of each grid cell</param> /// <param name = "cellList">List of cells to be fetched</param> /// <param name="FetchClimateDataSource">Data source from which to fetch environmental data</param> public EnviroData(string dataName, string dataResolution, double latMin, double lonMin, double latMax, double lonMax, double cellSize, List<uint[]> cellList, EnvironmentalDataSource FetchClimateDataSource) { Console.WriteLine("Fetching environmental data for: " + dataName + " with resolution " + dataResolution); // Initialise the utility functions Utilities = new UtilityFunctions(); _NumLats = Convert.ToUInt32((latMax - latMin) / cellSize); _NumLons = Convert.ToUInt32((lonMax - lonMin) / cellSize); _LatMin = latMin; _LonMin = lonMin; _Lats = new double[_NumLats]; _Lons = new double[_NumLons]; for (int ii = 0; ii < _NumLats; ii++) { _Lats[ii] = Math.Round(_LatMin + (ii * cellSize), 2); } for (int jj = 0; jj < _NumLons; jj++) { _Lons[jj] = Math.Round(_LonMin + (jj * cellSize), 2); } _LatStep = Math.Round(Lats[1] - _Lats[0], 2); _LonStep = Math.Round(Lons[1] - Lons[0], 2); //Declare a dataset to perform the fetch var ds = DataSet.Open("msds:memory2"); _DataArray = new List<double[,]>(); //Add the required time dimension to the dataset switch (dataResolution) { case "year": ds.AddClimatologyAxisYearly(yearmin: 1961, yearmax: 1990, yearStep: 30); break; case "month": ds.AddClimatologyAxisMonthly(); break; default: break; } //Add lat and lon information to the dataset for (int ii = 0; ii < cellList.Count; ii++) { ds.AddAxisCells("longitude", "degrees_east", _Lons[cellList[ii][1]], Lons[cellList[ii][1]] + cellSize, cellSize); ds.AddAxisCells("latitude", "degrees_north", _Lats[cellList[ii][0]], _Lats[cellList[ii][0]] + cellSize, cellSize); double[, ,] temp = null; //Fetch for the required data switch (dataName.ToLower()) { case "land_dtr": ds.Fetch(ClimateParameter.FC_LAND_DIURNAL_TEMPERATURE_RANGE, "landdtr", dataSource: FetchClimateDataSource); //this call will create 2D variable on dimensions records and months and fill it with a FetchClimate //int NumberOfRecords = ds.Dimensions["RecordNumber"].Length; // get number of records temp = (double[, ,])ds.Variables["landdtr"].GetData(); _MissingValue = (double)ds.Variables["landdtr"].GetMissingValue(); break; case "temperature": ds.Fetch(ClimateParameter.FC_TEMPERATURE, "airt", dataSource: FetchClimateDataSource); //this call will create 2D variable on dimensions records and months and fill it with a FetchClimate //int NumberOfRecords = ds.Dimensions["RecordNumber"].Length; // get number of records temp = (double[, ,])ds.Variables["airt"].GetData(); _MissingValue = (double)ds.Variables["airt"].GetMissingValue(); break; // Commenting out ocean air temperature because it is running too slow when using FetchClimate case "temperature_ocean": ds.Fetch(ClimateParameter.FC_OCEAN_AIR_TEMPERATURE, "oceanairt", dataSource: FetchClimateDataSource); //this call will create 2D variable on dimensions records and months and fill it with a FetchClimate //int NumberOfRecords = ds.Dimensions["RecordNumber"].Length; // get number of records temp = (double[, ,])ds.Variables["oceanairt"].GetData(); _MissingValue = (double)ds.Variables["oceanairt"].GetMissingValue(); break; case "precipitation": ds.Fetch(ClimateParameter.FC_PRECIPITATION, "precip", dataSource: FetchClimateDataSource); //this call will create 2D variable on dimensions records and months and fill it with a FetchClimate //int NumberOfRecords = ds.Dimensions["RecordNumber"].Length; // get number of records temp = (double[, ,])ds.Variables["precip"].GetData(); _MissingValue = (double)ds.Variables["precip"].GetMissingValue(); break; case "frost": ds.Fetch(ClimateParameter.FC_LAND_FROST_DAY_FREQUENCY, "frost", dataSource: FetchClimateDataSource); temp = (double[, ,])ds.Variables["frost"].GetData(); _MissingValue = (double)ds.Variables["frost"].GetMissingValue(); break; default: Debug.Fail("No Enviro data read in for " + dataName); break; } _NumTimes = (uint)ds.Dimensions["time"].Length; //Add the fetched data to the Envirodata array for (int tt = 0; tt < _NumTimes; tt++) { double[,] TempArray; if (_DataArray.Count > tt) { TempArray = _DataArray[tt]; } else { TempArray = new double[NumLats, NumLons]; } // Currently FetchClimate returns longitudes as the last array dimension TempArray[cellList[ii][0], cellList[ii][1]] = temp[tt, 0, 0]; if (_DataArray.Count > tt) { _DataArray.RemoveAt(tt); _DataArray.Insert(tt, TempArray); } else { _DataArray.Add(TempArray); } } } //DataSet Out = ds.Clone("output/" + dataName + ".nc"); //Out.Dispose(); ds.Dispose(); }
/// <summary> /// Constructor for predation: assigns all parameter values /// </summary> /// <param name="cellArea">The area (in square km) of the grid cell</param> /// <param name="globalModelTimeStepUnit">The time step unit used in the model</param> public RevisedPredation(double cellArea, string globalModelTimeStepUnit) { InitialiseParametersPredation(); // Initialise the utility functions Utilities = new UtilityFunctions(); // Calculate the scalar to convert from the time step units used by this implementation of predation to the global model time step units _DeltaT = Utilities.ConvertTimeUnits(globalModelTimeStepUnit, _TimeUnitImplementation); // Store the specified cell area in this instance of this predation implementation _CellArea = cellArea; _CellAreaHectares = cellArea * 100; HalfNumberOfBins = NumberOfBins / 2; FeedingPreferenceHalfStandardDeviation = _FeedingPreferenceStandardDeviation * 0.5; }
/// <summary> /// Constructor for the plant model /// </summary> public RevisedTerrestrialPlantModel() { // Initialise parameters InitialisePlantModelParameters(); // Initialise the utility functions Utilities = new UtilityFunctions(); }