示例#1
0
        /// <summary>
        /// Set the n uptake for today
        /// </summary>
        public void SetActualNitrogenUptakes(List <ZoneWaterAndN> info)
        {
            NO3Uptake = info[0].NO3N;
            NH4Uptake = info[0].NH4N;

            NO3.SetKgHa(SoluteSetterType.Plant, MathUtilities.Subtract(NO3.kgha, NO3Uptake));
            NH4.SetKgHa(SoluteSetterType.Plant, MathUtilities.Subtract(NH4.kgha, NH4Uptake));
        }
示例#2
0
        /// <summary>Add urine to the soil.</summary>
        private void AddUrineToSoil()
        {
            // find the layer that the fertilizer is to be added to.
            int layer = soil.LayerIndexOfDepth(DepthUrineIsAdded);

            var no3Values = NO3.kgha;

            no3Values[layer] += AmountUrineNReturned;
            NO3.SetKgHa(SoluteSetterType.Fertiliser, no3Values);
        }
示例#3
0
        /// <summary>Apply fertiliser.</summary>
        /// <param name="Amount">The amount.</param>
        /// <param name="Type">The type.</param>
        /// <param name="Depth">The depth.</param>
        /// <param name="doOutput">If true, output will be written to the summary.</param>
        public void Apply(double Amount, Types Type, double Depth = 0.0, bool doOutput = true)
        {
            if (Amount > 0)
            {
                // find the layer that the fertilizer is to be added to.
                int layer = SoilUtilities.LayerIndexOfDepth(soilPhysical.Thickness, Depth);

                FertiliserType fertiliserType = Definitions.FirstOrDefault(f => f.Name == Type.ToString());
                if (fertiliserType == null)
                {
                    throw new ApsimXException(this, "Cannot find fertiliser type '" + Type + "'");
                }

                // We find the current amount of N in each form, add to it as needed,
                // then set the new value. An alternative approach could call AddKgHaDelta
                // rather than SetKgHa
                if (fertiliserType.FractionNO3 != 0)
                {
                    var values = NO3.kgha;
                    values[layer] += Amount * fertiliserType.FractionNO3;
                    NO3.SetKgHa(SoluteSetterType.Fertiliser, values);
                    NitrogenApplied += Amount * fertiliserType.FractionNO3;
                }
                if (fertiliserType.FractionNH4 != 0)
                {
                    var values = NH4.kgha;
                    values[layer] += Amount * fertiliserType.FractionNH4;
                    NH4.SetKgHa(SoluteSetterType.Fertiliser, values);
                    NitrogenApplied += Amount * fertiliserType.FractionNH4;
                }
                if (fertiliserType.FractionUrea != 0)
                {
                    var values = Urea.kgha;
                    values[layer] += Amount * fertiliserType.FractionUrea;
                    Urea.SetKgHa(SoluteSetterType.Fertiliser, values);
                    NitrogenApplied += Amount * fertiliserType.FractionUrea;
                }
                if (doOutput)
                {
                    Summary.WriteMessage(this, string.Format("{0} kg/ha of {1} added at depth {2} layer {3}", Amount, Type, Depth, layer + 1));
                }

                Fertilised?.Invoke(this, new FertiliserApplicationType()
                {
                    Amount = Amount, Depth = Depth, FertiliserType = Type
                });
            }
        }
