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