/// <summary> /// Calculate the distance between two cohorts in multi-dimensional trait space (body mass, adult mass, juvenile mass) /// </summary> /// <param name="Cohort1">The first cohort to calculate distance to</param> /// <param name="Cohort2">The cohort to compare to</param> /// <returns>The relative distance in trait space</returns> public double CalculateDistance(Cohort Cohort1, Cohort Cohort2) { double AdultMassDistance = Math.Abs(Cohort1.AdultMass - Cohort2.AdultMass)/Cohort1.AdultMass; double JuvenileMassDistance = Math.Abs(Cohort1.JuvenileMass - Cohort2.JuvenileMass)/Cohort1.JuvenileMass; double CurrentMassDistance = Math.Abs(Cohort1.IndividualBodyMass - Cohort2.IndividualBodyMass)/Cohort1.IndividualBodyMass; return Math.Sqrt((AdultMassDistance * AdultMassDistance) + (JuvenileMassDistance * JuvenileMassDistance) + (CurrentMassDistance * CurrentMassDistance)); }
/// <summary> /// Run responsive dispersal /// </summary> /// <param name="cellIndices">The longitudinal and latitudinal indices of the current grid cell</param> /// <param name="gridForDispersal">The model grid to run dispersal for</param> /// <param name="cohortToDisperse">The cohort for which to apply the dispersal process</param> /// <param name="actingCohortFunctionalGroup">The functional group index of the acting cohort</param> /// <param name="actingCohortNumber">The position of the acting cohort within the functional group in the array of grid cell cohorts</param> /// <param name="currentMonth">The current model month</param> public void RunDispersal(uint[] cellIndices, ModelGrid gridForDispersal, Cohort cohortToDisperse, int actingCohortFunctionalGroup, int actingCohortNumber, uint currentMonth) { // Starvation driven dispersal takes precedence over density driven dispersal (i.e. a cohort can't do both). Also, the delta // arrays only allow each cohort to perform one type of dispersal each time step bool CohortDispersed = false; // Check for starvation-driven dispersal CohortDispersed = CheckStarvationDispersal(gridForDispersal, cellIndices[0], cellIndices[1], cohortToDisperse, actingCohortFunctionalGroup, actingCohortNumber); if (!CohortDispersed) { // Check for density driven dispersal CheckDensityDrivenDispersal(gridForDispersal, cellIndices[0], cellIndices[1], cohortToDisperse, actingCohortFunctionalGroup, actingCohortNumber); } }
public static Madingley.Common.Cohort ConvertCohortData(Cohort cohort) { return new Madingley.Common.Cohort( cohort.FunctionalGroupIndex, (int)cohort.BirthTimeStep, (int)cohort.MaturityTimeStep, cohort.CohortID.Select(cs => (int)cs).ToArray(), cohort.JuvenileMass, cohort.AdultMass, cohort.IndividualBodyMass, cohort.IndividualReproductivePotentialMass, cohort.MaximumAchievedBodyMass, cohort.CohortAbundance, cohort.Merged, cohort.ProportionTimeActive, cohort.TrophicIndex, cohort.LogOptimalPreyBodySizeRatio); }
/// <summary> /// Run diffusive dispersal /// </summary> /// <param name="cellIndices">List of indices of active cells in the model grid</param> /// <param name="gridForDispersal">The model grid to run dispersal for</param> /// <param name="cohortToDisperse">The cohort for which to run the dispersal process for</param> /// <param name="actingCohortFunctionalGroup">The functional group index of the acting cohort</param> /// <param name="actingCohortNumber">The position of the cohort within the functional group in the array of grid cell cohorts</param> /// <param name="currentMonth">The current model month</param> public void RunDispersal(uint[] cellIndices, ModelGrid gridForDispersal, Cohort cohortToDisperse, int actingCohortFunctionalGroup, int actingCohortNumber, uint currentMonth) { // Calculate dispersal speed for the cohort double DispersalSpeed = CalculateDispersalSpeed(cohortToDisperse.IndividualBodyMass); // 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; // Get the probability of dispersal double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, cellIndices[0], cellIndices[1], DispersalSpeed); // 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, cellIndices[0], cellIndices[1], DispersalArray, CohortDispersed, DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[cellIndices[0], cellIndices[1]].Add((uint)actingCohortFunctionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[cellIndices[0], cellIndices[1]].Add((uint)actingCohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[cellIndices[0], cellIndices[1]].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[cellIndices[0], cellIndices[1]].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[cellIndices[0], cellIndices[1]].Add(EntryDirection); } } }
/// <summary> /// Generate new cohorts from reproductive potential mass /// </summary> /// <param name="gridCellCohorts">The cohorts in the current grid cell</param> /// <param name="gridCellStocks">The stocks in the current grid cell</param> /// <param name="actingCohort">The position of the acting cohort in the jagged array of grid cell cohorts</param> /// <param name="cellEnvironment">The environment of the current grid cell</param> /// <param name="deltas">The sorted list to track changes in biomass and abundance of the acting cohort in this grid cell</param> /// <param name="madingleyCohortDefinitions">The definitions of cohort functional groups in the model</param> /// <param name="madingleyStockDefinitions">The definitions of stock functional groups in the model</param> /// <param name="currentTimestep">The current model time step</param> /// <param name="tracker">An instance of ProcessTracker to hold diagnostics for reproduction</param> /// <param name="partial">Thread-locked variables</param> public void RunReproduction(GridCellCohortHandler gridCellCohorts, GridCellStockHandler gridCellStocks, int[] actingCohort, SortedList <string, double[]> cellEnvironment, Dictionary <string, Dictionary <string, double> > deltas, FunctionalGroupDefinitions madingleyCohortDefinitions, FunctionalGroupDefinitions madingleyStockDefinitions, uint currentTimestep, ProcessTracker tracker, ref ThreadLockedParallelVariables partial) { // Check that the abundance in the cohort to produce is greater than or equal to zero Debug.Assert(_OffspringCohortAbundance >= 0.0, "Offspring abundance < 0"); // Get the adult and juvenile masses of the cohort to produce double[] OffspringProperties = GetOffspringCohortProperties(gridCellCohorts, actingCohort, madingleyCohortDefinitions); // Update cohort abundance in case juvenile mass has been altered _OffspringCohortAbundance = (_OffspringCohortAbundance * gridCellCohorts[actingCohort].JuvenileMass) / OffspringProperties[0]; //Create the offspring cohort Cohort OffspringCohort = new Cohort((byte)actingCohort[0], OffspringProperties[0], OffspringProperties[1], OffspringProperties[0], _OffspringCohortAbundance, (ushort)currentTimestep, ref partial.NextCohortIDThreadLocked); // Add the offspring cohort to the grid cell cohorts array gridCellCohorts[actingCohort[0]].Add(OffspringCohort); // If the cohort has never been merged with another cohort, then add it to the tracker for output as diagnostics if ((!gridCellCohorts[actingCohort].Merged) && tracker.TrackProcesses) { tracker.RecordNewCohort((uint)cellEnvironment["LatIndex"][0], (uint)cellEnvironment["LonIndex"][0], currentTimestep, _OffspringCohortAbundance, gridCellCohorts[actingCohort].AdultMass, gridCellCohorts[actingCohort].FunctionalGroupIndex); } // Subtract all of the reproductive potential mass of the parent cohort, which has been used to generate the new // cohort, from the delta reproductive potential mass deltas["reproductivebiomass"]["reproduction"] -= (gridCellCohorts[actingCohort].IndividualReproductivePotentialMass); }
/// <summary> /// Generate new cohorts from reproductive potential mass /// </summary> /// <param name="gridCellCohorts">The cohorts in the current grid cell</param> /// <param name="gridCellStocks">The stocks in the current grid cell</param> /// <param name="actingCohort">The position of the acting cohort in the jagged array of grid cell cohorts</param> /// <param name="cellEnvironment">The environment of the current grid cell</param> /// <param name="deltas">The sorted list to track changes in biomass and abundance of the acting cohort in this grid cell</param> /// <param name="madingleyCohortDefinitions">The definitions of cohort functional groups in the model</param> /// <param name="madingleyStockDefinitions">The definitions of stock functional groups in the model</param> /// <param name="currentTimestep">The current model time step</param> /// <param name="tracker">An instance of ProcessTracker to hold diagnostics for reproduction</param> /// <param name="partial">Thread-locked variables</param> public void RunReproduction(GridCellCohortHandler gridCellCohorts, GridCellStockHandler gridCellStocks, int[] actingCohort, SortedList<string, double[]> cellEnvironment, Dictionary<string, Dictionary<string, double>> deltas, FunctionalGroupDefinitions madingleyCohortDefinitions, FunctionalGroupDefinitions madingleyStockDefinitions, uint currentTimestep, ProcessTracker tracker, ref ThreadLockedParallelVariables partial) { // Check that the abundance in the cohort to produce is greater than or equal to zero Debug.Assert(_OffspringCohortAbundance >= 0.0, "Offspring abundance < 0"); // Get the adult and juvenile masses of the cohort to produce double[] OffspringProperties = GetOffspringCohortProperties(gridCellCohorts, actingCohort, madingleyCohortDefinitions); // Update cohort abundance in case juvenile mass has been altered _OffspringCohortAbundance = (_OffspringCohortAbundance * gridCellCohorts[actingCohort].JuvenileMass) / OffspringProperties[0]; //Create the offspring cohort Cohort OffspringCohort = new Cohort((byte)actingCohort[0], OffspringProperties[0], OffspringProperties[1], OffspringProperties[0], _OffspringCohortAbundance, (ushort)currentTimestep, ref partial.NextCohortIDThreadLocked); // Add the offspring cohort to the grid cell cohorts array gridCellCohorts[actingCohort[0]].Add(OffspringCohort); // If the cohort has never been merged with another cohort, then add it to the tracker for output as diagnostics if ((!gridCellCohorts[actingCohort].Merged) && tracker.TrackProcesses) tracker.RecordNewCohort((uint)cellEnvironment["LatIndex"][0], (uint)cellEnvironment["LonIndex"][0], currentTimestep, _OffspringCohortAbundance, gridCellCohorts[actingCohort].AdultMass, gridCellCohorts[actingCohort].FunctionalGroupIndex); // Subtract all of the reproductive potential mass of the parent cohort, which has been used to generate the new // cohort, from the delta reproductive potential mass deltas["reproductivebiomass"]["reproduction"] -= (gridCellCohorts[actingCohort].IndividualReproductivePotentialMass); }
public static void ToJson(Newtonsoft.Json.JsonWriter jsonWriter, Cohort cohort) { Action <Newtonsoft.Json.JsonWriter, uint> WriteUInt = (jsonWriter2, value) => { Madingley.Serialization.Common.Writer.WriteInt(jsonWriter2, (int)value); }; jsonWriter.WriteStartObject(); Madingley.Serialization.Common.Writer.PropertyInt(jsonWriter, "_BirthTimeStep", (int)cohort._BirthTimeStep); Madingley.Serialization.Common.Writer.PropertyInt(jsonWriter, "_MaturityTimeStep", (int)cohort._MaturityTimeStep); Madingley.Serialization.Common.Writer.PropertyInlineArray(jsonWriter, "_CohortID", cohort._CohortID, WriteUInt); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_JuvenileMass", cohort._JuvenileMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_AdultMass", cohort._AdultMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_IndividualBodyMass", cohort._IndividualBodyMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_IndividualReproductivePotentialMass", cohort._IndividualReproductivePotentialMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_MaximumAchievedBodyMass", cohort._MaximumAchievedBodyMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_CohortAbundance", cohort._CohortAbundance); Madingley.Serialization.Common.Writer.PropertyInt(jsonWriter, "_FunctionalGroupIndex", cohort._FunctionalGroupIndex); Madingley.Serialization.Common.Writer.PropertyBoolean(jsonWriter, "_Merged", cohort._Merged); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_ProportionTimeActive", cohort._ProportionTimeActive); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_TrophicIndex", cohort._TrophicIndex); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_LogOptimalPreyBodySizeRatio", cohort._LogOptimalPreyBodySizeRatio); jsonWriter.WriteEndObject(); }
public InputModelState(string outputPath, string filename, ModelGrid ecosystemModelGrid, List<uint[]> cellList) { //Set the input state flag to be true _InputState = true; // Construct the string required to access the file using Scientific Dataset string _ReadFileString = "msds:nc?file=input/ModelStates/" + filename +".nc&openMode=readOnly"; // Open the data file using Scientific Dataset DataSet StateDataSet = DataSet.Open(_ReadFileString); float[] Latitude = StateDataSet.GetData<float[]>("Latitude"); float[] Longitude = StateDataSet.GetData<float[]>("Longitude"); float[] CohortFunctionalGroup = StateDataSet.GetData<float[]>("Cohort Functional Group"); float[] Cohort = StateDataSet.GetData<float[]>("Cohort"); float[] StockFunctionalGroup = StateDataSet.GetData<float[]>("Stock Functional Group"); float[] Stock = StateDataSet.GetData<float[]>("Stock"); // Check that the longitudes and latitudes in the input state match the cell environment for (int la = 0; la < Latitude.Length; la++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment((uint)la, 0)["Latitude"][0] == Latitude[la], "Error: input-state grid doesn't match current model grid"); } for (int lo = 0; lo < Longitude.Length; lo++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment(0, (uint)lo)["Longitude"][0] == Longitude[lo], "Error: input-state grid doesn't match current model grid"); } List<double[,,]> CohortJuvenileMass = new List<double[,,]>(); List<double[,,]> CohortAdultMass = new List<double[,,]>(); List<double[,,]> CohortIndividualBodyMass = new List<double[,,]>(); List<double[,,]> CohortCohortAbundance = new List<double[,,]>(); List<double[,,]> CohortLogOptimalPreyBodySizeRatio = new List<double[,,]>(); List<double[,,]> CohortBirthTimeStep = new List<double[,,]>(); List<double[,,]> CohortProportionTimeActive = new List<double[,,]>(); List<double[,,]> CohortTrophicIndex = new List<double[,,]>(); double[,,,] tempData = new double[Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]; tempData = StateDataSet.GetData<double[,,,]>("CohortJuvenileMass"); for (int la = 0; la < Latitude.Length; la++) { CohortJuvenileMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortJuvenileMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortAdultMass"); for (int la = 0; la < Latitude.Length; la++) { CohortAdultMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortAdultMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { CohortIndividualBodyMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortCohortAbundance"); for (int la = 0; la < Latitude.Length; la++) { CohortCohortAbundance.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortCohortAbundance[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortLogOptimalPreyBodySizeRatio"); for (int la = 0; la < Latitude.Length; la++) { CohortLogOptimalPreyBodySizeRatio.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortLogOptimalPreyBodySizeRatio[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortBirthTimeStep"); for (int la = 0; la < Latitude.Length; la++) { CohortBirthTimeStep.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortBirthTimeStep[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortProportionTimeActive"); for (int la = 0; la < Latitude.Length; la++) { CohortProportionTimeActive.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortProportionTimeActive[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData<double[,,,]>("CohortTrophicIndex"); for (int la = 0; la < Latitude.Length; la++) { CohortTrophicIndex.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortTrophicIndex[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } _GridCellCohorts = new GridCellCohortHandler[Latitude.Length, Longitude.Length]; long temp = 0; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]] = new GridCellCohortHandler(CohortFunctionalGroup.Length); for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg] = new List<Cohort>(); for (int c = 0; c < Cohort.Length; c++) { if (CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1],fg,c] > 0.0) { Cohort TempCohort = new Cohort( (byte)fg, CohortJuvenileMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortAdultMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1], fg, c], Math.Exp(CohortLogOptimalPreyBodySizeRatio[(int)cellList[cell][0]][cellList[cell][1], fg, c]), Convert.ToUInt16(CohortBirthTimeStep[(int)cellList[cell][0]][cellList[cell][1], fg, c]), CohortProportionTimeActive[(int)cellList[cell][0]][cellList[cell][1], fg, c], ref temp, CohortTrophicIndex[(int)cellList[cell][0]][cellList[cell][1], fg, c], false); _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg].Add(TempCohort); } } } } CohortJuvenileMass.RemoveRange(0, CohortJuvenileMass.Count); CohortAdultMass.RemoveRange(0, CohortAdultMass.Count); CohortIndividualBodyMass.RemoveRange(0, CohortIndividualBodyMass.Count); CohortCohortAbundance.RemoveRange(0, CohortCohortAbundance.Count); CohortLogOptimalPreyBodySizeRatio.RemoveRange(0, CohortLogOptimalPreyBodySizeRatio.Count); CohortBirthTimeStep.RemoveRange(0, CohortBirthTimeStep.Count); CohortProportionTimeActive.RemoveRange(0, CohortProportionTimeActive.Count); CohortTrophicIndex.RemoveRange(0, CohortTrophicIndex.Count); List<double[,,]> StockIndividualBodyMass = new List<double[,,]>(); List<double[,,]> StockTotalBiomass = new List<double[,,]>(); double[,,,] tempData2 = new double[Latitude.Length, Longitude.Length, StockFunctionalGroup.Length,Stock.Length]; tempData2 = StateDataSet.GetData<double[,,,]>("StockIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { StockIndividualBodyMass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } tempData2 = StateDataSet.GetData<double[,,,]>("StockTotalBiomass"); for (int la = 0; la < Latitude.Length; la++) { StockTotalBiomass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockTotalBiomass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } _GridCellStocks = new GridCellStockHandler[Latitude.Length, Longitude.Length]; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]] = new GridCellStockHandler(StockFunctionalGroup.Length); for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg] = new List<Stock>(); for (int c = 0; c < Stock.Length; c++) { if (StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c] > 0.0) { Stock TempStock = new Stock( (byte)fg, StockIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c]); _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg].Add(TempStock); } } } } }
public Cohort(Cohort c) { _FunctionalGroupIndex = c._FunctionalGroupIndex; _JuvenileMass = c._JuvenileMass; _AdultMass = c._AdultMass; _IndividualBodyMass = c._IndividualBodyMass; _CohortAbundance = c._CohortAbundance; _BirthTimeStep = c._BirthTimeStep; _MaturityTimeStep = c._MaturityTimeStep; _LogOptimalPreyBodySizeRatio = c._LogOptimalPreyBodySizeRatio; _MaximumAchievedBodyMass = c._MaximumAchievedBodyMass; _Merged = c._Merged; _TrophicIndex = c._TrophicIndex; _ProportionTimeActive = c._ProportionTimeActive; _CohortID = c.CohortID; }
private bool CheckStarvationDispersal(ModelGrid gridForDispersal, uint latIndex, uint lonIndex, Cohort cohortToDisperse, int functionalGroup, int cohortNumber) { // A boolean to check whether a cohort has dispersed bool CohortHasDispersed = false; // Check for starvation driven dispersal // What is the present body mass of the cohort? // Note that at present we are just tracking starvation for adults double IndividualBodyMass = cohortToDisperse.IndividualBodyMass; double AdultMass = cohortToDisperse.AdultMass; // 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; // Assume a linear relationship between probability of dispersal and body mass loss, up to _StarvationDispersalBodyMassThreshold // at which point the cohort will try to disperse every time step if (IndividualBodyMass < AdultMass) { double ProportionalPresentMass = IndividualBodyMass / AdultMass; // If the body mass loss is greater than the starvation dispersal body mass threshold, then the cohort tries to disperse if (ProportionalPresentMass < _StarvationDispersalBodyMassThreshold) { // Cohort tries to disperse double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, latIndex, lonIndex, CalculateDispersalSpeed(AdultMass)); double CohortDispersed = CheckForDispersal(DispersalArray[0]); if (CohortDispersed > 0) { uint[] DestinationCell = CellToDisperseTo(gridForDispersal, latIndex, lonIndex, DispersalArray, DispersalArray[0], DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // Update the delta array of cells to disperse to, if the cohort moves if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[latIndex, lonIndex].Add((uint)functionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[latIndex, lonIndex].Add((uint)cohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[latIndex, lonIndex].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[latIndex, lonIndex].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[latIndex, lonIndex].Add(EntryDirection); } } // Note that regardless of whether or not it succeeds, if a cohort tries to disperse, it is counted as having dispersed for // the purposes of not then allowing it to disperse based on its density. CohortHasDispersed = true; } // Otherwise, the cohort has a chance of trying to disperse proportional to its mass loss else { // Cohort tries to disperse with a particular probability // Draw a random number if (((1.0 - ProportionalPresentMass) / (1.0 - _StarvationDispersalBodyMassThreshold)) > RandomNumberGenerator.GetUniform()) { // Cohort tries to disperse double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, latIndex, lonIndex, CalculateDispersalSpeed(AdultMass)); double CohortDispersed = CheckForDispersal(DispersalArray[0]); if (CohortDispersed > 0) { uint[] DestinationCell = CellToDisperseTo(gridForDispersal, latIndex, lonIndex, DispersalArray, DispersalArray[0], DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // Update the delta array of cells to disperse to, if the cohort moves if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[latIndex, lonIndex].Add((uint)functionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[latIndex, lonIndex].Add((uint)cohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[latIndex, lonIndex].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[latIndex, lonIndex].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[latIndex, lonIndex].Add(EntryDirection); } } CohortHasDispersed = true; } } } return CohortHasDispersed; }
/// <summary> /// Generate new cohorts from reproductive potential mass /// </summary> /// <param name="gridCellCohorts">The cohorts in the current grid cell</param> /// <param name="gridCellStocks">The stocks in the current grid cell</param> /// <param name="actingCohort">The position of the acting cohort in the jagged array of grid cell cohorts</param> /// <param name="cellEnvironment">The environment of the current grid cell</param> /// <param name="deltas">The sorted list to track changes in biomass and abundance of the acting cohort in this grid cell</param> /// <param name="madingleyCohortDefinitions">The definitions of cohort functional groups in the model</param> /// <param name="madingleyStockDefinitions">The definitions of stock functional groups in the model</param> /// <param name="currentTimestep">The current model time step</param> /// <param name="tracker">An instance of ProcessTracker to hold diagnostics for reproduction</param> /// <param name="partial">Thread-locked variables</param> /// <param name="iteroparous">Whether the acting cohort is iteroparous, as opposed to semelparous</param> /// <param name="currentMonth">The current model month</param> public void RunReproductionEvents(GridCellCohortHandler gridCellCohorts, GridCellStockHandler gridCellStocks, int[] actingCohort, SortedList <string, double[]> cellEnvironment, Dictionary <string, Dictionary <string, double> > deltas, FunctionalGroupDefinitions madingleyCohortDefinitions, FunctionalGroupDefinitions madingleyStockDefinitions, uint currentTimestep, ProcessTracker tracker, ref ThreadLockedParallelVariables partial, bool iteroparous, uint currentMonth) { // Adult non-reproductive biomass lost by semelparous organisms double AdultMassLost; // Offspring cohort abundance double _OffspringCohortAbundance; // Mass ratio of body mass + reproductive mass to adult body mass double CurrentMassRatio; // Individual body mass including change this time step as a result of other ecological processes double BodyMassIncludingChangeThisTimeStep; // Offspring juvenile and adult body masses double[] OffspringJuvenileAndAdultBodyMasses = new double[2]; // Offspring cohort Cohort OffspringCohort; // Individual reproductive mass including change this time step as a result of other ecological processes double ReproductiveMassIncludingChangeThisTimeStep; // Calculate the biomass of an individual in this cohort including changes this time step from other ecological processes BodyMassIncludingChangeThisTimeStep = 0.0; foreach (var Biomass in deltas["biomass"]) { // Add the delta biomass to net biomass BodyMassIncludingChangeThisTimeStep += Biomass.Value; } BodyMassIncludingChangeThisTimeStep += gridCellCohorts[actingCohort].IndividualBodyMass; // Calculate the reproductive biomass of an individual in this cohort including changes this time step from other ecological processes ReproductiveMassIncludingChangeThisTimeStep = 0.0; foreach (var ReproBiomass in deltas["reproductivebiomass"]) { // Add the delta reproductive biomass to net biomass ReproductiveMassIncludingChangeThisTimeStep += ReproBiomass.Value; } ReproductiveMassIncludingChangeThisTimeStep += gridCellCohorts[actingCohort].IndividualReproductivePotentialMass; // Get the current ratio of total individual mass (including reproductive potential) to adult body mass CurrentMassRatio = (BodyMassIncludingChangeThisTimeStep + ReproductiveMassIncludingChangeThisTimeStep) / gridCellCohorts[actingCohort].AdultMass; // Must have enough mass to hit reproduction threshold criterion, and either (1) be in breeding season, or (2) be a marine cell (no breeding season in marine cells) if ((CurrentMassRatio > _MassRatioThreshold) && ((cellEnvironment["Breeding Season"][currentMonth] == 1.0) || ((cellEnvironment["Realm"][0] == 2.0)))) { // Iteroparous and semelparous organisms have different strategies if (iteroparous) { // Iteroparous organisms do not allocate any of their current non-reproductive biomass to reproduction AdultMassLost = 0.0; // Calculate the number of offspring that could be produced given the reproductive potential mass of individuals _OffspringCohortAbundance = gridCellCohorts[actingCohort].CohortAbundance * ReproductiveMassIncludingChangeThisTimeStep / gridCellCohorts[actingCohort].JuvenileMass; } else { // Semelparous organisms allocate a proportion of their current non-reproductive biomass (including the effects of other ecological processes) to reproduction AdultMassLost = _SemelparityAdultMassAllocation * BodyMassIncludingChangeThisTimeStep; // Calculate the number of offspring that could be produced given the reproductive potential mass of individuals _OffspringCohortAbundance = gridCellCohorts[actingCohort].CohortAbundance * (AdultMassLost + ReproductiveMassIncludingChangeThisTimeStep) / gridCellCohorts[actingCohort].JuvenileMass; } // Check that the abundance in the cohort to produce is greater than or equal to zero Debug.Assert(_OffspringCohortAbundance >= 0.0, "Offspring abundance < 0"); // Get the adult and juvenile masses of the offspring cohort OffspringJuvenileAndAdultBodyMasses = GetOffspringCohortProperties(gridCellCohorts, actingCohort, madingleyCohortDefinitions); // Update cohort abundance in case juvenile mass has been altered through 'evolution' _OffspringCohortAbundance = (_OffspringCohortAbundance * gridCellCohorts[actingCohort].JuvenileMass) / OffspringJuvenileAndAdultBodyMasses[0]; double TrophicIndex; switch (madingleyCohortDefinitions.GetTraitNames("nutrition source", actingCohort[0])) { case "herbivore": TrophicIndex = 2; break; case "omnivore": TrophicIndex = 2.5; break; case "carnivore": TrophicIndex = 3; break; default: Debug.Fail("Unexpected nutrition source trait value when assigning trophic index"); TrophicIndex = 0.0; break; } // Create the offspring cohort OffspringCohort = new Cohort((byte)actingCohort[0], OffspringJuvenileAndAdultBodyMasses[0], OffspringJuvenileAndAdultBodyMasses[1], OffspringJuvenileAndAdultBodyMasses[0], _OffspringCohortAbundance, Math.Exp(gridCellCohorts[actingCohort].LogOptimalPreyBodySizeRatio), (ushort)currentTimestep, gridCellCohorts[actingCohort].ProportionTimeActive, ref partial.NextCohortIDThreadLocked, TrophicIndex, tracker.TrackProcesses); // Add the offspring cohort to the grid cell cohorts array gridCellCohorts[actingCohort[0]].Add(OffspringCohort); // If track processes has been specified then add the new cohort to the process tracker if (tracker.TrackProcesses) { tracker.RecordNewCohort((uint)cellEnvironment["LatIndex"][0], (uint)cellEnvironment["LonIndex"][0], currentTimestep, _OffspringCohortAbundance, gridCellCohorts[actingCohort].AdultMass, gridCellCohorts[actingCohort].FunctionalGroupIndex, gridCellCohorts[actingCohort].CohortID, (uint)partial.NextCohortIDThreadLocked); } // Subtract all of the reproductive potential mass of the parent cohort, which has been used to generate the new // cohort, from the delta reproductive potential mass and delta adult body mass deltas["reproductivebiomass"]["reproduction"] -= ReproductiveMassIncludingChangeThisTimeStep; deltas["biomass"]["reproduction"] -= AdultMassLost; } else { // Organism is not large enough, or it is not the breeding season, so take no action } }
/// <summary> /// Generate new cohorts from reproductive potential mass /// </summary> /// <param name="gridCellCohorts">The cohorts in the current grid cell</param> /// <param name="gridCellStocks">The stocks in the current grid cell</param> /// <param name="actingCohort">The position of the acting cohort in the jagged array of grid cell cohorts</param> /// <param name="cellEnvironment">The environment of the current grid cell</param> /// <param name="deltas">The sorted list to track changes in biomass and abundance of the acting cohort in this grid cell</param> /// <param name="madingleyCohortDefinitions">The definitions of cohort functional groups in the model</param> /// <param name="madingleyStockDefinitions">The definitions of stock functional groups in the model</param> /// <param name="currentTimestep">The current model time step</param> /// <param name="tracker">An instance of ProcessTracker to hold diagnostics for reproduction</param> /// <param name="partial">Thread-locked variables</param> /// <param name="iteroparous">Whether the acting cohort is iteroparous, as opposed to semelparous</param> /// <param name="currentMonth">The current model month</param> public void RunReproductionEvents(GridCellCohortHandler gridCellCohorts, GridCellStockHandler gridCellStocks, int[] actingCohort, SortedList<string, double[]> cellEnvironment, Dictionary<string, Dictionary<string, double>> deltas, FunctionalGroupDefinitions madingleyCohortDefinitions, FunctionalGroupDefinitions madingleyStockDefinitions, uint currentTimestep, ProcessTracker tracker, ref ThreadLockedParallelVariables partial, bool iteroparous, uint currentMonth) { // Adult non-reproductive biomass lost by semelparous organisms double AdultMassLost; // Offspring cohort abundance double _OffspringCohortAbundance; // Mass ratio of body mass + reproductive mass to adult body mass double CurrentMassRatio; // Individual body mass including change this time step as a result of other ecological processes double BodyMassIncludingChangeThisTimeStep; // Offspring juvenile and adult body masses double[] OffspringJuvenileAndAdultBodyMasses = new double[2]; // Offspring cohort Cohort OffspringCohort; // Individual reproductive mass including change this time step as a result of other ecological processes double ReproductiveMassIncludingChangeThisTimeStep; // Calculate the biomass of an individual in this cohort including changes this time step from other ecological processes BodyMassIncludingChangeThisTimeStep = 0.0; foreach (var Biomass in deltas["biomass"]) { // Add the delta biomass to net biomass BodyMassIncludingChangeThisTimeStep += Biomass.Value; } BodyMassIncludingChangeThisTimeStep += gridCellCohorts[actingCohort].IndividualBodyMass; // Calculate the reproductive biomass of an individual in this cohort including changes this time step from other ecological processes ReproductiveMassIncludingChangeThisTimeStep = 0.0; foreach (var ReproBiomass in deltas["reproductivebiomass"]) { // Add the delta reproductive biomass to net biomass ReproductiveMassIncludingChangeThisTimeStep += ReproBiomass.Value; } ReproductiveMassIncludingChangeThisTimeStep += gridCellCohorts[actingCohort].IndividualReproductivePotentialMass; // Get the current ratio of total individual mass (including reproductive potential) to adult body mass CurrentMassRatio = (BodyMassIncludingChangeThisTimeStep + ReproductiveMassIncludingChangeThisTimeStep) / gridCellCohorts[actingCohort].AdultMass; // Must have enough mass to hit reproduction threshold criterion, and either (1) be in breeding season, or (2) be a marine cell (no breeding season in marine cells) if ((CurrentMassRatio > _MassRatioThreshold) && ((cellEnvironment["Breeding Season"][currentMonth] == 1.0) || ((cellEnvironment["Realm"][0] == 2.0)))) { // Iteroparous and semelparous organisms have different strategies if (iteroparous) { // Iteroparous organisms do not allocate any of their current non-reproductive biomass to reproduction AdultMassLost = 0.0; // Calculate the number of offspring that could be produced given the reproductive potential mass of individuals _OffspringCohortAbundance = gridCellCohorts[actingCohort].CohortAbundance * ReproductiveMassIncludingChangeThisTimeStep / gridCellCohorts[actingCohort].JuvenileMass; } else { // Semelparous organisms allocate a proportion of their current non-reproductive biomass (including the effects of other ecological processes) to reproduction AdultMassLost = _SemelparityAdultMassAllocation * BodyMassIncludingChangeThisTimeStep; // Calculate the number of offspring that could be produced given the reproductive potential mass of individuals _OffspringCohortAbundance = gridCellCohorts[actingCohort].CohortAbundance * (AdultMassLost + ReproductiveMassIncludingChangeThisTimeStep) / gridCellCohorts[actingCohort].JuvenileMass; } // Check that the abundance in the cohort to produce is greater than or equal to zero Debug.Assert(_OffspringCohortAbundance >= 0.0, "Offspring abundance < 0"); // Get the adult and juvenile masses of the offspring cohort OffspringJuvenileAndAdultBodyMasses = GetOffspringCohortProperties(gridCellCohorts, actingCohort, madingleyCohortDefinitions); // Update cohort abundance in case juvenile mass has been altered through 'evolution' _OffspringCohortAbundance = (_OffspringCohortAbundance * gridCellCohorts[actingCohort].JuvenileMass) / OffspringJuvenileAndAdultBodyMasses[0]; double TrophicIndex; switch (madingleyCohortDefinitions.GetTraitNames("nutrition source", actingCohort[0])) { case "herbivore": TrophicIndex = 2; break; case "omnivore": TrophicIndex = 2.5; break; case "carnivore": TrophicIndex = 3; break; default: Debug.Fail("Unexpected nutrition source trait value when assigning trophic index"); TrophicIndex = 0.0; break; } // Create the offspring cohort OffspringCohort = new Cohort((byte)actingCohort[0], OffspringJuvenileAndAdultBodyMasses[0], OffspringJuvenileAndAdultBodyMasses[1], OffspringJuvenileAndAdultBodyMasses[0], _OffspringCohortAbundance, Math.Exp(gridCellCohorts[actingCohort].LogOptimalPreyBodySizeRatio), (ushort)currentTimestep, gridCellCohorts[actingCohort].ProportionTimeActive, ref partial.NextCohortIDThreadLocked, TrophicIndex, tracker.TrackProcesses); // Add the offspring cohort to the grid cell cohorts array gridCellCohorts[actingCohort[0]].Add(OffspringCohort); // If track processes has been specified then add the new cohort to the process tracker if (tracker.TrackProcesses) tracker.RecordNewCohort((uint)cellEnvironment["LatIndex"][0], (uint)cellEnvironment["LonIndex"][0], currentTimestep, _OffspringCohortAbundance, gridCellCohorts[actingCohort].AdultMass, gridCellCohorts[actingCohort].FunctionalGroupIndex, gridCellCohorts[actingCohort].CohortID, (uint)partial.NextCohortIDThreadLocked); // Subtract all of the reproductive potential mass of the parent cohort, which has been used to generate the new // cohort, from the delta reproductive potential mass and delta adult body mass deltas["reproductivebiomass"]["reproduction"] -= ReproductiveMassIncludingChangeThisTimeStep; deltas["biomass"]["reproduction"] -= AdultMassLost; } else { // Organism is not large enough, or it is not the breeding season, so take no action } }
private void CheckDensityDrivenDispersal(ModelGrid gridForDispersal, uint latIndex, uint lonIndex, Cohort cohortToDisperse, int functionalGroup, int cohortNumber) { // Check the population density double NumberOfIndividuals = cohortToDisperse.CohortAbundance; // Get the cell area, in kilometres squared double CellArea = gridForDispersal.GetCellEnvironment(latIndex, lonIndex)["Cell Area"][0]; // If below the density threshold if ((NumberOfIndividuals / CellArea) < _DensityThresholdScaling / cohortToDisperse.AdultMass) { // 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; // Check to see if it disperses (based on the same movement scaling as used in diffusive movement) // Calculate dispersal speed for that cohort double DispersalSpeed = CalculateDispersalSpeed(cohortToDisperse.IndividualBodyMass); // Cohort tries to disperse double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, latIndex, lonIndex, CalculateDispersalSpeed(cohortToDisperse.AdultMass)); double CohortDispersed = CheckForDispersal(DispersalArray[0]); if (CohortDispersed > 0) { uint[] DestinationCell = CellToDisperseTo(gridForDispersal, latIndex, lonIndex, DispersalArray, DispersalArray[0], DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // Update the delta array of cells to disperse to, if the cohort moves if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[latIndex, lonIndex].Add((uint)functionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[latIndex, lonIndex].Add((uint)cohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[latIndex, lonIndex].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[latIndex, lonIndex].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[latIndex, lonIndex].Add(EntryDirection); } } } }
private bool CheckStarvationDispersal(ModelGrid gridForDispersal, uint latIndex, uint lonIndex, Cohort cohortToDisperse, int functionalGroup, int cohortNumber) { // A boolean to check whether a cohort has dispersed bool CohortHasDispersed = false; // Check for starvation driven dispersal // What is the present body mass of the cohort? // Note that at present we are just tracking starvation for adults double IndividualBodyMass = cohortToDisperse.IndividualBodyMass; double AdultMass = cohortToDisperse.AdultMass; // 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; // Assume a linear relationship between probability of dispersal and body mass loss, up to _StarvationDispersalBodyMassThreshold // at which point the cohort will try to disperse every time step if (IndividualBodyMass < AdultMass) { double ProportionalPresentMass = IndividualBodyMass / AdultMass; // If the body mass loss is greater than the starvation dispersal body mass threshold, then the cohort tries to disperse if (ProportionalPresentMass < _StarvationDispersalBodyMassThreshold) { // Cohort tries to disperse double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, latIndex, lonIndex, CalculateDispersalSpeed(AdultMass)); double CohortDispersed = CheckForDispersal(DispersalArray[0]); if (CohortDispersed > 0) { uint[] DestinationCell = CellToDisperseTo(gridForDispersal, latIndex, lonIndex, DispersalArray, DispersalArray[0], DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // Update the delta array of cells to disperse to, if the cohort moves if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[latIndex, lonIndex].Add((uint)functionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[latIndex, lonIndex].Add((uint)cohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[latIndex, lonIndex].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[latIndex, lonIndex].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[latIndex, lonIndex].Add(EntryDirection); } } // Note that regardless of whether or not it succeeds, if a cohort tries to disperse, it is counted as having dispersed for // the purposes of not then allowing it to disperse based on its density. CohortHasDispersed = true; } // Otherwise, the cohort has a chance of trying to disperse proportional to its mass loss else { // Cohort tries to disperse with a particular probability // Draw a random number if (((1.0 - ProportionalPresentMass) / (1.0 - _StarvationDispersalBodyMassThreshold)) > RandomNumberGenerator.GetUniform()) { // Cohort tries to disperse double[] DispersalArray = CalculateDispersalProbability(gridForDispersal, latIndex, lonIndex, CalculateDispersalSpeed(AdultMass)); double CohortDispersed = CheckForDispersal(DispersalArray[0]); if (CohortDispersed > 0) { uint[] DestinationCell = CellToDisperseTo(gridForDispersal, latIndex, lonIndex, DispersalArray, DispersalArray[0], DispersalArray[4], DispersalArray[5], ref ExitDirection, ref EntryDirection); // Update the delta array of cells to disperse to, if the cohort moves if (DestinationCell[0] < 999999) { // Update the delta array of cohorts gridForDispersal.DeltaFunctionalGroupDispersalArray[latIndex, lonIndex].Add((uint)functionalGroup); gridForDispersal.DeltaCohortNumberDispersalArray[latIndex, lonIndex].Add((uint)cohortNumber); // Update the delta array of cells to disperse to gridForDispersal.DeltaCellToDisperseToArray[latIndex, lonIndex].Add(DestinationCell); // Update the delta array of exit and entry directions gridForDispersal.DeltaCellExitDirection[latIndex, lonIndex].Add(ExitDirection); gridForDispersal.DeltaCellEntryDirection[latIndex, lonIndex].Add(EntryDirection); } } CohortHasDispersed = true; } } } return(CohortHasDispersed); }
/// <summary> /// Calculate the proportion of time for which this cohort could be active and assign it to the cohort's properties /// </summary> /// <param name="actingCohort">The Cohort for which proportion of time active is being calculated</param> /// <param name="cellEnvironment">The environmental information for current grid cell</param> /// <param name="madingleyCohortDefinitions">Functional group definitions and code to interrogate the cohorts in current grid cell</param> /// <param name="currentTimestep">Current timestep index</param> /// <param name="currentMonth">Current month</param> public void AssignProportionTimeActive(Cohort actingCohort, SortedList<string, double[]> cellEnvironment, FunctionalGroupDefinitions madingleyCohortDefinitions,uint currentTimestep, uint currentMonth) { double Realm = cellEnvironment["Realm"][0]; //Only work on heterotroph cohorts if (madingleyCohortDefinitions.GetTraitNames("Heterotroph/Autotroph", actingCohort.FunctionalGroupIndex) == "heterotroph") { //Check if this is an endotherm or ectotherm Boolean Endotherm = madingleyCohortDefinitions.GetTraitNames("Endo/Ectotherm", actingCohort.FunctionalGroupIndex) == "endotherm"; if (Endotherm) { //Assumes the whole timestep is suitable for endotherms to be active - actual time active is therefore the proportion specified for this functional group. actingCohort.ProportionTimeActive = madingleyCohortDefinitions.GetBiologicalPropertyOneFunctionalGroup("proportion suitable time active", actingCohort.FunctionalGroupIndex); } else { //If ectotherm then use realm specific function if (Realm == 1.0) { actingCohort.ProportionTimeActive = CalculateProportionTimeSuitableTerrestrial(cellEnvironment, currentMonth, Endotherm) * madingleyCohortDefinitions.GetBiologicalPropertyOneFunctionalGroup("proportion suitable time active", actingCohort.FunctionalGroupIndex); } else { actingCohort.ProportionTimeActive = CalculateProportionTimeSuitableMarine(cellEnvironment, currentMonth, Endotherm) * madingleyCohortDefinitions.GetBiologicalPropertyOneFunctionalGroup("proportion suitable time active", actingCohort.FunctionalGroupIndex); } } } }
/// <summary> /// Seed grid cell with cohorts, as specified in the model input files /// </summary> /// <param name="functionalGroups">The functional group definitions for cohorts in the grid cell</param> /// <param name="cellEnvironment">The environment in the grid cell</param> /// <param name="globalDiagnostics">A list of global diagnostic variables</param> /// <param name="nextCohortID">YThe unique ID to assign to the next cohort produced</param> /// <param name="tracking">boolean to indicate if cohorts are to be tracked in this model</param> /// <param name="totalCellTerrestrialCohorts">The total number of cohorts to be seeded in each terrestrial grid cell</param> /// <param name="totalCellMarineCohorts">The total number of cohorts to be seeded in each marine grid cell</param> /// <param name="DrawRandomly">Whether the model is set to use random draws</param> /// <param name="ZeroAbundance">Set this parameter to 'true' if you want to seed the cohorts with zero abundance</param> private void SeedGridCellCohorts(ref FunctionalGroupDefinitions functionalGroups, ref SortedList<string, double[]> cellEnvironment, SortedList<string, double> globalDiagnostics, Int64 nextCohortID, Boolean tracking, double totalCellTerrestrialCohorts, double totalCellMarineCohorts, Boolean DrawRandomly, Boolean ZeroAbundance) { // Set the seed for the random number generator from the system time RandomNumberGenerator.SetSeedFromSystemTime(); // StreamWriter tempsw = new StreamWriter("C://Temp//adult_juvenile_masses.txt"); // tempsw.WriteLine("adult mass\tjuvenilemass"); // Define local variables double CohortJuvenileMass; double CohortAdultMassRatio; double CohortAdultMass; double ExpectedLnAdultMassRatio; int[] FunctionalGroupsToUse; double NumCohortsThisCell; double TotalNewBiomass =0.0; // Get the minimum and maximum possible body masses for organisms in each functional group double[] MassMinima = functionalGroups.GetBiologicalPropertyAllFunctionalGroups("minimum mass"); double[] MassMaxima = functionalGroups.GetBiologicalPropertyAllFunctionalGroups("maximum mass"); string[] NutritionSource = functionalGroups.GetTraitValuesAllFunctionalGroups("nutrition source"); double[] ProportionTimeActive = functionalGroups.GetBiologicalPropertyAllFunctionalGroups("proportion suitable time active"); //Variable for altering the juvenile to adult mass ratio for marine cells when handling certain functional groups eg baleen whales double Scaling = 0.0; Int64 CohortIDIncrementer = nextCohortID; // Check which realm the cell is in if (cellEnvironment["Realm"][0] == 1.0) { // Get the indices of all terrestrial functional groups FunctionalGroupsToUse = functionalGroups.GetFunctionalGroupIndex("realm", "terrestrial", true); NumCohortsThisCell = totalCellTerrestrialCohorts; } else { // Get the indices of all marine functional groups FunctionalGroupsToUse = functionalGroups.GetFunctionalGroupIndex("realm", "marine", true); NumCohortsThisCell = totalCellMarineCohorts; } Debug.Assert(cellEnvironment["Realm"][0] > 0.0, "Missing realm for grid cell"); if (NumCohortsThisCell > 0) { // Loop over all functional groups in the model for (int FunctionalGroup = 0; FunctionalGroup < functionalGroups.GetNumberOfFunctionalGroups(); FunctionalGroup++) { // Create a new list to hold the cohorts in the grid cell _GridCellCohorts[FunctionalGroup] = new List<Cohort>(); // If it is a functional group that corresponds to the current realm, then seed cohorts if (FunctionalGroupsToUse.Contains(FunctionalGroup)) { // Loop over the initial number of cohorts double NumberOfCohortsInThisFunctionalGroup = 1.0; if (!ZeroAbundance) { NumberOfCohortsInThisFunctionalGroup = functionalGroups.GetBiologicalPropertyOneFunctionalGroup("initial number of gridcellcohorts", FunctionalGroup); } for (int jj = 0; jj < NumberOfCohortsInThisFunctionalGroup; jj++) { // Check whether the model is set to randomly draw the body masses of new cohorts if (DrawRandomly) { // Draw adult mass from a log-normal distribution with mean -6.9 and standard deviation 10.0, // within the bounds of the minimum and maximum body masses for the functional group CohortAdultMass = Math.Pow(10, (RandomNumberGenerator.GetUniform() * (Math.Log10(MassMaxima[FunctionalGroup]) - Math.Log10(50 * MassMinima[FunctionalGroup])) + Math.Log10(50 * MassMinima[FunctionalGroup]))); // Terrestrial and marine organisms have different optimal prey/predator body mass ratios if (cellEnvironment["Realm"][0] == 1.0) // Optimal prey body size 10% OptimalPreyBodySizeRatio = Math.Max(0.01, RandomNumberGenerator.GetNormal(0.1, 0.02)); else { if (functionalGroups.GetTraitNames("Diet", FunctionalGroup) == "allspecial") { // Note that for this group // it is actually (despite the name) not an optimal prey body size ratio, but an actual body size. // This is because it is invariant as the predator (filter-feeding baleen whale) grows. // See also the predation classes. OptimalPreyBodySizeRatio = Math.Max(0.00001, RandomNumberGenerator.GetNormal(0.0001, 0.1)); } else { // Optimal prey body size or marine organisms is 10% OptimalPreyBodySizeRatio = Math.Max(0.01, RandomNumberGenerator.GetNormal(0.1, 0.02)); } } // Draw from a log-normal distribution with mean 10.0 and standard deviation 5.0, then add one to obtain // the ratio of adult to juvenile body mass, and then calculate juvenile mass based on this ratio and within the // bounds of the minimum and maximum body masses for this functional group if (cellEnvironment["Realm"][0] == 1.0) { do { ExpectedLnAdultMassRatio = 2.24 + 0.13 * Math.Log(CohortAdultMass); CohortAdultMassRatio = 1.0 + RandomNumberGenerator.GetLogNormal(ExpectedLnAdultMassRatio, 0.5); CohortJuvenileMass = CohortAdultMass * 1.0 / CohortAdultMassRatio; } while (CohortAdultMass <= CohortJuvenileMass || CohortJuvenileMass < MassMinima[FunctionalGroup]); } // In the marine realm, have a greater difference between the adult and juvenile body masses, on average else { uint Counter = 0; Scaling = 0.2; // Use the scaling to deal with baleen whales not having such a great difference do { ExpectedLnAdultMassRatio = 2.5 + Scaling * Math.Log(CohortAdultMass); CohortAdultMassRatio = 1.0 + 10 * RandomNumberGenerator.GetLogNormal(ExpectedLnAdultMassRatio, 0.5); CohortJuvenileMass = CohortAdultMass * 1.0 / CohortAdultMassRatio; Counter++; if (Counter > 10) { Scaling -= 0.01; Counter = 0; } } while (CohortAdultMass <= CohortJuvenileMass || CohortJuvenileMass < MassMinima[FunctionalGroup]); } } else { // Use the same seed for the random number generator every time RandomNumberGenerator.SetSeed((uint)(jj + 1), (uint)((jj + 1) * 3)); // Draw adult mass from a log-normal distribution with mean -6.9 and standard deviation 10.0, // within the bounds of the minimum and maximum body masses for the functional group CohortAdultMass = Math.Pow(10, (RandomNumberGenerator.GetUniform() * (Math.Log10(MassMaxima[FunctionalGroup]) - Math.Log10(50 * MassMinima[FunctionalGroup])) + Math.Log10(50 * MassMinima[FunctionalGroup]))); OptimalPreyBodySizeRatio = Math.Max(0.01, RandomNumberGenerator.GetNormal(0.1, 0.02)); // Draw from a log-normal distribution with mean 10.0 and standard deviation 5.0, then add one to obtain // the ratio of adult to juvenile body mass, and then calculate juvenile mass based on this ratio and within the // bounds of the minimum and maximum body masses for this functional group if (cellEnvironment["Realm"][0] == 1.0) { do { ExpectedLnAdultMassRatio = 2.24 + 0.13 * Math.Log(CohortAdultMass); CohortAdultMassRatio = 1.0 + RandomNumberGenerator.GetLogNormal(ExpectedLnAdultMassRatio, 0.5); CohortJuvenileMass = CohortAdultMass * 1.0 / CohortAdultMassRatio; } while (CohortAdultMass <= CohortJuvenileMass || CohortJuvenileMass < MassMinima[FunctionalGroup]); } // In the marine realm, have a greater difference between the adult and juvenile body masses, on average else { do { ExpectedLnAdultMassRatio = 2.24 + 0.13 * Math.Log(CohortAdultMass); CohortAdultMassRatio = 1.0 + 10 * RandomNumberGenerator.GetLogNormal(ExpectedLnAdultMassRatio, 0.5); CohortJuvenileMass = CohortAdultMass * 1.0 / CohortAdultMassRatio; } while (CohortAdultMass <= CohortJuvenileMass || CohortJuvenileMass < MassMinima[FunctionalGroup]); } } // An instance of Cohort to hold the new cohort Cohort NewCohort; //double NewBiomass = Math.Pow(0.2, (Math.Log10(CohortAdultMass))) * (1.0E9 * _CellEnvironment["Cell Area"][0]) / NumCohortsThisCell; // 3000*(0.6^log(mass)) gives individual cohort biomass density in g ha-1 // * 100 to give g km-2 // * cell area to give g grid cell //*3300/NumCohortsThisCell scales total initial biomass in the cell to some approximately reasonable mass double NewBiomass = (3300 / NumCohortsThisCell) * 100 * 3000 * Math.Pow(0.6, (Math.Log10(CohortJuvenileMass))) * (_CellEnvironment["Cell Area"][0]); TotalNewBiomass += NewBiomass; double NewAbund = 0.0; if (!ZeroAbundance) { NewAbund = NewBiomass / CohortJuvenileMass; } /* // TEMPORARILY MARINE ONLY if (cellEnvironment["Realm"][0] == 1) { NewAbund = 0.0; } */ double TrophicIndex; switch (NutritionSource[FunctionalGroup]) { case "herbivore": TrophicIndex = 2; break; case "omnivore": TrophicIndex = 2.5; break; case "carnivore": TrophicIndex = 3; break; default: Debug.Fail("Unexpected nutrition source trait value when assigning trophic index"); TrophicIndex = 0.0; break; } // Initialise the new cohort with the relevant properties NewCohort = new Cohort((byte)FunctionalGroup, CohortJuvenileMass, CohortAdultMass, CohortJuvenileMass, NewAbund, OptimalPreyBodySizeRatio, (ushort)0, ProportionTimeActive[FunctionalGroup], ref CohortIDIncrementer,TrophicIndex, tracking); // Add the new cohort to the list of grid cell cohorts _GridCellCohorts[FunctionalGroup].Add(NewCohort); // TEMPORARY /* // Check whether the model is set to randomly draw the body masses of new cohorts if ((Longitude % 4 == 0) && (Latitude % 4 == 0)) { if (DrawRandomly) { CohortAdultMass = 100000; CohortJuvenileMass = 100000; } else { CohortAdultMass = 100000; CohortJuvenileMass = 100000; } // An instance of Cohort to hold the new cohort Cohort NewCohort; double NewBiomass = (1.0E7 * _CellEnvironment["Cell Area"][0]) / NumCohortsThisCell; double NewAbund = 0.0; NewAbund = 3000; // Initialise the new cohort with the relevant properties NewCohort = new Cohort((byte)FunctionalGroup, CohortJuvenileMass, CohortAdultMass, CohortJuvenileMass, NewAbund, (ushort)0, ref nextCohortID, tracking); // Add the new cohort to the list of grid cell cohorts _GridCellCohorts[FunctionalGroup].Add(NewCohort); } */ // Incrememt the variable tracking the total number of cohorts in the model globalDiagnostics["NumberOfCohortsInModel"]++; } } } } else { // Loop over all functional groups in the model for (int FunctionalGroup = 0; FunctionalGroup < functionalGroups.GetNumberOfFunctionalGroups(); FunctionalGroup++) { // Create a new list to hold the cohorts in the grid cell _GridCellCohorts[FunctionalGroup] = new List<Cohort>(); } } // tempsw.Dispose(); }
public static void ToJson(Newtonsoft.Json.JsonWriter jsonWriter, Cohort cohort) { Action<Newtonsoft.Json.JsonWriter, uint> WriteUInt = (jsonWriter2, value) => { Madingley.Serialization.Common.Writer.WriteInt(jsonWriter2, (int)value); }; jsonWriter.WriteStartObject(); Madingley.Serialization.Common.Writer.PropertyInt(jsonWriter, "_BirthTimeStep", (int)cohort._BirthTimeStep); Madingley.Serialization.Common.Writer.PropertyInt(jsonWriter, "_MaturityTimeStep", (int)cohort._MaturityTimeStep); Madingley.Serialization.Common.Writer.PropertyInlineArray(jsonWriter, "_CohortID", cohort._CohortID, WriteUInt); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_JuvenileMass", cohort._JuvenileMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_AdultMass", cohort._AdultMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_IndividualBodyMass", cohort._IndividualBodyMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_IndividualReproductivePotentialMass", cohort._IndividualReproductivePotentialMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_MaximumAchievedBodyMass", cohort._MaximumAchievedBodyMass); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_CohortAbundance", cohort._CohortAbundance); Madingley.Serialization.Common.Writer.PropertyInt(jsonWriter, "_FunctionalGroupIndex", cohort._FunctionalGroupIndex); Madingley.Serialization.Common.Writer.PropertyBoolean(jsonWriter, "_Merged", cohort._Merged); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_ProportionTimeActive", cohort._ProportionTimeActive); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_TrophicIndex", cohort._TrophicIndex); Madingley.Serialization.Common.Writer.PropertyDouble(jsonWriter, "_LogOptimalPreyBodySizeRatio", cohort._LogOptimalPreyBodySizeRatio); jsonWriter.WriteEndObject(); }
/// <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); } }
public InputModelState(string outputPath, string filename, ModelGrid ecosystemModelGrid, List <uint[]> cellList) { //Set the input state flag to be true _InputState = true; // Construct the string required to access the file using Scientific Dataset string _ReadFileString = "msds:nc?file=input/ModelStates/" + filename + ".nc&openMode=readOnly"; // Open the data file using Scientific Dataset DataSet StateDataSet = DataSet.Open(_ReadFileString); float[] Latitude = StateDataSet.GetData <float[]>("Latitude"); float[] Longitude = StateDataSet.GetData <float[]>("Longitude"); float[] CohortFunctionalGroup = StateDataSet.GetData <float[]>("Cohort Functional Group"); float[] Cohort = StateDataSet.GetData <float[]>("Cohort"); float[] StockFunctionalGroup = StateDataSet.GetData <float[]>("Stock Functional Group"); float[] Stock = StateDataSet.GetData <float[]>("Stock"); // Check that the longitudes and latitudes in the input state match the cell environment for (int la = 0; la < Latitude.Length; la++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment((uint)la, 0)["Latitude"][0] == Latitude[la], "Error: input-state grid doesn't match current model grid"); } for (int lo = 0; lo < Longitude.Length; lo++) { Debug.Assert(ecosystemModelGrid.GetCellEnvironment(0, (uint)lo)["Longitude"][0] == Longitude[lo], "Error: input-state grid doesn't match current model grid"); } List <double[, , ]> CohortJuvenileMass = new List <double[, , ]>(); List <double[, , ]> CohortAdultMass = new List <double[, , ]>(); List <double[, , ]> CohortIndividualBodyMass = new List <double[, , ]>(); List <double[, , ]> CohortCohortAbundance = new List <double[, , ]>(); List <double[, , ]> CohortLogOptimalPreyBodySizeRatio = new List <double[, , ]>(); List <double[, , ]> CohortBirthTimeStep = new List <double[, , ]>(); List <double[, , ]> CohortProportionTimeActive = new List <double[, , ]>(); List <double[, , ]> CohortTrophicIndex = new List <double[, , ]>(); double[,,,] tempData = new double[Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]; tempData = StateDataSet.GetData <double[, , , ]>("CohortJuvenileMass"); for (int la = 0; la < Latitude.Length; la++) { CohortJuvenileMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortJuvenileMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortAdultMass"); for (int la = 0; la < Latitude.Length; la++) { CohortAdultMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortAdultMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { CohortIndividualBodyMass.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortCohortAbundance"); for (int la = 0; la < Latitude.Length; la++) { CohortCohortAbundance.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortCohortAbundance[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortLogOptimalPreyBodySizeRatio"); for (int la = 0; la < Latitude.Length; la++) { CohortLogOptimalPreyBodySizeRatio.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortLogOptimalPreyBodySizeRatio[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortBirthTimeStep"); for (int la = 0; la < Latitude.Length; la++) { CohortBirthTimeStep.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortBirthTimeStep[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortProportionTimeActive"); for (int la = 0; la < Latitude.Length; la++) { CohortProportionTimeActive.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortProportionTimeActive[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } tempData = StateDataSet.GetData <double[, , , ]>("CohortTrophicIndex"); for (int la = 0; la < Latitude.Length; la++) { CohortTrophicIndex.Add(new double[Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { for (int c = 0; c < Cohort.Length; c++) { CohortTrophicIndex[(int)cell[0]][cell[1], fg, c] = tempData[ cell[0], cell[1], fg, c]; } } } _GridCellCohorts = new GridCellCohortHandler[Latitude.Length, Longitude.Length]; long temp = 0; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]] = new GridCellCohortHandler(CohortFunctionalGroup.Length); for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg] = new List <Cohort>(); for (int c = 0; c < Cohort.Length; c++) { if (CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1], fg, c] > 0.0) { Cohort TempCohort = new Cohort( (byte)fg, CohortJuvenileMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortAdultMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], CohortCohortAbundance[(int)cellList[cell][0]][cellList[cell][1], fg, c], Math.Exp(CohortLogOptimalPreyBodySizeRatio[(int)cellList[cell][0]][cellList[cell][1], fg, c]), Convert.ToUInt16(CohortBirthTimeStep[(int)cellList[cell][0]][cellList[cell][1], fg, c]), CohortProportionTimeActive[(int)cellList[cell][0]][cellList[cell][1], fg, c], ref temp, CohortTrophicIndex[(int)cellList[cell][0]][cellList[cell][1], fg, c], false); _GridCellCohorts[cellList[cell][0], cellList[cell][1]][fg].Add(TempCohort); } } } } CohortJuvenileMass.RemoveRange(0, CohortJuvenileMass.Count); CohortAdultMass.RemoveRange(0, CohortAdultMass.Count); CohortIndividualBodyMass.RemoveRange(0, CohortIndividualBodyMass.Count); CohortCohortAbundance.RemoveRange(0, CohortCohortAbundance.Count); CohortLogOptimalPreyBodySizeRatio.RemoveRange(0, CohortLogOptimalPreyBodySizeRatio.Count); CohortBirthTimeStep.RemoveRange(0, CohortBirthTimeStep.Count); CohortProportionTimeActive.RemoveRange(0, CohortProportionTimeActive.Count); CohortTrophicIndex.RemoveRange(0, CohortTrophicIndex.Count); List <double[, , ]> StockIndividualBodyMass = new List <double[, , ]>(); List <double[, , ]> StockTotalBiomass = new List <double[, , ]>(); double[,,,] tempData2 = new double[Latitude.Length, Longitude.Length, StockFunctionalGroup.Length, Stock.Length]; tempData2 = StateDataSet.GetData <double[, , , ]>("StockIndividualBodyMass"); for (int la = 0; la < Latitude.Length; la++) { StockIndividualBodyMass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockIndividualBodyMass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } tempData2 = StateDataSet.GetData <double[, , , ]>("StockTotalBiomass"); for (int la = 0; la < Latitude.Length; la++) { StockTotalBiomass.Add(new double[Longitude.Length, StockFunctionalGroup.Length, Stock.Length]); } foreach (uint[] cell in cellList) { for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { for (int c = 0; c < Stock.Length; c++) { StockTotalBiomass[(int)cell[0]][cell[1], fg, c] = tempData2[ cell[0], cell[1], fg, c]; } } } _GridCellStocks = new GridCellStockHandler[Latitude.Length, Longitude.Length]; for (int cell = 0; cell < cellList.Count; cell++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]] = new GridCellStockHandler(StockFunctionalGroup.Length); for (int fg = 0; fg < StockFunctionalGroup.Length; fg++) { _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg] = new List <Stock>(); for (int c = 0; c < Stock.Length; c++) { if (StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c] > 0.0) { Stock TempStock = new Stock( (byte)fg, StockIndividualBodyMass[(int)cellList[cell][0]][cellList[cell][1], fg, c], StockTotalBiomass[(int)cellList[cell][0]][cellList[cell][1], fg, c]); _GridCellStocks[cellList[cell][0], cellList[cell][1]][fg].Add(TempStock); } } } } }
/// <summary> /// Add a new cohort to an existing list of cohorts in the grid cell - or create a new list if there is not one present /// </summary> /// <param name="latIndex">Latitude index of the grid cell</param> /// <param name="lonIndex">Longitude index of the grid cell</param> /// <param name="functionalGroup">Functional group of the cohort (i.e. array index)</param> /// <param name="cohortToAdd">The cohort object to add</param> public void AddNewCohortToGridCell(uint latIndex, uint lonIndex, int functionalGroup, Cohort cohortToAdd) { InternalGrid[latIndex, lonIndex].GridCellCohorts[functionalGroup].Add(cohortToAdd); }