示例#4
0
        /// <summary>Apply fertiliser.</summary>
        /// <param name="Amount">The amount.</param>
        /// <param name="Type">The type.</param>
        /// <param name="Depth">The depth.</param>
        /// <param name="doOutput">If true, output will be written to the summary.</param>
        /// <exception cref="ApsimXException">Cannot find fertiliser type ' + Type + '</exception>
        public void Apply(double Amount, Types Type, double Depth = 0.0, bool doOutput = true)
        {
            if (Amount > 0)
            {
                // find the layer that the fertilizer is to be added to.
                int layer = GetLayerDepth(Depth, Soil.Thickness);

                FertiliserType fertiliserType = Definitions.FirstOrDefault(f => f.Name == Type.ToString());
                if (fertiliserType == null)
                {
                    throw new ApsimXException(this, "Cannot find fertiliser type '" + Type + "'");
                }

                if (fertiliserType.FractionNO3 != 0)
                {
                    var values = NO3.kgha;
                    values[layer] += Amount * fertiliserType.FractionNO3;
                    NO3.SetKgHa(SoluteSetterType.Fertiliser, values);
                    NitrogenApplied += Amount * fertiliserType.FractionNO3;
                }
                if (fertiliserType.FractionNH4 != 0)
                {
                    var values = NH4.kgha;
                    values[layer] += Amount * fertiliserType.FractionNH4;
                    NH4.SetKgHa(SoluteSetterType.Fertiliser, values);
                    NitrogenApplied += Amount * fertiliserType.FractionNH4;
                }
                if (fertiliserType.FractionUrea != 0)
                {
                    var values = Urea.kgha;
                    values[layer] += Amount * fertiliserType.FractionUrea;
                    Urea.SetKgHa(SoluteSetterType.Fertiliser, values);
                    NitrogenApplied += Amount * fertiliserType.FractionUrea;
                }
                if (doOutput)
                {
                    Summary.WriteMessage(this, string.Format("{0} kg/ha of {1} added at depth {2} layer {3}", Amount, Type, Depth, layer + 1));
                }

                Fertilised?.Invoke(this, new FertiliserApplicationType()
                {
                    Amount = Amount, Depth = Depth, FertiliserType = Type
                });
            }
        }
示例#5
0
文件: PFlow.cs 项目: lie112/ApsimX
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            if (sourceSolute == null)
            {
                sourceSolute      = FindInScope <ISolute>(Parent.Name);
                destinationSolute = FindInScope <ISolute>(destinationName);
            }

            double[] source    = sourceSolute.kgha;
            int      numLayers = source.Length;

            if (Value == null)
            {
                Value = new double[source.Length];
            }

            double[] destination = null;
            if (destinationName != null)
            {
                destination = destinationSolute.kgha;
            }

            for (int i = 0; i < numLayers; i++)
            {
                double phosphorusFlow = 0;
                if (source[i] > 0)
                {
                    phosphorusFlow = rate.Value(i) * source[i];
                }

                source[i]      -= phosphorusFlow;
                Value[i]        = phosphorusFlow;
                destination[i] += phosphorusFlow;
            }
            sourceSolute.SetKgHa(SoluteSetterType.Soil, source);
            destinationSolute.SetKgHa(SoluteSetterType.Soil, destination);
        }
示例#6
0
        /// <summary>Add urine to the soil.</summary>
        private void AddUrineToSoil()
        {
            if (DoUrineReturn == null)
            {
                // We will do the urine return.
                // find the layer that the fertilizer is to be added to.
                int layer = SoilUtilities.LayerIndexOfDepth(soilPhysical.Thickness, DepthUrineIsAdded);

                var ureaValues = Urea.kgha;
                ureaValues[layer] += AmountUrineNReturned;
                Urea.SetKgHa(SoluteSetterType.Fertiliser, ureaValues);
            }
            else
            {
                // Another model (e.g. urine patch) will do the urine return.
                DoUrineReturn.Invoke(this,
                                     new UrineReturnType()
                {
                    Amount   = AmountUrineNReturned,
                    Depth    = DepthUrineIsAdded,
                    GrazedDM = GrazedDM
                });
            }
        }
