/// <summary>Removes biomass from live and dead biomass pools and send to surface organic matter</summary> /// <param name="biomassRemoveType">Name of event that triggered this biomass remove call.</param> /// <param name="amount">The fractions of biomass to remove</param> /// <param name="Live">Live biomass pool</param> /// <param name="Dead">Dead biomass pool</param> /// <param name="Removed">The removed pool to add to.</param> /// <param name="Detached">The detached pool to add to.</param> /// <param name="writeToSummary">Write the biomass removal to summary file?</param> /// <returns>The remaining live fraction.</returns> public double RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType amount, Biomass Live, Biomass Dead, Biomass Removed, Biomass Detached, bool writeToSummary = true) { if (amount == null) amount = FindDefault(biomassRemoveType); double totalFractionToRemove = amount.FractionLiveToRemove + amount.FractionDeadToRemove + amount.FractionLiveToResidue + amount.FractionDeadToResidue; if (totalFractionToRemove > 0.0) { Biomass detaching; double remainingLiveFraction = RemoveBiomassFromLiveAndDead(amount, Live, Dead, out Removed, Detached, out detaching); // Add the detaching biomass to surface organic matter model. //TODO: theoretically the dead material is different from the live, so it should be added as a separate pool to SurfaceOM surfaceOrganicMatter.Add(detaching.Wt * 10, detaching.N * 10, 0.0, plant.CropType, Name); if (writeToSummary) { double toResidue = (amount.FractionLiveToResidue + amount.FractionDeadToResidue) / totalFractionToRemove * 100; double removedOff = (amount.FractionLiveToRemove + amount.FractionDeadToRemove) / totalFractionToRemove * 100; summary.WriteMessage(this, "Removing " + (totalFractionToRemove * 100).ToString("0.0") + "% of " + Parent.Name + " Biomass from " + plant.Name + ". Of this " + removedOff.ToString("0.0") + "% is removed from the system and " + toResidue.ToString("0.0") + "% is returned to the surface organic matter"); } return remainingLiveFraction; } return 1; }
protected void OnSimulationCommencing(object sender, EventArgs e) { DMDemand = new BiomassPoolType(); NDemand = new BiomassPoolType(); DMSupply = new BiomassSupplyType(); NSupply = new BiomassSupplyType(); potentialDMAllocation = new BiomassPoolType(); Detached = new Biomass(); Clear(); }
/// <summary>Clears this instance.</summary> protected virtual void Clear() { Live = new Biomass(); Dead = new Biomass(); DMSupply.Clear(); NSupply.Clear(); DMDemand.Clear(); NDemand.Clear(); potentialDMAllocation.Clear(); }
private void OnDoDailyInitialisation(object sender, EventArgs e) { if (Plant.IsAlive) { Allocated = new PMF.Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); } }
protected void OnSimulationCommencing(object sender, EventArgs e) { Allocated = new PMF.Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); NDemand = new BiomassPoolType(); DMDemand = new BiomassPoolType(); NSupply = new BiomassSupplyType(); DMSupply = new BiomassSupplyType(); }
private void SetNSupply(object sender, EventArgs e) { double LabileN = Math.Max(0, StartLive.StorageN - StartLive.StorageWt * MinimumNConc.Value()); Biomass Senescing = new Biomass(); GetSenescingLeafBiomass(out Senescing); NSupply.Reallocation = Senescing.StorageN * NReallocationFactor.Value(); NSupply.Retranslocation = (LabileN - StartNReallocationSupply) * NRetranslocationFactor.Value(); NSupply.Uptake = 0.0; }
private void GetSenescingLeafBiomass(out Biomass Senescing) { Senescing = new Biomass(); foreach (PerrenialLeafCohort L in Leaves) { if (L.Age >= LeafResidenceTime.Value()) { Senescing.Add(L.Live); } } }
protected void OnSimulationCommencing(object sender, EventArgs e) { startLive = new Biomass(); Allocated = new Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); Live = new Biomass(); Dead = new Biomass(); Clear(); }
public MockOrgan(string name, double liveWt, double deadWt = 0) { Name = name; Live = new Biomass() { StructuralWt = liveWt }; Dead = new Biomass() { StructuralWt = deadWt }; }
private void DetachLeaves(out Biomass Detached) { Detached = new Biomass(); foreach (PerrenialLeafCohort L in Leaves) { if (L.Age >= (LeafResidenceTime.Value() + LeafDetachmentTime.Value())) { Detached.Add(L.Dead); } } Leaves.RemoveAll(L => L.Age >= (LeafResidenceTime.Value() + LeafDetachmentTime.Value())); }
/// <summary>Removes biomass from organs when harvest, graze or cut events are called.</summary> /// <param name="biomassRemoveType">Name of event that triggered this biomass remove call.</param> /// <param name="amountToRemove">The fractions of biomass to remove</param> virtual public void RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType amountToRemove) { Biomass liveAfterRemoval = Live; Biomass deadAfterRemoval = Dead; biomassRemovalModel.RemoveBiomass(biomassRemoveType, amountToRemove, liveAfterRemoval, deadAfterRemoval, Removed, Detached); double remainingLiveFraction = MathUtilities.Divide(liveAfterRemoval.Wt, Live.Wt, 0); double remainingDeadFraction = MathUtilities.Divide(deadAfterRemoval.Wt, Dead.Wt, 0); cohort.ReduceLeavesUniformly(remainingLiveFraction, remainingDeadFraction); }
private void OnPlantEnding(object sender, EventArgs e) { Biomass total = Live + Dead; if (total.Wt > 0.0) { Detached.Add(Live); Detached.Add(Dead); SurfaceOrganicMatter.Add(total.Wt * 10, total.N * 10, 0, Plant.CropType, Name); } Clear(); }
/// <summary>Removes biomass from live and dead biomass pools, may send to surface organic matter</summary> /// <param name="biomassRemoveType">Name of event that triggered this biomass removal call.</param> /// <param name="amount">The fractions of biomass to remove</param> /// <param name="Live">Live biomass pool</param> /// <param name="Dead">Dead biomass pool</param> /// <param name="Removed">The removed pool to add to.</param> /// <param name="Detached">The detached pool to add to.</param> /// <param name="writeToSummary">Write the biomass removal to summary file?</param> /// <returns>The remaining live fraction.</returns> public double RemoveBiomass(string biomassRemoveType, OrganBiomassRemovalType amount, Biomass Live, Biomass Dead, Biomass Removed, Biomass Detached, bool writeToSummary = true) { if (amount == null) { amount = FindDefault(biomassRemoveType); } else { CheckRemoveFractions(biomassRemoveType, amount); } double liveFractionToRemove = amount.FractionLiveToRemove + amount.FractionLiveToResidue; double deadFractionToRemove = amount.FractionDeadToRemove + amount.FractionDeadToResidue; if (liveFractionToRemove + deadFractionToRemove > 0.0) { Biomass removing; Biomass detaching; double totalBiomass = Live.Wt + Dead.Wt; if (totalBiomass > 0) { double remainingLiveFraction = RemoveBiomassFromLiveAndDead(amount, Live, Dead, out removing, out detaching); // Add the detaching biomass to total removed and detached Removed.Add(removing); Detached.Add(detaching); // Pass the detaching biomass to surface organic matter model. //TODO: in reality, the dead material is different from the live, so it would be better to add them as separate pools to SurfaceOM surfaceOrganicMatter.Add(detaching.Wt * 10.0, detaching.N * 10.0, 0.0, plant.PlantType, Name); if (writeToSummary) { double totalFractionToRemove = (Removed.Wt + detaching.Wt) * 100.0 / totalBiomass; double toResidue = detaching.Wt * 100.0 / (Removed.Wt + detaching.Wt); double removedOff = Removed.Wt * 100.0 / (Removed.Wt + detaching.Wt); summary.WriteMessage(Parent, "Removing " + totalFractionToRemove.ToString("0.0") + "% of " + Parent.Name.ToLower() + " biomass from " + plant.Name + ". Of this " + removedOff.ToString("0.0") + "% is removed from the system and " + toResidue.ToString("0.0") + "% is returned to the surface organic matter."); summary.WriteMessage(Parent, "Removed " + Removed.Wt.ToString("0.0") + " g/m2 of dry matter weight and " + Removed.N.ToString("0.0") + " g/m2 of N."); } return(remainingLiveFraction); } } return(1.0); }
public override void DoNDemand1Pot(double dltDmPotRue) { Biomass OldGrowth = Growth; Growth.StructuralWt = dltDmPotRue * MathUtility.Divide(Live.Wt, TotalLive.Wt, 0.0); Util.Debug("Leaf.Growth.StructuralWt=%f", Growth.StructuralWt); Util.CalcNDemand(dltDmPotRue, dltDmPotRue, n_conc_crit, n_conc_max, Growth, Live, Retranslocation.N, 1.0, ref _NDemand, ref NMax); Growth.StructuralWt = 0.0; Growth.NonStructuralWt = 0.0; Util.Debug("Leaf.NDemand=%f", _NDemand); Util.Debug("Leaf.NMax=%f", NMax); }
/// <summary>Clears this instance.</summary> private void Clear() { Live = new Biomass(); Dead = new Biomass(); DMSupply.Clear(); NSupply.Clear(); DMDemand.Clear(); NDemand.Clear(); potentialDMAllocation.Clear(); Height = 0; LAI = 0; LeafInitialised = false; }
/// <summary>Calculate and return the nitrogen supply (g/m2)</summary> public virtual BiomassSupplyType CalculateNitrogenSupply() { double LabileN = Math.Max(0, StartLive.StorageN - StartLive.StorageWt * MinimumNConc.Value()); Biomass Senescing = new Biomass(); GetSenescingLeafBiomass(out Senescing); nitrogenSupply.Reallocation = Senescing.StorageN * NReallocationFactor.Value(); nitrogenSupply.Retranslocation = (LabileN - StartNReallocationSupply) * NRetranslocationFactor.Value(); nitrogenSupply.Uptake = 0.0; return(nitrogenSupply); }
private void KillLeavesUniformly(double fraction) { foreach (PerrenialLeafCohort L in Leaves) { Biomass Loss = new Biomass(); Loss.SetTo(L.Live); Loss.Multiply(fraction); L.Dead.Add(Loss); L.Live.Subtract(Loss); L.AreaDead += L.Area * fraction; L.Area *= (1 - fraction); } }
/// <summary>Clears this instance.</summary> protected virtual void Clear() { Live = new Biomass(); Dead = new Biomass(); DMSupply.Clear(); NSupply.Clear(); DMDemand.Clear(); NDemand.Clear(); potentialDMAllocation.Clear(); Allocated.Clear(); Senesced.Clear(); Detached.Clear(); Removed.Clear(); }
protected void OnSimulationCommencing(object sender, EventArgs e) { DMDemand = new BiomassPoolType(); DMDemandPriorityFactor = new BiomassPoolType(); DMDemandPriorityFactor.Structural = 1.0; DMDemandPriorityFactor.Metabolic = 1.0; DMDemandPriorityFactor.Storage = 1.0; NDemand = new BiomassPoolType(); DMSupply = new BiomassSupplyType(); NSupply = new BiomassSupplyType(); potentialDMAllocation = new BiomassPoolType(); Detached = new Biomass(); Clear(); }
protected void OnDoActualPlantGrowth(object sender, EventArgs e) { if (Plant.IsAlive) { Biomass Loss = new Biomass(); Loss.StructuralWt = Live.StructuralWt * SenescenceRate; Loss.NonStructuralWt = Live.NonStructuralWt * SenescenceRate; Loss.StructuralN = Live.StructuralN * SenescenceRate; Loss.NonStructuralN = Live.NonStructuralN * SenescenceRate; Live.StructuralWt -= Loss.StructuralWt; Live.NonStructuralWt -= Loss.NonStructuralWt; Live.StructuralN -= Loss.StructuralN; Live.NonStructuralN -= Loss.NonStructuralN; Dead.StructuralWt += Loss.StructuralWt; Dead.NonStructuralWt += Loss.NonStructuralWt; Dead.StructuralN += Loss.StructuralN; Dead.NonStructuralN += Loss.NonStructuralN; double DetachedFrac = 0; if (DetachmentRateFunction != null) { DetachedFrac = DetachmentRateFunction.Value; } if (DetachedFrac > 0.0) { double DetachedWt = Dead.Wt * DetachedFrac; double DetachedN = Dead.N * DetachedFrac; Dead.StructuralWt *= (1 - DetachedFrac); Dead.StructuralN *= (1 - DetachedFrac); Dead.NonStructuralWt *= (1 - DetachedFrac); Dead.NonStructuralN *= (1 - DetachedFrac); Dead.MetabolicWt *= (1 - DetachedFrac); Dead.MetabolicN *= (1 - DetachedFrac); if (DetachedWt > 0) { SurfaceOrganicMatter.Add(DetachedWt * 10, DetachedN * 10, 0, Plant.CropType, Name); } } if (DryMatterContent != null) { LiveFWt = Live.Wt / DryMatterContent.Value; } } }
protected void OnSimulationCommencing(object sender, EventArgs e) { Live = new Biomass(); Dead = new Biomass(); StartLive = new Biomass(); DMDemand = new BiomassPoolType(); NDemand = new BiomassPoolType(); DMSupply = new BiomassSupplyType(); NSupply = new BiomassSupplyType(); potentialDMAllocation = new BiomassPoolType(); Allocated = new Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); }
/// <summary>Clears this instance.</summary> private void Clear() { Live = new Biomass(); Dead = new Biomass(); DMDemand = new BiomassPoolType(); NDemand = new BiomassPoolType(); DMSupply = new BiomassSupplyType(); NSupply = new BiomassSupplyType(); potentialDMAllocation = new BiomassPoolType(); Allocated = new Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); GrowthRespiration = 0; }
void Initialise() { Senescing = new Biomass(); Retranslocation = new Biomass(); Growth = new Biomass(); Detaching = new Biomass(); GreenRemoved = new Biomass(); SenescedRemoved = new Biomass(); LeafNo = new double[max_node]; LeafNoSen = new double[max_node]; LeafArea = new double[max_node]; if (CO2 != 350 && (TEModifier == null || NConcCriticalModifier == null)) { throw new Exception("CO2 isn't at the default level, and model: " + Plant.Name + " has no CO2 parameterisations."); } }
public override void OnSow(SowPlant2Type Sow) { SowingInfo = Sow; if (LayerLive == null) { LayerLive = new Biomass[dlayer.Length]; LayerDead = new Biomass[dlayer.Length]; for (int i = 0; i < dlayer.Length; i++) { LayerLive[i] = new Biomass(); LayerDead[i] = new Biomass(); } } DeltaNO3 = new double[dlayer.Length]; DeltaNH4 = new double[dlayer.Length]; }
/// <summary> /// Remove some dm. The fraction removed is calculation and put into the RemovedPool so that /// later one it can be removed from the actual Pool in the update routine. /// Routine was called giveDMGreenRemoved and giveDMSenescedRemoved in old Plant. /// </summary> internal static Biomass RemoveDM(double delta, Biomass Pool, string OrganName) { double fraction = MathUtility.Divide(delta, Pool.Wt, 0.0); Biomass RemovedPool = Pool * fraction; double error_margin = 1.0e-6f; if (delta > Pool.Wt + error_margin) { string msg; msg = "Attempting to remove more green " + OrganName + " biomass than available:-\r\n"; msg += "Removing -" + delta.ToString() + " (g/m2) from " + Pool.Wt.ToString() + " (g/m2) available."; throw new Exception(msg); } return(RemovedPool); }
private Biomass DetachLeaves() { Detached = new Biomass(); double LRT = LeafResidenceTime.Value(); double LDT = LeafDetachmentTime.Value(); foreach (PerrenialLeafCohort L in Leaves) { if (L.Age >= (LRT + LDT)) { Detached.Add(L.Dead); } } Leaves.RemoveAll(L => L.Age >= (LRT + LDT)); return(Detached); }
/// <summary>Removes biomass from live and dead biomass pools and send to soil</summary> /// <param name="biomassRemoveType">Name of event that triggered this biomass remove call.</param> /// <param name="removal">The fractions of biomass to remove</param> /// <param name="Live">Live biomass pool</param> /// <param name="Dead">Dead biomass pool</param> /// <param name="Removed">The removed pool to add to.</param> /// <param name="Detached">The detached pool to add to.</param> public void RemoveBiomassToSoil(string biomassRemoveType, OrganBiomassRemovalType removal, Biomass[] Live, Biomass[] Dead, Biomass Removed, Biomass Detached) { if (removal == null) { removal = FindDefault(biomassRemoveType); } //NOTE: roots don't have dead biomass double totalFractionToRemove = removal.FractionLiveToRemove + removal.FractionLiveToResidue; if (totalFractionToRemove > 0) { //NOTE: at the moment Root has no Dead pool FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[Live.Length]; double remainingFraction = 1.0 - (removal.FractionLiveToResidue + removal.FractionLiveToRemove); for (int layer = 0; layer < Live.Length; layer++) { Biomass removing; Biomass detaching; double remainingLiveFraction = RemoveBiomassFromLiveAndDead(removal, Live[layer], Dead[layer], out removing, out detaching); // Add the detaching biomass to total removed and detached Removed.Add(removing); Detached.Add(detaching); // Pass the detaching biomass to surface organic matter model. FOMType fom = new FOMType(); fom.amount = (float)(detaching.Wt * 10); fom.N = (float)(detaching.N * 10); fom.C = (float)(0.40 * detaching.Wt * 10); fom.P = 0.0; fom.AshAlk = 0.0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0.0; Layer.LabileP = 0.0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = plant.PlantType; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); } }
public static void CalcNDemand(double dltDm, double dltDmPotRue, double n_conc_crit, double n_conc_max, Biomass Growth, Biomass Green, double RetranslocationN, double n_deficit_uptake_fraction, ref double NDemand, ref double NMax) { double part_fract = MathUtility.Divide(Growth.Wt, dltDm, 0.0); double dlt_dm_pot = dltDmPotRue * part_fract; // potential dry weight increase (g/m^2) dlt_dm_pot = MathUtility.Constrain(dlt_dm_pot, 0.0, dltDmPotRue); if (Green.Wt > 0.0) { // get N demands due to difference between // actual N concentrations and critical N concentrations double N_crit = Green.Wt * n_conc_crit; // critical N amount (g/m^2) double N_potential = Green.Wt * n_conc_max; // maximum N uptake potential (g/m^2) // retranslocation is -ve for outflows double N_demand_old = N_crit // demand for N by old biomass (g/m^2) - (Green.N + RetranslocationN); if (N_demand_old > 0.0) // Don't allow demand to satisfy all deficit { N_demand_old *= n_deficit_uptake_fraction; } double N_max_old = N_potential // N required by old biomass to reach N_conc_max (g/m^2) - (Green.N + RetranslocationN); if (N_max_old > 0.0) { N_max_old *= n_deficit_uptake_fraction; // Don't allow demand to satisfy all deficit } // get potential N demand (critical N) of potential growth double N_demand_new = dlt_dm_pot * n_conc_crit; // demand for N by new growth (g/m^2) double N_max_new = dlt_dm_pot * n_conc_max; // N required by new growth to reach N_conc_max (g/m^2) NDemand = N_demand_old + N_demand_new; NMax = N_max_old + N_max_new; NDemand = MathUtility.Constrain(NDemand, 0.0, double.MaxValue); NMax = MathUtility.Constrain(NMax, 0.0, double.MaxValue); } else { NDemand = NMax = 0.0; } }
protected void OnSimulationCommencing(object sender, EventArgs e) { Live = new Biomass(); Dead = new Biomass(); DMDemand = new BiomassPoolType(); DMDemandPriorityFactor = new BiomassPoolType(); DMDemandPriorityFactor.Structural = 1.0; DMDemandPriorityFactor.Metabolic = 1.0; DMDemandPriorityFactor.Storage = 1.0; NDemand = new BiomassPoolType(); DMSupply = new BiomassSupplyType(); NSupply = new BiomassSupplyType(); Allocated = new Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); }
/// <summary>Clears this instance.</summary> protected void Clear() { Height = 0; StartNRetranslocationSupply = 0; StartNReallocationSupply = 0; PotentialDMAllocation = 0; PotentialStructuralDMAllocation = 0; PotentialMetabolicDMAllocation = 0; StructuralDMDemand = 0; StorageDMDemand = 0; LiveFWt = 0; dryMatterDemand.Clear(); dryMatterSupply.Clear(); nitrogenDemand.Clear(); nitrogenSupply.Clear(); Detached = new Biomass(); }
protected void OnSimulationCommencing(object sender, EventArgs e) { startLive = new Biomass(); DMDemand = new BiomassPoolType(); NDemand = new BiomassPoolType(); DMSupply = new BiomassSupplyType(); NSupply = new BiomassSupplyType(); potentialDMAllocation = new BiomassPoolType(); Allocated = new Biomass(); Senesced = new Biomass(); Detached = new Biomass(); Removed = new Biomass(); Height = 0.0; LAI = 0.0; leafInitialised = false; Clear(); }
//--------------------------------------------------------------------- // Event handler when a cohort is killed by an age-only disturbance. public void CohortKilledByAgeOnlyDisturbance(object sender, Biomass.DeathEventArgs eventArgs) { // If this plug-in is not running, then some base disturbance // plug-in killed the cohort. if (! running) return; SiteVars.BiomassRemoved[eventArgs.Site] += eventArgs.Cohort.Biomass; }
//--------------------------------------------------------------------- // Event handler when a cohort is killed by an age-only disturbance. public static void CohortKilledByAgeOnlyDisturbance(object sender, Biomass.DeathEventArgs eventArgs) { // If this plug-in is not running, then some base disturbance // plug-in killed the cohort. if (! running) return; // If this plug-in is running, then the age-only disturbance must // be a cohort-selector from Base Harvest. int reduction = eventArgs.Cohort.Biomass; SiteVars.BiomassRemoved[eventArgs.Site] += reduction; //UI.WriteLine("Cohort Biomass removed={0:0.0}; Total Killed={1:0.0}.", reduction, SiteVars.BiomassRemoved[eventArgs.Site]); //SiteVars.CohortsPartiallyDamaged[eventArgs.Site]++; }
//--------------------------------------------------------------------- // This method replaces the delegate method. It is called every year when // ACT_ANPP is calculated, for each cohort. Therefore, this method is operating at // an ANNUAL time step and separate from the normal extension time step. public static double DefoliateCohort(Biomass.ICohort cohort, Site site, int siteBiomass) { //UI.WriteLine(" Calculating insect defoliation..."); int sppIndex = cohort.Species.Index; double totalDefoliation = 0.0; foreach(IInsect insect in manyInsect) { if(!insect.ActiveOutbreak) continue; double defoliation = 0.0; double weightedDefoliation = 0.0; int suscIndex = insect.SppTable[sppIndex].Susceptibility - 1; if (suscIndex < 0) suscIndex = 0; // Get the Neighborhood GrowthReduction Density double meanNeighborhoodDefoliation = 0.0; int neighborCnt = 0; // If it is the first year, the neighborhood growth reduction // will have been initialized in Outbreak.InitializeDefoliationPatches if(insect.NeighborhoodDefoliation[site] > 0) { //UI.WriteLine(" First Year of Defoliation: Using initial patch defo={0:0.00}.", SiteVars.NeighborhoodDefoliation[site]); meanNeighborhoodDefoliation = insect.NeighborhoodDefoliation[site]; } // If not the first year, calculate mean neighborhood defoliation based on the // previous year. else { double sumNeighborhoodDefoliation = 0.0; //UI.WriteLine("Look at the Neighbors... "); foreach (RelativeLocation relativeLoc in insect.Neighbors) { Site neighbor = site.GetNeighbor(relativeLoc); if (neighbor != null && neighbor.IsActive) { neighborCnt++; // The previous year... //if(SiteVars.DefoliationByYear[neighbor].ContainsKey(Model.Core.CurrentTime - 1)) // sumNeighborhoodDefoliation += SiteVars.DefoliationByYear[neighbor][Model.Core.CurrentTime - 1]; sumNeighborhoodDefoliation += insect.LastYearDefoliation[neighbor]; } } if(neighborCnt > 0.0) meanNeighborhoodDefoliation = sumNeighborhoodDefoliation / (double) neighborCnt; } //endif if(meanNeighborhoodDefoliation > 1.0 || meanNeighborhoodDefoliation < 0) { UI.WriteLine("MeanNeighborhoodDefoliation={0}; NeighborCnt={1}.", meanNeighborhoodDefoliation, neighborCnt); throw new ApplicationException("Error: Mean Neighborhood GrowthReduction is not between 1.0 and 0.0"); } // First assume that there are no neighbors whatsoever: DistributionType dist = insect.SusceptibleTable[suscIndex].Distribution_0.Name; double value1 = insect.SusceptibleTable[suscIndex].Distribution_0.Value1; double value2 = insect.SusceptibleTable[suscIndex].Distribution_0.Value2; if(meanNeighborhoodDefoliation <= 1.0 && meanNeighborhoodDefoliation >= 0.8) { dist = insect.SusceptibleTable[suscIndex].Distribution_80.Name; value1 = insect.SusceptibleTable[suscIndex].Distribution_80.Value1; value2 = insect.SusceptibleTable[suscIndex].Distribution_80.Value2; } else if(meanNeighborhoodDefoliation < 0.8 && meanNeighborhoodDefoliation >= 0.6) { dist = insect.SusceptibleTable[suscIndex].Distribution_60.Name; value1 = insect.SusceptibleTable[suscIndex].Distribution_60.Value1; value2 = insect.SusceptibleTable[suscIndex].Distribution_60.Value2; } else if(meanNeighborhoodDefoliation < 0.6 && meanNeighborhoodDefoliation >= 0.4) { dist = insect.SusceptibleTable[suscIndex].Distribution_40.Name; value1 = insect.SusceptibleTable[suscIndex].Distribution_40.Value1; value2 = insect.SusceptibleTable[suscIndex].Distribution_40.Value2; } else if(meanNeighborhoodDefoliation < 0.4 && meanNeighborhoodDefoliation >= 0.2) { dist = insect.SusceptibleTable[suscIndex].Distribution_20.Name; value1 = insect.SusceptibleTable[suscIndex].Distribution_20.Value1; value2 = insect.SusceptibleTable[suscIndex].Distribution_20.Value2; } else if(meanNeighborhoodDefoliation < 0.2 && meanNeighborhoodDefoliation >= 0.0) { dist = insect.SusceptibleTable[suscIndex].Distribution_0.Name; value1 = insect.SusceptibleTable[suscIndex].Distribution_0.Value1; value2 = insect.SusceptibleTable[suscIndex].Distribution_0.Value2; } // Next, ensure that all cohorts of the same susceptibility class // receive the same level of defoliation. if(insect.HostDefoliationByYear[site].ContainsKey(Model.Core.CurrentTime)) { if(insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex] <= 0.00000000) { defoliation = Distribution.GenerateRandomNum(dist, value1, value2); insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex] = defoliation; } else defoliation = insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex]; } else { insect.HostDefoliationByYear[site].Add(Model.Core.CurrentTime, new Double[3]{0.0, 0.0, 0.0}); defoliation = Distribution.GenerateRandomNum(dist, value1, value2); insect.HostDefoliationByYear[site][Model.Core.CurrentTime][suscIndex] = defoliation; } // Alternatively, allow defoliation to vary even among cohorts and species with // the same susceptibility. //defoliation = Distribution.GenerateRandomNum(dist, value1, value2); if(defoliation > 1.0 || defoliation < 0) { UI.WriteLine("DEFOLIATION TOO BIG or SMALL: {0}, {1}, {2}, {3}.", dist, value1, value2, defoliation); throw new ApplicationException("Error: New defoliation is not between 1.0 and 0.0"); } //UI.WriteLine("Cohort age={0}, species={1}, suscIndex={2}, defoliation={3}.", cohort.Age, cohort.Species.Name, (suscIndex -1), defoliation); // For first insect in a given year, actual defoliation equals the potential defoliation drawn from insect distributions. if (totalDefoliation == 0.0) { weightedDefoliation = (defoliation * ((double)cohort.Biomass / (double)siteBiomass)); //UI.WriteLine("Cohort age={0}, species={1}, suscIndex={2}, cohortDefoliation={3}.", cohort.Age, cohort.Species.Name, (suscIndex+1), cohortDefoliation); } // For second insect in a given year, actual defoliation can only be as high as the amount of canopy foliage left by first insect. // This change makes sure next year's neighborhoodDefoliation will reflect actual defoliation, rather than "potential" defoliation. // It should also ensure that the sum of defoliation maps for all insects adds up to 1 for a given year. else { weightedDefoliation = (Math.Min((1 - totalDefoliation), defoliation) * ((double)cohort.Biomass / (double)siteBiomass)); } insect.ThisYearDefoliation[site] += weightedDefoliation; if (insect.ThisYearDefoliation[site] > 1.0) // Weighted defoliation cannot exceed 100% of site biomass. insect.ThisYearDefoliation[site] = 1.0; //Put in error statement to see if sum of weighted defoliation is ever over 1. if (insect.ThisYearDefoliation[site] > 1.0 || insect.ThisYearDefoliation[site] < 0) { UI.WriteLine("Site Weighted Defoliation = {0:0.000000}. Site R/C={1}/{2}. Last Weighted Defoliation = {3}.", insect.ThisYearDefoliation[site], site.Location.Row, site.Location.Column, weightedDefoliation); throw new ApplicationException("Error: Site Weighted Defoliation is not between 1.0 and 0.0"); } totalDefoliation += defoliation; // Is totalDefoliation getting used anywhere else? Or an orphan? } if(totalDefoliation > 1.0) // Cannot exceed 100% defoliation, comment out to see if it ever does. totalDefoliation = 1.0; if(totalDefoliation > 1.0 || totalDefoliation < 0) { UI.WriteLine("Cohort Total Defoliation = {0:0.00}. Site R/C={1}/{2}.", totalDefoliation, site.Location.Row, site.Location.Column); throw new ApplicationException("Error: Total Defoliation is not between 1.0 and 0.0"); } return totalDefoliation; }
private void OnSimulationCommencing(object sender, EventArgs e) { SwimIsPresent = swim3 > 0; if (SwimIsPresent) Summary.WriteMessage(this, "Using SWIM3 for Soil Water Uptake."); Senescing = new Biomass(); Retranslocation = new Biomass(); Growth = new Biomass(); Detaching = new Biomass(); GreenRemoved = new Biomass(); SenescedRemoved = new Biomass(); dlt_sw_dep = new double[Soil.Thickness.Length]; sw_avail = new double[Soil.Thickness.Length]; sw_avail_pot = new double[Soil.Thickness.Length]; sw_supply = new double[Soil.Thickness.Length]; dlt_no3gsm = new double[Soil.Thickness.Length]; dlt_nh4gsm = new double[Soil.Thickness.Length]; no3gsm_uptake_pot = new double[Soil.Thickness.Length]; nh4gsm_uptake_pot = new double[Soil.Thickness.Length]; dltRootLength = new double[Soil.Thickness.Length]; dltRootLengthSenesced = new double[Soil.Thickness.Length]; dltRootLengthDead = new double[Soil.Thickness.Length]; no3gsm_min = new double[Soil.Thickness.Length]; nh4gsm_min = new double[Soil.Thickness.Length]; RootLength = new double[Soil.Thickness.Length]; RootLengthSenesced = new double[Soil.Thickness.Length]; SoilCrop soilCrop = Soil.Crop(Plant.Name) as SoilCrop; ll = soilCrop.LL; kl = soilCrop.KL; xf = soilCrop.XF; DULmm = MathUtilities.Multiply(Soil.DUL, Soil.Thickness); ll_dep = MathUtilities.Multiply(ll, Soil.Thickness); Util.ZeroArray(no3gsm_min); Util.ZeroArray(nh4gsm_min); }
//--------------------------------------------------------------------- // This method replaces the delegate method. It is called every year when // ACT_ANPP is calculated, for each cohort. Therefore, this method is operating at // an ANNUAL time step and separate from the normal extension time step. public static double ReduceCohortGrowth(Biomass.ICohort cohort, Site site, int siteBiomass) { //UI.WriteLine(" Calculating cohort growth reduction due to insect defoliation..."); double summaryGrowthReduction = 0.0; int sppIndex = cohort.Species.Index; foreach(IInsect insect in PlugIn.ManyInsect) { if(!insect.ActiveOutbreak) continue; int suscIndex = insect.SppTable[sppIndex].Susceptibility - 1; //if (suscIndex < 0) suscIndex = 0; int yearBack = 0; double annualDefoliation = 0.0; if(insect.HostDefoliationByYear[site].ContainsKey(Model.Core.CurrentTime - yearBack)) { //UI.WriteLine("Host Defoliation By Year: Time={0}, suscIndex={1}, spp={2}.", (Model.Core.CurrentTime - yearBack), suscIndex+1, cohort.Species.Name); annualDefoliation += insect.HostDefoliationByYear[site][Model.Core.CurrentTime - yearBack][suscIndex]; } double cumulativeDefoliation = annualDefoliation; while(annualDefoliation > 0) { yearBack++; annualDefoliation = 0.0; if(insect.HostDefoliationByYear[site].ContainsKey(Model.Core.CurrentTime - yearBack)) { //UI.WriteLine("Host Defoliation By Year: Time={0}, suscIndex={1}, spp={2}.", (Model.Core.CurrentTime - yearBack), suscIndex+1, cohort.Species.Name); annualDefoliation = insect.HostDefoliationByYear[site][Model.Core.CurrentTime - yearBack][suscIndex]; cumulativeDefoliation += annualDefoliation; } } double slope = insect.SppTable[sppIndex].GrowthReduceSlope; double intercept = insect.SppTable[sppIndex].GrowthReduceIntercept; double growthReduction = 1.0 - (cumulativeDefoliation * slope + intercept); double weightedGD = (growthReduction * ((double) cohort.Biomass / (double) siteBiomass)); //Below looks like it should be multiplied by weightedGD above, but it isn't?? CHECK! summaryGrowthReduction += growthReduction; //UI.WriteLine("Time={0}, Spp={1}, SummaryGrowthReduction={2:0.00}.", Model.Core.CurrentTime,cohort.Species.Name, summaryGrowthReduction); } if (summaryGrowthReduction > 1.0) // Cannot exceed 100% summaryGrowthReduction = 1.0; if(summaryGrowthReduction > 1.0 || summaryGrowthReduction < 0) { UI.WriteLine("Cohort Total Growth Reduction = {0:0.00}. Site R/C={1}/{2}.", summaryGrowthReduction, site.Location.Row, site.Location.Column); throw new ApplicationException("Error: Total Growth Reduction is not between 1.0 and 0.0"); } return summaryGrowthReduction; }
/// <summary>Disposes the detached material.</summary> /// <param name="BiomassToDisposeOf">The biomass to dispose of.</param> /// <param name="RootLength">Length of the root.</param> private void DisposeDetachedMaterial(Biomass BiomassToDisposeOf, double[] RootLength) { if (BiomassToDisposeOf.Wt > 0.0) { // DM double[] dlt_dm_incorp = RootDist(BiomassToDisposeOf.Wt * Conversions.gm2kg / Conversions.sm2ha, RootLength); // Nitrogen double[] dlt_N_incorp = RootDist(BiomassToDisposeOf.N * Conversions.gm2kg / Conversions.sm2ha, RootLength); // Phosporous //double[] dlt_P_incorp = RootDist(BiomassToDisposeOf.P * Conversions.gm2kg / Conversions.sm2ha); FOMLayerType IncorpFOMData = new FOMLayerType(); IncorpFOMData.Type = Plant.CropType; Util.Debug("Root.IncorpFOM.Type=%s", IncorpFOMData.Type.ToLower()); IncorpFOMData.Layer = new FOMLayerLayerType[dlt_dm_incorp.Length]; for (int i = 0; i != dlt_dm_incorp.Length; i++) { IncorpFOMData.Layer[i] = new FOMLayerLayerType(); IncorpFOMData.Layer[i].FOM = new FOMType(); IncorpFOMData.Layer[i].FOM.amount = (float)dlt_dm_incorp[i]; IncorpFOMData.Layer[i].FOM.N = (float)dlt_N_incorp[i]; //IncorpFOMData.Layer[i].FOM.P = (float)dlt_P_incorp[i]; IncorpFOMData.Layer[i].FOM.C = (float)0.0; IncorpFOMData.Layer[i].FOM.AshAlk = (float)0.0; IncorpFOMData.Layer[i].CNR = 0; IncorpFOMData.Layer[i].LabileP = 0; Util.Debug("Root.IncorpFOM.FOM.amount=%f2", IncorpFOMData.Layer[i].FOM.amount); Util.Debug("Root.IncorpFOM.FOM.N=%f", IncorpFOMData.Layer[i].FOM.N); } IncorpFOM.Invoke(IncorpFOMData); } else { // no roots to incorporate } }
/// <summary>Removes biomass from live and dead biomass pools</summary> /// <param name="amount">The fractions of biomass to remove</param> /// <param name="Live">Live biomass pool</param> /// <param name="Dead">Dead biomass pool</param> /// <param name="Removed">The removed pool to add to.</param> /// <param name="Detached">The detached pool to add to.</param> /// <param name="detaching">The amount of detaching material</param> private static double RemoveBiomassFromLiveAndDead(OrganBiomassRemovalType amount, Biomass Live, Biomass Dead, out Biomass Removed, Biomass Detached, out Biomass detaching) { double remainingLiveFraction = 1.0 - (amount.FractionLiveToResidue + amount.FractionLiveToRemove); double remainingDeadFraction = 1.0 - (amount.FractionDeadToResidue + amount.FractionDeadToRemove); detaching = Live * amount.FractionLiveToResidue + Dead * amount.FractionDeadToResidue; Removed = Live * amount.FractionLiveToRemove + Dead * amount.FractionDeadToRemove; Detached.Add(detaching); Live.Multiply(remainingLiveFraction); Dead.Multiply(remainingDeadFraction); return remainingLiveFraction; }
private void OnSimulationCommencing(object sender, EventArgs e) { Senescing = new Biomass(); Retranslocation = new Biomass(); Growth = new Biomass(); Detaching = new Biomass(); GreenRemoved = new Biomass(); SenescedRemoved = new Biomass(); LeafNo = new double[max_node]; LeafNoSen = new double[max_node]; LeafArea = new double[max_node]; if (CO2 != 350 && (TEModifier == null || NConcCriticalModifier == null)) throw new Exception("CO2 isn't at the default level, and model: " + Plant.Name + " has no CO2 parameterisations."); }
/// <summary>Removes biomass from live and dead biomass pools and send to soil</summary> /// <param name="biomassRemoveType">Name of event that triggered this biomass remove call.</param> /// <param name="removal">The fractions of biomass to remove</param> /// <param name="Live">Live biomass pool</param> /// <param name="Dead">Dead biomass pool</param> /// <param name="Removed">The removed pool to add to.</param> /// <param name="Detached">The detached pool to add to.</param> public void RemoveBiomassToSoil(string biomassRemoveType, OrganBiomassRemovalType removal, Biomass[] Live, Biomass[] Dead, Biomass Removed, Biomass Detached) { if (removal == null) removal = FindDefault(biomassRemoveType); //NOTE: roots don't have dead biomass double totalFractionToRemove = removal.FractionLiveToRemove + removal.FractionLiveToResidue; if (totalFractionToRemove > 0) { //NOTE: at the moment Root has no Dead pool FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[Live.Length]; double remainingFraction = 1.0 - (removal.FractionLiveToResidue + removal.FractionLiveToRemove); for (int layer = 0; layer < Live.Length; layer++) { Biomass detaching; double remainingLiveFraction = RemoveBiomassFromLiveAndDead(removal, Live[layer], Dead[layer], out Removed, Detached, out detaching); FOMType fom = new FOMType(); fom.amount = (float)(detaching.Wt * 10); fom.N = (float)(detaching.N * 10); fom.C = (float)(0.40 * detaching.Wt * 10); fom.P = 0.0; fom.AshAlk = 0.0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0.0; Layer.LabileP = 0.0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = plant.CropType; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); } }
/// <summary>Called when [end crop].</summary> public void OnEndCrop() { NewCropType Crop = new NewCropType(); Crop.crop_type = CropType; Crop.sender = Name; if (CropEnding != null) CropEnding.Invoke(Crop); if (PlantEnding != null) PlantEnding.Invoke(this, new ModelArgs() { Model = this }); // Keep track of some variables for reporting. Biomass AboveGroundBiomass = new Biomass(AboveGround); Biomass BelowGroundBiomass = new Biomass(BelowGround); // Call each organ's OnHarvest. They fill a BiomassRemoved structure. We then publish a // BiomassRemoved event. BiomassRemovedType BiomassRemovedData = new BiomassRemovedType(); foreach (Organ1 Organ in Organ1s) Organ.OnEndCrop(BiomassRemovedData); BiomassRemovedData.crop_type = CropType; BiomassRemoved.Invoke(BiomassRemovedData); string message = string.Format("Organic matter from crop to surface organic matter:-\r\n" + " DM tops (kg/ha) = {0,10:F1}\r\n" + " DM roots (kg/ha) = {1,10:F1}\r\n" + " N tops (kg/ha) = {0,10:F2}\r\n" + " N roots (lh/ha) = {1,10:F2}", AboveGroundBiomass.Wt, BelowGroundBiomass.Wt, AboveGroundBiomass.N, BelowGroundBiomass.N); Summary.WriteMessage(this, message); cultivarDefinition.Unapply(); SowingData = null; }
/// <summary>Clears this instance.</summary> protected override void Clear() { base.Clear(); Uptake = null; DeltaNH4 = null; DeltaNO3 = null; _SenescenceRate = 0; Length = 0; Depth = 0; if (LayerLive == null || LayerLive.Length == 0) { LayerLive = new Biomass[Soil.Thickness.Length]; LayerDead = new Biomass[Soil.Thickness.Length]; for (int i = 0; i < Soil.Thickness.Length; i++) { LayerLive[i] = new Biomass(); LayerDead[i] = new Biomass(); } } else { for (int i = 0; i < Soil.Thickness.Length; i++) { LayerLive[i].Clear(); LayerDead[i].Clear(); } } DeltaNO3 = new double[Soil.Thickness.Length]; DeltaNH4 = new double[Soil.Thickness.Length]; }
protected void OnDoPotentialPlantGrowth(object sender, EventArgs e) { if (Plant.IsEmerged) { SenescenceRate = 0; if (SenescenceRateFunction != null) //Default of zero means no senescence SenescenceRate = SenescenceRateFunction.Value; _StructuralFraction = 1; if (StructuralFraction != null) //Default of 1 means all biomass is structural _StructuralFraction = StructuralFraction.Value; InitialWt = 0; //Default of zero means no initial Wt if (InitialWtFunction != null) InitialWt = InitialWtFunction.Value; InitStutFraction = 1.0; //Default of 1 means all initial DM is structural if (InitialStructuralFraction != null) InitStutFraction = InitialStructuralFraction.Value; //Initialise biomass and nitrogen if (Live.Wt == 0) { Live.StructuralWt = InitialWt * InitStutFraction; Live.NonStructuralWt = InitialWt * (1 - InitStutFraction); Live.StructuralN = Live.StructuralWt * MinimumNConc.Value; Live.NonStructuralN = (InitialWt * MaximumNConc.Value) - Live.StructuralN; } StartLive = Live; StartNReallocationSupply = NSupply.Reallocation; StartNRetranslocationSupply = NSupply.Retranslocation; } }
protected void OnDoActualPlantGrowth(object sender, EventArgs e) { if (Plant.IsAlive) { Biomass Loss = new Biomass(); Loss.StructuralWt = Live.StructuralWt * mySenescenceRate; Loss.NonStructuralWt = Live.NonStructuralWt * mySenescenceRate; Loss.StructuralN = Live.StructuralN * mySenescenceRate; Loss.NonStructuralN = Live.NonStructuralN * mySenescenceRate; Live.StructuralWt -= Loss.StructuralWt; Live.NonStructuralWt -= Loss.NonStructuralWt; Live.StructuralN -= Loss.StructuralN; Live.NonStructuralN -= Loss.NonStructuralN; Dead.StructuralWt += Loss.StructuralWt; Dead.NonStructuralWt += Loss.NonStructuralWt; Dead.StructuralN += Loss.StructuralN; Dead.NonStructuralN += Loss.NonStructuralN; double DetachedFrac = 0; if (DetachmentRateFunction != null) DetachedFrac = DetachmentRateFunction.Value; if (DetachedFrac > 0.0) { double detachingWt = Dead.Wt * DetachedFrac; double detachingN = Dead.N * DetachedFrac; Dead.StructuralWt *= (1 - DetachedFrac); Dead.StructuralN *= (1 - DetachedFrac); Dead.NonStructuralWt *= (1 - DetachedFrac); Dead.NonStructuralN *= (1 - DetachedFrac); Dead.MetabolicWt *= (1 - DetachedFrac); Dead.MetabolicN *= (1 - DetachedFrac); if (detachingWt > 0.0) { DetachedWt += detachingWt; DetachedN += detachingN; SurfaceOrganicMatter.Add(detachingWt * 10, detachingN * 10, 0, Plant.CropType, Name); } } MaintenanceRespiration = 0; //Do Maintenance respiration if (MaintenanceRespirationFunction != null) { MaintenanceRespiration += Live.MetabolicWt * MaintenanceRespirationFunction.Value; Live.MetabolicWt *= (1 - MaintenanceRespirationFunction.Value); MaintenanceRespiration += Live.NonStructuralWt * MaintenanceRespirationFunction.Value; Live.NonStructuralWt *= (1 - MaintenanceRespirationFunction.Value); } if (DryMatterContent != null) LiveFWt = Live.Wt / DryMatterContent.Value; } }
protected void OnDoPotentialPlantGrowth(object sender, EventArgs e) { if (Plant.IsEmerged) { if (MicroClimatePresent == false) throw new Exception(this.Name + " is trying to calculate water demand but no MicroClimate module is present. Include a microclimate node in your zone"); Detached.Clear(); FRGR = FRGRFunction.Value; LAI = LAIFunction.Value; Height = HeightFunction.Value; LAIDead = LaiDeadFunction.Value; //Initialise biomass and nitrogen Leaves.Add(new PerrenialLeafCohort()); if (Leaves.Count == 1) AddNewLeafMaterial(StructuralWt: InitialWtFunction.Value, NonStructuralWt: 0, StructuralN: InitialWtFunction.Value * MinimumNConc.Value, NonStructuralN: InitialWtFunction.Value * (MaximumNConc.Value - MinimumNConc.Value)); foreach (PerrenialLeafCohort L in Leaves) L.Age++; StartLive = Live; StartNReallocationSupply = NSupply.Reallocation; StartNRetranslocationSupply = NSupply.Retranslocation; } }
//--------------------------------------------------------------------- // Event handler when a cohort is killed by an age-only disturbance. public void CohortKilledByAgeOnlyDisturbance(object sender, Biomass.DeathEventArgs eventArgs) { // If this plug-in is not running, then some base disturbance // plug-in killed the cohort. if (! running) return; // If this plug-in is running, then the age-only disturbance must // be a cohort-selector from Base Harvest. SiteVars.BiomassRemoved[eventArgs.Site] += (int) (eventArgs.Cohort.LeafBiomass + eventArgs.Cohort.WoodBiomass); }
/// <summary>Does the potential growth.</summary> /// <param name="TT">The tt.</param> /// <param name="LeafCohortParameters">The leaf cohort parameters.</param> public virtual void DoPotentialGrowth(double TT, Models.PMF.Organs.Leaf.LeafCohortParameters LeafCohortParameters) { //Reduce leaf Population in Cohort due to plant mortality double StartPopulation = CohortPopulation; if (Structure.ProportionPlantMortality > 0) { CohortPopulation -= CohortPopulation * Structure.ProportionPlantMortality; } //Reduce leaf Population in Cohort due to branch mortality if ((Structure.ProportionBranchMortality > 0) && (CohortPopulation > Structure.MainStemPopn)) //Ensure we there are some branches. { double deltaPopn = Math.Min(CohortPopulation * Structure.ProportionBranchMortality, CohortPopulation - Structure.MainStemPopn); //Ensure we are not killing more branches that the cohort has. CohortPopulation -= CohortPopulation * Structure.ProportionBranchMortality; } double PropnStemMortality = (StartPopulation - CohortPopulation) / StartPopulation; //Calculate Accumulated Stress Factor for reducing potential leaf size if (IsNotAppeared && (LeafCohortParameters.CellDivisionStress != null)) { CellDivisionStressDays += 1; CellDivisionStressAccumulation += LeafCohortParameters.CellDivisionStress.Value; //FIXME HEB The limitation below should be used to avoid zero values for maximum leaf size. //CellDivisionStressFactor = Math.Max(CellDivisionStressAccumulation / CellDivisionStressDays, 0.01); CellDivisionStressFactor = CellDivisionStressAccumulation / CellDivisionStressDays; } if (IsAppeared) { // The following line needs to be CHANGED!!!!!! //Leaf.CurrentRank = Rank - 1; //Set currentRank variable in parent leaf for use in experssion functions //Acellerate thermal time accumulation if crop is water stressed. double _ThermalTime; if ((LeafCohortParameters.DroughtInducedSenAcceleration != null) && (IsFullyExpanded)) _ThermalTime = TT * LeafCohortParameters.DroughtInducedSenAcceleration.Value; else _ThermalTime = TT; //Leaf area growth parameters DeltaPotentialArea = PotentialAreaGrowthFunction(_ThermalTime); //Calculate delta leaf area in the absence of water stress DeltaWaterConstrainedArea = DeltaPotentialArea * LeafCohortParameters.ExpansionStress.Value; //Reduce potential growth for water stress CoverAbove = Leaf.CoverAboveCohort(Rank); // Calculate cover above leaf cohort (unit??? FIXME-EIT) if (LeafCohortParameters.ShadeInducedSenescenceRate != null) ShadeInducedSenRate = LeafCohortParameters.ShadeInducedSenescenceRate.Value; SenescedFrac = FractionSenescing(_ThermalTime, PropnStemMortality); // Doing leaf mass growth in the cohort Biomass LiveBiomass = new Biomass(Live); //Set initial leaf status values LeafStartArea = LiveArea; LiveStart = new Biomass(Live); //If the model allows reallocation of senescent DM do it. if ((DMReallocationFactor > 0) && (SenescedFrac > 0)) { // DM to reallocate. LeafStartMetabolicDMReallocationSupply = LiveStart.MetabolicWt * SenescedFrac * DMReallocationFactor; LeafStartNonStructuralDMReallocationSupply = LiveStart.NonStructuralWt * SenescedFrac * DMReallocationFactor; LeafStartDMReallocationSupply = LeafStartMetabolicDMReallocationSupply + LeafStartNonStructuralDMReallocationSupply; LiveBiomass.MetabolicWt -= LeafStartMetabolicDMReallocationSupply; LiveBiomass.NonStructuralWt -= LeafStartNonStructuralDMReallocationSupply; } else { LeafStartMetabolicDMReallocationSupply = LeafStartNonStructuralDMReallocationSupply = LeafStartDMReallocationSupply = 0; } LeafStartDMRetranslocationSupply = LiveBiomass.NonStructuralWt * DMRetranslocationFactor; //Nretranslocation is that which occurs before uptake (senessed metabolic N and all non-structuralN) LeafStartMetabolicNReallocationSupply = SenescedFrac * LiveBiomass.MetabolicN * NReallocationFactor; LeafStartNonStructuralNReallocationSupply = SenescedFrac * LiveBiomass.NonStructuralN * NReallocationFactor; //Retranslocated N is only that which occurs after N uptake. Both Non-structural and metabolic N are able to be retranslocated but metabolic N will only be moved if remobilisation of non-structural N does not meet demands LeafStartMetabolicNRetranslocationSupply = Math.Max(0.0, (LiveBiomass.MetabolicN * NRetranslocationFactor) - LeafStartMetabolicNReallocationSupply); LeafStartNonStructuralNRetranslocationSupply = Math.Max(0.0, (LiveBiomass.NonStructuralN * NRetranslocationFactor) - LeafStartNonStructuralNReallocationSupply); LeafStartNReallocationSupply = NReallocationSupply; LeafStartNRetranslocationSupply = NRetranslocationSupply; //zero locals variables //StructuralDMDemand = 0; //MetabolicDMDemand = 0; //StructuralNDemand = 0; //MetabolicNDemand = 0; //NonStructuralNDemand = 0; PotentialStructuralDMAllocation = 0; PotentialMetabolicDMAllocation = 0; DMRetranslocated = 0; MetabolicNReallocated = 0; NonStructuralNReallocated = 0; MetabolicWtReallocated = 0; NonStructuralWtReallocated = 0; MetabolicNRetranslocated = 0; NonStructuralNRetrasnlocated = 0; MetabolicNAllocation = 0; StructuralDMAllocation = 0; MetabolicDMAllocation = 0; } }
/// <summary>Clears this instance.</summary> public void Clear() { Uptake = null; NitUptake = null; DeltaNO3 = new double[soil.Thickness.Length]; DeltaNH4 = new double[soil.Thickness.Length]; Length = 0.0; Depth = 0.0; if (LayerLive == null || LayerLive.Length == 0) { LayerLive = new Biomass[soil.Thickness.Length]; LayerDead = new Biomass[soil.Thickness.Length]; for (int i = 0; i < soil.Thickness.Length; i++) { LayerLive[i] = new Biomass(); LayerDead[i] = new Biomass(); } } else { for (int i = 0; i < soil.Thickness.Length; i++) { LayerLive[i].Clear(); LayerDead[i].Clear(); } } }
private void DetachLeaves(out Biomass Detached) { Detached = new Biomass(); foreach (PerrenialLeafCohort L in Leaves) if (L.Age >= (LeafResidenceTime.Value+ LeafDetachmentTime.Value)) Detached.Add(L.Dead); Leaves.RemoveAll(L => L.Age >= (LeafResidenceTime.Value + LeafDetachmentTime.Value)); }
private void KillLeavesUniformly(double fraction) { foreach (PerrenialLeafCohort L in Leaves) { Biomass Loss = new Biomass(); Loss.SetTo(L.Live); Loss.Multiply(fraction); L.Dead.Add(Loss); L.Live.Subtract(Loss); } }
private void GetSenescingLeafBiomass(out Biomass Senescing) { Senescing = new Biomass(); foreach (PerrenialLeafCohort L in Leaves) if (L.Age >= LeafResidenceTime.Value) Senescing.Add(L.Live); }
protected void OnDoPotentialPlantGrowth(object sender, EventArgs e) { if (Plant.IsEmerged) { mySenescenceRate = 0; if (SenescenceRate != null) //Default of zero means no senescence mySenescenceRate = SenescenceRate.Value; //Initialise biomass and nitrogen if (Live.Wt == 0) { Live.StructuralWt = InitialWtFunction.Value; Live.NonStructuralWt = 0.0; Live.StructuralN = Live.StructuralWt * MinimumNConc.Value; Live.NonStructuralN = (InitialWtFunction.Value * MaximumNConc.Value) - Live.StructuralN; } StartLive = Live; StartNReallocationSupply = NSupply.Reallocation; StartNRetranslocationSupply = NSupply.Retranslocation; } }
protected void OnSimulationCommencing(object sender, EventArgs e) { Detached = new Biomass(); Removed = new Biomass(); Clear(); }
private void OnSimulationCommencing(object sender, EventArgs e) { Senescing = new Biomass(); Retranslocation = new Biomass(); Growth = new Biomass(); Detaching = new Biomass(); GreenRemoved = new Biomass(); SenescedRemoved = new Biomass(); }
protected void OnDoActualPlantGrowth(object sender, EventArgs e) { if (Plant.IsAlive) { Biomass Loss = new Biomass(); Loss.StructuralWt = Live.StructuralWt * SenescenceRate; Loss.NonStructuralWt = Live.NonStructuralWt * SenescenceRate; Loss.StructuralN = Live.StructuralN * SenescenceRate; Loss.NonStructuralN = Live.NonStructuralN * SenescenceRate; Live.StructuralWt -= Loss.StructuralWt; Live.NonStructuralWt -= Loss.NonStructuralWt; Live.StructuralN -= Loss.StructuralN; Live.NonStructuralN -= Loss.NonStructuralN; Dead.StructuralWt += Loss.StructuralWt; Dead.NonStructuralWt += Loss.NonStructuralWt; Dead.StructuralN += Loss.StructuralN; Dead.NonStructuralN += Loss.NonStructuralN; double DetachedFrac = 0; if (DetachmentRateFunction != null) DetachedFrac = DetachmentRateFunction.Value; if (DetachedFrac > 0.0) { double DetachedWt = Dead.Wt * DetachedFrac; double DetachedN = Dead.N * DetachedFrac; Dead.StructuralWt *= (1 - DetachedFrac); Dead.StructuralN *= (1 - DetachedFrac); Dead.NonStructuralWt *= (1 - DetachedFrac); Dead.NonStructuralN *= (1 - DetachedFrac); Dead.MetabolicWt *= (1 - DetachedFrac); Dead.MetabolicN *= (1 - DetachedFrac); if (DetachedWt > 0) SurfaceOrganicMatter.Add(DetachedWt * 10, DetachedN * 10, 0, Plant.CropType, Name); } if ((DryMatterContent != null) && (Live.Wt != 0)) LiveFWt = Live.Wt / DryMatterContent.Value; } }