Ejemplo n.º 1
0
        /// <summary>
        /// Senesce any leaves matching the given condition.
        /// </summary>
        /// <param name="predicate">Any leaves matching this predicate will be senesced.</param>
        public void SenesceWhere(Func <PerennialLeafCohort, bool> predicate)
        {
            foreach (PerennialLeafCohort leaf in leaves.Where(predicate))
            {
                leaf.IsSenesced = true;

                if (leaf.Live.Wt > 0)
                {
                    // Move leaf biomass from live to dead pool.
                    live.Subtract(leaf.Live);
                    dead.Add(leaf.Live);

                    // Update the leaf's internal biomass pools.
                    leaf.Dead.Add(leaf.Live);
                    leaf.Senesced.SetTo(leaf.Live);
                    leaf.Live.Clear();

                    // Move leaf area into dead area.
                    leaf.AreaDead += leaf.Area;
                    LaiDead       += leaf.Area;
                    Lai           -= leaf.Area;
                    leaf.Area      = 0;
                }
            }
        }
Ejemplo n.º 2
0
 protected void DoPlantEnding(object sender, EventArgs e)
 {
     if (Wt > 0.0)
     {
         Detached.Add(Live);
         Detached.Add(Dead);
         SurfaceOrganicMatter.Add(Wt * 10, N * 10, 0, Plant.CropType, Name);
     }
     Clear();
 }
Ejemplo n.º 3
0
        protected void DoPlantEnding(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();
        }
Ejemplo n.º 4
0
        /// <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
                    if (plant.PlantType == null)
                    {
                        throw new Exception($"PlantType is null in plant {plant.Name}. The most likely cause is the use of an unofficial/unreleased plant model.");
                    }
                    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.", MessageType.Diagnostic);
                        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.", MessageType.Diagnostic);
                    }
                    return(remainingLiveFraction);
                }
            }

            return(1.0);
        }
Ejemplo n.º 5
0
 private void GetSenescingLeafBiomass(out Biomass Senescing)
 {
     Senescing = new Biomass();
     foreach (PerrenialLeafCohort L in Leaves)
     {
         if (L.Age >= LeafResidenceTime.Value())
         {
             Senescing.Add(L.Live);
         }
     }
 }
Ejemplo n.º 6
0
 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()));
 }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        /// <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);
            }
        }
Ejemplo n.º 9
0
 /// <summary>Recalculate live and dead biomass if necessary</summary>
 private void RecalculateLiveDead()
 {
     if (needToRecalculateLiveDead)
     {
         needToRecalculateLiveDead = false;
         liveBiomass.Clear();
         deadBiomass.Clear();
         foreach (Biomass b in PlantZone.LayerLive)
         {
             liveBiomass.Add(b);
         }
         foreach (Biomass b in PlantZone.LayerDead)
         {
             deadBiomass.Add(b);
         }
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Detach any leaves older than the specified age.
        /// </summary>
        /// <param name="predicate">Any leaves matching this predicate will be deatched..</param>
        public Biomass DetachWhere(Func <PerennialLeafCohort, bool> predicate)
        {
            Biomass detached = new Biomass();

            foreach (PerennialLeafCohort leaf in leaves.Where(predicate))
            {
                detached.Add(leaf.Dead);

                // Need to check this. The assumption here is that leaves will
                // be senesced before they are detached. If this assumption
                // doesn't hold up, mass balance will be violated.
                if (leaf.IsSenesced)
                {
                    LaiDead -= leaf.AreaDead;
                    dead.Subtract(leaf.Senesced);
                }
            }
            leaves.RemoveAll(l => predicate(l));
            return(detached);
        }
Ejemplo n.º 11
0
        protected void OnDoActualPlantGrowth(object sender, EventArgs e)
        {
            if (Plant.IsAlive)
            {
                // Do senescence
                double senescedFrac = SenescenceRate.Value();
                if (Live.Wt * (1.0 - senescedFrac) < BiomassToleranceValue)
                {
                    senescedFrac = 1.0;  // remaining amount too small, senesce all
                }
                Biomass Loss = Live * senescedFrac;
                Live.Subtract(Loss);
                Dead.Add(Loss);
                Senesced.Add(Loss);

                // Do detachment
                double detachedFrac = DetachmentRateFunction.Value();
                if (Dead.Wt * (1.0 - detachedFrac) < BiomassToleranceValue)
                {
                    detachedFrac = 1.0;  // remaining amount too small, detach all
                }
                Biomass detaching = Dead * detachedFrac;
                Dead.Multiply(1.0 - detachedFrac);
                if (detaching.Wt > 0.0)
                {
                    Detached.Add(detaching);
                    SurfaceOrganicMatter.Add(detaching.Wt * 10, detaching.N * 10, 0, Plant.CropType, Name);
                }

                // Do maintenance respiration
                MaintenanceRespiration += Live.MetabolicWt * MaintenanceRespirationFunction.Value();
                Live.MetabolicWt       *= (1 - MaintenanceRespirationFunction.Value());
                MaintenanceRespiration += Live.StorageWt * MaintenanceRespirationFunction.Value();
                Live.StorageWt         *= (1 - MaintenanceRespirationFunction.Value());
            }
        }
Ejemplo n.º 12
0
 private void GetSenescingLeafBiomass(out Biomass Senescing)
 {
     Senescing = new Biomass();
     foreach (PerrenialLeafCohort L in Leaves)
         if (L.Age >= LeafResidenceTime.Value)
             Senescing.Add(L.Live);
 }
Ejemplo n.º 13
0
 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));
 }
Ejemplo n.º 14
0
        /// <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;
        }