示例#7
0
        private void OnDoSoilWaterMovement(object sender, EventArgs e)
        {
            // Calculate lateral flow.
            lateralFlowModel.Calculate();
            if (LateralFlow.Length > 0)
            {
                Water = MathUtilities.Subtract(Water, LateralFlow);
            }

            // Calculate runoff.
            Runoff = runoffModel.Value();

            // Calculate infiltration.
            Infiltration = PotentialInfiltration - Runoff;

            Water[0] = Water[0] + Infiltration + Runon;

            // Allow irrigation to infiltrate.
            foreach (var irrigation in irrigations)
            {
                if (irrigation.Amount > 0)
                {
                    int irrigationLayer = soil.LayerIndexOfDepth(Convert.ToInt32(irrigation.Depth, CultureInfo.InvariantCulture));
                    Water[irrigationLayer] += irrigation.Amount;
                    if (irrigationLayer == 0)
                    {
                        Infiltration += irrigation.Amount;
                    }

                    if (no3 != null)
                    {
                        no3.kgha[irrigationLayer] += irrigation.NO3;
                    }

                    if (nh4 != null)
                    {
                        nh4.kgha[irrigationLayer] += irrigation.NH4;
                    }

                    if (cl != null)
                    {
                        cl.kgha[irrigationLayer] += irrigation.CL;
                    }
                }
            }

            // Saturated flow.
            Flux = saturatedFlow.Values;

            // Add backed up water to runoff.
            Water[0] = Water[0] - saturatedFlow.backedUpSurface;

            // Now reduce the infiltration amount by what backed up.
            Infiltration = Infiltration - saturatedFlow.backedUpSurface;

            // Turn the proportion of the infiltration that backed up into runoff.
            Runoff = Runoff + saturatedFlow.backedUpSurface;

            // Should go to pond if one exists.
            //  pond = Math.Min(Runoff, max_pond);
            MoveDown(Water, Flux);

            double[] no3Values  = no3.kgha;
            double[] ureaValues = urea.kgha;

            // Calcualte solute movement down with water.
            double[] no3Down = CalculateSoluteMovementDown(no3Values, Water, Flux, SoluteFluxEfficiency);
            MoveDown(no3Values, no3Down);
            double[] ureaDown = CalculateSoluteMovementDown(ureaValues, Water, Flux, SoluteFluxEfficiency);
            MoveDown(ureaValues, ureaDown);

            // Calculate evaporation and remove from top layer.
            double es = evaporationModel.Calculate();

            Water[0] = Water[0] - es;

            // Calculate unsaturated flow of water and apply.
            Flow = unsaturatedFlow.Values;
            MoveUp(Water, Flow);

            // Check for errors in water variables.
            //CheckForErrors();

            // Calculate water table depth.
            waterTableModel.Calculate();

            // Calculate and apply net solute movement.
            double[] no3Up = CalculateNetSoluteMovement(no3Values, Water, Flow, SoluteFlowEfficiency);
            MoveUp(no3Values, no3Up);
            double[] ureaUp = CalculateNetSoluteMovement(ureaValues, Water, Flow, SoluteFlowEfficiency);
            MoveUp(ureaValues, ureaUp);

            // Update flow output variables.
            FlowNO3  = MathUtilities.Subtract(no3Down, no3Up);
            FlowUrea = MathUtilities.Subtract(ureaDown, ureaUp);

            // Set solute state variables.
            no3.SetKgHa(SoluteSetterType.Soil, no3Values);
            urea.SetKgHa(SoluteSetterType.Soil, ureaValues);

            // Now that we've finished moving water, calculate volumetric water
            waterVolumetric = MathUtilities.Divide(Water, soil.Thickness);
        }
