Пример #1
0
        /// <summary>Does the Nitrogen uptake.</summary>
        /// <param name="NO3NAmount">The NO3NAmount.</param>
        /// <param name="NH4NAmount">The NH4NAmount.</param>
        public override void DoNitrogenUptake(double[] NO3NAmount, double[] NH4NAmount)
        {
            // Send the delta water back to SoilN that we're going to uptake.
            NitrogenChangedType NitrogenUptake = new NitrogenChangedType();

            NitrogenUptake.DeltaNO3 = MathUtilities.Multiply_Value(NO3NAmount, -1.0);
            NitrogenUptake.DeltaNH4 = MathUtilities.Multiply_Value(NH4NAmount, -1.0);

            NitUptake = MathUtilities.Add(NitrogenUptake.DeltaNO3, NitrogenUptake.DeltaNH4);
            if (NitrogenChanged != null)
            {
                NitrogenChanged.Invoke(NitrogenUptake);
            }
        }
Пример #2
0
        /// <summary>Send a nitrogen changed event.</summary>
        /// <param name="NO3">The no3 values.</param>
        /// <param name="NH4">The nh4 values.</param>
        private void SendNitrogenChangedEvent(double[] NO3, double[] NH4)
        {
            NitrogenChangedType NitrogenDeltas = new NitrogenChangedType();

            NitrogenDeltas.Sender     = "Soil";
            NitrogenDeltas.SenderType = "Soil";

            NitrogenDeltas.DeltaNO3 = MathUtilities.Subtract(soilNitrogen.NO3, NO3);
            NitrogenDeltas.DeltaNH4 = MathUtilities.Subtract(soilNitrogen.NH4, NH4);

            if (NitrogenChanged != null)
            {
                NitrogenChanged.Invoke(NitrogenDeltas);
            }
        }
Пример #3
0
        /// <summary>Does the Nitrogen uptake.</summary>
        /// <param name="zonesFromSoilArbitrator">List of zones from soil arbitrator</param>
        public void DoNitrogenUptake(List <ZoneWaterAndN> zonesFromSoilArbitrator)
        {
            foreach (ZoneWaterAndN thisZone in zonesFromSoilArbitrator)
            {
                ZoneState zone = Zones.Find(z => z.Name == thisZone.Zone.Name);
                if (zone != null)
                {
                    // Send the delta water back to SoilN that we're going to uptake.
                    NitrogenChangedType NitrogenUptake = new NitrogenChangedType();
                    NitrogenUptake.DeltaNO3 = MathUtilities.Multiply_Value(thisZone.NO3N, -1.0);
                    NitrogenUptake.DeltaNH4 = MathUtilities.Multiply_Value(thisZone.NH4N, -1.0);

                    zone.NitUptake = MathUtilities.Add(NitrogenUptake.DeltaNO3, NitrogenUptake.DeltaNH4);
                    zone.soil.SoilNitrogen.SetNitrogenChanged(NitrogenUptake);
                }
            }
        }
Пример #4
0
    /// <summary>
    /// Make the changes from solute degradation effective . Uses the SoluteChanged event
    /// </summary>
    public override void EffectivateSoluteDegradation()
    {
        // First reduce the amount of this solute
        SoluteChangedType SoluteChanges = new SoluteChangedType();

        SoluteChanges.Sender      = "SoluteDegradation";
        SoluteChanges.SoluteName  = Name;
        SoluteChanges.SoluteUnits = "kg/ha";
        SoluteChanges.DeltaSolute = deltaSoluteTransformed;
        SoluteChanged.Invoke(SoluteChanges);

        // Now increase the degradation product (assumed also solute)
        NitrogenChangedType NitrogenChanges = new NitrogenChangedType();

        NitrogenChanges.Sender     = "SoluteDegradation";
        NitrogenChanges.SenderType = "Solute";
        NitrogenChanges.DeltaUrea  = Array.ConvertAll(deltaSoluteTransformed, i => - i);
        NitrogenChanged.Invoke(NitrogenChanges);
    }
