/// <summary> /// Calculate trophic evenness using the Rao Index /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of cells to be run in the current simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to be run</param> /// <returns>Trophic evenness</returns> public double CalculateFunctionalEvennessRao(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortDefinitions, List <uint[]> cellIndices, int cellIndex, string trait) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double[] EvennessValues = new double[2]; double[,] Distances = new double[CellCohorts.GetNumberOfCohorts(), CellCohorts.GetNumberOfCohorts()]; double[] FunctionalTrait = new double[CellCohorts.GetNumberOfCohorts()]; double MaxModelTraitValue = 0; double MinModelTraitValue = 0; // Construct a vector of cohort biomass (in case we want to weight by them) double[] CohortTotalBiomasses = new double[CellCohorts.GetNumberOfCohorts()]; int CohortNumberCounter = 0; switch (trait.ToLower()) { case "biomass": for (int fg = 0; fg < CellCohorts.Count; fg++) { foreach (Cohort c in CellCohorts[fg]) { FunctionalTrait[CohortNumberCounter] = c.IndividualBodyMass; CohortTotalBiomasses[CohortNumberCounter] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CohortNumberCounter++; } } //Define upper and lower limits for body mass MinModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("minimum mass").Min(); MaxModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("maximum mass").Max(); break; case "trophic index": for (int fg = 0; fg < CellCohorts.Count; fg++) { foreach (Cohort c in CellCohorts[fg]) { FunctionalTrait[CohortNumberCounter] = c.IndividualBodyMass; CohortTotalBiomasses[CohortNumberCounter] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CohortNumberCounter++; } } MinModelTraitValue = MinTI; MaxModelTraitValue = MaxTI; break; } Distances = CalculateDistanceMatrix(FunctionalTrait, MaxModelTraitValue, MinModelTraitValue); return(RaoEntropy(Distances, CohortTotalBiomasses)); }
public double[] CalculateFunctionalRichness(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortDefinitions, List<uint[]> cellIndices, int cellIndex, string trait) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double MinCurrentTraitValue = double.MaxValue; double MaxCurrentTraitValue = double.MinValue; double MinModelTraitValue = 0.0; double MaxModelTraitValue = 0.0; switch (trait.ToLower()) { case "biomass": foreach (var CohortList in CellCohorts) { foreach (var cohort in CohortList) { if (cohort.IndividualBodyMass < MinCurrentTraitValue) MinCurrentTraitValue = cohort.IndividualBodyMass; if (cohort.IndividualBodyMass > MaxCurrentTraitValue) MaxCurrentTraitValue = cohort.IndividualBodyMass; } } //Define upper and lower limits for body mass MinModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("minimum mass").Min(); MaxModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("maximum mass").Max(); break; case "trophic index": foreach (var CohortList in CellCohorts) { foreach (var cohort in CohortList) { if (cohort.TrophicIndex < MinCurrentTraitValue) MinCurrentTraitValue = cohort.TrophicIndex; if (cohort.TrophicIndex > MaxCurrentTraitValue) MaxCurrentTraitValue = cohort.TrophicIndex; } } //Define upper and lower limits for body mass MinModelTraitValue = MinTI; MaxModelTraitValue = MaxTI; break; default: Debug.Fail("Trait not recognised in calculation of ecosystem metrics: " + trait); break; } Debug.Assert((MaxModelTraitValue - MinModelTraitValue) > 0.0, "Division by zero or negative model trait values in calculation of functional richness"); double[] NewArray = {(MaxCurrentTraitValue-MinCurrentTraitValue)/(MaxModelTraitValue-MinModelTraitValue),MinCurrentTraitValue,MaxCurrentTraitValue}; return NewArray; }
/// <summary> /// Calculate trophic evenness using the Rao Index /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of cells to be run in the current simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to be run</param> /// <returns>Trophic evenness</returns> public double CalculateFunctionalEvennessRao(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortDefinitions, List<uint[]> cellIndices, int cellIndex, string trait) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double[] EvennessValues = new double[2]; double[,] Distances = new double[CellCohorts.GetNumberOfCohorts(), CellCohorts.GetNumberOfCohorts()]; double[] FunctionalTrait = new double[CellCohorts.GetNumberOfCohorts()]; double MaxModelTraitValue=0; double MinModelTraitValue=0; // Construct a vector of cohort biomass (in case we want to weight by them) double[] CohortTotalBiomasses = new double[CellCohorts.GetNumberOfCohorts()]; int CohortNumberCounter = 0; switch (trait.ToLower()) { case "biomass": for (int fg = 0; fg < CellCohorts.Count; fg++) { foreach (Cohort c in CellCohorts[fg]) { FunctionalTrait[CohortNumberCounter] = c.IndividualBodyMass; CohortTotalBiomasses[CohortNumberCounter] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CohortNumberCounter++; } } //Define upper and lower limits for body mass MinModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("minimum mass").Min(); MaxModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("maximum mass").Max(); break; case "trophic index": for (int fg = 0; fg < CellCohorts.Count; fg++) { foreach (Cohort c in CellCohorts[fg]) { FunctionalTrait[CohortNumberCounter] = c.IndividualBodyMass; CohortTotalBiomasses[CohortNumberCounter] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CohortNumberCounter++; } } MinModelTraitValue = MinTI; MaxModelTraitValue = MaxTI; break; } Distances = CalculateDistanceMatrix(FunctionalTrait, MaxModelTraitValue, MinModelTraitValue); return RaoEntropy(Distances, CohortTotalBiomasses); }
/// <summary> /// Calculates functional diversity of cohorts in a grid cell as functional richness and functional diveregence (using the Rao Index) /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cohortDefinitions">The functional group definitions for cohorts in the model</param> /// <param name="cellIndices">The list of cell indices in the current model simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to run</param> /// <returns>A pair of values representing the functional richness and functional divergence (functional richness currently disabled!)</returns> public double[] CalculateFunctionalDiversity(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortDefinitions, List<uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); //Variable to hold the functional richness value for the current cohorts double FunctionalRichness; //Variable to hold the functional divergence value for the current cohorts double RaoFunctionalDivergence = 0.0; double[,] Distances= new double[CellCohorts.GetNumberOfCohorts(), CellCohorts.GetNumberOfCohorts()]; List<string> AllTraitNames = cohortDefinitions.GetAllTraitNames().ToList(); AllTraitNames.Remove("realm"); AllTraitNames.Remove("heterotroph/autotroph"); AllTraitNames.Remove("diet"); string[] TraitNames = AllTraitNames.ToArray(); //Define upper and lower limits for body mass double MinMass = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("minimum mass").Min(); double MaxMass = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("maximum mass").Max(); //Define upp and lower limits for trophic index double MaxTI = 40.0; double MinTI = 1.0; // Construct an array of functional trait values for each cohort // Rows are specific cohorts // Columns are the functional traits (these include different types: // quantative: current mass, trophic index // nominal: diet, reproductive strategy, mobility, metabolism Tuple<double[], string[]>[] CohortFunctionalTraits = new Tuple<double[], string[]>[CellCohorts.GetNumberOfCohorts()]; double[] IndividualBodyMasses = new double[CellCohorts.GetNumberOfCohorts()]; double[] TrophicIndex = new double[CellCohorts.GetNumberOfCohorts()]; string[][] CohortNominalTraitValues= new string[TraitNames.Length][]; for (int i = 0; i < TraitNames.Length; i++) { CohortNominalTraitValues[i] = new string[CellCohorts.GetNumberOfCohorts()]; } // Construct a vector of cohort biomass (in case we want to weight by them) double[] CohortTotalBiomasses = new double[CellCohorts.GetNumberOfCohorts()]; string[] TraitValues = new string[TraitNames.Length]; double[] QuantitativeTraitValues= new double[2]; int CohortNumberCounter = 0; for (int fg = 0; fg < CellCohorts.Count; fg++) { foreach (Cohort c in CellCohorts[fg]) { TraitValues = cohortDefinitions.GetTraitValues(TraitNames, fg); for (int ii = 0; ii < TraitValues.Length; ii++) { CohortNominalTraitValues[ii][CohortNumberCounter] = TraitValues[ii]; } IndividualBodyMasses[CohortNumberCounter] = c.IndividualBodyMass; TrophicIndex[CohortNumberCounter] = c.TrophicIndex; QuantitativeTraitValues[0] = c.IndividualBodyMass; QuantitativeTraitValues[1] = c.TrophicIndex; CohortFunctionalTraits[CohortNumberCounter] = new Tuple<double[], string[]>(QuantitativeTraitValues, TraitValues); CohortTotalBiomasses[CohortNumberCounter] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CohortNumberCounter++; } } List<double[,]> DistanceList = new List<double[,]>(); DistanceList.Add(CalculateDistanceMatrix(IndividualBodyMasses, MaxMass, MinMass)); DistanceList.Add(CalculateDistanceMatrix(TrophicIndex, MaxTI, MinTI)); foreach (string[] t in CohortNominalTraitValues) { DistanceList.Add(CalculateDistanceMatrix(t)); } Distances = CalculateAggregateDistance(DistanceList); RaoFunctionalDivergence = RaoEntropy(Distances, CohortTotalBiomasses); return new double[] {0.0,RaoFunctionalDivergence}; }
/// <summary> /// Calculates functional diversity of cohorts in a grid cell as functional richness and functional diveregence (using the Rao Index) /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cohortDefinitions">The functional group definitions for cohorts in the model</param> /// <param name="cellIndices">The list of cell indices in the current model simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to run</param> /// <returns>A pair of values representing the functional richness and functional divergence (functional richness currently disabled!)</returns> public double[] CalculateFunctionalDiversity(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortDefinitions, List <uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); //Variable to hold the functional richness value for the current cohorts double FunctionalRichness; //Variable to hold the functional divergence value for the current cohorts double RaoFunctionalDivergence = 0.0; double[,] Distances = new double[CellCohorts.GetNumberOfCohorts(), CellCohorts.GetNumberOfCohorts()]; List <string> AllTraitNames = cohortDefinitions.GetAllTraitNames().ToList(); AllTraitNames.Remove("realm"); AllTraitNames.Remove("heterotroph/autotroph"); AllTraitNames.Remove("diet"); string[] TraitNames = AllTraitNames.ToArray(); //Define upper and lower limits for body mass double MinMass = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("minimum mass").Min(); double MaxMass = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("maximum mass").Max(); //Define upp and lower limits for trophic index double MaxTI = 40.0; double MinTI = 1.0; // Construct an array of functional trait values for each cohort // Rows are specific cohorts // Columns are the functional traits (these include different types: // quantative: current mass, trophic index // nominal: diet, reproductive strategy, mobility, metabolism Tuple <double[], string[]>[] CohortFunctionalTraits = new Tuple <double[], string[]> [CellCohorts.GetNumberOfCohorts()]; double[] IndividualBodyMasses = new double[CellCohorts.GetNumberOfCohorts()]; double[] TrophicIndex = new double[CellCohorts.GetNumberOfCohorts()]; string[][] CohortNominalTraitValues = new string[TraitNames.Length][]; for (int i = 0; i < TraitNames.Length; i++) { CohortNominalTraitValues[i] = new string[CellCohorts.GetNumberOfCohorts()]; } // Construct a vector of cohort biomass (in case we want to weight by them) double[] CohortTotalBiomasses = new double[CellCohorts.GetNumberOfCohorts()]; string[] TraitValues = new string[TraitNames.Length]; double[] QuantitativeTraitValues = new double[2]; int CohortNumberCounter = 0; for (int fg = 0; fg < CellCohorts.Count; fg++) { foreach (Cohort c in CellCohorts[fg]) { TraitValues = cohortDefinitions.GetTraitValues(TraitNames, fg); for (int ii = 0; ii < TraitValues.Length; ii++) { CohortNominalTraitValues[ii][CohortNumberCounter] = TraitValues[ii]; } IndividualBodyMasses[CohortNumberCounter] = c.IndividualBodyMass; TrophicIndex[CohortNumberCounter] = c.TrophicIndex; QuantitativeTraitValues[0] = c.IndividualBodyMass; QuantitativeTraitValues[1] = c.TrophicIndex; CohortFunctionalTraits[CohortNumberCounter] = new Tuple <double[], string[]>(QuantitativeTraitValues, TraitValues); CohortTotalBiomasses[CohortNumberCounter] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CohortNumberCounter++; } } List <double[, ]> DistanceList = new List <double[, ]>(); DistanceList.Add(CalculateDistanceMatrix(IndividualBodyMasses, MaxMass, MinMass)); DistanceList.Add(CalculateDistanceMatrix(TrophicIndex, MaxTI, MinTI)); foreach (string[] t in CohortNominalTraitValues) { DistanceList.Add(CalculateDistanceMatrix(t)); } Distances = CalculateAggregateDistance(DistanceList); RaoFunctionalDivergence = RaoEntropy(Distances, CohortTotalBiomasses); return(new double[] { 0.0, RaoFunctionalDivergence }); }
public double[] CalculateFunctionalRichness(ModelGrid ecosystemModelGrid, FunctionalGroupDefinitions cohortDefinitions, List <uint[]> cellIndices, int cellIndex, string trait) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double MinCurrentTraitValue = double.MaxValue; double MaxCurrentTraitValue = double.MinValue; double MinModelTraitValue = 0.0; double MaxModelTraitValue = 0.0; switch (trait.ToLower()) { case "biomass": foreach (var CohortList in CellCohorts) { foreach (var cohort in CohortList) { if (cohort.IndividualBodyMass < MinCurrentTraitValue) { MinCurrentTraitValue = cohort.IndividualBodyMass; } if (cohort.IndividualBodyMass > MaxCurrentTraitValue) { MaxCurrentTraitValue = cohort.IndividualBodyMass; } } } //Define upper and lower limits for body mass MinModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("minimum mass").Min(); MaxModelTraitValue = cohortDefinitions.GetBiologicalPropertyAllFunctionalGroups("maximum mass").Max(); break; case "trophic index": foreach (var CohortList in CellCohorts) { foreach (var cohort in CohortList) { if (cohort.TrophicIndex < MinCurrentTraitValue) { MinCurrentTraitValue = cohort.TrophicIndex; } if (cohort.TrophicIndex > MaxCurrentTraitValue) { MaxCurrentTraitValue = cohort.TrophicIndex; } } } //Define upper and lower limits for body mass MinModelTraitValue = MinTI; MaxModelTraitValue = MaxTI; break; default: Debug.Fail("Trait not recognised in calculation of ecosystem metrics: " + trait); break; } Debug.Assert((MaxModelTraitValue - MinModelTraitValue) > 0.0, "Division by zero or negative model trait values in calculation of functional richness"); double[] NewArray = { (MaxCurrentTraitValue - MinCurrentTraitValue) / (MaxModelTraitValue - MinModelTraitValue), MinCurrentTraitValue, MaxCurrentTraitValue }; return(NewArray); }
/// <summary> /// Seed grid cell with stocks, as specified in the model input files /// </summary> /// <param name="functionalGroups">A reference to the stock functional group handler</param> /// <param name="cellEnvironment">The environment in the grid cell</param> /// <param name="globalDiagnostics">A list of global diagnostic variables for the model grid</param> private void SeedGridCellStocks(ref FunctionalGroupDefinitions functionalGroups, ref SortedList<string, double[]> cellEnvironment, SortedList<string, double> globalDiagnostics) { // Set the seed for the random number generator from the system time RandomNumberGenerator.SetSeedFromSystemTime(); Stock NewStock; // Define local variables int[] FunctionalGroupsToUse; // Get the individual body masses for organisms in each stock functional group double[] IndividualMass = functionalGroups.GetBiologicalPropertyAllFunctionalGroups("individual mass"); // Check which realm the cell is in if (cellEnvironment["Realm"][0] == 1.0 && _CellEnvironment["Precipitation"][0] != _CellEnvironment["Missing Value"][0] && _CellEnvironment["Temperature"][0] != _CellEnvironment["Missing Value"][0]) { // Get the indices of all terrestrial functional groups FunctionalGroupsToUse = functionalGroups.GetFunctionalGroupIndex("realm", "terrestrial", true); } else if (cellEnvironment["Realm"][0] == 2.0 && _CellEnvironment["NPP"][0] != _CellEnvironment["Missing Value"][0]) { // Get the indices of all marine functional groups FunctionalGroupsToUse = functionalGroups.GetFunctionalGroupIndex("realm", "marine", true); } else { // For cells without a realm designation, no functional groups will be used FunctionalGroupsToUse = new int[0]; } // Loop over all functional groups in the model for (int FunctionalGroup = 0; FunctionalGroup < functionalGroups.GetNumberOfFunctionalGroups(); FunctionalGroup++) { // Create a new list to hold the stocks in the grid cell _GridCellStocks[FunctionalGroup] = new List<Stock>(); // If it is a functional group that corresponds to the current realm, then seed the stock if (FunctionalGroupsToUse.Contains(FunctionalGroup)) { if (_CellEnvironment["Realm"][0] == 1.0) { // An instance of the terrestrial carbon model class RevisedTerrestrialPlantModel PlantModel = new RevisedTerrestrialPlantModel(); // Calculate predicted leaf mass at equilibrium for this stock double LeafMass = PlantModel.CalculateEquilibriumLeafMass(_CellEnvironment, functionalGroups.GetTraitNames("leaf strategy", FunctionalGroup) == "deciduous"); // Initialise the new stock with the relevant properties NewStock = new Stock((byte)FunctionalGroup, IndividualMass[FunctionalGroup], LeafMass); // Add the new stock to the list of grid cell stocks _GridCellStocks[FunctionalGroup].Add(NewStock); // Increment the variable tracking the total number of stocks in the model globalDiagnostics["NumberOfStocksInModel"]++; } else if (FunctionalGroupsToUse.Contains(FunctionalGroup)) { // Initialise the new stock with the relevant properties NewStock = new Stock((byte)FunctionalGroup, IndividualMass[FunctionalGroup], 1e12); // Add the new stock to the list of grid cell stocks _GridCellStocks[FunctionalGroup].Add(NewStock); // Increment the variable tracking the total number of stocks in the model globalDiagnostics["NumberOfStocksInModel"]++; } else { } } } }
/// <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(); }