Пример #1
0
        private void OnPrune(PruneType Prune)
        {
            Summary.WriteMessage(this, "Pruning");

            Live.Clear();
            Dead.Clear();
        }
Пример #2
0
        /// <summary>Sow the crop with the specified parameters.</summary>
        /// <param name="cultivar">The cultivar.</param>
        /// <param name="population">The population.</param>
        /// <param name="depth">The depth.</param>
        /// <param name="rowSpacing">The row spacing.</param>
        /// <param name="maxCover">The maximum cover.</param>
        /// <param name="budNumber">The bud number.</param>
        public void Sow(string cultivar, double population, double depth, double rowSpacing, double maxCover = 1, double budNumber = 1)
        {
            SowingData            = new SowPlant2Type();
            SowingData.Plant      = this;
            SowingData.Population = population;
            SowingData.Depth      = depth;
            SowingData.Cultivar   = cultivar;
            SowingData.MaxCover   = maxCover;
            SowingData.BudNumber  = budNumber;
            SowingData.RowSpacing = rowSpacing;
            this.Population       = population;

            // Find cultivar and apply cultivar overrides.
            cultivarDefinition = PMF.Cultivar.Find(Cultivars, SowingData.Cultivar);
            cultivarDefinition.Apply(this);

            // Invoke an AboutToSow event.
            if (Sowing != null)
            {
                Sowing.Invoke(this, new EventArgs());
            }

            // Invoke a sowing event.
            if (PlantSowing != null)
            {
                PlantSowing.Invoke(this, SowingData);
            }

            Summary.WriteMessage(this, string.Format("A crop of " + CropType + " (cultivar = " + cultivar + ") was sown today at a population of " + Population + " plants/m2 with " + budNumber + " buds per plant at a row spacing of " + rowSpacing + " and a depth of " + depth + " mm"));
        }
Пример #3
0
        //MODEL


        #region Add Water to Pond


        private void AddWater(double Volume, WaterProperties addedProps)
        {
            //This logic is valid because people can not overfill their ponds in the real world
            //because the water comes from a river by opening up the gates and letting gravity fill the pond.
            //Therefore you can not overfill it because the water level just becomes equal to the river.
            //Not sure about filling due to pumping the water though.

            //If it overfills due to rain, then because saltwater is more dense than rain water
            //the rainwater just runs straight off without mixing with the pond water.
            //Therefore no solutes are lost due to this runoff.

            double maxPondVolume = SurfaceArea * MaxPondDepth;

            if (pondVolume + Volume > maxPondVolume)
            {
                Volume = maxPondVolume - pondVolume;
                Summary.WriteMessage(this, "You have overfilled the pond. Reduced the volume added to volume the pond could accept", MessageType.Warning);
            }

            AddWater_TempChange(Volume, addedProps.Temperature);
            AddWater_SalinityChange(Volume, addedProps.Salinity);
            AddWater_PHChange(Volume, addedProps.PH);
            AddWater_NChange(Volume, addedProps.N);
            AddWater_PChange(Volume, addedProps.P);
            AddWater_TSSChange(Volume, addedProps.TSS);
            //Add DOX

            pondVolume = pondVolume + Volume;
        }
Пример #4
0
        private void OnStartOfSimulation(object sender, EventArgs e)
        {
            ChildStages = new List <LifeStage>();
            foreach (LifeStage stage in Apsim.Children(this, typeof(LifeStage)))
            {
                stage.OwningCycle = this;
                ChildStages.Add(stage);
            }

            int i = 0;

            //create new cohorts from the InitialPopulation[]
            foreach (LifeStage stage in ChildStages)
            {
                if ((InitialPopulation != null) && (InitialPopulation.Length > i))
                {
                    Cohort newCohort = stage.NewCohort();
                    newCohort.Count = InitialPopulation[i];
                    mySummary.WriteMessage(this, "LifeStage " + stage.Name + " starting with " + newCohort.Count.ToString());
                }
                else
                {
                    mySummary.WriteWarning(this, "No initial population in " + stage.Name);
                }
                i++;
            }
        }
