/// <summary> /// Run dispersal /// </summary> public void RunCrossGridCellEcologicalProcess(uint[] cellIndex, ModelGrid gridForDispersal, bool dispersalOnly, FunctionalGroupDefinitions madingleyCohortDefinitions, FunctionalGroupDefinitions madingleyStockDefinitions, uint currentMonth) { // Create a temporary handler for grid cell cohorts GridCellCohortHandler WorkingGridCellCohorts; // Get the lat and lon indices uint ii = cellIndex[0]; uint jj = cellIndex[1]; // A boolean to check that the environmental layer exists bool varExists; // Check to see if the cell is marine double CellRealm = gridForDispersal.GetEnviroLayer("Realm", 0, ii, jj, out varExists); // Go through all of the cohorts in turn and see if they disperse WorkingGridCellCohorts = gridForDispersal.GetGridCellCohorts(ii, jj); // Loop through cohorts, and perform dispersal according to cohort type and status for (int kk = 0; kk < WorkingGridCellCohorts.Count; kk++) { // Work through the list of cohorts for (int ll = 0; ll < WorkingGridCellCohorts[kk].Count; ll++) { // Check to see if the cell is marine and the cohort type is planktonic if (CellRealm == 2.0 && ((madingleyCohortDefinitions.GetTraitNames("Mobility", WorkingGridCellCohorts[kk][ll].FunctionalGroupIndex) == "planktonic") || (WorkingGridCellCohorts[kk][ll].IndividualBodyMass <= PlanktonThreshold))) { // Run advective dispersal Implementations["basic advective dispersal"].RunDispersal(cellIndex, gridForDispersal, WorkingGridCellCohorts[kk][ll], kk, ll, currentMonth); } // Otherwise, if mature do responsive dispersal else if (WorkingGridCellCohorts[kk][ll].MaturityTimeStep < uint.MaxValue) { // Run diffusive dispersal Implementations["basic responsive dispersal"].RunDispersal(cellIndex, gridForDispersal, WorkingGridCellCohorts[kk][ll], kk, ll, currentMonth); } // If the cohort is immature, run diffusive dispersal else { Implementations["basic diffusive dispersal"].RunDispersal(cellIndex, gridForDispersal, WorkingGridCellCohorts[kk][ll], kk, ll, currentMonth); } } } }
/// <summary> /// Calculate outputs associated with low-level outputs /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of active cells in the model grid</param> /// <param name="cellIndex">The position of the current cell in the list of active cells</param> /// <param name="globalDiagnosticVariables">The global diagnostic variables for this model run</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="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> private void CalculateLowLevelOutputs(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellIndex, SortedList<string,double> globalDiagnosticVariables, FunctionalGroupDefinitions cohortFunctionalGroupDefinitions, FunctionalGroupDefinitions stockFunctionalGroupDefinitions, MadingleyModelInitialisation initialisation, uint month, Boolean MarineCell) { // Reset the total living biomass TotalLivingBiomass = 0.0; string[] Keys; if (MarineCell) { // Get the list of cohort trait combinations to consider Keys = CohortTraitIndicesMarine.Keys.ToArray(); // Get biomass, abundance and densities for each of the trait combinations. Note that the GetStateVariableDensity function deals with the assessment of whether cohorts contain individuals // of low enough mass to be considered zooplankton in the marine realm foreach (string TraitValue in Keys) { // Biomass density TotalBiomassDensitiesOut[TraitValue] = ecosystemModelGrid.GetStateVariableDensity("Biomass", TraitValue, CohortTraitIndicesMarine[TraitValue], cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation) / 1000.0; // Density TotalDensitiesOut[TraitValue] = ecosystemModelGrid.GetStateVariableDensity("Abundance", TraitValue, CohortTraitIndicesMarine[TraitValue], cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation); } } else { // Get the list of cohort trait combinations to consider Keys = CohortTraitIndices.Keys.ToArray(); // Get biomass, abundance and densities for each of the trait combinations foreach (string TraitValue in Keys) { // Biomass density TotalBiomassDensitiesOut[TraitValue] = ecosystemModelGrid.GetStateVariableDensity("Biomass", TraitValue, CohortTraitIndices[TraitValue], cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation) / 1000.0; // Density TotalDensitiesOut[TraitValue] = ecosystemModelGrid.GetStateVariableDensity("Abundance", TraitValue, CohortTraitIndices[TraitValue], cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation); } } // Add the total biomass of all cohorts to the total living biomass variable TotalLivingBiomass += ecosystemModelGrid.GetStateVariable("Biomass", "NA", cohortFunctionalGroupDefinitions.AllFunctionalGroupsIndex, cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation); TotalLivingBiomassDensity = ecosystemModelGrid.GetStateVariableDensity("Biomass", "NA", cohortFunctionalGroupDefinitions.AllFunctionalGroupsIndex, cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation) / 1000.0; TotalHeterotrophAbundanceDensity = ecosystemModelGrid.GetStateVariableDensity("Abundance", "NA", cohortFunctionalGroupDefinitions.AllFunctionalGroupsIndex, cellIndices[cellIndex][0], cellIndices[cellIndex][1], "cohort", initialisation); TotalHeterotrophBiomassDensity = TotalLivingBiomassDensity; if (MarineCell) { // Get the list of stock trait combinations to consider Keys = StockTraitIndicesMarine.Keys.ToArray(); // Get biomass and biomass density for each of the trait combinations foreach (string TraitValue in Keys) { // Density TotalBiomassDensitiesOut[TraitValue] = ecosystemModelGrid.GetStateVariableDensity("Biomass", TraitValue, StockTraitIndicesMarine[TraitValue], cellIndices[cellIndex][0], cellIndices[cellIndex][1], "stock", initialisation) / 1000.0; } } else { // Get the list of stock trait combinations to consider Keys = StockTraitIndices.Keys.ToArray(); // Get biomass and biomass density for each of the trait combinations foreach (string TraitValue in Keys) { // Density TotalBiomassDensitiesOut[TraitValue] = ecosystemModelGrid.GetStateVariableDensity("Biomass", TraitValue, StockTraitIndices[TraitValue], cellIndices[cellIndex][0], cellIndices[cellIndex][1], "stock", initialisation) / 1000.0; } } // Add the total biomass of all stocks to the total living biomass variable TotalLivingBiomass += ecosystemModelGrid.GetStateVariable("Biomass", "NA", stockFunctionalGroupDefinitions.AllFunctionalGroupsIndex, cellIndices[cellIndex][0], cellIndices[cellIndex][1], "stock", initialisation); TotalLivingBiomassDensity += ecosystemModelGrid.GetStateVariableDensity("Biomass", "NA", stockFunctionalGroupDefinitions.AllFunctionalGroupsIndex, cellIndices[cellIndex][0], cellIndices[cellIndex][1], "stock", initialisation) / 1000.0; if (TrackMarineSpecifics && MarineCell) { bool varExists; TotalIncomingNPP = ecosystemModelGrid.GetEnviroLayer("NPP", month, cellIndices[cellIndex][0], cellIndices[cellIndex][1], out varExists); } }
/// <summary> /// Run advective dispersal /// </summary> /// <param name="cellIndex">The longitudinal and latitudinal indices of the focal grid cell</param> /// <param name="gridForDispersal">The model grid to run dispersal for</param> /// <param name="cohortToDisperse">The cohort to run dispersal for</param> /// <param name="actingCohortFunctionalGroup">The functional group index of the acting cohort</param> /// <param name="actingCohortNumber">The position of the acting cohort wihtin the functional group in the array of grid cell cohorts</param> /// <param name="currentMonth">The current model month</param> public void RunDispersal(uint[] cellIndex, ModelGrid gridForDispersal, Cohort cohortToDisperse, int actingCohortFunctionalGroup, int actingCohortNumber, uint currentMonth) { // An array to hold the dispersal information double[] DispersalArray = new double[6]; // A double to indicate whether or not the cohort has dispersed, and if it has dispersed, where to double CohortDispersed = 0; // Temporary variables to keep track of directions in which cohorts enter/exit cells during the multiple advection steps per time step uint ExitDirection = new uint(); uint EntryDirection = new uint(); ExitDirection = 9999; // An array to hold the present cohort location for the intermediate steps that occur before the final dispersal this time step uint[] PresentLocation = { cellIndex[0], cellIndex[1] }; // Get the u speed and the v speed from the cell data double uAdvectiveSpeed = gridForDispersal.GetEnviroLayer("uVel", currentMonth, PresentLocation[0], PresentLocation[1], out varExists); Debug.Assert(uAdvectiveSpeed != -9999); double vAdvectiveSpeed = gridForDispersal.GetEnviroLayer("vVel", currentMonth, PresentLocation[0], PresentLocation[1], out varExists); Debug.Assert(vAdvectiveSpeed != -9999); uAdvectiveSpeed = RescaleDispersalSpeed(uAdvectiveSpeed); vAdvectiveSpeed = RescaleDispersalSpeed(vAdvectiveSpeed); // Loop through a number of times proportional to the rescaled dispersal for (int mm = 0; mm < _AdvectionTimeStepsPerModelTimeStep; mm++) { // Get the probability of dispersal DispersalArray = CalculateDispersalProbability(gridForDispersal, PresentLocation[0], PresentLocation[1], currentMonth, uAdvectiveSpeed, vAdvectiveSpeed); // Check to see if it does disperse CohortDispersed = CheckForDispersal(DispersalArray[0]); // If it does, check to see where it will end up if (CohortDispersed > 0) { // Check to see if the direction is actually dispersable uint[] DestinationCell = CellToDisperseTo(gridForDispersal, PresentLocation[0], PresentLocation[1], DispersalArray, CohortDispersed, DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // If it is, go ahead and update the cohort location if (DestinationCell[0] < 999999) { PresentLocation = DestinationCell; // Get the u speed and the v speed from the cell data uAdvectiveSpeed = gridForDispersal.GetEnviroLayer("uVel", currentMonth, PresentLocation[0], PresentLocation[1], out varExists); vAdvectiveSpeed = gridForDispersal.GetEnviroLayer("vVel", currentMonth, PresentLocation[0], PresentLocation[1], out varExists); uAdvectiveSpeed = RescaleDispersalSpeed(uAdvectiveSpeed); vAdvectiveSpeed = RescaleDispersalSpeed(vAdvectiveSpeed); } } } // Update the dipersal deltas for this cohort, if necessary if ((cellIndex[0] != PresentLocation[0]) || (cellIndex[1] != PresentLocation[1])) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[cellIndex[0], cellIndex[1]].Add((uint)actingCohortFunctionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[cellIndex[0], cellIndex[1]].Add((uint)actingCohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[cellIndex[0], cellIndex[1]].Add(PresentLocation); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[cellIndex[0], cellIndex[1]].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[cellIndex[0], cellIndex[1]].Add(EntryDirection); } }
/// <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; }