/// <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> /// Apply all updates from the ecological processes to the properties of the acting cohort and to the environment /// </summary> public void UpdateAllCrossGridCellEcology(ModelGrid madingleyModelGrid, ref uint dispersalCounter, CrossCellProcessTracker trackCrossCellProcesses, uint currentTimeStep) { // Create an array to hold the number of cohorts dispersing in each direction from each grid cell uint[, ,] InboundCohorts = new uint[madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0), madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1), 8]; // Create an array to hold the number of cohorts dispersing in each direction to each grid cell uint[, ,] OutboundCohorts = new uint[madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0), madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1), 8]; // Create an list array to hold the weights of cohorts dispersing from grid cell. Dimensions are: num grid cells lon, num grid cells lat, num cohorts dispersing List <double>[,] OutboundCohortWeights = new List <double> [madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0), madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1)]; for (uint ii = 0; ii < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0); ii++) { for (uint jj = 0; jj < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1); jj++) { OutboundCohortWeights[ii, jj] = new List <double>(); } } // Loop through the delta array that holds the grid cells of the cohorts that are flagged as needing to be moved for (uint ii = 0; ii < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0); ii++) { for (uint jj = 0; jj < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1); jj++) { // No cohorts to move if there are none in the delta dispersal array if (madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].Count == 0) { } // Otherwise, loop through the cohorts and change the pointers/references to them one-by-one else { for (int kk = 0; kk < madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].Count; kk++) { // Find out which grid cell it is going to uint[] CellToDisperseTo = madingleyModelGrid.DeltaCellToDisperseToArray[ii, jj].ElementAt(kk); // Functional group is identified by the first array uint CohortToDisperseFG = madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].ElementAt(kk); // Cohort number is identified by the second array uint CohortToDisperseNum = madingleyModelGrid.DeltaCohortNumberDispersalArray[ii, jj].ElementAt(kk); // If track processes is on, add this to the list of inbound and outbound cohorts if (trackCrossCellProcesses.TrackCrossCellProcesses) { WriteOutCrossGridCell(madingleyModelGrid, CellToDisperseTo, InboundCohorts, OutboundCohorts, OutboundCohortWeights, ii, jj, CohortToDisperseFG, CohortToDisperseNum, madingleyModelGrid.DeltaCellExitDirection[ii, jj].ElementAt(kk), madingleyModelGrid.DeltaCellEntryDirection[ii, jj].ElementAt(kk)); } // Simmply add it to the existing cohorts in that FG in the grid cell to disperse to madingleyModelGrid.AddNewCohortToGridCell(CellToDisperseTo[0], CellToDisperseTo[1], (int)CohortToDisperseFG, madingleyModelGrid.GetGridCellIndividualCohort(ii, jj, (int)CohortToDisperseFG, (int)CohortToDisperseNum)); // Update the dispersal counter dispersalCounter++; // So now there is a pointer in the grid cell to which it is going. We have to delete the pointers in the original cell and in the // delta array, but we need to do this without messing with the list structure; i.e. wait until all cohorts have been moved } } } } // Reset the delta arrays and remove the pointers to the cohorts in the original list for (uint ii = 0; ii < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0); ii++) { for (uint jj = 0; jj < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1); jj++) { // No cohorts to move if there are none in the delta dispersal array if (madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].Count == 0) { } // Otherwise, loop through the cohorts and change the pointers/references to them one-by-one else { // Delete the cohorts from the original grid cell. Note that this needs to be done carefully to ensure that the correct ones // are deleted (lists shift about when an internal element is deleted. madingleyModelGrid.DeleteGridCellIndividualCohorts(ii, jj, madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj], madingleyModelGrid.DeltaCohortNumberDispersalArray[ii, jj]); // Reset the lists in the delta dispersal arrays madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj] = new List <uint>(); madingleyModelGrid.DeltaCohortNumberDispersalArray[ii, jj] = new List <uint>(); // Reset the list in the grid cells to disperse to array madingleyModelGrid.DeltaCellToDisperseToArray[ii, jj] = new List <uint[]>(); // Reset the lists in the delta dispersal arrays madingleyModelGrid.DeltaCellExitDirection[ii, jj] = new List <uint>(); madingleyModelGrid.DeltaCellEntryDirection[ii, jj] = new List <uint>(); } } } if (trackCrossCellProcesses.TrackCrossCellProcesses) { // If we are tracking dispersal, then write out how many cohorts have moved to a file trackCrossCellProcesses.RecordDispersalForACell(InboundCohorts, OutboundCohorts, OutboundCohortWeights, currentTimeStep, madingleyModelGrid); } }
/// <summary> /// Apply all updates from the ecological processes to the properties of the acting cohort and to the environment /// </summary> public void UpdateAllCrossGridCellEcology(ModelGrid madingleyModelGrid, ref uint dispersalCounter, CrossCellProcessTracker trackCrossCellProcesses, uint currentTimeStep) { // Create an array to hold the number of cohorts dispersing in each direction from each grid cell uint[, ,] InboundCohorts = new uint[madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0), madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1), 8]; // Create an array to hold the number of cohorts dispersing in each direction to each grid cell uint[, ,] OutboundCohorts = new uint[madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0), madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1), 8]; // Create an list array to hold the weights of cohorts dispersing from grid cell. Dimensions are: num grid cells lon, num grid cells lat, num cohorts dispersing List<double>[,] OutboundCohortWeights = new List<double>[madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0), madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1)]; for (uint ii = 0; ii < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0); ii++) { for (uint jj = 0; jj < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1); jj++) { OutboundCohortWeights[ii,jj] = new List<double>(); } } // Loop through the delta array that holds the grid cells of the cohorts that are flagged as needing to be moved for (uint ii = 0; ii < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0) ; ii++) { for (uint jj = 0; jj < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1); jj++) { if (madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj] != null) { // No cohorts to move if there are none in the delta dispersal array if (madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].Count == 0) { } // Otherwise, loop through the cohorts and change the pointers/references to them one-by-one else { for (int kk = 0; kk < madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].Count; kk++) { // Find out which grid cell it is going to uint[] CellToDisperseTo = madingleyModelGrid.DeltaCellToDisperseToArray[ii, jj].ElementAt(kk); // Functional group is identified by the first array uint CohortToDisperseFG = madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].ElementAt(kk); // Cohort number is identified by the second array uint CohortToDisperseNum = madingleyModelGrid.DeltaCohortNumberDispersalArray[ii, jj].ElementAt(kk); // If track processes is on, add this to the list of inbound and outbound cohorts if (trackCrossCellProcesses.TrackCrossCellProcesses) { WriteOutCrossGridCell(madingleyModelGrid, CellToDisperseTo, InboundCohorts, OutboundCohorts, OutboundCohortWeights, ii, jj, CohortToDisperseFG, CohortToDisperseNum, madingleyModelGrid.DeltaCellExitDirection[ii, jj].ElementAt(kk), madingleyModelGrid.DeltaCellEntryDirection[ii, jj].ElementAt(kk)); } // Simmply add it to the existing cohorts in that FG in the grid cell to disperse to madingleyModelGrid.AddNewCohortToGridCell(CellToDisperseTo[0], CellToDisperseTo[1], (int)CohortToDisperseFG, madingleyModelGrid.GetGridCellIndividualCohort(ii, jj, (int)CohortToDisperseFG, (int)CohortToDisperseNum)); // Update the dispersal counter dispersalCounter++; // So now there is a pointer in the grid cell to which it is going. We have to delete the pointers in the original cell and in the // delta array, but we need to do this without messing with the list structure; i.e. wait until all cohorts have been moved } } } } } // Reset the delta arrays and remove the pointers to the cohorts in the original list for (uint ii = 0; ii < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(0); ii++) { for (uint jj = 0; jj < madingleyModelGrid.DeltaFunctionalGroupDispersalArray.GetLength(1); jj++) { if (madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj] != null) { // No cohorts to move if there are none in the delta dispersal array if (madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj].Count == 0) { } // Otherwise, loop through the cohorts and change the pointers/references to them one-by-one else { // Delete the cohorts from the original grid cell. Note that this needs to be done carefully to ensure that the correct ones // are deleted (lists shift about when an internal element is deleted. madingleyModelGrid.DeleteGridCellIndividualCohorts(ii, jj, madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj], madingleyModelGrid.DeltaCohortNumberDispersalArray[ii, jj]); // Reset the lists in the delta dispersal arrays madingleyModelGrid.DeltaFunctionalGroupDispersalArray[ii, jj] = new List<uint>(); madingleyModelGrid.DeltaCohortNumberDispersalArray[ii, jj] = new List<uint>(); // Reset the list in the grid cells to disperse to array madingleyModelGrid.DeltaCellToDisperseToArray[ii, jj] = new List<uint[]>(); // Reset the lists in the delta dispersal arrays madingleyModelGrid.DeltaCellExitDirection[ii, jj] = new List<uint>(); madingleyModelGrid.DeltaCellEntryDirection[ii, jj] = new List<uint>(); } } } } if (trackCrossCellProcesses.TrackCrossCellProcesses) { // If we are tracking dispersal, then write out how many cohorts have moved to a file trackCrossCellProcesses.RecordDispersalForACell(InboundCohorts, OutboundCohorts, OutboundCohortWeights, currentTimeStep, madingleyModelGrid); } }
/// <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); #endif // Set up the model grid #if true this._CellList = initialisation.CellList.ToList(); SetUpModelGrid(initialisation); EcosystemModelGrid.SetGridCells(gridCells, this._CellList); #else SetUpModelGrid(initialisation, scenarioParameters, scenarioIndex, simulation); #endif // 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 time step timer TimeStepTimer = new StopWatch(); EcologyTimer = new StopWatch(); OutputTimer = new StopWatch(); // Set the global model time step unit _GlobalModelTimeStepUnit = globalModelTimeStepUnit; }
/// <summary> /// Update the properties of all cohorts across all grid cells /// </summary> public void UpdateCrossGridCellEcology(ModelGrid madingleyModelGrid, ref uint dispersalCounter, CrossCellProcessTracker trackCrossCellProcesses, uint currentTimeStep) { // Apply the results of cross-cell ecological processes ApplyCrossGridCellEcologicalProcessResults.UpdateAllCrossGridCellEcology(madingleyModelGrid, ref dispersalCounter, trackCrossCellProcesses, currentTimeStep); }