예제 #1
0
 private void OnSimulationCommencing(object sender, EventArgs e)
 {
     foreach (string destinationName in destinationNames)
     {
         NutrientPool destination = Apsim.Find(this, destinationName) as NutrientPool;
         if (destination == null)
         {
             throw new Exception("Cannot find destination pool with name: " + destinationName);
         }
         destinations.Add(destination);
     }
 }
예제 #2
0
 private void OnSimulationCommencing(object sender, EventArgs e)
 {
     foreach (string destinationName in destinationNames)
     {
         NutrientPool destination = Apsim.Find(this, destinationName) as NutrientPool;
         if (destination == null)
         {
             throw new Exception("Cannot find destination pool with name: " + destinationName);
         }
         destinations.Add(destination);
     }
     MineralisedN = new double[(Parent as NutrientPool).C.Length];
     Catm         = new double[(Parent as NutrientPool).C.Length];
 }
예제 #3
0
파일: CarbonFlow.cs 프로젝트: hrpasl/ApsimX
        private void OnSimulationCommencing(object sender, EventArgs e)
        {
            destinations = new NutrientPool[destinationNames.Length];

            for (int i = 0; i < destinationNames.Length; i++)
            {
                NutrientPool destination = FindInScope <NutrientPool>(destinationNames[i]);
                if (destination == null)
                {
                    throw new Exception("Cannot find destination pool with name: " + destinationNames[i]);
                }
                destinations[i] = destination;
            }
            MineralisedN              = new double[(Parent as NutrientPool).C.Length];
            Catm                      = new double[(Parent as NutrientPool).C.Length];
            carbonFlowToDestination   = new double[destinations.Length];
            nitrogenFlowToDestination = new double[destinations.Length];
        }