Пример #5
0
        private void OnStartOfSimulation(object sender, EventArgs e)
        {
            // Check parameter values
            if ((zone.Slope < 0.0) || (zone.Slope > 90))
            {
                throw new Exception("Slope angle is out of the expected range (0-90 deg)");
            }
            if ((zone.AspectAngle < 0.0) || (zone.AspectAngle > 360))
            {
                throw new Exception("Aspect angle is out of the expected range (0-360 deg)");
            }
            if ((zone.Altitude < -100.0) || (SurroundsAlbedo > 5000))
            {
                throw new Exception("Altitude value is out of bounds (0-1)");
            }
            if ((SurroundsAlbedo < 0.0) || (SurroundsAlbedo > 1.0))
            {
                throw new Exception("Albedo value is out of bounds (0-1)");
            }
            if ((TurbidityCoefficient < 0.0) || (TurbidityCoefficient > 1.0))
            {
                throw new Exception("Turbidity coefficient value is out of bounds (0-1)");
            }

            // Convert and fix some parameters
            // zone.AspectAngle is degrees from north. This algorithm seems to work using aspect from south in radians.
            // Should really check this against original sources of the equations. Seems to make sense.
            aspectFromSouthInRadians = zone.AspectAngle + 180;
            if (aspectFromSouthInRadians > 360)
            {
                aspectFromSouthInRadians -= 360;
            }

            zone.Slope = Math.PI * zone.Slope / 180;
            aspectFromSouthInRadians = Math.PI * aspectFromSouthInRadians / 180;
            latitudeAngle            = Math.PI * weather.Latitude / 180;

            // Get the local mean atmospheric pressure, similar to Allen et al (1998)
            double expPressure = standardGravitationalAcceleration * standardAtmosphericMolarMass / (universalGasConstant * standardTemperatureLapseRate);

            AtmosphericPressure  = Math.Pow(1 - (standardTemperatureLapseRate * zone.Altitude / standardAtmosphericTemperature), expPressure);
            AtmosphericPressure *= standardAtmosphericPressure;

            // Get the slope factor for correcting reflected radiation, based on Allen et al. (2006)
            slopeFactor = 0.75 + (0.25 * Math.Cos(zone.Slope)) - (0.5 * zone.Slope / Math.PI);

            // Covert the user defined changes from percent into fraction
            dRain        = Math.Max(-1.0, 0.01 * dRain);
            dWind        = Math.Max(-1.0, 0.01 * dWind);
            dVapPressure = Math.Max(-1.0, 0.01 * dVapPressure);
            // NOTE: dVapPressure has a variable upper bound, it cannot be higher than the saturated VP
            //       this upper limit will be assumed equal to 95% of saturation at daily Tmax

            summary.WriteMessage(this, "     Weather variables will be adjusted for slope and aspect", MessageType.Diagnostic);
            summary.WriteMessage(this, "      - Radiation and temperature adjusted based on the model described by Cichota (2015)", MessageType.Diagnostic);
            summary.WriteMessage(this, "      - Rainfall, wind, and vapour pressure are simple relative changes - not explicitly linked to slope", MessageType.Diagnostic);
            summary.WriteMessage(this, "      - The values of RH, if existent, will be adjusted whenever the temperature or vp change", MessageType.Diagnostic);
        }
