/// <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 void OutputCurrentModelState(ModelGrid currentModelGrid, List <uint[]> cellIndices, uint currentTimestep) { GridCellCohortHandler TempCohorts; GridCellStockHandler TempStocks; string context; string organism; context = Convert.ToString(currentTimestep) + "\t"; foreach (uint[] cell in cellIndices) { context = Convert.ToString(currentTimestep) + "\t" + Convert.ToString(currentModelGrid.GetCellLatitude(cell[0])) + "\t" + Convert.ToString(currentModelGrid.GetCellLongitude(cell[1])) + "\t"; TempStocks = currentModelGrid.GetGridCellStocks(cell[0], cell[1]); TempCohorts = currentModelGrid.GetGridCellCohorts(cell[0], cell[1]); foreach (List <Stock> ListS in TempStocks) { foreach (Stock S in ListS) { organism = "-999\tS" + Convert.ToString(S.FunctionalGroupIndex) + "\t" + "-999\t-999\t" + Convert.ToString(S.IndividualBodyMass) + "\t" + Convert.ToString(S.TotalBiomass) + "\t" + "-999\t-999\t-999\t-999\t-999\t-999"; SyncStateWriter.WriteLine(context + organism); } } foreach (List <Cohort> ListC in TempCohorts) { foreach (Cohort C in ListC) { organism = Convert.ToString(C.CohortID) + "\t" + Convert.ToString(C.FunctionalGroupIndex) + "\t" + Convert.ToString(C.JuvenileMass) + "\t" + Convert.ToString(C.AdultMass) + "\t" + Convert.ToString(C.IndividualBodyMass) + "\t" + Convert.ToString(C.CohortAbundance) + "\t" + Convert.ToString(C.IndividualReproductivePotentialMass) + "\t" + Convert.ToString(C.BirthTimeStep) + "\t" + Convert.ToString(C.MaturityTimeStep) + "\t" + Convert.ToString(C.LogOptimalPreyBodySizeRatio) + "\t" + Convert.ToString(C.MaximumAchievedBodyMass) + "\t" + Convert.ToString(C.TrophicIndex) + "\t" + Convert.ToString(C.ProportionTimeActive); SyncStateWriter.WriteLine(context + organism); } } } }
/// <summary> /// Run dispersal /// </summary> public void RunCrossGridCellEcologicalProcess(uint[] cellIndex, ModelGrid gridForDispersal, bool dispersalOnly, FunctionalGroupDefinitions madingleyCohortDefinitions, FunctionalGroupDefinitions madingleyStockDefinitions, uint currentMonth) { // Create a temporary handler for grid cell cohorts GridCellCohortHandler WorkingGridCellCohorts; // Get the lat and lon indices uint ii = cellIndex[0]; uint jj = cellIndex[1]; // A boolean to check that the environmental layer exists bool varExists; // Check to see if the cell is marine double CellRealm = gridForDispersal.GetEnviroLayer("Realm", 0, ii, jj, out varExists); // Go through all of the cohorts in turn and see if they disperse WorkingGridCellCohorts = gridForDispersal.GetGridCellCohorts(ii, jj); // Loop through cohorts, and perform dispersal according to cohort type and status for (int kk = 0; kk < WorkingGridCellCohorts.Count; kk++) { // Work through the list of cohorts for (int ll = 0; ll < WorkingGridCellCohorts[kk].Count; ll++) { // Check to see if the cell is marine and the cohort type is planktonic if (CellRealm == 2.0 && ((madingleyCohortDefinitions.GetTraitNames("Mobility", WorkingGridCellCohorts[kk][ll].FunctionalGroupIndex) == "planktonic") || (WorkingGridCellCohorts[kk][ll].IndividualBodyMass <= PlanktonThreshold))) { // Run advective dispersal Implementations["basic advective dispersal"].RunDispersal(cellIndex, gridForDispersal, WorkingGridCellCohorts[kk][ll], kk, ll, currentMonth); } // Otherwise, if mature do responsive dispersal else if (WorkingGridCellCohorts[kk][ll].MaturityTimeStep < uint.MaxValue) { // Run diffusive dispersal Implementations["basic responsive dispersal"].RunDispersal(cellIndex, gridForDispersal, WorkingGridCellCohorts[kk][ll], kk, ll, currentMonth); } // If the cohort is immature, run diffusive dispersal else { Implementations["basic diffusive dispersal"].RunDispersal(cellIndex, gridForDispersal, WorkingGridCellCohorts[kk][ll], kk, ll, currentMonth); } } } }
/// <summary> /// Calculates trophic evenness using the FRO Index of Mouillot et al. /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of cells to be run in the current model simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to be run</param> /// <returns>Trophic evenness</returns> /// <remarks>From Mouillot et al (2005) Functional regularity: a neglected aspect of functional diversity, Oecologia</remarks> public double CalculateTrophicEvennessFRO(ModelGrid ecosystemModelGrid, List <uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); List <double[]> TrophicIndexBiomassDistribution = new List <double[]>(); double[] TIBiomass; double[] EW; foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { TIBiomass = new double[2]; TIBiomass[0] = c.TrophicIndex; TIBiomass[1] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; TrophicIndexBiomassDistribution.Add(TIBiomass); } } TrophicIndexBiomassDistribution = TrophicIndexBiomassDistribution.OrderBy(x => x[0]).ToList(); //Use the Mouillot Evenness index - Functional Regularity Index or FRO //From Mouillot et al (2005) Functional regularity: a neglected aspect of functional diversity, Oecologia EW = new double[TrophicIndexBiomassDistribution.Count]; double TotalEW = 0.0; for (int ii = 0; ii < TrophicIndexBiomassDistribution.Count - 1; ii++) { EW[ii] = (TrophicIndexBiomassDistribution[ii + 1][0] - TrophicIndexBiomassDistribution[ii][0]) / (TrophicIndexBiomassDistribution[ii + 1][1] + TrophicIndexBiomassDistribution[ii][1]); TotalEW += EW[ii]; } double FRO = 0.0; for (int ii = 0; ii < TrophicIndexBiomassDistribution.Count - 1; ii++) { FRO += Math.Min(EW[ii] / TotalEW, 1.0 / (TrophicIndexBiomassDistribution.Count - 1)); } return(FRO); }
/// <summary> /// Return the distribution of biomasses among trophic level bins /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of cell indices to be run in the current model simulation</param> /// <param name="cellIndex">The index of the current cell in the list of cells to be run</param> /// <returns>The distribution of biomasses among trophic level bins</returns> public double[] CalculateTrophicDistribution(ModelGrid ecosystemModelGrid, List <uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double[] TrophicIndexBinMasses = new double[NumberTrophicBins]; int BinIndex; foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { BinIndex = _TrophicIndexBinValues.ToList().IndexOf(_TrophicIndexBinValues.Last(x => x < c.TrophicIndex)); TrophicIndexBinMasses[BinIndex] += (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; } } return(TrophicIndexBinMasses); }
/// <summary> /// Calculates the mean trophic level of all individual organisms in a grid cell /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of cell indices in the current model simulation</param> /// <param name="cellIndex">The index of the current cell in the list of cells to run</param> /// <returns>The mean trophic level of individuals in the grid cell</returns> public double CalculateMeanTrophicLevelCell(ModelGrid ecosystemModelGrid, List <uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double BiomassWeightedTI = 0.0; double TotalBiomass = 0.0; double CohortBiomass = 0.0; foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { CohortBiomass = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; BiomassWeightedTI += CohortBiomass * c.TrophicIndex; TotalBiomass += CohortBiomass; } } return(BiomassWeightedTI / TotalBiomass); }
/// <summary> /// Calculates the geometric community weighted mean body mass /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of cells to be run in the current model simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to be run</param> /// <returns>geometric community weighted mean body mass</returns> public double CalculateGeometricCommunityMeanBodyMass(ModelGrid ecosystemModelGrid, List <uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double CumulativeAbundance = 0.0; double CumulativeLogBiomass = 0.0; //Retrieve the biomass foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { CumulativeLogBiomass += Math.Log(c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CumulativeAbundance += c.CohortAbundance; } } double CWGMBM = Math.Exp(CumulativeLogBiomass / CumulativeAbundance); return(CWGMBM); }
/// <summary> /// Make a record of the properties of the intial model cohorts in the new cohorts output file /// </summary> public void RecordInitialCohorts() { int i = 0; foreach (uint[] cell in _CellList) { if (ProcessTrackers[i].TrackProcesses) { GridCellCohortHandler TempCohorts = EcosystemModelGrid.GetGridCellCohorts(cell[0], cell[1]); for (int FunctionalGroup = 0; FunctionalGroup < TempCohorts.Count; FunctionalGroup++) { foreach (Cohort item in TempCohorts[FunctionalGroup]) { ProcessTrackers[i].RecordNewCohort(cell[0], cell[1], 0, item.CohortAbundance, item.AdultMass, item.FunctionalGroupIndex, new List<uint> { uint.MaxValue }, item.CohortID[0]); } } } i += 1; } }
private double[, , ,] CalculateCurrentCohortState(ModelGrid currentModelState, string variableName, int numLats, int numLons, int numFG, int numCohorts, List<uint[]> cellList) { //Calculate the cohort state double[, , ,] State = new double[numLats, numLons, numFG, numCohorts]; GridCellCohortHandler CellCohorts; for (int cellIndex = 0; cellIndex < cellList.Count; cellIndex++) { CellCohorts = currentModelState.GetGridCellCohorts(cellList[cellIndex][0], cellList[cellIndex][1]); for (int functionalGroupIndex = 0; functionalGroupIndex < CellCohorts.Count; functionalGroupIndex++) { for (int cohortIndex = 0; cohortIndex < CellCohorts[functionalGroupIndex].Count; cohortIndex++) { switch (variableName) { case "JuvenileMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].JuvenileMass; break; case "AdultMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].AdultMass; break; case "IndividualBodyMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].IndividualBodyMass; break; case "CohortAbundance": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].CohortAbundance; break; case "BirthTimeStep": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = (double)CellCohorts[functionalGroupIndex][cohortIndex].BirthTimeStep; break; case "MaturityTimeStep": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = (double)CellCohorts[functionalGroupIndex][cohortIndex].MaturityTimeStep; break; case "LogOptimalPreyBodySizeRatio": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].LogOptimalPreyBodySizeRatio; break; case "MaximumAchievedBodyMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].MaximumAchievedBodyMass; break; case "Merged": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = (double)CellCohorts[functionalGroupIndex][cohortIndex].BirthTimeStep; break; case "TrophicIndex": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].BirthTimeStep; break; case "ProportionTimeActive": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].ProportionTimeActive; break; } } } } return State; }
/// <summary> /// Record dispersal events in the dispersal tracker /// </summary> /// <param name="inboundCohorts">The cohorts arriving in a grid cell in the current time step</param> /// <param name="outboundCohorts">The cohorts leaving a ce ll in the current time step</param> /// <param name="outboundCohortWeights">The body masses of cohorts leaving the cell in the current time step</param> /// <param name="currentTimeStep">The current model time step</param> /// <param name="madingleyModelGrid">The model grid</param> public void RecordDispersal(uint[, ,] inboundCohorts, uint[, ,] outboundCohorts, List<double>[,] outboundCohortWeights, uint currentTimeStep, ModelGrid madingleyModelGrid) { // Loop through cells in the grid and write out the necessary data for (uint ii = 0; ii < outboundCohorts.GetLength(0); ii++) { for (uint jj = 0; jj < outboundCohorts.GetLength(1); jj++) { double MeanOutboundCohortWeight = new double(); // Calculate the mean weight of outbound cohorts (ignoring abundance) if (outboundCohortWeights[ii, jj].Count == 0) { MeanOutboundCohortWeight = 0.0; } else { MeanOutboundCohortWeight = outboundCohortWeights[ii, jj].Average(); } // Calculate the mean weight of all cohorts (ignoring abundance) List<double> TempList = new List<double>(); GridCellCohortHandler Temp1 = madingleyModelGrid.GetGridCellCohorts(ii, jj); // Loop through functional groups for (int kk = 0; kk < Temp1.Count; kk++) { // Loop through cohorts for (int hh = 0; hh < Temp1[kk].Count;hh++) { // Add the cohort weight to the list TempList.Add(Temp1[kk][hh].IndividualBodyMass); } } // Calculate the mean weight double MeanCohortWeight = new double(); if (TempList.Count == 0) { MeanCohortWeight = 0.0; } else { MeanCohortWeight = TempList.Average(); } string newline = Convert.ToString(currentTimeStep) + '\t' + Convert.ToString(ii) + '\t' + Convert.ToString(jj) + '\t' + Convert.ToString(madingleyModelGrid.GetCellLatitude(ii)) + '\t' + Convert.ToString(madingleyModelGrid.GetCellLongitude(jj)) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 0]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 1]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 2]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 3]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 4]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 5]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 6]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 7]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 0]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 1]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 2]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 3]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 4]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 5]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 6]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 7]) + '\t' + Convert.ToString(String.Format("{0:.000000}", MeanOutboundCohortWeight) + '\t' + Convert.ToString(String.Format("{0:.000000}", MeanCohortWeight))); SyncedDispersalWriter.WriteLine(newline); } } }
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> /// Calculates the abundances and biomasses within mass bins for all functional groups in the cohort indices array /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">List of indices of active cells in the model grid</param> /// <param name="cellIndex">The number of the current cell in the list of indices of active cells</param> /// <param name="marineCell">Whether the current cell is a marine cell</param> private void CalculateMassBinOutputs(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellIndex, Boolean marineCell) { string[] Keys; if (marineCell) { // Get the cohort trait combinations to consider Keys = CohortTraitIndicesMarine.Keys.ToArray(); } else { // Get the cohort trait combinations to consider Keys = CohortTraitIndices.Keys.ToArray(); } // Loop over trait combinations foreach (var TraitValue in Keys) { // Declare vectors to hold abundance and biomass in mass bins for this trait combination double[] WorkingAbundanceInMassBins = new double[MassBinNumber]; double[] WorkingBiomassInMassBins = new double[MassBinNumber]; // Declare arrays to hold abundance and biomass in juvenile vs. adult mass bins for this trait combination double[,] WorkingAbundanceJuvenileAdultMassBins = new double[MassBinNumber, MassBinNumber]; double[,] WorkingBiomassJuvenileAdultMassBins = new double[MassBinNumber, MassBinNumber]; // Create a temporary local copy of the cohorts in this grid cell GridCellCohortHandler TempCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0],cellIndices[cellIndex][1]); if (marineCell) { // Loop over functional groups foreach (int FunctionalGroupIndex in CohortTraitIndicesMarine[TraitValue]) { // Loop over all cohorts in this functional group for (int cohort = 0; cohort < TempCohorts[FunctionalGroupIndex].Count; cohort++) { // Find the appropriate mass bin for the cohort int mb = 0; do { mb++; } while (mb < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass > MassBins[mb]); // Add the cohort's abundance to the approriate mass bin. Note that we have to differentiate here for non-obligate zooplankton, because they are only added in if they are // below the zooplankton mass threshold (or an obligate zooplankton) if (String.Equals(TraitValue, "Zooplankton (all)")) { if (TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass < PlanktonSizeThreshold || CohortTraitIndicesMarine["Obligate zooplankton"].Contains(FunctionalGroupIndex)) { WorkingAbundanceInMassBins[mb - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance; // Add the cohort's biomass to the approriate mass bin WorkingBiomassInMassBins[mb - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance * TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass; // Find the mass bin appropriate for this cohort's juvenile mass int j = 0; do { j++; } while (j < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].JuvenileMass > MassBins[j]); // Find the mass bin appropriate for this cohort's adult mass int a = 0; do { a++; } while (a < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].AdultMass > MassBins[a]); // Add the cohort's abundance to this adult vs juvenile mass bins WorkingAbundanceJuvenileAdultMassBins[a - 1, j - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance; // Add the cohort's biomass to this adult vs juvenile mass bins WorkingBiomassJuvenileAdultMassBins[a - 1, j - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance * TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass; } } else { WorkingAbundanceInMassBins[mb - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance; // Add the cohort's biomass to the approriate mass bin WorkingBiomassInMassBins[mb - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance * TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass; // Find the mass bin appropriate for this cohort's juvenile mass int j = 0; do { j++; } while (j < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].JuvenileMass > MassBins[j]); // Find the mass bin appropriate for this cohort's adult mass int a = 0; do { a++; } while (a < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].AdultMass > MassBins[a]); // Add the cohort's abundance to this adult vs juvenile mass bins WorkingAbundanceJuvenileAdultMassBins[a - 1, j - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance; // Add the cohort's biomass to this adult vs juvenile mass bins WorkingBiomassJuvenileAdultMassBins[a - 1, j - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance * TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass; } } } //Copy the working vectors and arrays to the sortedlist for the current key value AbundancesInMassBins[TraitValue] = WorkingAbundanceInMassBins; BiomassesInMassBins[TraitValue] = WorkingBiomassInMassBins; AbundancesInJuvenileAdultMassBins[TraitValue] = WorkingAbundanceJuvenileAdultMassBins; BiomassesInJuvenileAdultMassBins[TraitValue] = WorkingBiomassJuvenileAdultMassBins; } else { // Loop over functional groups foreach (int FunctionalGroupIndex in CohortTraitIndices[TraitValue]) { // Loop over all cohorts in this functional group for (int cohort = 0; cohort < TempCohorts[FunctionalGroupIndex].Count; cohort++) { // Find the appropriate mass bin for the cohort int mb = 0; do { mb++; } while (mb < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass > MassBins[mb]); // Add the cohort's abundance to the approriate mass bin WorkingAbundanceInMassBins[mb - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance; // Add the cohort's biomass to the approriate mass bin WorkingBiomassInMassBins[mb - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance * TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass; // Find the mass bin appropriate for this cohort's juvenile mass int j = 0; do { j++; } while (j < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].JuvenileMass > MassBins[j]); // Find the mass bin appropriate for this cohort's adult mass int a = 0; do { a++; } while (a < (MassBins.Length - 1) && TempCohorts[FunctionalGroupIndex][cohort].AdultMass > MassBins[a]); // Add the cohort's abundance to this adult vs juvenile mass bins WorkingAbundanceJuvenileAdultMassBins[a - 1, j - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance; // Add the cohort's biomass to this adult vs juvenile mass bins WorkingBiomassJuvenileAdultMassBins[a - 1, j - 1] += TempCohorts[FunctionalGroupIndex][cohort].CohortAbundance * TempCohorts[FunctionalGroupIndex][cohort].IndividualBodyMass; } } //Copy the working vectors and arrays to the sortedlist for the current key value AbundancesInMassBins[TraitValue] = WorkingAbundanceInMassBins; BiomassesInMassBins[TraitValue] = WorkingBiomassInMassBins; AbundancesInJuvenileAdultMassBins[TraitValue] = WorkingAbundanceJuvenileAdultMassBins; BiomassesInJuvenileAdultMassBins[TraitValue] = WorkingBiomassJuvenileAdultMassBins; } } // Loop over trait combinations and log abundances and body masses foreach (var TraitValue in Keys) { for (int i = 0; i < MassBins.Length; i++) { AbundancesInMassBins[TraitValue][i] = (AbundancesInMassBins[TraitValue][i] > 0) ? Math.Log(AbundancesInMassBins[TraitValue][i]) : ecosystemModelGrid.GlobalMissingValue; BiomassesInMassBins[TraitValue][i] = (BiomassesInMassBins[TraitValue][i] > 0) ? Math.Log(BiomassesInMassBins[TraitValue][i]) : ecosystemModelGrid.GlobalMissingValue; for (int j = 0; j < MassBins.Length; j++) { AbundancesInJuvenileAdultMassBins[TraitValue][i, j] = (AbundancesInJuvenileAdultMassBins[TraitValue][i, j] > 0) ? Math.Log(AbundancesInJuvenileAdultMassBins[TraitValue][i, j]) : ecosystemModelGrid.GlobalMissingValue; BiomassesInJuvenileAdultMassBins[TraitValue][i, j] = (BiomassesInJuvenileAdultMassBins[TraitValue][i, j] > 0) ? Math.Log(BiomassesInJuvenileAdultMassBins[TraitValue][i, j]) : ecosystemModelGrid.GlobalMissingValue; } } } }
public void OutputCurrentModelState(ModelGrid currentModelGrid, List <uint[]> cellIndices, uint currentTimestep) { GridCellCohortHandler TempCohorts; GridCellStockHandler TempStocks; string context; string organism; context = Convert.ToString(currentTimestep) + "\t"; using (var StateWriter = File.AppendText(this.FileName)) { foreach (uint[] cell in cellIndices) { context = Convert.ToString(currentTimestep) + "\t" + Convert.ToString(currentModelGrid.GetCellLatitude(cell[0])) + "\t" + Convert.ToString(currentModelGrid.GetCellLongitude(cell[1])) + "\t"; TempStocks = currentModelGrid.GetGridCellStocks(cell[0], cell[1]); TempCohorts = currentModelGrid.GetGridCellCohorts(cell[0], cell[1]); foreach (List <Stock> ListS in TempStocks) { foreach (Stock S in ListS) { organism = "-999\tS" + Convert.ToString(S.FunctionalGroupIndex) + "\t" + "-999\t-999\t" + Convert.ToString(S.IndividualBodyMass) + "\t" + Convert.ToString(S.TotalBiomass / S.IndividualBodyMass) + "\t" + "-999\t-999\t-999\t-999\t-999\t-999"; StateWriter.WriteLine(context + organism); } } foreach (List <Cohort> ListC in TempCohorts) { foreach (Cohort C in ListC) { #if true var cohortIds = C.CohortID.Select(id => Convert.ToString(id)); organism = String.Join(";", cohortIds) + "\t" + #else organism = Convert.ToString(C.CohortID) + "\t" + #endif Convert.ToString(C.FunctionalGroupIndex) + "\t" + Convert.ToString(C.JuvenileMass) + "\t" + Convert.ToString(C.AdultMass) + "\t" + Convert.ToString(C.IndividualBodyMass) + "\t" + Convert.ToString(C.CohortAbundance) + "\t" + Convert.ToString(C.BirthTimeStep) + "\t" + Convert.ToString(C.MaturityTimeStep) + "\t" + Convert.ToString(C.LogOptimalPreyBodySizeRatio) + "\t" + Convert.ToString(C.MaximumAchievedBodyMass) + "\t" + Convert.ToString(C.TrophicIndex) + "\t" + Convert.ToString(C.ProportionTimeActive); StateWriter.WriteLine(context + organism); } } } } }
/// <summary> /// Return the distribution of biomasses among trophic level bins /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of cell indices to be run in the current model simulation</param> /// <param name="cellIndex">The index of the current cell in the list of cells to be run</param> /// <returns>The distribution of biomasses among trophic level bins</returns> public double[] CalculateTrophicDistribution(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double[] TrophicIndexBinMasses = new double[NumberTrophicBins]; int BinIndex; foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { BinIndex = _TrophicIndexBinValues.ToList().IndexOf(_TrophicIndexBinValues.Last(x => x < c.TrophicIndex)); TrophicIndexBinMasses[BinIndex] += (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; } } return TrophicIndexBinMasses; }
/// <summary> /// Calculates the geometric community weighted mean body mass /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of cells to be run in the current model simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to be run</param> /// <returns>geometric community weighted mean body mass</returns> public double CalculateGeometricCommunityMeanBodyMass(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double CumulativeAbundance = 0.0; double CumulativeLogBiomass = 0.0; //Retrieve the biomass foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { CumulativeLogBiomass += Math.Log(c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; CumulativeAbundance += c.CohortAbundance; } } double CWGMBM = Math.Exp(CumulativeLogBiomass / CumulativeAbundance); return (CWGMBM); }
/// <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 }); }
public void OutputCurrentModelState(ModelGrid currentModelGrid, FunctionalGroupDefinitions functionalGroupHandler, List<uint[]> cellIndices, uint currentTimestep, int maximumNumberOfCohorts, string filename) { float[] Latitude = currentModelGrid.Lats; float[] Longitude = currentModelGrid.Lons; float[] CohortFunctionalGroup = new float[functionalGroupHandler.GetNumberOfFunctionalGroups()]; for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { CohortFunctionalGroup[fg] = fg; } int CellCohortNumber = 0; GridCellCohortHandler CellCohorts; for (int cellIndex = 0; cellIndex < cellIndices.Count; cellIndex++) { CellCohorts = currentModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); for (int i = 0; i < CellCohorts.Count; i++) { if (CellCohorts[i].Count > CellCohortNumber) CellCohortNumber = CellCohorts[i].Count; } } int MaxNumberCohorts = Math.Max(CellCohortNumber, maximumNumberOfCohorts); float[] Cohort = new float[MaxNumberCohorts]; for (int c = 0; c < Cohort.Length; c++) { Cohort[c] = c; } //Define an array for stock functional group - there are only three currently float[] StockFunctionalGroup = new float[] { 1, 2, 3 }; //Define an array for index of stocks - there is only one currently float[] Stock = new float[] { 1 }; string Filename = filename + "_" + currentTimestep.ToString() + Simulation.ToString(); StateOutput = SDSCreator.CreateSDS("netCDF", Filename, _OutputPath); //Define the cohort properties for output string[] CohortProperties = new string[] {"JuvenileMass", "AdultMass", "IndividualBodyMass", "CohortAbundance", "BirthTimeStep", "MaturityTimeStep", "LogOptimalPreyBodySizeRatio", "MaximumAchievedBodyMass","Merged","TrophicIndex","ProportionTimeActive"}; //define the dimensions for cohort outputs string[] dims = new string[] { "Latitude", "Longitude", "Cohort Functional Group", "Cohort" }; // Add the variables for each cohort property // Then calculate the state for this property and put the data to this variable foreach (string v in CohortProperties) { DataConverter.AddVariable(StateOutput, "Cohort" + v, 4, dims, currentModelGrid.GlobalMissingValue, Latitude, Longitude, CohortFunctionalGroup, Cohort); StateOutput.PutData<double[, , ,]>("Cohort" + v, CalculateCurrentCohortState(currentModelGrid, v, Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length, cellIndices)); StateOutput.Commit(); } //Define the stock properties for output string[] StockProperties = new string[] { "IndividualBodyMass", "TotalBiomass" }; //define the dimensions for cohort outputs dims = new string[] { "Latitude", "Longitude", "Stock Functional Group", "Stock" }; // Add the variables for each stock property // Then calculate the state for this property and put the data to this variable foreach (string v in StockProperties) { DataConverter.AddVariable(StateOutput, "Stock" + v, 4, dims, currentModelGrid.GlobalMissingValue, Latitude, Longitude, StockFunctionalGroup, Stock); StateOutput.PutData<double[, , ,]>("Stock" + v, CalculateCurrentStockState(currentModelGrid, v, Latitude.Length, Longitude.Length, StockFunctionalGroup.Length, Stock.Length, cellIndices)); StateOutput.Commit(); } //Close this data set StateOutput.Dispose(); }
private double[, , ,] CalculateCurrentCohortState(ModelGrid currentModelState, string variableName, int numLats, int numLons, int numFG, int numCohorts, List <uint[]> cellList) { //Calculate the cohort state double[, , ,] State = new double[numLats, numLons, numFG, numCohorts]; GridCellCohortHandler CellCohorts; for (int cellIndex = 0; cellIndex < cellList.Count; cellIndex++) { CellCohorts = currentModelState.GetGridCellCohorts(cellList[cellIndex][0], cellList[cellIndex][1]); for (int functionalGroupIndex = 0; functionalGroupIndex < CellCohorts.Count; functionalGroupIndex++) { for (int cohortIndex = 0; cohortIndex < CellCohorts[functionalGroupIndex].Count; cohortIndex++) { switch (variableName) { case "JuvenileMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].JuvenileMass; break; case "AdultMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].AdultMass; break; case "IndividualBodyMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].IndividualBodyMass; break; case "CohortAbundance": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].CohortAbundance; break; case "BirthTimeStep": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = (double)CellCohorts[functionalGroupIndex][cohortIndex].BirthTimeStep; break; case "MaturityTimeStep": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = (double)CellCohorts[functionalGroupIndex][cohortIndex].MaturityTimeStep; break; case "LogOptimalPreyBodySizeRatio": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].LogOptimalPreyBodySizeRatio; break; case "MaximumAchievedBodyMass": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].MaximumAchievedBodyMass; break; case "Merged": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = Convert.ToDouble(CellCohorts[functionalGroupIndex][cohortIndex].Merged); break; case "TrophicIndex": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].TrophicIndex; break; case "ProportionTimeActive": State[cellList[cellIndex][0], cellList[cellIndex][1], functionalGroupIndex, cohortIndex] = CellCohorts[functionalGroupIndex][cohortIndex].ProportionTimeActive; break; } } } } return(State); }
public void OutputCurrentModelState(ModelGrid currentModelGrid, FunctionalGroupDefinitions functionalGroupHandler, List <uint[]> cellIndices, uint currentTimestep, int maximumNumberOfCohorts, string filename) { float[] Latitude = currentModelGrid.Lats; float[] Longitude = currentModelGrid.Lons; float[] CohortFunctionalGroup = new float[functionalGroupHandler.GetNumberOfFunctionalGroups()]; for (int fg = 0; fg < CohortFunctionalGroup.Length; fg++) { CohortFunctionalGroup[fg] = fg; } int CellCohortNumber = 0; GridCellCohortHandler CellCohorts; for (int cellIndex = 0; cellIndex < cellIndices.Count; cellIndex++) { CellCohorts = currentModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); for (int i = 0; i < CellCohorts.Count; i++) { if (CellCohorts[i].Count > CellCohortNumber) { CellCohortNumber = CellCohorts[i].Count; } } } int MaxNumberCohorts = Math.Max(CellCohortNumber, maximumNumberOfCohorts); float[] Cohort = new float[MaxNumberCohorts]; for (int c = 0; c < Cohort.Length; c++) { Cohort[c] = c; } //Define an array for stock functional group - there are only three currently float[] StockFunctionalGroup = new float[] { 1, 2, 3 }; //Define an array for index of stocks - there is only one currently float[] Stock = new float[] { 1 }; string Filename = filename + "_" + currentTimestep.ToString() + Simulation.ToString(); StateOutput = SDSCreator.CreateSDS("netCDF", Filename, _OutputPath); //Define the cohort properties for output string[] CohortProperties = new string[] { "JuvenileMass", "AdultMass", "IndividualBodyMass", "IndividualReproductivePotentialMass", "CohortAbundance", "BirthTimeStep", "MaturityTimeStep", "LogOptimalPreyBodySizeRatio", "MaximumAchievedBodyMass", "Merged", "TrophicIndex", "ProportionTimeActive" }; //define the dimensions for cohort outputs string[] dims = new string[] { "Latitude", "Longitude", "Cohort Functional Group", "Cohort" }; // Add the variables for each cohort property // Then calculate the state for this property and put the data to this variable foreach (string v in CohortProperties) { DataConverter.AddVariable(StateOutput, "Cohort" + v, 4, dims, currentModelGrid.GlobalMissingValue, Latitude, Longitude, CohortFunctionalGroup, Cohort); StateOutput.PutData <double[, , , ]>("Cohort" + v, CalculateCurrentCohortState(currentModelGrid, v, Latitude.Length, Longitude.Length, CohortFunctionalGroup.Length, Cohort.Length, cellIndices)); StateOutput.Commit(); } //Define the stock properties for output string[] StockProperties = new string[] { "IndividualBodyMass", "TotalBiomass" }; //define the dimensions for cohort outputs dims = new string[] { "Latitude", "Longitude", "Stock Functional Group", "Stock" }; // Add the variables for each stock property // Then calculate the state for this property and put the data to this variable foreach (string v in StockProperties) { DataConverter.AddVariable(StateOutput, "Stock" + v, 4, dims, currentModelGrid.GlobalMissingValue, Latitude, Longitude, StockFunctionalGroup, Stock); StateOutput.PutData <double[, , , ]>("Stock" + v, CalculateCurrentStockState(currentModelGrid, v, Latitude.Length, Longitude.Length, StockFunctionalGroup.Length, Stock.Length, cellIndices)); StateOutput.Commit(); } //Close this data set StateOutput.Dispose(); }
/// <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 void OutputCurrentModelState(ModelGrid currentModelGrid, List<uint[]> cellIndices, uint currentTimestep) { GridCellCohortHandler TempCohorts; GridCellStockHandler TempStocks; string context; string organism; context = Convert.ToString(currentTimestep) + "\t"; using (var StateWriter = File.AppendText(this.FileName)) { foreach (uint[] cell in cellIndices) { context = Convert.ToString(currentTimestep) + "\t" + Convert.ToString(currentModelGrid.GetCellLatitude(cell[0])) + "\t" + Convert.ToString(currentModelGrid.GetCellLongitude(cell[1])) + "\t"; TempStocks = currentModelGrid.GetGridCellStocks(cell[0], cell[1]); TempCohorts = currentModelGrid.GetGridCellCohorts(cell[0], cell[1]); foreach (List<Stock> ListS in TempStocks) { foreach (Stock S in ListS) { organism = "-999\tS" + Convert.ToString(S.FunctionalGroupIndex) + "\t" + "-999\t-999\t" + Convert.ToString(S.IndividualBodyMass) + "\t" + Convert.ToString(S.TotalBiomass / S.IndividualBodyMass) + "\t" + "-999\t-999\t-999\t-999\t-999\t-999"; StateWriter.WriteLine(context + organism); } } foreach (List<Cohort> ListC in TempCohorts) { foreach (Cohort C in ListC) { #if true var cohortIds = C.CohortID.Select(id => Convert.ToString(id)); organism = String.Join(";", cohortIds) + "\t" + #else organism = Convert.ToString(C.CohortID) + "\t" + #endif Convert.ToString(C.FunctionalGroupIndex) + "\t" + Convert.ToString(C.JuvenileMass) + "\t" + Convert.ToString(C.AdultMass) + "\t" + Convert.ToString(C.IndividualBodyMass) + "\t" + Convert.ToString(C.CohortAbundance) + "\t" + Convert.ToString(C.BirthTimeStep) + "\t" + Convert.ToString(C.MaturityTimeStep) + "\t" + Convert.ToString(C.LogOptimalPreyBodySizeRatio) + "\t" + Convert.ToString(C.MaximumAchievedBodyMass) + "\t" + Convert.ToString(C.TrophicIndex) + "\t" + Convert.ToString(C.ProportionTimeActive); StateWriter.WriteLine(context + organism); } } } } }
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> /// Sets up the outputs associated with the high level of output detail /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The indices of active cells in the model grid</param> /// <param name="cellNumber">The index of the current cell in the list of active cells</param> /// <param name="cohortFunctionalGroupDefinitions">The functional group definitions for cohorts in the model</param> /// <param name="marineCell">Whether the current cell is a marine cell</param> private void SetUpHighLevelOutputs(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellNumber, FunctionalGroupDefinitions cohortFunctionalGroupDefinitions, Boolean marineCell) { // Create an SDS object for outputs by mass bin // MassBinsOutput = SDSCreator.CreateSDS("netCDF", "MassBins" + _OutputSuffix, _OutputPath); MassBinsOutputMemory = SDSCreator.CreateSDSInMemory(true); // Add relevant output variables to the mass bin output file string[] MassBinDimensions = { "Time step", "Mass bin" }; string[] DoubleMassBinDimensions = new string[] { "Adult Mass bin", "Juvenile Mass bin", "Time step" }; if (OutputMetrics) { DataConverter.AddVariable(MassBinsOutputMemory, "Trophic Index Distribution", 2, new string[] {"Time step","Trophic Index Bins"}, ecosystemModelGrid.GlobalMissingValue, TimeSteps, Metrics.TrophicIndexBinValues); } if (marineCell) { foreach (string TraitValue in CohortTraitIndicesMarine.Keys) { DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " abundance in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " biomass in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " abundance in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " biomass in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); } } else { foreach (string TraitValue in CohortTraitIndices.Keys) { DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " abundance in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " biomass in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " abundance in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValue + " biomass in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); } } // Create an SDS object in memory for tracked cohorts outputs // TrackedCohortsOutput = SDSCreator.CreateSDS("netCDF", "TrackedCohorts" + _OutputSuffix, _OutputPath); TrackedCohortsOutputMemory = SDSCreator.CreateSDSInMemory(true); // Initialise list to hold tracked cohorts TrackedCohorts = new List<uint>(); // Identify cohorts to track GridCellCohortHandler TempCohorts = null; bool FoundCohorts = false; // Get a local copy of the cohorts in the grid cell TempCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellNumber][0], cellIndices[cellNumber][1]); // Loop over functional groups and check whether any cohorts exist in this grid cell foreach (var CohortList in TempCohorts) { if (CohortList.Count > 0) { FoundCohorts = true; break; } } // If there are some cohorts in the grid cell, then setup the tracked cohorts if (FoundCohorts) { // Initialise stream writer to hold details of tracked cohorts StreamWriter sw = new StreamWriter(_OutputPath + "TrackedCohortProperties" + _OutputSuffix + ".txt"); sw.WriteLine("Output ID\tCohort ID\tFunctional group index\tNutrition source\tDiet\tRealm\tMobility\tJuvenile mass\tAdult mass"); // Counter for tracked cohorts int TrackedCohortCounter = 0; for (int i = 0; i < TempCohorts.Count; i++) { if (TempCohorts[i].Count > 0) { for (int j = 0; j < TempCohorts[i].Count; j++) { // Write out properties of the selected cohort sw.WriteLine(Convert.ToString(TrackedCohortCounter) + '\t' + Convert.ToString(TempCohorts[i][j].CohortID[0]) + '\t' + i + '\t' + cohortFunctionalGroupDefinitions.GetTraitNames("Nutrition source", i) + '\t' + cohortFunctionalGroupDefinitions. GetTraitNames("Diet", i) + '\t' + cohortFunctionalGroupDefinitions.GetTraitNames("Realm", i) + '\t' + cohortFunctionalGroupDefinitions.GetTraitNames("Mobility", i) + '\t' + TempCohorts[i][j].JuvenileMass + '\t' + TempCohorts[i][j].AdultMass); // Add the ID of the cohort to the list of tracked cohorts TrackedCohorts.Add(TempCohorts[i][j].CohortID[0]); // Increment the counter of tracked cohorts TrackedCohortCounter++; } } } // Generate an array of floating points to index the tracked cohorts in the output file float[] OutTrackedCohortIDs = new float[TrackedCohortCounter]; for (int i = 0; i < TrackedCohortCounter; i++) { OutTrackedCohortIDs[i] = i; } // Set up outputs for tracked cohorts string[] TrackedCohortsDimensions = { "Time step", "Cohort ID" }; // Add output variables for the tracked cohorts output DataConverter.AddVariable(TrackedCohortsOutputMemory, "Individual body mass", 2, TrackedCohortsDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, OutTrackedCohortIDs); DataConverter.AddVariable(TrackedCohortsOutputMemory, "Number of individuals", 2, TrackedCohortsDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, OutTrackedCohortIDs); // Dispose of the streamwriter sw.Dispose(); } // Get a list of all possible combinations of trait values as a jagged array string[][] TraitValueSearch; if (marineCell) TraitValueSearch = CalculateAllCombinations(CohortTraitValuesMarine[CohortTraits[0]], CohortTraitValuesMarine[CohortTraits[1]]); else TraitValueSearch = CalculateAllCombinations(CohortTraitValues[CohortTraits[0]], CohortTraitValues[CohortTraits[1]]); // Add the functional group indices of these trait combinations to the list of indices of the trait values to consider, // keyed with a concatenated version of the trait values string TraitValueJoin = ""; string[] TimeDimension = { "Time step" }; for (int i = 0; i < TraitValueSearch.Count(); i++) { TraitValueJoin = ""; foreach (string TraitValue in TraitValueSearch[i]) { TraitValueJoin += TraitValue + " "; } if (marineCell) { // Only add indices of marine functional groups int[] TempIndices = cohortFunctionalGroupDefinitions.GetFunctionalGroupIndex(CohortTraits, TraitValueSearch[i], true); Boolean[] TempIndices2 = new Boolean[TempIndices.GetLength(0)]; for (int ii = 0; ii < TempIndices.GetLength(0); ii++) { if (cohortFunctionalGroupDefinitions.GetTraitNames("Realm", TempIndices[ii]).Equals("Marine", StringComparison.OrdinalIgnoreCase)) { TempIndices2[ii] = true; } } // Extract only the indices which are marine int[] TempIndices3 = Enumerable.Range(0, TempIndices2.Length).Where(zz => TempIndices2[zz]).ToArray(); if (TempIndices3.Length > 0) { // Extract the values at these indices for (int ii = 0; ii < TempIndices3.Length; ii++) { TempIndices3[ii] = TempIndices[TempIndices3[ii]]; } // Add in the indices for this functional group and this realm CohortTraitIndices.Add(TraitValueJoin, TempIndices3); DataConverter.AddVariable(BasicOutputMemory, TraitValueJoin + " density", "Individuals / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps); DataConverter.AddVariable(BasicOutputMemory, TraitValueJoin + " biomass density", "Kg / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " abundance in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " biomass in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " abundance in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " biomass in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); TotalBiomassDensitiesOut.Add(TraitValueJoin, 0.0); TotalDensitiesOut.Add(TraitValueJoin, 0.0); } } else { // Only add indices of terrestrial functional groups int[] TempIndices = cohortFunctionalGroupDefinitions.GetFunctionalGroupIndex(CohortTraits, TraitValueSearch[i], true); Boolean[] TempIndices2 = new Boolean[TempIndices.GetLength(0)]; for (int ii = 0; ii < TempIndices.GetLength(0); ii++) { if (cohortFunctionalGroupDefinitions.GetTraitNames("Realm", TempIndices[ii]).Equals("Terrestrial", StringComparison.OrdinalIgnoreCase)) { TempIndices2[ii] = true; } } // Extract only the indices which are terrestrial int[] TempIndices3 = Enumerable.Range(0, TempIndices2.Length).Where(zz => TempIndices2[zz]).ToArray(); if (TempIndices3.Length > 0) { // Extract the values at these indices for (int ii = 0; ii < TempIndices3.Length; ii++) { TempIndices3[ii] = TempIndices[TempIndices3[ii]]; } // Add in the indices for this functional group and this realm CohortTraitIndices.Add(TraitValueJoin, TempIndices3); DataConverter.AddVariable(BasicOutputMemory, TraitValueJoin + " density", "Individuals / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps); DataConverter.AddVariable(BasicOutputMemory, TraitValueJoin + " biomass density", "Kg / km^2", 1, TimeDimension, ecosystemModelGrid.GlobalMissingValue, TimeSteps); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " abundance in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " biomass in mass bins", 2, MassBinDimensions, ecosystemModelGrid.GlobalMissingValue, TimeSteps, MassBins); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " abundance in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); DataConverter.AddVariable(MassBinsOutputMemory, "Log " + TraitValueJoin + " biomass in juvenile vs adult bins", 3, DoubleMassBinDimensions, ecosystemModelGrid.GlobalMissingValue, MassBins, MassBins, TimeSteps); TotalBiomassDensitiesOut.Add(TraitValueJoin, 0.0); TotalDensitiesOut.Add(TraitValueJoin, 0.0); } } } }
/// <summary> /// Calculates the mean trophic level of all individual organisms in a grid cell /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of cell indices in the current model simulation</param> /// <param name="cellIndex">The index of the current cell in the list of cells to run</param> /// <returns>The mean trophic level of individuals in the grid cell</returns> public double CalculateMeanTrophicLevelCell(ModelGrid ecosystemModelGrid,List<uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); double BiomassWeightedTI = 0.0; double TotalBiomass = 0.0; double CohortBiomass = 0.0; foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { CohortBiomass = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; BiomassWeightedTI += CohortBiomass * c.TrophicIndex; TotalBiomass += CohortBiomass; } } return BiomassWeightedTI/TotalBiomass; }
/// <summary> /// Calculate outputs associated with high-level outputs /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">List of indices of active cells in the model grid</param> /// <param name="cellIndex">The number of the current cell in the list of active cells</param> /// <param name="marineCell">Whether the current cell is a marine cell</param> private void CalculateHighLevelOutputs(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellIndex, Boolean marineCell) { // Calcalate the outputs arranged by mass bin CalculateMassBinOutputs(ecosystemModelGrid, cellIndices, cellIndex, marineCell); // Declare vectors to hold properties of tracked cohorts TrackedCohortIndividualMasses = new double[TrackedCohorts.Count]; TrackedCohortAbundances = new double[TrackedCohorts.Count]; // Get a temporary local copy of the cohorts in the grid cell GridCellCohortHandler TempCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); // Loop over functional groups in the grid cell cohorts for (int j = 0; j < TempCohorts.Count; j++) { // Loop over cohorts within this functional group for (int k = 0; k < TempCohorts[j].Count; k++) { // Loop over all cohort IDs foreach (uint CohortID in TempCohorts[j][k].CohortID) { // Check whether the cohort ID corresponds to a tracked cohort if (TrackedCohorts.Contains(CohortID)) { // Get the position of the cohort in the list of tracked cohorts int position = TrackedCohorts.FindIndex( delegate(uint i) { return i == CohortID; }); // Add the body mass and abundance of the tracked cohort to the appropriate position in the output vector TrackedCohortIndividualMasses[position] = TempCohorts[j][k].IndividualBodyMass; TrackedCohortAbundances[position] = TempCohorts[j][k].CohortAbundance; } } } } }
/// <summary> /// Calculates trophic evenness using the FRO Index of Mouillot et al. /// </summary> /// <param name="ecosystemModelGrid">The model grid</param> /// <param name="cellIndices">The list of indices of cells to be run in the current model simulation</param> /// <param name="cellIndex">The index of the current cell within the list of cells to be run</param> /// <returns>Trophic evenness</returns> /// <remarks>From Mouillot et al (2005) Functional regularity: a neglected aspect of functional diversity, Oecologia</remarks> public double CalculateTrophicEvennessFRO(ModelGrid ecosystemModelGrid, List<uint[]> cellIndices, int cellIndex) { //Get the cohorts for the specified cell GridCellCohortHandler CellCohorts = ecosystemModelGrid.GetGridCellCohorts(cellIndices[cellIndex][0], cellIndices[cellIndex][1]); List<double[]> TrophicIndexBiomassDistribution = new List<double[]>(); double[] TIBiomass; double[] EW; foreach (var CohortList in CellCohorts) { foreach (Cohort c in CohortList) { TIBiomass = new double[2]; TIBiomass[0] = c.TrophicIndex; TIBiomass[1] = (c.IndividualBodyMass + c.IndividualReproductivePotentialMass) * c.CohortAbundance; TrophicIndexBiomassDistribution.Add(TIBiomass); } } TrophicIndexBiomassDistribution = TrophicIndexBiomassDistribution.OrderBy(x => x[0]).ToList(); //Use the Mouillot Evenness index - Functional Regularity Index or FRO //From Mouillot et al (2005) Functional regularity: a neglected aspect of functional diversity, Oecologia EW = new double[TrophicIndexBiomassDistribution.Count]; double TotalEW = 0.0 ; for (int ii = 0; ii < TrophicIndexBiomassDistribution.Count-1; ii++) { EW[ii] = (TrophicIndexBiomassDistribution[ii + 1][0] - TrophicIndexBiomassDistribution[ii][0]) / (TrophicIndexBiomassDistribution[ii + 1][1] + TrophicIndexBiomassDistribution[ii][1]); TotalEW += EW[ii]; } double FRO = 0.0; for (int ii = 0; ii < TrophicIndexBiomassDistribution.Count - 1; ii++) { FRO += Math.Min(EW[ii]/TotalEW,1.0/(TrophicIndexBiomassDistribution.Count-1)); } return FRO; }
/// <summary> /// Record dispersal events in the dispersal tracker /// </summary> /// <param name="inboundCohorts">The cohorts arriving in a grid cell in the current time step</param> /// <param name="outboundCohorts">The cohorts leaving a ce ll in the current time step</param> /// <param name="outboundCohortWeights">The body masses of cohorts leaving the cell in the current time step</param> /// <param name="currentTimeStep">The current model time step</param> /// <param name="madingleyModelGrid">The model grid</param> public void RecordDispersal(uint[, ,] inboundCohorts, uint[, ,] outboundCohorts, List <double>[,] outboundCohortWeights, uint currentTimeStep, ModelGrid madingleyModelGrid) { // Loop through cells in the grid and write out the necessary data for (uint ii = 0; ii < outboundCohorts.GetLength(0); ii++) { for (uint jj = 0; jj < outboundCohorts.GetLength(1); jj++) { double MeanOutboundCohortWeight = new double(); // Calculate the mean weight of outbound cohorts (ignoring abundance) if (outboundCohortWeights[ii, jj].Count == 0) { MeanOutboundCohortWeight = 0.0; } else { MeanOutboundCohortWeight = outboundCohortWeights[ii, jj].Average(); } // Calculate the mean weight of all cohorts (ignoring abundance) List <double> TempList = new List <double>(); GridCellCohortHandler Temp1 = madingleyModelGrid.GetGridCellCohorts(ii, jj); // Loop through functional groups for (int kk = 0; kk < Temp1.Count; kk++) { // Loop through cohorts for (int hh = 0; hh < Temp1[kk].Count; hh++) { // Add the cohort weight to the list TempList.Add(Temp1[kk][hh].IndividualBodyMass); } } // Calculate the mean weight double MeanCohortWeight = new double(); if (TempList.Count == 0) { MeanCohortWeight = 0.0; } else { MeanCohortWeight = TempList.Average(); } string newline = Convert.ToString(currentTimeStep) + '\t' + Convert.ToString(ii) + '\t' + Convert.ToString(jj) + '\t' + Convert.ToString(madingleyModelGrid.GetCellLatitude(ii)) + '\t' + Convert.ToString(madingleyModelGrid.GetCellLongitude(jj)) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 0]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 1]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 2]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 3]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 4]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 5]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 6]) + '\t' + Convert.ToString(outboundCohorts[ii, jj, 7]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 0]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 1]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 2]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 3]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 4]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 5]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 6]) + '\t' + Convert.ToString(inboundCohorts[ii, jj, 7]) + '\t' + Convert.ToString(String.Format("{0:.000000}", MeanOutboundCohortWeight) + '\t' + Convert.ToString(String.Format("{0:.000000}", MeanCohortWeight))); SyncedDispersalWriter.WriteLine(newline); } } }