示例#8
0
        private void OnDoSoilWaterMovement(object sender, EventArgs e)
        {
            // Calculate lateral flow.
            LateralFlow = lateralFlowModel.Values;
            MathUtilities.Subtract(Water, LateralFlow);

            // Calculate runoff.
            Runoff = runoffModel.Value();

            // Calculate infiltration.
            Infiltration = PotentialInfiltration - Runoff;
            Water[0]     = Water[0] + Infiltration;

            // Allow irrigation to infiltrate.
            if (!irrigation.WillRunoff)
            {
                int irrigationLayer = APSIM.Shared.APSoil.SoilUtilities.FindLayerIndex(properties, Convert.ToInt32(irrigation.Depth, CultureInfo.InvariantCulture));
                Water[irrigationLayer] = irrigation.IrrigationApplied;
                Infiltration          += irrigation.IrrigationApplied;

                // DeanH - haven't implemented solutes in irrigation water yet.
                // NO3[irrigationLayer] = irrigation.NO3;
                // NH4[irrigationLayer] = irrigation.NH4;
                // CL[irrigationLayer] = irrigation.Cl;
            }

            // Saturated flow.
            Flux = saturatedFlow.Values;

            // Add backed up water to runoff.
            Water[0] = Water[0] - saturatedFlow.backedUpSurface;

            // Now reduce the infiltration amount by what backed up.
            Infiltration = Infiltration - saturatedFlow.backedUpSurface;

            // Turn the proportion of the infiltration that backed up into runoff.
            Runoff = Runoff + saturatedFlow.backedUpSurface;

            // Should go to pond if one exists.
            //  pond = Math.Min(Runoff, max_pond);
            MoveDown(Water, Flux);

            double[] NO3Values = soilNitrogen.CalculateNO3();
            double[] NH4Values = soilNitrogen.CalculateNH4();

            // Calcualte solute movement down with water.
            double[] NO3Down = CalculateSoluteMovementDown(NO3Values, Water, Flux, SoluteFluxEfficiency);
            double[] NH4Down = CalculateSoluteMovementDown(NH4Values, Water, Flux, SoluteFluxEfficiency);
            MoveDown(NO3Values, NO3Down);
            MoveDown(NH4Values, NH4Down);

            double es = evaporationModel.Calculate();

            Water[0] = Water[0] - es;

            Flow = unsaturatedFlow.Values;
            MoveUp(Water, Flow);

            CheckForErrors();

            double waterTableDepth = waterTableModel.Value();

            double[] NO3Up = CalculateSoluteMovementUpDown(soilNitrogen.CalculateNO3(), Water, Flow, SoluteFlowEfficiency);
            double[] NH4Up = CalculateSoluteMovementUpDown(soilNitrogen.CalculateNH4(), Water, Flow, SoluteFlowEfficiency);
            MoveUp(NO3Values, NO3Up);
            MoveUp(NH4Values, NH4Up);

            // Set deltas
            NO3.SetKgHa(SoluteSetterType.Soil, MathUtilities.Subtract(soilNitrogen.CalculateNO3(), NO3Values));
            NH4.SetKgHa(SoluteSetterType.Soil, MathUtilities.Subtract(soilNitrogen.CalculateNH4(), NH4Values));
        }
 /// <summary>Remove nutrients from soil - uptake.</summary>
 /// <param name="no3Amount">Amount of no3 to remove.</param>
 /// <param name="nh4Amount">Amount of nh4 to remove.</param>
 public void PerformNutrientUptake(double[] no3Amount, double[] nh4Amount)
 {
     no3.SetKgHa(SoluteSetterType.Plant, MathUtilities.Subtract(no3.kgha, no3Amount));
     nh4.SetKgHa(SoluteSetterType.Plant, MathUtilities.Subtract(nh4.kgha, nh4Amount));
 }
示例#10
0
文件: NFlow.cs 项目: Chloe0317/ApsimX
        private void OnDoSoilOrganicMatter(object sender, EventArgs e)
        {
            if (sourceSolute == null)
            {
                sourceSolute      = FindInScope <ISolute>(Parent.Name);
                destinationSolute = FindInScope <ISolute>(destinationName);
            }

            double[] source    = sourceSolute.kgha;
            int      numLayers = source.Length;

            if (Value == null)
            {
                Value = new double[source.Length];
            }
            if (Natm == null)
            {
                Natm = new double[source.Length];
            }
            if (N2Oatm == null)
            {
                N2Oatm = new double[source.Length];
            }


            double[] destination = null;
            if (destinationName != null)
            {
                destination = destinationSolute.kgha;
            }

            for (int i = 0; i < numLayers; i++)
            {
                double nitrogenFlow = 0;
                if (source[i] > 0)
                {
                    nitrogenFlow = rate.Value(i) * source[i];
                }

                if (nitrogenFlow > 0)
                {
                    Natm[i] = nitrogenFlow * NLoss.Value(i);  // keep value of loss for use in output
                }
                else
                {
                    Natm[i] = 0;
                }

                if (Natm[i] > 0)
                {
                    N2Oatm[i] = Natm[i] * N2OFraction.Value(i);
                }
                else
                {
                    N2Oatm[i] = 0;
                }

                double nitrogenFlowToDestination = nitrogenFlow - Natm[i];

                if (destination == null && NLoss.Value(i) != 1)
                {
                    throw new Exception("N loss fraction for N flow must be 1 if no destination is specified.");
                }

                source[i] -= nitrogenFlow;
                Value[i]   = nitrogenFlowToDestination; // keep value of flow for use in output
                if (destination != null)
                {
                    destination[i] += nitrogenFlowToDestination;
                }
            }
            sourceSolute.SetKgHa(SoluteSetterType.Soil, source);
            if (destination != null)
            {
                destinationSolute.SetKgHa(SoluteSetterType.Soil, destination);
            }
        }