Пример #6
0
        /// <summary>
        /// Generate a weather file.
        /// </summary>
        /// <param name="cancelToken">Optional token which allows for cancellation of the child process.</param>
        public IWeather GenerateWeatherFile(CancellationToken cancelToken = default(CancellationToken))
        {
            if (!Directory.Exists(bestiapopPath))
            {
                Status = "Installing Bestiapop";
                InstallBestiapop(bestiapopPath);
            }

            string output = OutputPath;

            if (string.IsNullOrEmpty(output))
            {
                output = Path.Combine(Path.GetTempPath(), $"bestiapop-{Guid.NewGuid()}");
                if (summary != null)
                {
                    summary.WriteMessage(this, $"OutputPath was not specified. Files will be generated to temp directory: '{output}'");
                }
            }

            if (!Directory.Exists(output))
            {
                Directory.CreateDirectory(output);
            }

            string        bestiapop = Path.Combine(bestiapopPath, "bestiapop", "bestiapop.py");
            StringBuilder args      = new StringBuilder($"{bestiapop} -a generate-climate-file -s silo -y {StartDate.Year}-{EndDate.Year} -lat {Latitude} -lon {Longitude} ");

            // todo: check that these are correct variables
            args.Append("-c \"daily_rain max_temp min_temp vp vp_deficit evap_pan radiation et_short_crop\" ");
            if (MultiProcess)
            {
                args.Append($"-m ");
            }
            args.Append($"-o {output}");

            if (summary != null)
            {
                summary.WriteMessage(this, $"Running bestiapop with command: 'python {args}' from directory {output}");
            }

            Status = "Running bestiapop";
            try
            {
                string stdout = RunCommand("python", args.ToString(), output);
                summary.WriteMessage(this, $"Ran command 'python {args}' from directory '{output}'. Output from bestiapop:{Environment.NewLine}{stdout}");
            }
            catch (Exception err)
            {
                throw new Exception("Encountered an error while running bestiapop", err);
            }

            Weather result = CreateWeatherComponent(Directory.GetFiles(output, "*.met").FirstOrDefault());

            Status = null;

            return(result);
        }
Пример #7
0
        /// <summary>Apply some irrigation.</summary>
        /// <param name="amount">The amount to apply (mm).</param>
        /// <param name="depth">The depth of application (mm).</param>
        /// <param name="duration">The duration of the irrigation event (minutes).</param>
        /// <param name="efficiency">The irrigation efficiency (mm/mm).</param>
        /// <param name="willRunoff">Whether irrigation can run off (<c>true</c>/<c>false</c>).</param>
        /// <param name="no3">Amount of NO3 in irrigation water</param>
        /// <param name="nh4">Amount of NH4 in irrigation water</param>
        public void Apply(double amount, double depth = 0.0, double duration = 1440.0, double efficiency = 1.0, bool willRunoff = false,
                          double no3 = -1.0, double nh4 = -1.0)
        {
            if (Irrigated != null && amount > 0.0)
            {
                if (depth > soil.Thickness.Sum())
                {
                    throw new ApsimXException(this, "Check the depth for irrigation, it cannot be deeper than the soil depth");
                }
                Depth = depth;

                if (duration > 1440.0)
                {
                    throw new ApsimXException(this, "Check the duration for the irrigation, it must be less than 1440 minutes");
                }
                Duration = duration;

                if (efficiency > 1.0)
                {
                    throw new ApsimXException(this, "Check the value of irrigation efficiency, it must be between 0 and 1");
                }
                Efficiency = efficiency;

                if (Depth > 0.0)
                { // Sub-surface irrigation: it cannot be intercepted nor run off directly
                    willRunoff = false;
                }

                IrrigationApplied = amount;
                WillRunoff        = willRunoff;

                // Prepare the irrigation data
                IrrigationApplicationType irrigData = new IrrigationApplicationType();
                irrigData.Amount     = IrrigationApplied;
                irrigData.Depth      = Depth;
                irrigData.Duration   = Duration;
                irrigData.WillRunoff = WillRunoff;
                if (no3 != -1)
                {
                    irrigData.NO3 = no3;
                }
                if (nh4 != -1)
                {
                    irrigData.NH4 = nh4;
                }

                // Raise event and write log
                Irrigated.Invoke(this, irrigData);
                summary.WriteMessage(this, string.Format("{0:F1} mm of water added via irrigation at depth {1} mm", IrrigationApplied, Depth));
            }
            else
            {
                // write log of aborted event
                summary.WriteMessage(this, "Irrigation did not occur because the amount given was negative");
            }
        }
