/// <summary>Adds a given amount of detached root material (DM and N) to the soil's FOM pool.</summary> /// <param name="amountDM">The DM amount to send (kg/ha)</param> /// <param name="amountN">The N amount to send (kg/ha)</param> public override void DetachBiomass(double amountDM, double amountN) { if (amountDM + amountN > 0.0) { FOMLayerLayerType[] FOMdataLayer = new FOMLayerLayerType[nLayers]; for (int layer = 0; layer < nLayers; layer++) { FOMType fomData = new FOMType(); fomData.amount = amountDM * FractionWt[layer]; fomData.N = amountN * FractionWt[layer]; fomData.C = amountDM * CarbonFractionInDM * FractionWt[layer]; fomData.P = 0.0; // P not considered here fomData.AshAlk = 0.0; // Ash not considered here FOMLayerLayerType layerData = new FOMLayerLayerType(); layerData.FOM = fomData; layerData.CNR = 0.0; // not used here layerData.LabileP = 0.0; // not used here FOMdataLayer[layer] = layerData; } FOMLayerType FOMData = new FOMLayerType(); FOMData.Type = speciesName; FOMData.Layer = FOMdataLayer; nutrientModel.DoIncorpFOM(FOMData); } }
/// <summary>Adds a given amount of detached root material (DM and N) to the soil's FOM pool, per layer.</summary> /// <param name="amountDM">The DM amount to detach (kg/ha).</param> /// <param name="amountN">The N amount to detach (kg/ha).</param> public void DetachBiomass(double[] amountDM, double[] amountN) { if (amountDM.Sum() + amountN.Sum() > 0.0) { FOMLayerLayerType[] FOMdataLayer = new FOMLayerLayerType[dmByLayer.Length]; for (int layer = 0; layer < dmByLayer.Length; layer++) { FOMType fomData = new FOMType(); fomData.amount = amountDM[layer]; fomData.N = amountN[layer]; fomData.C = fomData.amount * carbonFractionInDM; fomData.P = 0.0; // P not considered here fomData.AshAlk = 0.0; // Ash not considered here FOMLayerLayerType layerData = new FOMLayerLayerType(); layerData.FOM = fomData; layerData.CNR = 0.0; // not used here layerData.LabileP = 0.0; // not used here FOMdataLayer[layer] = layerData; } FOMLayerType FOMData = new FOMLayerType(); FOMData.Type = species.Name; FOMData.Layer = FOMdataLayer; nutrient.DoIncorpFOM(FOMData); } }
public override void OnEndCrop() { FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[dlayer.Length]; for (int layer = 0; layer < dlayer.Length; layer++) { double DM = (LayerLive[layer].Wt + LayerDead[layer].Wt) * 10.0; double N = (LayerLive[layer].N + LayerDead[layer].N) * 10.0; FOMType fom = new FOMType(); fom.amount = (float)DM; fom.N = (float)N; fom.C = (float)(0.40 * DM); fom.P = 0; fom.AshAlk = 0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0; Layer.LabileP = 0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = Plant.CropType; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); }
private void OnPlantEnding(object sender, EventArgs e) { if (sender == Plant) { FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[Soil.Thickness.Length]; for (int layer = 0; layer < Soil.Thickness.Length; layer++) { double DM = (LayerLive[layer].Wt + LayerDead[layer].Wt) * 10.0; double N = (LayerLive[layer].N + LayerDead[layer].N) * 10.0; FOMType fom = new FOMType(); fom.amount = (float)DM; fom.N = (float)N; fom.C = (float)(0.40 * DM); fom.P = 0; fom.AshAlk = 0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0; Layer.LabileP = 0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = Plant.CropType; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); } }
public override void DoActualGrowth() { base.DoActualGrowth(); // Do Root Front Advance int RootLayer = LayerIndex(Depth); double TEM = (TemperatureEffect == null)? 1: TemperatureEffect.Value; Depth = Depth + RootFrontVelocity.Value * xf[RootLayer] * TEM; if (!(MaximumRootDepth == null)) { Depth = Math.Min(Depth, MaximumRootDepth.Value); } double MaxDepth = 0; for (int i = 0; i < dlayer.Length; i++) { if (xf[i] > 0) { MaxDepth += dlayer[i]; } } Depth = Math.Min(Depth, MaxDepth); // Do Root Senescence FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[dlayer.Length]; for (int layer = 0; layer < dlayer.Length; layer++) { double DM = LayerLive[layer].Wt * _SenescenceRate * 10.0; double N = LayerLive[layer].StructuralN * _SenescenceRate * 10.0; LayerLive[layer].StructuralWt *= (1.0 - _SenescenceRate); LayerLive[layer].NonStructuralWt *= (1.0 - _SenescenceRate); LayerLive[layer].StructuralN *= (1.0 - _SenescenceRate); LayerLive[layer].NonStructuralN *= (1.0 - _SenescenceRate); FOMType fom = new FOMType(); fom.amount = (float)DM; fom.N = (float)N; fom.C = (float)(0.40 * DM); fom.P = 0; fom.AshAlk = 0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0; Layer.LabileP = 0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = Plant.CropType; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); }
private void OnDoActualPlantGrowth(object sender, EventArgs e) { if (Plant.IsAlive) { // Do Root Front Advance int RootLayer = LayerIndex(Depth); double TEM = (TemperatureEffect == null) ? 1 : TemperatureEffect.Value; Depth = Depth + RootFrontVelocity.Value * soilCrop.XF[RootLayer] * TEM; double MaxDepth = 0; for (int i = 0; i < Soil.Thickness.Length; i++) { if (soilCrop.XF[i] > 0) { MaxDepth += Soil.Thickness[i]; } } Depth = Math.Min(Depth, MaxDepth); // Do Root Senescence FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[Soil.Thickness.Length]; for (int layer = 0; layer < Soil.Thickness.Length; layer++) { double DM = LayerLive[layer].Wt * _SenescenceRate * 10.0; double N = LayerLive[layer].StructuralN * _SenescenceRate * 10.0; LayerLive[layer].StructuralWt *= (1.0 - _SenescenceRate); LayerLive[layer].NonStructuralWt *= (1.0 - _SenescenceRate); LayerLive[layer].StructuralN *= (1.0 - _SenescenceRate); LayerLive[layer].NonStructuralN *= (1.0 - _SenescenceRate); FOMType fom = new FOMType(); fom.amount = (float)DM; fom.N = (float)N; fom.C = (float)(0.40 * DM); fom.P = 0; fom.AshAlk = 0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0; Layer.LabileP = 0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = Plant.CropType; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); } }
/// <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); } }
/// <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); } }
private void DoRootGrowth(double Allocation) { int RootLayer = LayerIndex(RootDepth); RootDepth = RootDepth + RootFrontVelocity.Value * xf[RootLayer]; RootDepth = Math.Min(MaximumRootDepth, RootDepth); RootDepth = Math.Min(MathUtility.Sum(dlayer), RootDepth); // Calculate Root Activity Values for water and nitrogen double[] RAw = new double[dlayer.Length]; double[] RAn = new double[dlayer.Length]; double TotalRAw = 0; double TotalRAn = 0; for (int layer = 0; layer < dlayer.Length; layer++) { if (layer <= LayerIndex(RootDepth)) { if (Roots[layer].Mass > 0) { RAw[layer] = SWUptake[layer] / Roots[layer].Mass * dlayer[layer] * RootProportion(layer, RootDepth); RAw[layer] = Math.Max(RAw[layer], 1e-20); // Make sure small numbers to avoid lack of info for partitioning RAn[layer] = NUptake[layer] / Roots[layer].Mass * dlayer[layer] * RootProportion(layer, RootDepth); RAn[layer] = Math.Max(RAw[layer], 1e-10); // Make sure small numbers to avoid lack of info for partitioning } else if (layer > 0) { RAw[layer] = RAw[layer - 1]; RAn[layer] = RAn[layer - 1]; } else { RAw[layer] = 0; RAn[layer] = 0; } } TotalRAw += RAw[layer]; TotalRAn += RAn[layer]; } double allocated = 0; for (int layer = 0; layer < dlayer.Length; layer++) { if (TotalRAw > 0) { Roots[layer].Mass += Allocation * RAw[layer] / TotalRAw; } else if (Allocation > 0) { throw new Exception("Error trying to partition root biomass"); } allocated += Allocation * RAw[layer] / TotalRAw; } // Do Root Senescence FOMLayerLayerType[] FOMLayers = new FOMLayerLayerType[dlayer.Length]; for (int layer = 0; layer < dlayer.Length; layer++) { double Fr = RootSenescenceRate.Value; double DM = Roots[layer].Mass * Fr * 10.0; double N = Roots[layer].N * Fr * 10.0; Roots[layer].Mass *= (1.0 - Fr); Roots[layer].N *= (1.0 - Fr); Roots[layer].Length *= (1.0 - Fr); FOMType fom = new FOMType(); fom.amount = (float)DM; fom.N = (float)N; fom.C = (float)(0.44 * DM); fom.P = 0; fom.AshAlk = 0; FOMLayerLayerType Layer = new FOMLayerLayerType(); Layer.FOM = fom; Layer.CNR = 0; Layer.LabileP = 0; FOMLayers[layer] = Layer; } FOMLayerType FomLayer = new FOMLayerType(); FomLayer.Type = Crop_Type; FomLayer.Layer = FOMLayers; IncorpFOM.Invoke(FomLayer); }