Example #1
0
        /// <summary>
        /// Calculate actual decomposition
        /// </summary>
        public SurfaceOrganicMatterDecompType CalculateActualSOMDecomp()
        {
            SurfaceOrganicMatterDecompType actualSOMDecomp = new SurfaceOrganicMatterDecompType();

            actualSOMDecomp.Pool = new SurfaceOrganicMatterDecompPoolType[PotentialSOMDecomp.Pool.Length];
            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                actualSOMDecomp.Pool[i]      = new SurfaceOrganicMatterDecompPoolType();
                actualSOMDecomp.Pool[i].Name = PotentialSOMDecomp.Pool[i].Name;
                actualSOMDecomp.Pool[i].OrganicMatterType = PotentialSOMDecomp.Pool[i].OrganicMatterType;
                actualSOMDecomp.Pool[i].FOM        = new FOMType();
                actualSOMDecomp.Pool[i].FOM.amount = PotentialSOMDecomp.Pool[i].FOM.amount;
            }

            double InitialResidueC = 0;  // Potential residue decomposition provided by surfaceorganicmatter model
            double FinalResidueC   = 0;  // How much is left after decomposition
            double FractionDecomposed;

            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                InitialResidueC += PotentialSOMDecomp.Pool[i].FOM.C;
            }
            FinalResidueC      = SurfaceResidue.C[0];
            FractionDecomposed = 1.0 - MathUtilities.Divide(FinalResidueC, InitialResidueC, 0);
            if (FractionDecomposed < 1)
            {
            }
            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                actualSOMDecomp.Pool[i].FOM.C = PotentialSOMDecomp.Pool[i].FOM.C * FractionDecomposed;
                actualSOMDecomp.Pool[i].FOM.N = PotentialSOMDecomp.Pool[i].FOM.N * FractionDecomposed;
            }
            return(actualSOMDecomp);
        }
        /// <summary>Notify other modules of the potential to decompose.</summary>
        /// <returns></returns>
        private SurfaceOrganicMatterDecompType SendPotDecompEvent()
        {
            SurfaceOrganicMatterDecompType SOMDecomp = new SurfaceOrganicMatterDecompType()
            {
                Pool = new SurfaceOrganicMatterDecompPoolType[numSurfom]
            };

            if (numSurfom <= 0)
            {
                return(SOMDecomp);
            }

            double[] c_pot_decomp, n_pot_decomp, p_pot_decomp;
            PotDecomp(out c_pot_decomp, out n_pot_decomp, out p_pot_decomp);

            for (int residue = 0; residue < numSurfom; residue++)
            {
                SOMDecomp.Pool[residue] = new SurfaceOrganicMatterDecompPoolType()
                {
                    Name = SurfOM[residue].name,
                    OrganicMatterType = SurfOM[residue].OrganicMatterType,

                    FOM = new FOMType()
                    {
                        amount = MathUtilities.Divide(c_pot_decomp[residue], C_fract[residue], 0.0),
                        C      = c_pot_decomp[residue],
                        N      = n_pot_decomp[residue],
                        P      = p_pot_decomp[residue],
                        AshAlk = 0.0
                    }
                }
            }
            ;
            return(SOMDecomp);
        }
Example #3
0
        /// <summary>
        /// Calculate actual decomposition
        /// </summary>
        public SurfaceOrganicMatterDecompType CalculateActualSOMDecomp()
        {
            SurfaceOrganicMatterDecompType ActualSOMDecomp = new SurfaceOrganicMatterDecompType();

            ActualSOMDecomp = ReflectionUtilities.Clone(PotentialSOMDecomp) as SurfaceOrganicMatterDecompType;

            double InitialResidueC = 0;  // Potential residue decomposition provided by surfaceorganicmatter model
            double FinalResidueC   = 0;  // How much is left after decomposition
            double FractionDecomposed;

            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                InitialResidueC += PotentialSOMDecomp.Pool[i].FOM.C;
            }
            FinalResidueC      = SurfaceResidue.C[0];
            FractionDecomposed = 1.0 - MathUtilities.Divide(FinalResidueC, InitialResidueC, 0);
            if (FractionDecomposed < 1)
            {
            }
            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                ActualSOMDecomp.Pool[i].FOM.C = PotentialSOMDecomp.Pool[i].FOM.C * FractionDecomposed;
                ActualSOMDecomp.Pool[i].FOM.N = PotentialSOMDecomp.Pool[i].FOM.N * FractionDecomposed;
            }
            return(ActualSOMDecomp);
        }