Пример #8
0
        /// <summary>Apply some irrigation.</summary>
        /// <param name="amount">The amount to apply (mm).</param>
        /// <param name="depth">The depth of application (mm).</param>
        /// <param name="duration">The duration of the irrigation event (minutes).</param>
        /// <param name="efficiency">The irrigation efficiency (mm/mm).</param>
        /// <param name="willRunoff">Whether irrigation can run off (<c>true</c>/<c>false</c>).</param>
        /// <param name="no3">Amount of NO3 in irrigation water</param>
        /// <param name="nh4">Amount of NH4 in irrigation water</param>
        /// <param name="doOutput">If true, output will be written to the summary.</param>
        public void Apply(double amount, double depth = 0.0, double duration = 1440.0, double efficiency = 1.0, bool willRunoff = false,
                          double no3 = 0.0, double nh4 = 0.0, bool doOutput = true)
        {
            if (Irrigated != null && amount > 0.0)
            {
                if (depth > soilPhysical.Thickness.Sum())
                {
                    throw new ApsimXException(this, "Check the depth for irrigation, it cannot be deeper than the soil depth");
                }
                Depth = depth;

                if (duration > 1440.0)
                {
                    throw new ApsimXException(this, "Check the duration for the irrigation, it must be less than 1440 minutes");
                }
                Duration = duration;

                if (efficiency > 1.0)
                {
                    throw new ApsimXException(this, "Check the value of irrigation efficiency, it must be between 0 and 1");
                }
                Efficiency = efficiency;

                // Sub-surface irrigation cannot run off
                if (Depth > 0.0)
                {
                    willRunoff = false;
                }

                WillRunoff = willRunoff;

                // Prepare the irrigation data
                IrrigationApplicationType irrigData = new IrrigationApplicationType();
                irrigData.Amount     = amount * efficiency;
                irrigData.Depth      = Depth;
                irrigData.Duration   = Duration;
                irrigData.WillRunoff = WillRunoff;
                irrigData.NO3        = no3;
                irrigData.NH4        = nh4;

                // Raise event and write log
                Irrigated.Invoke(this, irrigData);
                if (doOutput)
                {
                    summary.WriteMessage(this, string.Format("{0:F1} mm of water added via irrigation at depth {1} mm", irrigData.Amount, Depth), MessageType.Diagnostic);
                }

                IrrigationApplied += irrigData.Amount;
            }
            else if (doOutput && amount < 0)
            {
                summary.WriteMessage(this, "Irrigation did not occur because the amount given was negative", MessageType.Warning);
            }
        }
Пример #9
0
 private void OnPhaseChanged(object sender, PhaseChangedType phaseChange)
 {
     if (sender == this && Phenology != null && Canopy != null && AboveGround != null)
     {
         string message = Phenology.CurrentPhase.Start + "\r\n";
         if (Canopy != null)
         {
             message += "  LAI = " + Canopy.LAI.ToString("f2") + " (m^2/m^2)" + "\r\n";
             message += "  Above Ground Biomass = " + AboveGround.Wt.ToString("f2") + " (g/m^2)" + "\r\n";
         }
         Summary.WriteMessage(this, message);
     }
 }
Пример #10
0
 private void OnPhaseChanged(PhaseChangedType PhaseChange)
 {
     if (Phenology != null && Leaf != null && AboveGround != null)
     {
         string message = Phenology.CurrentPhase.Start + "\r\n";
         if (Leaf != null)
         {
             message += "  LAI = " + Leaf.LAI.ToString("f2") + " (m^2/m^2)" + "\r\n";
             message += "  Above Ground Biomass = " + AboveGround.Wt.ToString("f2") + " (g/m^2)" + "\r\n";
         }
         Summary.WriteMessage(this, message);
     }
 }
Пример #11
0
        private void OnSimulationCommencing(object sender, EventArgs e)
        {
            if (Verbose)
            {
                summary.WriteMessage(this, "Initialising the Manager for grazing, urine return and reporting");
            }

            if (GrazingRotationType == GrazingRotationTypeEnum.TargetMass ||
                GrazingRotationType == GrazingRotationTypeEnum.TargetMassAndLength)
            {
                if (PreGrazeDMArray == null || PreGrazeDMArray.Length != 12)
                {
                    throw new Exception("There must be 12 values input for the pre-grazing DM");
                }
                if (PostGrazeDMArray == null || PostGrazeDMArray.Length != 12)
                {
                    throw new Exception("There must be 12 values input for the post-grazing DM");
                }
            }
            if (GrazingRotationType == GrazingRotationTypeEnum.TargetMassAndLength)
            {
                if (RotationLengthArray == null || RotationLengthArray.Length != 12)
                {
                    throw new Exception("There must be 12 values input for rotation length");
                }
            }

            if (FractionOfBiomassToDung.Length != 1 && FractionOfBiomassToDung.Length != 12)
            {
                throw new Exception("You must specify either a single value for 'proportion of biomass going to dung' or 12 monthly values.");
            }

            if (FractionOfBiomassToUrine.Length != 1 && FractionOfBiomassToUrine.Length != 12)
            {
                throw new Exception("You must specify either a single value for 'proportion of biomass going to urine' or 12 monthly values.");
            }

            if (Verbose)
            {
                summary.WriteMessage(this, "Finished initialising the Manager for grazing, urine return and reporting");
            }

            if (NoGrazingStartString != null)
            {
                NoGrazingStart = DateUtilities.GetDate(NoGrazingStartString);
            }
            if (NoGrazingEndString != null)
            {
                NoGrazingEnd = DateUtilities.GetDate(NoGrazingEndString);
            }
        }
