/// <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> /// 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; } }