public static void processPlant(ref Plant plant) { // calculate the tolerances, optimum levels, and sequestration rates float age = plant.age; float volume = (plant.rootDepth * plant.rootWidth) * 0.5f + plant.foliageHeight * plant.foliageWidth; //revise this, a cone has different volume // TODO: these two foreach loops can be merged at some point foreach (KeyValuePair <string, PlantNutrientManager> nutrient in plant.plantNutrientManagers) { nutrient.Value.assignNutrientTolerancesAndRates(volume, age); nutrient.Value.calculateSequestrationRates(); } sequestNutrient(ref plant); float limitingGrowthFactor = float.PositiveInfinity; float growthFactor; foreach (string name in plant.plantNutrientManagers.Keys) { PlantNutrientManager nutrient = plant.plantNutrientManagers[name]; setGrowthFactor(ref nutrient, ref plant, out growthFactor); //healthy, unhealthy etc if (growthFactor < limitingGrowthFactor) { limitingGrowthFactor = growthFactor; } } grow(limitingGrowthFactor, ref plant); }
private static void sequestNutrient(ref Plant plant) { Segment segment = plant.segment; float rootDepth = plant.rootDepth; //might overwrite, but shouldn't float rootRadius = plant.rootWidth / 2; SoilProfile soilProfile = segment.soilProfile; foreach (SoilHorizon soilHorizon in soilProfile.soilHorizons) { float x1 = Mathf.Abs(soilHorizon.upperBound); float x2 = Mathf.Abs(soilHorizon.lowerBound); x2 = x2 > rootDepth ? x2 : rootDepth; float volume = volumeInDiagonalSubsection(x1, x2, rootRadius, rootDepth); foreach (string name in plant.plantNutrientManagers.Keys) { PlantNutrientManager nutrient = plant.plantNutrientManagers[name]; nutrient.sequestNutrients(name, soilHorizon, volume); } } }
// TODO: optimize this method. Too much stuff in the if statements. private static void setGrowthFactor(ref PlantNutrientManager nutrient, ref Plant plant, out float growthFactor) { // TODO: currently a linear first approximation // consider changing this to gaussian distance // optimal growth factor is 1. float a, b; bool belowOptimal = nutrient.currentLevel < nutrient.optimalLevel; if (nutrient.currentLevel < nutrient.minAliveTolerance || nutrient.currentLevel > nutrient.maxAliveTolerance) { growthFactor = -1; plant.isAlive = false; return; } // if the current level is between the healthy levels, then the growth is positive if (belowOptimal && nutrient.currentLevel > nutrient.minHealthyTolerance) { a = 1 / (nutrient.optimalLevel - nutrient.minHealthyTolerance); b = -1 * a * nutrient.minHealthyTolerance; float value = a * nutrient.currentLevel + b; nutrient.setNutrientGrowthFactor(value); growthFactor = value; } else if (!belowOptimal && nutrient.currentLevel < nutrient.maxHealthyTolerance) { a = 1 / (nutrient.optimalLevel - nutrient.maxHealthyTolerance); b = -1 * a * nutrient.maxHealthyTolerance; float value = a * nutrient.currentLevel + b; nutrient.setNutrientGrowthFactor(value); growthFactor = value; } else { // if the current levels are outside the bounds then the growth rates are zero. nutrient.setNutrientGrowthFactor(0); growthFactor = 0; } }