Пример #12
0
        /// <summary>
        /// Execute harvest logic for reproductive organ
        /// </summary>
        public override void DoHarvest()
        {
            double YieldDW = (Live.Wt + Dead.Wt);

            Summary.WriteMessage(this, "Harvesting " + Name + " from " + Plant.Name);
            Summary.WriteMessage(this, " Yield DWt: " + YieldDW.ToString("f2") + " (g/m^2)");
            Summary.WriteMessage(this, " Size: " + Size.ToString("f2") + " (g)");
            Summary.WriteMessage(this, " Number: " + Number.ToString("f2") + " (/m^2)");

            Live.Clear();
            Dead.Clear();
            Number           = 0;
            _ReadyForHarvest = false;
        }
Пример #13
0
        /// <summary>Perform grazing</summary>
        /// <param name="amountDMToRemove">The amount of biomas to remove (kg/ha).</param>
        public void Graze(double amountDMToRemove)
        {
            GrazingInterval = DaysSinceGraze;  // i.e. yesterday's value
            DaysSinceGraze  = 0;

            RemoveDMFromPlants(amountDMToRemove);

            AddUrineToSoil();

            AddDungToSurface();

            // Calculate post-grazed dry matter.
            PostGrazeDM = 0.0;
            foreach (var forage in allForages)
            {
                PostGrazeDM += forage.Material.Sum(m => m.Total.Wt);
            }

            // Calculate proportions of each species to the total biomass.
            for (int i = 0; i < allForages.Count; i++)
            {
                var proportionToTotalDM = MathUtilities.Divide(allForages[i].Material.Sum(m => m.Total.Wt), PostGrazeDM, 0);
                ProportionOfTotalDM[i] = proportionToTotalDM;
            }

            summary.WriteMessage(this, string.Format("Grazed {0:0.0} kgDM/ha, N content {1:0.0} kgN/ha, ME {2:0.0} MJME/ha", GrazedDM, GrazedN, GrazedME));

            // Reduce plant population if necessary.
            if (FractionPopulationDecline > 0)
            {
                foreach (var forage in allForages)
                {
                    if ((forage as IModel) is IHasPopulationReducer populationReducer)
                    {
                        populationReducer.ReducePopulation(populationReducer.Population * (1.0 - FractionPopulationDecline));
                    }
                    else
                    {
                        throw new Exception($"Model {forage.Name} is unable to reduce its population due to grazing. Not implemented.");
                    }
                }
            }

            // Convert PostGrazeDM to kg/ha
            PostGrazeDM *= 10;

            // Invoke grazed event.
            Grazed?.Invoke(this, new EventArgs());
        }