예제 #4
0
파일: CarbonFlow.cs 프로젝트: lie112/ApsimX
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            NutrientPool source = Parent as NutrientPool;

            double[] no3     = NO3.kgha;
            double[] nh4     = NH4.kgha;
            double[] labileP = LabileP.kgha;

            int numLayers       = source.C.Length;
            int numDestinations = destinations.Length;

            for (int i = 0; i < numLayers; i++)
            {
                double carbonFlowFromSource     = Rate.Value(i) * source.C[i];
                double nitrogenFlowFromSource   = MathUtilities.Divide(carbonFlowFromSource * source.N[i], source.C[i], 0);
                double phosphorusFlowFromSource = MathUtilities.Divide(carbonFlowFromSource * source.P[i], source.C[i], 0);

                double totalNitrogenFlowToDestinations   = 0;
                double totalPhosphorusFlowToDestinations = 0;

                double co2Efficiency = CO2Efficiency.Value(i);
                for (int j = 0; j < numDestinations; j++)
                {
                    var destination = destinations[j];
                    carbonFlowToDestination[j]         = carbonFlowFromSource * co2Efficiency * destinationFraction[j];
                    nitrogenFlowToDestination[j]       = MathUtilities.Divide(carbonFlowToDestination[j] * destination.N[i], destination.C[i], 0.0);
                    totalNitrogenFlowToDestinations   += nitrogenFlowToDestination[j];
                    phosphorusFlowToDestination[j]     = MathUtilities.Divide(carbonFlowToDestination[j] * destination.P[i], destination.C[i], 0.0);
                    totalPhosphorusFlowToDestinations += phosphorusFlowToDestination[j];
                }

                // some pools do not fully occupy a layer (e.g. residue decomposition) and so need to incorporate fraction of layer
                double mineralNSupply = (no3[i] + nh4[i]) * source.LayerFraction[i];
                double nSupply        = nitrogenFlowFromSource + mineralNSupply;
                double mineralPSupply = labileP[i] * source.LayerFraction[i];
                double pSupply        = phosphorusFlowFromSource + mineralPSupply;

                double SupplyFactor = 1;

                if (totalNitrogenFlowToDestinations > nSupply)
                {
                    SupplyFactor = MathUtilities.Bound(MathUtilities.Divide(mineralNSupply, totalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0);
                }
                if (totalPhosphorusFlowToDestinations > pSupply)
                {
                    double pSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(mineralPSupply, totalPhosphorusFlowToDestinations - phosphorusFlowFromSource, 1.0), 0.0, 1.0);
                    // ALERT
                    pSupplyFactor = 1; // remove P constraint until P model fully operational
                    SupplyFactor  = Math.Min(SupplyFactor, pSupplyFactor);
                }

                if (SupplyFactor < 1)
                {
                    for (int j = 0; j < numDestinations; j++)
                    {
                        carbonFlowToDestination[j]     *= SupplyFactor;
                        nitrogenFlowToDestination[j]   *= SupplyFactor;
                        phosphorusFlowToDestination[j] *= SupplyFactor;
                    }
                    totalNitrogenFlowToDestinations   *= SupplyFactor;
                    totalPhosphorusFlowToDestinations *= SupplyFactor;

                    carbonFlowFromSource     *= SupplyFactor;
                    nitrogenFlowFromSource   *= SupplyFactor;
                    phosphorusFlowFromSource *= SupplyFactor;
                }

                source.C[i] -= carbonFlowFromSource;
                source.N[i] -= nitrogenFlowFromSource;
                source.P[i] -= phosphorusFlowFromSource;

                Catm[i] = carbonFlowFromSource - carbonFlowToDestination.Sum();
                for (int j = 0; j < numDestinations; j++)
                {
                    destinations[j].C[i] += carbonFlowToDestination[j];
                    destinations[j].N[i] += nitrogenFlowToDestination[j];
                    destinations[j].P[i] += phosphorusFlowToDestination[j];
                }

                if (totalNitrogenFlowToDestinations <= nitrogenFlowFromSource)
                {
                    MineralisedN[i] = nitrogenFlowFromSource - totalNitrogenFlowToDestinations;
                    nh4[i]         += MineralisedN[i];
                }
                else
                {
                    double NDeficit          = totalNitrogenFlowToDestinations - nitrogenFlowFromSource;
                    double NH4Immobilisation = Math.Min(nh4[i], NDeficit);
                    nh4[i]   -= NH4Immobilisation;
                    NDeficit -= NH4Immobilisation;

                    double NO3Immobilisation = Math.Min(no3[i], NDeficit);
                    no3[i]   -= NO3Immobilisation;
                    NDeficit -= NO3Immobilisation;

                    MineralisedN[i] = -NH4Immobilisation - NO3Immobilisation;

                    if (MathUtilities.IsGreaterThan(NDeficit, 0.0))
                    {
                        throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name);
                    }
                }

                if (totalPhosphorusFlowToDestinations <= phosphorusFlowFromSource)
                {
                    MineralisedP[i] = phosphorusFlowFromSource - totalPhosphorusFlowToDestinations;
                    labileP[i]     += MineralisedP[i];
                }
                else
                {
                    double PDeficit        = totalPhosphorusFlowToDestinations - phosphorusFlowFromSource;
                    double PImmobilisation = Math.Min(labileP[i], PDeficit);
                    labileP[i]     -= PImmobilisation;
                    PDeficit       -= PImmobilisation;
                    MineralisedP[i] = -PImmobilisation;

                    // ALERT
                    //if (MathUtilities.IsGreaterThan(PDeficit, 0.0))
                    //    throw new Exception("Insufficient mineral P for immobilisation demand for C flow " + Name);
                }
            }
        }
예제 #5
0
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            NutrientPool source = Parent as NutrientPool;

            double[] NH4 = solutes.GetSolute("NH4");
            double[] NO3 = solutes.GetSolute("NO3");

            for (int i = 0; i < source.C.Length; i++)
            {
                double carbonFlowFromSource   = Rate.Value(i) * source.C[i];
                double nitrogenFlowFromSource = MathUtilities.Divide(carbonFlowFromSource, source.CNRatio[i], 0);

                double[] carbonFlowToDestination   = new double[destinations.Count];
                double[] nitrogenFlowToDestination = new double[destinations.Count];

                for (int j = 0; j < destinations.Count; j++)
                {
                    carbonFlowToDestination[j]   = carbonFlowFromSource * CO2Efficiency.Value(i) * destinationFraction[j];
                    nitrogenFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j], destinations[j].CNRatio[i], 0.0);
                }

                double TotalNitrogenFlowToDestinations = MathUtilities.Sum(nitrogenFlowToDestination);
                double NSupply = nitrogenFlowFromSource + NO3[i] + NH4[i];

                if (MathUtilities.Sum(nitrogenFlowToDestination) > NSupply)
                {
                    double NSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(NO3[i] + NH4[i], TotalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0);

                    for (int j = 0; j < destinations.Count; j++)
                    {
                        carbonFlowToDestination[j]   *= NSupplyFactor;
                        nitrogenFlowToDestination[j] *= NSupplyFactor;
                        if (nitrogenFlowToDestination[j] > 0.5)
                        {
                        }
                    }
                    TotalNitrogenFlowToDestinations *= NSupplyFactor;

                    carbonFlowFromSource   *= NSupplyFactor;
                    nitrogenFlowFromSource *= NSupplyFactor;
                }

                source.C[i] -= carbonFlowFromSource;
                source.N[i] -= nitrogenFlowFromSource;
                for (int j = 0; j < destinations.Count; j++)
                {
                    destinations[j].C[i] += carbonFlowToDestination[j];
                    destinations[j].N[i] += nitrogenFlowToDestination[j];
                }


                if (TotalNitrogenFlowToDestinations <= nitrogenFlowFromSource)
                {
                    NH4[i] += nitrogenFlowFromSource - TotalNitrogenFlowToDestinations;
                }
                else
                {
                    double NDeficit          = TotalNitrogenFlowToDestinations - nitrogenFlowFromSource;
                    double NH4Immobilisation = Math.Min(NH4[i], NDeficit);
                    NH4[i]   -= NH4Immobilisation;
                    NDeficit -= NH4Immobilisation;

                    double NO3Immobilisation = Math.Min(NO3[i], NDeficit);
                    NO3[i]   -= NO3Immobilisation;
                    NDeficit -= NO3Immobilisation;

                    if (MathUtilities.IsGreaterThan(NDeficit, 0.0))
                    {
                        throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name);
                    }
                }
            }
            solutes.SetSolute("NH4", SoluteManager.SoluteSetterType.Soil, NH4);
            solutes.SetSolute("NO3", SoluteManager.SoluteSetterType.Soil, NO3);
        }