Пример #5
0
    /// <summary>
    /// Update the water and N balance.
    /// </summary>
    private void UpdateWaterAndNBalance()
    {
        NitrogenChangedType NitrogenUptake = new NitrogenChangedType();

        NitrogenUptake.Sender     = "Plant";
        NitrogenUptake.SenderType = "Plant";
        NitrogenUptake.DeltaNO3   = MathUtility.Multiply_Value(dlt_no3gsm, Conversions.gm2kg / Conversions.sm2ha);
        NitrogenUptake.DeltaNH4   = MathUtility.Multiply_Value(dlt_nh4gsm, Conversions.gm2kg / Conversions.sm2ha);
        Util.Debug("Root.NitrogenUptake.DeltaNO3=%f", MathUtility.Sum(NitrogenUptake.DeltaNO3));
        Util.Debug("Root.NitrogenUptake.DeltaNH4=%f", MathUtility.Sum(NitrogenUptake.DeltaNH4));
        NitrogenChanged.Invoke(NitrogenUptake);

        // Send back delta water and nitrogen back to APSIM.
        if (!SwimIsPresent)
        {
            WaterChangedType WaterUptake = new WaterChangedType();
            WaterUptake.DeltaWater = dlt_sw_dep;
            Util.Debug("Root.WaterUptake=%f", MathUtility.Sum(WaterUptake.DeltaWater));
            WaterChanged.Invoke(WaterUptake);
        }
    }
Пример #6
0
        /// <summary>
        /// Set the n uptake for today
        /// </summary>
        public void SetNUptake(List <ZoneWaterAndN> info)
        {
            NitrogenChangedType NUptakeType = new NitrogenChangedType();

            NUptakeType.Sender     = Name;
            NUptakeType.SenderType = "Plant";
            NUptakeType.DeltaNO3   = new double[Soil.Thickness.Length];
            NUptakeType.DeltaNH4   = new double[Soil.Thickness.Length];
            NO3Uptake = info[0].NO3N;
            NH4Uptake = info[0].NH4N;

            for (int j = 0; j < Soil.SoilWater.LL15mm.Length; j++)
            {
                NUptakeType.DeltaNO3[j] = -NO3Uptake[j];
                NUptakeType.DeltaNH4[j] = -NH4Uptake[j];
            }

            if (NitrogenChanged != null)
            {
                NitrogenChanged.Invoke(NUptakeType);
            }
        }
Пример #7
0
        /// <summary>Apply fertiliser.</summary>
        /// <param name="Amount">The amount.</param>
        /// <param name="Type">The type.</param>
        /// <param name="Depth">The depth.</param>
        /// <exception cref="ApsimXException">Cannot find fertiliser type ' + Type + '</exception>
        public void Apply(double Amount, Types Type, double Depth = 0.0)
        {
            if (Amount > 0 && NitrogenChanged != null)
            {
                // 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 + "'");
                }

                NitrogenChangedType NitrogenChanges = new NitrogenChangedType();
                NitrogenChanges.Sender = Apsim.FullPath(this);

                if (fertiliserType.FractionNO3 != 0)
                {
                    NitrogenChanges.DeltaNO3        = new double[Soil.Thickness.Length];
                    NitrogenChanges.DeltaNO3[layer] = Amount * fertiliserType.FractionNO3;
                    NitrogenApplied += Amount * fertiliserType.FractionNO3;
                }
                if (fertiliserType.FractionNH4 != 0)
                {
                    NitrogenChanges.DeltaNH4        = new double[Soil.Thickness.Length];
                    NitrogenChanges.DeltaNH4[layer] = Amount * fertiliserType.FractionNH4;
                    NitrogenApplied += Amount * fertiliserType.FractionNH4;
                }
                if (fertiliserType.FractionUrea != 0)
                {
                    NitrogenChanges.DeltaUrea        = new double[Soil.Thickness.Length];
                    NitrogenChanges.DeltaUrea[layer] = Amount * fertiliserType.FractionUrea;
                    NitrogenApplied += Amount * fertiliserType.FractionUrea;
                }

                NitrogenChanged.Invoke(NitrogenChanges);
                Summary.WriteMessage(this, string.Format("{0} kg/ha of {1} added at depth {2} layer {3}", Amount, Type, Depth, layer + 1));
            }
        }