Пример #14
0
        /// <summary>Removes biomass from organs when harvest, graze or cut events are called.</summary>
        /// <param name="value">Biomass to remove</param>
        virtual public void DoRemoveBiomass(OrganBiomassRemovalType value)
        {
            double RemainFrac = 1 - (value.FractionToResidue + value.FractionRemoved);

            if (RemainFrac < 0)
            {
                throw new Exception("The sum of FractionToResidue and FractionRemoved sent with your " + "!!!!PLACE HOLDER FOR EVENT SENDER!!!!" + " is greater than 1.  Had this execption not triggered you would be removing more biomass from " + Name + " than there is to remove");
            }
            if (RemainFrac < 1)
            {
                double TotalFracRemoved = value.FractionRemoved + value.FractionToResidue;
                double PcToResidue      = value.FractionToResidue / TotalFracRemoved * 100;
                double PcRemoved        = value.FractionRemoved / TotalFracRemoved * 100;
                Summary.WriteMessage(this, "Removing " + TotalFracRemoved * 100 + "% of " + Name + " Biomass from " + Plant.Name + ".  Of this " + PcRemoved + "% is removed from the system and " + PcToResidue + "% is returned to the surface organic matter");

                SurfaceOrganicMatter.Add(Wt * 10 * value.FractionToResidue, N * 10 * value.FractionToResidue, 0, Plant.CropType, Name);
                if (Live.StructuralWt > 0)
                {
                    Live.StructuralWt *= RemainFrac;
                }
                if (Live.NonStructuralWt > 0)
                {
                    Live.NonStructuralWt *= RemainFrac;
                }
                if (Live.StructuralN > 0)
                {
                    Live.StructuralN *= RemainFrac;
                }
                if (Live.NonStructuralN > 0)
                {
                    Live.NonStructuralN *= RemainFrac;
                }
            }
        }
Пример #15
0
 /// <summary>
 /// Check the sensibility of the zone. Write any warnings to the summary log.
 /// </summary>
 private void CheckSensibility()
 {
     if (FindInScope <MicroClimate>() == null)
     {
         summary.WriteMessage(this, "MicroClimate not found", MessageType.Warning);
     }
 }
Пример #16
0
 private void OnPlantSowing(object sender, SowPlant2Type data)
 {
     if (DaysFromSowingToEndPhase > 0)
     {
         summary.WriteMessage(this, "FIXED number of days from sowing to " + Name + " = " + DaysFromSowingToEndPhase);
     }
 }
Пример #17
0
        private void OnPlantSowing(object sender, SowPlant2Type data)
        {
            double SowDepth   = 0;
            double accumDepth = 0;

            if (Plant != null)
            {
                SowDepth = Plant.SowingData.Depth;
            }
            if (Plant15 != null)
            {
                SowDepth = Plant15.SowingData.Depth;
            }
            bool layerfound = false;

            for (int layer = 0; layerfound; layer++)
            {
                accumDepth += Soil.Thickness[layer];
                if (SowDepth <= accumDepth)
                {
                    SowLayer   = layer;
                    layerfound = true;
                }
            }
            if (DaysFromSowingToEndPhase > 0)
            {
                summary.WriteMessage(this, "FIXED number of days from sowing to " + Name + " = " + DaysFromSowingToEndPhase);
            }
        }
Пример #18
0
        /// <summary>Method to bring a new cohort of individuls to the specified LifeCyclePhase</summary>
        /// <param name="Immigrants"></param>
        public void Infest(Cohort Immigrants)
        {
            LifeCyclePhase InfestingPhase = Immigrants.BelongsToPhase;

            InfestingPhase.NewCohort(Immigrants.Population, Immigrants.ChronologicalAge, Immigrants.PhysiologicalAge);
            mySummary.WriteMessage(this, "An infestation of  " + Immigrants.Population + " " + Apsim.FullPath(this) + " " + Immigrants.BelongsToPhase.Name + "'s occured today, just now :-)");
        }
Пример #19
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)
            {
                // 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)
                {
                    solutes.AddToLayer(layer, "NO3", SoluteManager.SoluteSetterType.Fertiliser, Amount * fertiliserType.FractionNO3);
                    NitrogenApplied += Amount * fertiliserType.FractionNO3;
                }
                if (fertiliserType.FractionNH4 != 0)
                {
                    solutes.AddToLayer(layer, "NH4", SoluteManager.SoluteSetterType.Fertiliser, Amount * fertiliserType.FractionNH4);
                    NitrogenApplied += Amount * fertiliserType.FractionNH4;
                }
                if (fertiliserType.FractionUrea != 0)
                {
                    solutes.AddToLayer(layer, "Urea", SoluteManager.SoluteSetterType.Fertiliser, Amount * fertiliserType.FractionUrea);
                    NitrogenApplied += Amount * fertiliserType.FractionUrea;
                }
                Summary.WriteMessage(this, string.Format("{0} kg/ha of {1} added at depth {2} layer {3}", Amount, Type, Depth, layer + 1));
            }
        }