Example #4
0
        /// <summary>Calculate actual decomposition</summary>
        public SurfaceOrganicMatterDecompType CalculateActualSOMDecomp()
        {
            // Note:
            //   - If there wasn't enough mineral N to decompose, the rate will be reduced to zero !!  - MUST CHECK THE VALIDITY OF THIS

            SurfaceOrganicMatterDecompType returnSOMDecomp = null;

            foreach (var patch in patches)
            {
                var somDecomp = patch.CalculateActualSOMDecomp();
                foreach (var pool in somDecomp.Pool)
                {
                    pool.FOM.amount = 0;
                }

                if (returnSOMDecomp == null)
                {
                    returnSOMDecomp = somDecomp;
                }
                else
                {
                    returnSOMDecomp.Add(somDecomp);
                }
            }

            return(returnSOMDecomp);
        }
 private void OnDoSurfaceOrganicMatterDecomposition(object sender, EventArgs args)
 {
     actualSOMDecomp = SoilNitrogen.CalculateActualSOMDecomp();
     if (actualSOMDecomp != null)
     {
         DecomposeSurfom(actualSOMDecomp);
     }
 }
        /// <summary>Decomposes the surfom.</summary>
        /// <param name="SOMDecomp">The som decomp.</param>
        private void DecomposeSurfom(SurfaceOrganicMatterDecompType SOMDecomp)
        {
            int numSurfom = SOMDecomp.Pool.Length;       // local surfom counter from received event;
            int residue_no;                              // Index into the global array;

            double[] cPotDecomp = new double[numSurfom]; // pot amount of C to decompose (kg/ha)
            double[] nPotDecomp = new double[numSurfom]; // pot amount of N to decompose (kg/ha)
            double[] pTotDecomp = new double[numSurfom]; // pot amount of P to decompose (kg/ha)
            double   totCDecomp;                         // total amount of c to decompose;
            double   totNDecomp;                         // total amount of c to decompose;
            double   totPDecomp;                         // total amount of c to decompose;

            double SOMcnr = 0;
            double SOMc   = 0;
            double SOMn   = 0;

            // calculate potential decompostion of C, N, and P;
            PotDecomp(out cPotDecomp, out nPotDecomp, out pTotDecomp);

            for (int counter = 0; counter < numSurfom; counter++)
            {
                totCDecomp = SOMDecomp.Pool[counter].FOM.C;
                totNDecomp = SOMDecomp.Pool[counter].FOM.N;

                residue_no = GetResidueNumber(SOMDecomp.Pool[counter].Name);

                if (MathUtilities.IsLessThan(totNDecomp, 0.0) || MathUtilities.IsGreaterThan(totNDecomp, nPotDecomp[residue_no]))
                {
                    summary.WriteWarning(this, string.Format(@"'Total n decomposition' out of bounds! {0} < {1} < {2}",
                                                             0.0, totNDecomp, nPotDecomp[residue_no]));
                }

                SOMc = SurfOM[residue_no].Standing.Sum <OMFractionType>(x => x.C) + SurfOM[residue_no].Lying.Sum <OMFractionType>(x => x.C);
                SOMn = SurfOM[residue_no].Standing.Sum <OMFractionType>(x => x.N) + SurfOM[residue_no].Lying.Sum <OMFractionType>(x => x.N);

                SOMcnr = MathUtilities.Divide(SOMc, SOMn, 0.0);

                const double acceptableErr = 1e-4;

                if (MathUtilities.FloatsAreEqual(totCDecomp, 0.0) && MathUtilities.FloatsAreEqual(totNDecomp, 0.0))
                {
                    // all OK - nothing happening;
                }
                else if (totCDecomp > cPotDecomp[residue_no] + acceptableErr)
                {
                    throw new ApsimXException(this, "SurfaceOM - C decomposition exceeds potential rate");
                }
                else if (totNDecomp > nPotDecomp[residue_no] + acceptableErr)
                {
                    throw new ApsimXException(this, "SurfaceOM - N decomposition exceeds potential rate");
                }

                totPDecomp = totCDecomp * MathUtilities.Divide(pTotDecomp[residue_no], cPotDecomp[residue_no], 0.0);
                Decomp(totCDecomp, totNDecomp, totPDecomp, residue_no);
            }
        }
Example #7
0
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            // Get potential residue decomposition from surfaceom.
            PotentialSOMDecomp = SurfaceOrganicMatter.PotentialDecomposition();

            SurfaceResidue.C[0] = 0;
            SurfaceResidue.N[0] = 0;
            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                SurfaceResidue.C[0] += PotentialSOMDecomp.Pool[i].FOM.C;
                SurfaceResidue.N[0] += PotentialSOMDecomp.Pool[i].FOM.N;
            }
        }