Пример #8
0
        /// <summary>
        /// Send the nitrogen uptake arrays back to the plants and send the change in nitrogen back to the soil
        /// </summary>
        /// <param name="resourceToArbitrate"></param>
        private void SetNitrogenUptake(string resourceToArbitrate)
        {
            zones = -1;
            int maxPlants = 0;
            int maxLayers = 0;

            foreach (Zone zone in Apsim.FindAll(Simulation, typeof(Zone)))  //foreach (Zone zone in Simulation.FindAll(typeof(Zone)))
            {
                zones += 1;

                // Find plants in paddock.
                List <ICrop2> plants = zone.Plants;
                maxPlants = Math.Max(plants.Count, maxPlants);

                // Find soil in paddock.
                Soil Soil = (Soil)Apsim.Find(zone, typeof(Soil));
                maxLayers = Math.Max(Soil.Thickness.Length, maxLayers);

                double[] dummyArray1 = new double[Soil.Thickness.Length];  // have to create a new array for each plant to avoid the .NET pointer thing - will have to re-think this with when zones come in
                double[] dummyArray2 = new double[Soil.Thickness.Length];  // have to create a new array for each plant to avoid the .NET pointer thing - will have to re-think this with when zones come in

                // move this inside the zone loop - needs to get zeroed for each seperate zone
                NitrogenChangedType NUptakeType = new NitrogenChangedType();
                NUptakeType.Sender     = Name;
                NUptakeType.SenderType = "Plant";
                NUptakeType.DeltaNO3   = new double[Soil.Thickness.Length];
                NUptakeType.DeltaNH4   = new double[Soil.Thickness.Length];

                for (int p = 0; p < maxPlants; p++)
                {
                    for (int l = 0; l < maxLayers; l++)
                    {
                        for (int b = 0; b < bounds; b++)
                        {
                            for (int f = 0; f < forms; f++)
                            {
                                dummyArray1[l] += uptake[p, l, z, b, f];       // add the forms together to give the total nitrogen uptake
                                if (f == 0)
                                {
                                    NUptakeType.DeltaNO3[l] += -1.0 * uptake[p, l, z, b, f];
                                    dummyArray2[l]          += uptake[p, l, z, b, f]; // nitrate only uptake so can do the proportion before sending to the plant
                                }
                                else
                                {
                                    NUptakeType.DeltaNH4[l] += -1.0 * uptake[p, l, z, b, f];
                                }
                            }
                        }
                    }
                    // set uptakes in each plant
                    plants[p].uptakeNitrogen = dummyArray1;
                    for (int l = 0; l < Soil.Thickness.Length; l++)                                 // don't forget to deal with zones at some point
                    {
                        dummyArray2[l] = MathUtilities.Divide(dummyArray2[l], dummyArray1[l], 0.0); // would be nice to have a utility for this
                    }
                    plants[p].uptakeNitrogenPropNO3 = dummyArray2;
                }
                // and finally set the changed soil resources
                if (NitrogenChanged != null)
                {
                    NitrogenChanged.Invoke(NUptakeType);
                }
            }
        }
Пример #9
0
        /// <summary>Send a nitrogen changed event.</summary>
        /// <param name="NO3">The no3 values.</param>
        /// <param name="NH4">The nh4 values.</param>
        private void SendNitrogenChangedEvent(double[] NO3, double[] NH4)
        {
            NitrogenChangedType NitrogenDeltas = new NitrogenChangedType();
            NitrogenDeltas.Sender = "Soil";
            NitrogenDeltas.SenderType = "Soil";

            NitrogenDeltas.DeltaNO3 = MathUtilities.Subtract(soilNitrogen.NO3, NO3);
            NitrogenDeltas.DeltaNH4 = MathUtilities.Subtract(soilNitrogen.NH4, NH4);

            if (NitrogenChanged != null)
                NitrogenChanged.Invoke(NitrogenDeltas);
        }