Пример #20
0
        /// <summary>Method to bring a new cohort of individuls to the specified LifeCyclePhase</summary>
        /// <param name="InfestationInfo"></param>
        public void Infest(SourceInfo InfestationInfo)
        {
            LifeCyclePhase InfestingPhase = FindChild <LifeCyclePhase>(InfestationInfo.LifeCyclePhase);

            InfestingPhase.NewCohort(InfestationInfo);
            mySummary.WriteMessage(this, "An infestation of  " + InfestationInfo.Population + " " + FullPath + " " + InfestationInfo.LifeCyclePhase + "'s occured today, just now :-)");
        }
Пример #21
0
        /// <summary>Called to start the job.</summary>
        /// <param name="jobManager">The job manager running this job.</param>
        /// <param name="workerThread">The thread this job is running on.</param>
        public void Run(JobManager jobManager, BackgroundWorker workerThread)
        {
            try
            {
                StartRun();
                DoRun(jobManager, workerThread);
                CleanupRun();
            }
            catch (ApsimXException err)
            {
                ErrorMessage = "ERROR in file: " + FileName + "\r\n" +
                               "Simulation name: " + Name + "\r\n" +
                               err.ToString();

                ISummary summary = Apsim.Find(this, typeof(Summary)) as ISummary;
                summary.WriteMessage(this, ErrorMessage);
                CleanupRun();

                throw new Exception(ErrorMessage);
            }
            catch (Exception err)
            {
                ErrorMessage = "ERROR in file: " + FileName + "\r\n" +
                               "Simulation name: " + Name + "\r\n" +
                               err.ToString();

                ISummary summary = Apsim.Find(this, typeof(Summary)) as ISummary;
                summary.WriteMessage(this, ErrorMessage);
                CleanupRun();

                throw new Exception(ErrorMessage);
            }
        }
Пример #22
0
        private void OnSimulationCommencing(object sender, EventArgs e)
        {
            ProportionOfTotalDM = new double[forages.Count];

            if (Verbose)
            {
                summary.WriteMessage(this, "Initialising the Manager for grazing, urine return and reporting");
            }

            if (GrazingRotationType == GrazingRotationTypeEnum.TargetMass)
            {
                if (PreGrazeDMArray == null || PreGrazeDMArray.Length != 12)
                {
                    throw new Exception("There must be 12 values input for the pre-grazing DM");
                }
                if (PostGrazeDMArray == null || PostGrazeDMArray.Length != 12)
                {
                    throw new Exception("There must be 12 values input for the post-grazing DM");
                }
            }
            else if (GrazingRotationType == GrazingRotationTypeEnum.Flexible)
            {
                if (string.IsNullOrEmpty(FlexibleExpressionForTimingOfGrazing))
                {
                    throw new Exception("You must specify an expression for timing of grazing.");
                }
                expressionFunction            = new CSharpExpressionFunction();
                expressionFunction.Parent     = this;
                expressionFunction.Expression = "Convert.ToDouble(" + FlexibleExpressionForTimingOfGrazing + ")";
                expressionFunction.CompileExpression();
            }

            if (FractionOfBiomassToDung.Length != 1 && FractionOfBiomassToDung.Length != 12)
            {
                throw new Exception("You must specify either a single value for 'proportion of biomass going to dung' or 12 monthly values.");
            }

            if (FractionOfBiomassToUrine.Length != 1 && FractionOfBiomassToUrine.Length != 12)
            {
                throw new Exception("You must specify either a single value for 'proportion of biomass going to urine' or 12 monthly values.");
            }

            if (Verbose)
            {
                summary.WriteMessage(this, "Finished initialising the Manager for grazing, urine return and reporting");
            }
        }
Пример #23
0
        private void OnHarvesting(object sender, EventArgs e)
        {
            if (sender == Plant)
            {
                double YieldDW = (Live.Wt + Dead.Wt);

                Summary.WriteMessage(this, "Harvesting " + Name + " from " + Plant.Name);
                Summary.WriteMessage(this, " Yield DWt: " + YieldDW.ToString("f2") + " (g/m^2)");
                Summary.WriteMessage(this, " Size: " + Size.ToString("f2") + " (g)");
                Summary.WriteMessage(this, " Number: " + Number.ToString("f2") + " (/m^2)");

                Live.Clear();
                Dead.Clear();
                Number           = 0;
                _ReadyForHarvest = false;
            }
        }