Example #8
0
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            // Get potential residue decomposition from surfaceom.
            PotentialSOMDecomp = SurfaceOrganicMatter.PotentialDecomposition();

            SurfaceResidue.C[0]             = 0;
            SurfaceResidue.N[0]             = 0;
            SurfaceResidue.LayerFraction[0] = Math.Max(Math.Min(1.0, 100 / Soil.Thickness[0]), 0.0);
            for (int i = 0; i < PotentialSOMDecomp.Pool.Length; i++)
            {
                SurfaceResidue.C[0] += PotentialSOMDecomp.Pool[i].FOM.C;
                SurfaceResidue.N[0] += PotentialSOMDecomp.Pool[i].FOM.N;
            }
        }
Example #9
0
        /// <summary>
        /// Gather the information about actual residue decomposition, to be sent back to surface OM
        /// </summary>
        /// <remarks>
        /// Currently P is not being computed by SoilNitrogen, so the corresponding variables are set to zero here
        /// </remarks>
        private void PackActualResidueDecomposition()
        {
            int nLayers = g.dlayer.Length;          // number of layers in the soil

            soilp_dlt_org_p = new double[nLayers];
            double soilp_cpr = MathUtility.Divide(g.SumDoubleArray(g.pot_p_decomp), g.SumDoubleArray(g.pot_c_decomp), 0.0);  // C:P ratio for potential decomposition

            SurfOMActualDecomposition = new SurfaceOrganicMatterDecompType();
            Array.Resize(ref SurfOMActualDecomposition.Pool, g.nResidues);

            for (int residue = 0; residue < g.nResidues; residue++)
            {
                double c_summed = g.SumDoubleArray(dlt_c_decomp[residue]);
                if (Math.Abs(c_summed) < g.epsilon)
                {
                    c_summed = 0.0;
                }
                double n_summed = g.SumDoubleArray(dlt_n_decomp[residue]);
                if (Math.Abs(n_summed) < g.epsilon)
                {
                    n_summed = 0.0;
                }

                // pack up the structure to return decompositions to SurfaceOrganicMatter
                SurfOMActualDecomposition.Pool[residue]      = new SurfaceOrganicMatterDecompPoolType();
                SurfOMActualDecomposition.Pool[residue].FOM  = new FOMType();
                SurfOMActualDecomposition.Pool[residue].Name = g.residueName[residue];
                SurfOMActualDecomposition.Pool[residue].OrganicMatterType = g.residueType[residue];
                SurfOMActualDecomposition.Pool[residue].FOM.amount        = 0.0F;
                SurfOMActualDecomposition.Pool[residue].FOM.C             = (float)c_summed;
                SurfOMActualDecomposition.Pool[residue].FOM.N             = (float)n_summed;
                SurfOMActualDecomposition.Pool[residue].FOM.P             = 0.0F;
                SurfOMActualDecomposition.Pool[residue].FOM.AshAlk        = 0.0F;
                // Note: The values for 'amount', 'P', and 'AshAlk' will not be collected by SurfaceOrganicMatter, so send zero as default.
            }

            // dsg 131004  calculate the old dlt_org_p (from the old Decomposed event sent by residue2) for getting by soilp
            double act_c_decomp     = 0.0;
            double tot_pot_c_decomp = g.SumDoubleArray(g.pot_c_decomp);
            double tot_pot_p_decomp = g.SumDoubleArray(g.pot_p_decomp);

            for (int layer = 0; layer < nLayers; layer++)
            {
                act_c_decomp           = dlt_c_res_to_biom[layer] + dlt_c_res_to_hum[layer] + dlt_c_res_to_atm[layer];
                soilp_dlt_org_p[layer] = tot_pot_p_decomp * MathUtility.Divide(act_c_decomp, tot_pot_c_decomp, 0.0);
            }
        }
Example #10
0
        private void OnDoSurfaceOrganicMatterDecomposition(object sender, EventArgs args)
        {
            actualSOMDecomp = SoilNitrogen.CalculateActualSOMDecomp();
            if (actualSOMDecomp != null)
            {
                DecomposeSurfom(actualSOMDecomp);
            }

            Canopies = new List <ICanopy>();
            foreach (SurfOrganicMatterType pool in SurfOM)
            {
                if (pool.CanopyLying.CoverTotal > 0)
                {
                    Canopies.Add(pool.CanopyLying);
                }
                if (pool.CanopyStanding.CoverTotal > 0)
                {
                    Canopies.Add(pool.CanopyStanding);
                }
            }
        }