/// <summary> /// Sets up the model grid within a Madingley model run /// </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 that this model is to run</param> public void SetUpModelGrid(MadingleyModelInitialisation initialisation, ScenarioParameterInitialisation scenarioParameters, int scenarioIndex, int simulation) { // If the intialisation file contains a column pointing to another file of specific locations, and if this column is not blank then read the // file indicated if (SpecificLocations) { // Set up the model grid using these locations EcosystemModelGrid = new ModelGrid(BottomLatitude, LeftmostLongitude, TopLatitude, RightmostLongitude, CellSize, CellSize, _CellList, EnviroStack, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, GlobalDiagnosticVariables, initialisation.TrackProcesses, SpecificLocations, RunGridCellsInParallel,GlobalModelTimeStepUnit); } else { _CellList = new List<uint[]>(); //Switched order so we create cell list first then initialise cells using list rather than grid. uint NumLatCells = (uint)((TopLatitude - BottomLatitude) / CellSize); uint NumLonCells = (uint)((RightmostLongitude - LeftmostLongitude) / CellSize); // Loop over all cells in the model for (uint ii = 0; ii < NumLatCells; ii += 1) { for (uint jj = 0; jj < NumLonCells; jj += 1) { // Define a vector to hold the pair of latitude and longitude indices for this grid cell uint[] cellIndices = new uint[2]; // Add the latitude and longitude indices to this vector cellIndices[0] = ii; cellIndices[1] = jj; // Add the vector to the list of all active grid cells _CellList.Add(cellIndices); } } EcologyTimer = new StopWatch(); EcologyTimer.Start(); // Set up a full model grid (i.e. not for specific locations) // Set up the model grid using these locations EcosystemModelGrid = new ModelGrid(BottomLatitude, LeftmostLongitude, TopLatitude, RightmostLongitude, CellSize, CellSize, _CellList, EnviroStack, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, GlobalDiagnosticVariables, initialisation.TrackProcesses, SpecificLocations, RunGridCellsInParallel, GlobalModelTimeStepUnit); List<int> cellsToRemove = new List<int>(); if (initialisation.RunRealm == "terrestrial") { for (int ii = 0; ii < _CellList.Count; ii += 1) { if ((EcosystemModelGrid.GetCellEnvironment(_CellList[ii][0], _CellList[ii][1])["Realm"][0] == 2.0) || (EcosystemModelGrid.GetCellEnvironment(_CellList[ii][0], _CellList[ii][1])["LandSeaMask"][0] == 0.0)) { cellsToRemove.Add(ii); } } } else if (initialisation.RunRealm == "marine") { for (int ii = 0; ii < _CellList.Count; ii += 1) { if (EcosystemModelGrid.GetCellEnvironment(_CellList[ii][0], _CellList[ii][1])["Realm"][0] == 1.0) { cellsToRemove.Add(ii); } } } for (int ii = (cellsToRemove.Count - 1); ii >= 0; ii--) { _CellList.RemoveAt(cellsToRemove[ii]); } EcologyTimer.Stop(); Console.WriteLine("Time to initialise cells: {0}", EcologyTimer.GetElapsedTimeSecs()); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Madingley Model memory usage post grid cell seed: {0}", GC.GetTotalMemory(true) / 1E9, " (G Bytes)\n"); Console.ForegroundColor = ConsoleColor.White; } if (initialisation.InputState) { InputModelState = new InputModelState(initialisation.ModelStatePath[simulation], initialisation.ModelStateFilename[simulation],EcosystemModelGrid, _CellList); } // When the last simulation for the current scenario // if ((scenarioParameters.scenarioSimulationsNumber.Count == 1) && (scenarioIndex == scenarioParameters.scenarioSimulationsNumber[scenarioIndex] - 1)) EnviroStack.Clear(); // Seed stocks and cohorts in the grid cells // If input state from output from a previous simulation if (initialisation.InputState) { // Seed grid cell cohort and stocks EcosystemModelGrid.SeedGridCellStocksAndCohorts(_CellList, InputModelState, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions); //remove cohorts that do not contain any biomass foreach (uint[] CellPair in _CellList) { GridCellCohortHandler workingGridCellCohorts = EcosystemModelGrid.GetGridCellCohorts(CellPair[0], CellPair[1]); for (int kk = 0; kk < CohortFunctionalGroupDefinitions.GetNumberOfFunctionalGroups(); kk++) { // Loop through each cohort in the functional group for (int ll = (workingGridCellCohorts[kk].Count - 1); ll >= 0; ll--) { // If cohort abundance is less than the extinction threshold then add to the list for extinction if (workingGridCellCohorts[kk][ll].CohortAbundance.CompareTo(0) <= 0 || workingGridCellCohorts[kk][ll].IndividualBodyMass.CompareTo(0.0) == 0) { // Remove the extinct cohort from the list of cohorts workingGridCellCohorts[kk].RemoveAt(ll); } } } } } else { EcosystemModelGrid.SeedGridCellStocksAndCohorts(_CellList, CohortFunctionalGroupDefinitions, StockFunctionalGroupDefinitions, GlobalDiagnosticVariables, ref NextCohortID, InitialisationFileStrings["OutputDetail"] == "high", DrawRandomly, initialisation.DispersalOnly, InitialisationFileStrings["DispersalOnlyType"], RunGridCellsInParallel); } Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Madingley Model memory usage pre Collect: {0}", Math.Round(GC.GetTotalMemory(true) / 1E9, 2), " (GBytes)"); Console.ForegroundColor = ConsoleColor.White; GC.Collect(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Madingley Model memory usage post Collect: {0}", Math.Round(GC.GetTotalMemory(true) / 1E9, 5), " (GBytes)\n"); Console.ForegroundColor = ConsoleColor.White; }
/// <summary> /// Write to the output file values of the output variables during the model time steps /// </summary> /// <param name="ecosystemModelGrid">The model grid to get data from</param> /// <param name="cohortFunctionalGroupDefinitions">The definitions of the cohort functional groups in the model</param> /// <param name="stockFunctionalGroupDefinitions">The definitions of the stock functional groups in the model</param> /// <param name="cellIndices">List of indices of active cells in the model grid</param> /// <param name="cellNumber">The number of the current cell in the list of indices of active cells</param> /// <param name="globalDiagnosticVariables">List of global diagnostic variables</param> /// <param name="timeStepTimer">The timer for the current time step</param> /// <param name="numTimeSteps">The number of time steps in the model run</param> /// <param name="currentTimestep">The current model time step</param> /// <param name="initialisation">The Madingley Model initialisation</param> /// <param name="month">The current month in the model run</param> /// <param name="marineCell">Whether the current cell is a marine cell</param> public void TimeStepOutputs(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortFunctionalGroupDefinitions, FunctionalGroupDefinitions stockFunctionalGroupDefinitions, List<uint[]> cellIndices, int cellNumber, SortedList<string, double> globalDiagnosticVariables, StopWatch timeStepTimer, uint numTimeSteps, uint currentTimestep, MadingleyModelInitialisation initialisation, uint month, Boolean marineCell) { // Calculate values of the output variables to be used CalculateOutputs(ecosystemModelGrid, cohortFunctionalGroupDefinitions, stockFunctionalGroupDefinitions, cellIndices, cellNumber, globalDiagnosticVariables, initialisation, month, marineCell); // Generate the live outputs for this time step if (LiveOutputs) { TimeStepLiveOutputs(numTimeSteps, currentTimestep, ecosystemModelGrid, marineCell); } // Generate the console outputs for the current time step TimeStepConsoleOutputs(currentTimestep, timeStepTimer); // Generate the file outputs for the current time step TimeStepFileOutputs(ecosystemModelGrid, cohortFunctionalGroupDefinitions, currentTimestep, marineCell, cellIndices,cellNumber); }
/// <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> /// Generates the console outputs for the current time step /// </summary> /// <param name="currentTimeStep">The current time step</param> /// <param name="timeStepTimer">The timer for the current time step</param> private void TimeStepConsoleOutputs(uint currentTimeStep, StopWatch timeStepTimer) { }
/// <summary> /// Runs the specified number of simulations for each of the specified scenarios /// </summary> /// <param name="simulationInitialisationFilename">Filename of the file from which to read initialisation information</param> /// <param name="scenarios">Contains scenario information for this set of simulations</param> /// <param name="outputPath">The path to which outputs should be written</param> public void RunAllSimulations(string simulationInitialisationFilename, string definitionsFilename, string outputsFilename, ScenarioParameterInitialisation scenarios, string outputPath) { // Declare an instance of the class for initializing the Madingley model MadingleyModelInitialisation InitialiseMadingley = new MadingleyModelInitialisation(simulationInitialisationFilename, definitionsFilename, outputsFilename, outputPath); // Specify the output path in this instance InitialiseMadingley.OutputPath = outputPath; // List to hold the names of the scenarios to run List<string> ScenarioNames = new List<string>(); // String variable to hold the index suffix to apply to output files for a given simulation string OutputFilesSuffix; // Loop over scenario names and add the name of the scenario to the list of scenarion names foreach (var scenario in scenarios.scenarioParameters) { ScenarioNames.Add(scenario.Item1); } // Check whether there is only one simulation to run if (scenarios.scenarioNumber == 1 && scenarios.scenarioParameters.ElementAt(scenarios.scenarioNumber-1).Item2==1) { // For a single simulation // Set-up the suffix for the output files OutputFilesSuffix = "_"; // Loop over the parameters for this scenario for (int i = 0; i < ScenarioNames.Count; i++) { // Add the parameter information to the suffix for this simulation OutputFilesSuffix += ScenarioNames[0] + "_"; } // Add a zero index to the end of the suffix OutputFilesSuffix += "0"; //Run the simulation RunSimulation(scenarios, 0, InitialiseMadingley, OutputFilesSuffix, 0); Console.ReadKey(); } else { if (InitialiseMadingley.RunSimulationsInParallel) { // Loop over specified scenarios iteratively for (int ScenarioIndex = 0; ScenarioIndex < scenarios.scenarioNumber; ScenarioIndex++) { //Create an array of new MadingleyModel instances for simulations under this scenario combination MadingleyModel[] MadingleyEcosystemModels = new MadingleyModel [scenarios.scenarioParameters.ElementAt(ScenarioIndex).Item2]; for (int simulation = 0; simulation < scenarios.scenarioParameters.ElementAt(ScenarioIndex).Item2; simulation++) { // Set up the suffix for the output files OutputFilesSuffix = "_"; // Add the scenario label to the suffix for the output files OutputFilesSuffix += ScenarioNames[ScenarioIndex] + "_"; // Add the simulation index number to the suffix OutputFilesSuffix += simulation.ToString(); // Initialize the instance of MadingleyModel MadingleyEcosystemModels[simulation] = new MadingleyModel(InitialiseMadingley, scenarios, ScenarioIndex, OutputFilesSuffix, InitialiseMadingley.GlobalModelTimeStepUnit, simulation); } // Loop over the specified number of simulations for each scenario //for (int simulation = 0; simulation< scenarios.scenarioSimulationsNumber[ScenarioIndex]; simulation++) Parallel.For(0, scenarios.scenarioParameters.ElementAt(ScenarioIndex).Item2, simulation => { // Declare and start a timer StopWatch s = new StopWatch(); s.Start(); // Run the simulation MadingleyEcosystemModels[simulation].RunMadingley(InitialiseMadingley); // Stop the timer and write out the time taken to run this simulation s.Stop(); Console.WriteLine("Model run finished"); Console.WriteLine("Total elapsed time was {0} seconds", s.GetElapsedTimeSecs()); }); } } else { //Run simulations sequentially // Loop over specified scenarios for (int ScenarioIndex = 0; ScenarioIndex < scenarios.scenarioNumber; ScenarioIndex++) { // Loop over the specified number of simulations for each scenario for (int simulation = 0; simulation < scenarios.scenarioParameters.ElementAt(ScenarioIndex).Item2; simulation++) { // Set up the suffix for the output files OutputFilesSuffix = "_"; // Add the scenario label to the suffix for the output files OutputFilesSuffix += ScenarioNames[ScenarioIndex] + "_"; // Add the simulation index number to the suffix OutputFilesSuffix += simulation.ToString(); // Run the current simulation RunSimulation(scenarios, ScenarioIndex, InitialiseMadingley, OutputFilesSuffix, simulation); } } } } }
/// <summary> /// Runs a single simulation of the Madingley model /// </summary> /// <param name="scenarios">Parameter information and simulation number for all scenarios to be run</param> /// <param name="scenarioIndex">The index of the scenario to be run in this simulation</param> /// <param name="initialiseMadingley">Model initialization information for all simulations</param> /// <param name="outputFileSuffix">Suffix to be applied to the names of files written out by this simulation</param> /// <param name="simulation">The index of the simulation being run</param> public void RunSimulation(ScenarioParameterInitialisation scenarios, int scenarioIndex, MadingleyModelInitialisation initialiseMadingley, string outputFileSuffix, int simulation) { // Declare an instance of the class that runs a Madingley model simulation MadingleyModel MadingleyEcosystemModel; // Declare and start a timer StopWatch s = new StopWatch(); s.Start(); StopWatch t = new StopWatch(); t.Start(); // Initialize the instance of MadingleyModel MadingleyEcosystemModel = new MadingleyModel(initialiseMadingley, scenarios, scenarioIndex, outputFileSuffix, initialiseMadingley.GlobalModelTimeStepUnit,simulation); t.Stop(); // Run the simulation MadingleyEcosystemModel.RunMadingley(initialiseMadingley); // Stop the timer and write out the time taken to run this simulation s.Stop(); Console.WriteLine("Model run finished"); Console.WriteLine("Total elapsed time was {0} seconds", s.GetElapsedTimeSecs()); Console.WriteLine("Model setup time was {0} seconds", t.GetElapsedTimeSecs()); Console.WriteLine("Model run time was {0} seconds", s.GetElapsedTimeSecs() - t.GetElapsedTimeSecs()); }
/// <summary> /// Generates the console outputs for the current time step /// </summary> /// <param name="currentTimeStep">The current model time step</param> /// <param name="currentMonth">The current month in the model run</param> /// <param name="timeStepTimer">The timer for the current time step</param> private void TimeStepConsoleOutputs(uint currentTimeStep, uint currentMonth, StopWatch timeStepTimer) { // Console outputs for all levels of detail Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Completed time step " + (currentTimeStep + 1) + "(Month: " + (currentMonth + 1) + ")\n"); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("Elapsed time in seconds this time step: " + timeStepTimer.GetElapsedTimeSecs() + "\n"); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Living biomass = " + String.Format("{0:E}", TotalLivingBiomass / 1000) + " kg"); Console.WriteLine("Total abundance = " + String.Format("{0:E}", TotalAbundance) + " inds / km^2"); // Console outputs for medium or high detail levels if ((ModelOutputDetail == OutputDetailLevel.Medium) || (ModelOutputDetail == OutputDetailLevel.High)) { Console.WriteLine("Total number of cohorts = " + TotalNumberOfCohorts); Console.WriteLine("Total number of stocks = " + TotalNumberOfStocks); Console.WriteLine("Number of cohorts extinct = " + NumberOfCohortsExtinct); Console.WriteLine("Number of cohorts produced = " + NumberOfCohortsProduced); Console.WriteLine("Number of cohorts combined = " + NumberOfCohortsCombined); // Console ouputs for high detail level if (ModelOutputDetail == OutputDetailLevel.High) { Console.WriteLine("Total biomass (all) = " + String.Format("{0:E}", TotalBiomass / 1000) + " kg"); Console.WriteLine("Respiratory pool biomass = " + String.Format("{0:E}", RespiratoryPoolOut / 1000) + " kg"); Console.WriteLine("Organic pool biomass = " + String.Format("{0:E}", OrganicPoolOut / 1000) + " kg"); } } // Blank line at end of console time step outputs Console.WriteLine(" "); Console.ForegroundColor = ConsoleColor.White; }
/// <summary> /// Generates the outputs for the current time step /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="currentTimeStep">The current model time step</param> /// <param name="currentMonth">The current month in the model run</param> /// <param name="timeStepTimer">The timer for the current time step</param> /// <param name="cohortFunctionalGroupDefinitions">The functional group definitions of cohorts in the model</param> /// <param name="stockFunctionalGroupDefinitions">The functional group definitions of stocks in the model</param> /// <param name="cellIndices">List of indices of active cells in the model grid</param> /// <param name="globalDiagnosticVariables">The global diagnostic variables for the model run</param> /// <param name="initialisation">The Madingley Model initialisation</param> public void TimeStepOutputs(ModelGrid ecosystemModelGrid, uint currentTimeStep, uint currentMonth, StopWatch timeStepTimer, FunctionalGroupDefinitions cohortFunctionalGroupDefinitions, FunctionalGroupDefinitions stockFunctionalGroupDefinitions, List<uint[]> cellIndices, SortedList<string, double> globalDiagnosticVariables, MadingleyModelInitialisation initialisation) { // Calculate the output variables for this time step CalculateOutputs(cohortFunctionalGroupDefinitions, stockFunctionalGroupDefinitions, ecosystemModelGrid, cellIndices, globalDiagnosticVariables, initialisation); // Generate the time step console outputs TimeStepConsoleOutputs(currentTimeStep, currentMonth, timeStepTimer); // Generate the time step file outputs TimeStepFileOutputs(ecosystemModelGrid, currentTimeStep); }