예제 #6
0
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            NutrientPool source = Parent as NutrientPool;

            for (int i = 0; i < source.C.Length; i++)
            {
                double carbonFlowFromSource   = Rate.Value(i) * source.C[i];
                double nitrogenFlowFromSource = MathUtilities.Divide(carbonFlowFromSource, source.CNRatio[i], 0);

                double[] carbonFlowToDestination   = new double[destinations.Count];
                double[] nitrogenFlowToDestination = new double[destinations.Count];

                for (int j = 0; j < destinations.Count; j++)
                {
                    carbonFlowToDestination[j]   = carbonFlowFromSource * CO2Efficiency.Value(i) * destinationFraction[j];
                    nitrogenFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j], destinations[j].CNRatio[i], 0.0);
                }

                double TotalNitrogenFlowToDestinations = MathUtilities.Sum(nitrogenFlowToDestination);
                // some pools do not fully occupy a layer (e.g. residue decomposition) and so need to incorporate fraction of layer
                double MineralNSupply = (NO3.kgha[i] + NH4.kgha[i]) * source.LayerFraction[i];
                double NSupply        = nitrogenFlowFromSource + MineralNSupply;

                if (TotalNitrogenFlowToDestinations > NSupply)
                {
                    double NSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(MineralNSupply, TotalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0);

                    for (int j = 0; j < destinations.Count; j++)
                    {
                        carbonFlowToDestination[j]   *= NSupplyFactor;
                        nitrogenFlowToDestination[j] *= NSupplyFactor;
                    }
                    TotalNitrogenFlowToDestinations *= NSupplyFactor;

                    carbonFlowFromSource   *= NSupplyFactor;
                    nitrogenFlowFromSource *= NSupplyFactor;
                }

                source.C[i] -= carbonFlowFromSource;
                source.N[i] -= nitrogenFlowFromSource;
                Catm[i]      = carbonFlowFromSource - MathUtilities.Sum(carbonFlowToDestination);
                for (int j = 0; j < destinations.Count; j++)
                {
                    destinations[j].C[i] += carbonFlowToDestination[j];
                    destinations[j].N[i] += nitrogenFlowToDestination[j];
                }

                if (TotalNitrogenFlowToDestinations <= nitrogenFlowFromSource)
                {
                    MineralisedN[i] = nitrogenFlowFromSource - TotalNitrogenFlowToDestinations;
                    NH4.kgha[i]    += MineralisedN[i];
                }
                else
                {
                    double NDeficit          = TotalNitrogenFlowToDestinations - nitrogenFlowFromSource;
                    double NH4Immobilisation = Math.Min(NH4.kgha[i], NDeficit);
                    NH4.kgha[i] -= NH4Immobilisation;
                    NDeficit    -= NH4Immobilisation;

                    double NO3Immobilisation = Math.Min(NO3.kgha[i], NDeficit);
                    NO3.kgha[i] -= NO3Immobilisation;
                    NDeficit    -= NO3Immobilisation;

                    MineralisedN[i] = -NH4Immobilisation - NO3Immobilisation;

                    if (MathUtilities.IsGreaterThan(NDeficit, 0.0))
                    {
                        throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name);
                    }
                }
            }
        }