Пример #24
0
 /// <summary>
 /// Add new warning to the List if it hasn't been reported
 /// </summary>
 /// <param name="checkMessage">The warning message to check if it exists</param>
 /// <param name="summary">The summary model to write to</param>
 /// <param name="sender">The activity sending the warning</param>
 /// <param name="messageType">The type of message to write</param>
 /// <param name="fullMessage">A full message to report if check message does not exist, otherwise use check message</param>
 public void CheckAndWrite(string checkMessage, ISummary summary, IModel sender, MessageType messageType, string fullMessage = "")
 {
     if (!Exists(checkMessage) & summary != null)
     {
         summary.WriteMessage(sender, (fullMessage.Any())?fullMessage:checkMessage, messageType);
         Add(checkMessage);
     }
 }
Пример #25
0
 private void OnPhaseChanged(object sender, PhaseChangedType phaseChange)
 {
     if (sender == this && Leaf != null && AboveGround != null)
     {
         string message = Phenology.CurrentPhase.Start + "\r\n";
         if (Leaf != null)
         {
             message += "  LAI = " + Leaf.LAI.ToString("f2") + " (m^2/m^2)" + "\r\n";
             message += "  Above Ground Biomass = " + AboveGround.Wt.ToString("f2") + " (g/m^2)" + "\r\n";
         }
         summary.WriteMessage(this, message);
         if (Phenology.CurrentPhase.Start == "Flowering" && Flowering != null)
         {
             Flowering.Invoke(this, null);
         }
     }
 }
Пример #26
0
        private void OnCutting(object sender, EventArgs e)
        {
            Summary.WriteMessage(this, "Cutting " + Name + " from " + Plant.Name);

            Live.Clear();
            Dead.Clear();
            Number           = 0;
            _ReadyForHarvest = false;
        }
Пример #27
0
 private void OnCutting(object sender, EventArgs e)
 {
     if (sender == Plant)
     {
         Summary.WriteMessage(this, "Cutting " + Name + " from " + Plant.Name);
         Live.Clear();
         Dead.Clear();
     }
 }
Пример #28
0
        /// <summary>Incorporates the specified fraction.</summary>
        /// <param name="fraction">The fraction.</param>
        /// <param name="depth">The depth.</param>
        public void Incorporate(double fraction, double depth)
        {
            Incorp(fraction, depth);

            summary.WriteMessage(this, string.Format(@"Residue removed " + Environment.NewLine +
                                                     "Fraction Incorporated = {0:0.0##}" + Environment.NewLine +
                                                     "Incorporated Depth    = {1:0.0##}",
                                                     fraction, depth));
        }
Пример #29
0
        /// <summary>
        /// Accumulate rainfall for tillage cn reduction.
        /// The reduction in the runoff as a result of doing a tillage (tillage_cn_red) ceases after a set amount of rainfall (tillage_cn_rain).
        /// This function works out the accumulated rainfall since last tillage event, and turns off the reduction if it is over the amount of rain specified.
        /// </summary>
        private void ShouldIStopTillageCNReduction()
        {
            if (TillageCnCumWater > 0.0 && CumWaterSinceTillage > TillageCnCumWater)
            {
                // This tillage has lost all effect on cn. CN reduction
                // due to tillage is off until the next tillage operation.
                TillageCnCumWater = 0.0;
                TillageCnRed      = 0.0;

                summary.WriteMessage(this, "Tillage CN reduction finished");
            }
        }
Пример #30
0
 /// <summary>
 /// Set amount of animal food available
 /// </summary>
 /// <param name="NewValue">New value to set food store to</param>
 public void Set(double NewValue)
 {
     if ((NewValue < 0) || (NewValue > this.LandArea))
     {
         Summary.WriteMessage(this, "Tried to Set Available Land to Invalid New Amount." + Environment.NewLine
                              + "New Value must be between 0 and the Land Area.");
     }
     else
     {
         this.areaAvailable = NewValue;
     }
 }