예제 #1
0
 /// <summary>Create all necessary YP files (.apsim and .met) from a YieldProphet spec.</summary>
 /// <param name="simulation">The simulation to write.</param>
 /// <param name="workingFolder">The folder where files shoud be created.</param>
 /// <param name="fileNameToWrite">The name of a file to write.</param>
 /// <returns>The name of the created .apsim file.</returns>
 public static string Create(APSIMSpecification simulation, string workingFolder, string fileNameToWrite)
 {
     return(Create(new List <APSIMSpecification>()
     {
         simulation
     }, workingFolder, fileNameToWrite));
 }
예제 #2
0
        /// <summary>
        /// Correct the CONA / U parameters depending on LAT/LONG
        /// </summary>
        /// <param name="simulation"></param>
        /// <param name="soil"></param>
        /// <param name="workingFolder">The folder where files shoud be created.</param>
        private static void CorrectCONAU(APSIMSpecification simulation, Soil soil, string workingFolder)
        {
            // Get lat/long from weather file.
            ApsimTextFile weather = new ApsimTextFile();

            try
            {
                weather.Open(Path.Combine(workingFolder, simulation.WeatherFileName));
                double latitude  = Convert.ToDouble(weather.Constant("Latitude").Value);
                double longitude = Convert.ToDouble(weather.Constant("Longitude").Value);

                // Dubbo latitude = -32.24
                // NSW western border longitude = 141.0
                if (longitude >= 141.0 && latitude > -32.24)
                {
                    // Northern values.
                    soil.SoilWater.SummerU    = 6.0;
                    soil.SoilWater.SummerCona = 3.5;
                    soil.SoilWater.WinterU    = 4.0;
                    soil.SoilWater.WinterCona = 2.5;
                }
                else
                {
                    // Southern values.
                    soil.SoilWater.SummerU    = 6.0;
                    soil.SoilWater.SummerCona = 3.5;
                    soil.SoilWater.WinterU    = 2.0;
                    soil.SoilWater.WinterCona = 2.0;
                }
            }
            finally
            {
                weather.Close();
            }
        }
예제 #3
0
 /// <summary>Create a .apsim file node for the job and append it to the parentNode</summary>
 /// <param name="simulation">The specification to use</param>
 /// <param name="workingFolder">The folder where files shoud be created.</param>
 /// <param name="parentNode">Parent XmlNode to append the simulation to.</param>
 /// <param name="usingAPSIMx">Write APSIMx files?</param>
 private static void CreateApsimFile(APSIMSpecification simulation, string workingFolder, XmlNode parentNode, bool usingAPSIMx)
 {
     if (simulation.ErrorMessage == null)
     {
         XmlNode simulationXML = CreateSimulationXML(simulation, workingFolder, usingAPSIMx);
         if (simulationXML != null)
         {
             parentNode.AppendChild(parentNode.OwnerDocument.ImportNode(simulationXML, true));
         }
     }
 }
예제 #4
0
        /// <summary>Add in reset management events to the APSIM spec for the specified paddock.</summary>
        /// <param name="paddock">The paddock.</param>
        /// <param name="simulation">The simulation to add the management operations to.</param>
        /// <exception cref="System.Exception">Cannot find soil water reset date</exception>
        /// <exception cref="Exception">Cannot find soil water reset date</exception>
        private static void AddResetDatesToManagement(Paddock paddock, APSIMSpecification simulation)
        {
            // Reset
            if (paddock.SoilWaterSampleDate != DateTime.MinValue)
            {
                if (paddock.SoilNitrogenSampleDate == DateTime.MinValue)
                {
                    paddock.SoilNitrogenSampleDate = paddock.SoilWaterSampleDate;
                }

                Sow sowing = YieldProphetUtility.GetCropBeingSown(paddock.Management);
                if (sowing != null && sowing.Date != DateTime.MinValue)
                {
                    List <Management> resetActions = new List <Management>();

                    // reset at sowing if the sample dates are after sowing.
                    if (paddock.SoilWaterSampleDate > sowing.Date)
                    {
                        resetActions.Add(new ResetWater()
                        {
                            Date = sowing.Date
                        });
                        resetActions.Add(new ResetSurfaceOrganicMatter()
                        {
                            Date = sowing.Date
                        });
                    }
                    if (paddock.SoilNitrogenSampleDate > sowing.Date)
                    {
                        resetActions.Add(new ResetNitrogen()
                        {
                            Date = sowing.Date
                        });
                    }

                    // reset on the sample dates.
                    resetActions.Add(new ResetWater()
                    {
                        Date = paddock.SoilWaterSampleDate
                    });
                    resetActions.Add(new ResetSurfaceOrganicMatter()
                    {
                        Date = paddock.SoilWaterSampleDate
                    });
                    resetActions.Add(new ResetNitrogen()
                    {
                        Date = paddock.SoilNitrogenSampleDate
                    });

                    simulation.Management.InsertRange(0, resetActions);
                }
            }
        }
예제 #5
0
        /// <summary>Converts a Yield Prophet specification to an APSIM one.</summary>
        /// <param name="yieldProphet">The yield prophet spec.</param>
        /// <returns>The list of APSIM simulations that will need to be run.</returns>
        public static List <APSIMSpecification> ToAPSIM(YieldProphet yieldProphet)
        {
            List <APSIMSpecification> apsimSpecs = new List <APSIMSpecification>();

            foreach (Paddock paddock in yieldProphet.Paddock)
            {
                APSIMSpecification simulation;
                try
                {
                    simulation = CreateBaseSimulation(paddock);
                }
                catch (Exception err)
                {
                    simulation = new APSIMSpecification();
                    simulation.ErrorMessage = err.Message;
                }

                simulation.Name = paddock.Name;
                apsimSpecs.Add(simulation);
            }
            return(apsimSpecs);
        }
예제 #6
0
        /// <summary>Do all soil related settings.</summary>
        /// <param name="simulation">The specification to use</param>
        /// <param name="workingFolder">The folder where files shoud be created.</param>
        private static void DoSoil(APSIMSpecification simulation, string workingFolder)
        {
            Soil soil;

            if (simulation.Soil == null)
            {
                if (simulation.SoilPath.StartsWith("<Soil"))
                {
                    // Soil and Landscape grid
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(simulation.SoilPath);
                    soil = XmlUtilities.Deserialise(doc.DocumentElement, typeof(Soil)) as Soil;
                }
                else if (simulation.SoilPath.StartsWith("http"))
                {
                    // Soil and Landscape grid
                    string xml;
                    using (var client = new WebClient())
                    {
                        xml = client.DownloadString(simulation.SoilPath);
                    }
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(xml);
                    List <XmlNode> soils = XmlUtilities.ChildNodes(doc.DocumentElement, "Soil");
                    if (soils.Count == 0)
                    {
                        throw new Exception("Cannot find soil in Soil and Landscape Grid");
                    }
                    soil = XmlUtilities.Deserialise(soils[0], typeof(Soil)) as Soil;
                }
                else
                {
                    // Apsoil web service.
                    APSOIL.Service apsoilService = new APSOIL.Service();
                    string         soilXml       = apsoilService.SoilXML(simulation.SoilPath.Replace("\r\n", ""));
                    if (soilXml == string.Empty)
                    {
                        throw new Exception("Cannot find soil: " + simulation.SoilPath);
                    }
                    soil = SoilUtilities.FromXML(soilXml);
                }
            }
            else
            {
                // Just use the soil we already have
                soil = simulation.Soil;
            }

            // Make sure we have a soil crop parameterisation. If not then try creating one
            // based on wheat.
            Sow sowing = YieldProphetUtility.GetCropBeingSown(simulation.Management);

            string[] cropNames = soil.Water.Crops.Select(c => c.Name).ToArray();
            if (cropNames.Length == 0)
            {
                throw new Exception("Cannot find any crop parameterisations in soil: " + simulation.SoilPath);
            }

            if (sowing != null && !StringUtilities.Contains(cropNames, sowing.Crop))
            {
                SoilCrop wheat = soil.Water.Crops.Find(c => c.Name.Equals("wheat", StringComparison.InvariantCultureIgnoreCase));
                if (wheat == null)
                {
                    // Use the first crop instead.
                    wheat = soil.Water.Crops[0];
                }

                SoilCrop newSoilCrop = new SoilCrop();
                newSoilCrop.Name      = sowing.Crop;
                newSoilCrop.Thickness = wheat.Thickness;
                newSoilCrop.LL        = wheat.LL;
                newSoilCrop.KL        = wheat.KL;
                newSoilCrop.XF        = wheat.XF;
                soil.Water.Crops.Add(newSoilCrop);
            }

            // Remove any initwater nodes.
            soil.InitialWater = null;

            // Transfer the simulation samples to the soil
            if (simulation.Samples != null)
            {
                soil.Samples = simulation.Samples;
            }

            if (simulation.InitTotalWater != 0)
            {
                soil.InitialWater = new InitialWater();
                soil.InitialWater.PercentMethod = InitialWater.PercentMethodEnum.FilledFromTop;

                double pawc;
                if (sowing == null || sowing.Crop == null)
                {
                    pawc = MathUtilities.Sum(PAWC.OfSoilmm(soil));
                    soil.InitialWater.RelativeTo = "LL15";
                }
                else
                {
                    SoilCrop crop = soil.Water.Crops.Find(c => c.Name.Equals(sowing.Crop, StringComparison.InvariantCultureIgnoreCase));
                    pawc = MathUtilities.Sum(PAWC.OfCropmm(soil, crop));
                    soil.InitialWater.RelativeTo = crop.Name;
                }

                soil.InitialWater.FractionFull = Convert.ToDouble(simulation.InitTotalWater) / pawc;
            }

            if (simulation.InitTotalNitrogen != 0)
            {
                // Add in a sample.
                Sample nitrogenSample = new Sample();
                nitrogenSample.Name = "NitrogenSample";
                soil.Samples.Add(nitrogenSample);
                nitrogenSample.Thickness = new double[] { 150, 150, 3000 };
                nitrogenSample.NO3Units  = Nitrogen.NUnitsEnum.kgha;
                nitrogenSample.NH4Units  = Nitrogen.NUnitsEnum.kgha;
                nitrogenSample.NO3       = new double[] { 6.0, 2.1, 0.1 };
                nitrogenSample.NH4       = new double[] { 0.5, 0.1, 0.1 };
                nitrogenSample.OC        = new double[] { double.NaN, double.NaN, double.NaN };
                nitrogenSample.EC        = new double[] { double.NaN, double.NaN, double.NaN };
                nitrogenSample.PH        = new double[] { double.NaN, double.NaN, double.NaN };

                double Scale = Convert.ToDouble(simulation.InitTotalNitrogen) / MathUtilities.Sum(nitrogenSample.NO3);
                nitrogenSample.NO3 = MathUtilities.Multiply_Value(nitrogenSample.NO3, Scale);
            }

            // Add in soil temperature. Needed for Aflatoxin risk.
            soil.SoilTemperature = new SoilTemperature();
            soil.SoilTemperature.BoundaryLayerConductance = 15;
            soil.SoilTemperature.Thickness = new double[] { 2000 };
            soil.SoilTemperature.InitialSoilTemperature = new double[] { 22 };
            if (soil.Analysis.ParticleSizeClay == null)
            {
                soil.Analysis.ParticleSizeClay = MathUtilities.CreateArrayOfValues(60, soil.Analysis.Thickness.Length);
            }
            InFillMissingValues(soil.Analysis.ParticleSizeClay);

            foreach (Sample sample in soil.Samples)
            {
                CheckSample(soil, sample, sowing);
            }

            Defaults.FillInMissingValues(soil);

            // Correct the CONA / U parameters depending on LAT/LONG
            CorrectCONAU(simulation, soil, workingFolder);

            // get rid of <soiltype> from the soil
            // this is necessary because NPD uses this field and puts in really long
            // descriptive classifications. Soiln2 bombs with an FString internal error.
            soil.SoilType = null;

            // Set the soil name to 'soil'
            soil.Name = "Soil";

            simulation.Soil = soil;
        }
예제 #7
0
        /// <summary>
        /// Create a one year APSIM simulation for the specified yield prophet specification
        /// and paddock
        /// </summary>
        /// <param name="simulation">The specification to use</param>
        /// <param name="workingFolder">The folder where files shoud be created.</param>
        /// <param name="usingAPSIMx">Write APSIMx files?</param>
        /// <returns>The XML node of the APSIM simulation.</returns>
        private static XmlNode CreateSimulationXML(APSIMSpecification simulation, string workingFolder, bool usingAPSIMx)
        {
            IAPSIMFileWriter apsimWriter;

            if (usingAPSIMx)
            {
                apsimWriter = new APSIMxFileWriter();
            }
            else
            {
                apsimWriter = new APSIMFileWriter();
            }

            // Name the paddock.
            apsimWriter.NameSimulation(simulation.Name);

            // Set the clock start and end dates.
            apsimWriter.SetStartEndDate(simulation.StartDate, simulation.EndDate);

            // Set the report date.
            apsimWriter.SetReportDate(simulation.NowDate);

            // Set the weather file
            apsimWriter.SetWeatherFile(simulation.WeatherFileName);

            // Set the stubble
            apsimWriter.SetStubble(simulation.StubbleType, simulation.StubbleMass, YieldProphetUtility.GetStubbleCNRatio(simulation.StubbleType));

            // Set NUnlimited
            if (simulation.NUnlimited)
            {
                apsimWriter.SetNUnlimited();
            }

            // Set NUnlimited from today
            if (simulation.NUnlimitedFromToday)
            {
                apsimWriter.SetNUnlimitedFromToday();
            }

            if (simulation.WriteDepthFile)
            {
                apsimWriter.WriteDepthFile();
            }

            if (simulation.Next10DaysDry)
            {
                apsimWriter.Next10DaysDry();
            }

            apsimWriter.SetErosion(simulation.Slope, simulation.SlopeLength);

            // Do soil stuff.
            DoSoil(simulation, workingFolder);
            apsimWriter.SetSoil(simulation.Soil);

            // Loop through all management actions and create an operations list
            foreach (Management management in simulation.Management)
            {
                if (management is Sow)
                {
                    apsimWriter.AddSowingOperation(management as Sow, simulation.UseEC);
                }
                else if (management is Fertilise)
                {
                    apsimWriter.AddFertilseOperation(management as Fertilise);
                }
                else if (management is Irrigate)
                {
                    apsimWriter.AddIrrigateOperation(management as Irrigate);
                }
                else if (management is Tillage)
                {
                    apsimWriter.AddTillageOperation(management as Tillage);
                }
                else if (management is StubbleRemoved)
                {
                    apsimWriter.AddStubbleRemovedOperation(management as StubbleRemoved);
                }
                else if (management is ResetWater)
                {
                    apsimWriter.AddResetWaterOperation(management as ResetWater);
                }
                else if (management is ResetNitrogen)
                {
                    apsimWriter.AddResetNitrogenOperation(management as ResetNitrogen);
                }
                else if (management is ResetSurfaceOrganicMatter)
                {
                    apsimWriter.AddSurfaceOrganicMatterOperation(management as ResetSurfaceOrganicMatter);
                }
            }

            // Set Daily output
            if (simulation.DailyOutput)
            {
                apsimWriter.SetDailyOutput();
            }

            // Set Monthly output
            if (simulation.MonthlyOutput)
            {
                apsimWriter.SetMonthlyOutput();
            }

            // Set Yearly output
            if (simulation.YearlyOutput)
            {
                apsimWriter.SetYearlyOutput();
            }

            return(apsimWriter.ToXML());
        }
예제 #8
0
        /// <summary>Creates the weather files for all simulations.</summary>
        /// <param name="simulations">The simulations.</param>
        /// <param name="workingFolder">The working folder to create the files in.</param>
        /// <param name="allSimulationsAreSingleSeason">All simulations are short season?</param>
        private static void CreateWeatherFilesForSimulations(APSIMSpecification simulation, string workingFolder, WeatherFileCache weatherCache, bool allSimulationsAreSingleSeason)
        {
            if (simulation.ErrorMessage == null)
            {
                string rainFileName = Path.Combine(workingFolder, simulation.Name + ".met");

                string[] filesCreated = null;

                // Make sure the observed data has a codes column.
                if (simulation.ObservedData != null)
                {
                    Weather.AddCodesColumn(simulation.ObservedData, 'O');
                }

                if (simulation.RunType == APSIMSpecification.RunTypeEnum.LongTermPatched)
                {
                    // long term.
                    DateTime longTermStartDate = new DateTime(simulation.LongtermStartYear, 1, 1);
                    int      numYears          = simulation.StartDate.Year - longTermStartDate.Year + 1;

                    // Check to see if in cache.
                    filesCreated = weatherCache.GetWeatherFiles(simulation.StationNumber,
                                                                simulation.StartDate, simulation.NowDate,
                                                                simulation.ObservedData.TableName, numYears);
                    if (filesCreated == null)
                    {
                        // Create a long term weather file.
                        filesCreated = Weather.CreateLongTerm(rainFileName, simulation.StationNumber,
                                                              simulation.StartDate, simulation.NowDate,
                                                              simulation.ObservedData, simulation.DecileDate, numYears);
                        weatherCache.AddWeatherFiles(simulation.StationNumber,
                                                     simulation.StartDate, simulation.NowDate,
                                                     simulation.ObservedData.TableName, numYears, filesCreated);
                    }
                }
                else
                {
                    // short term.
                    // Create a short term weather file.
                    Weather.Data weatherFile = Weather.ExtractDataFromSILO(simulation.StationNumber, simulation.StartDate, simulation.EndDate);
                    Weather.OverlayData(simulation.ObservedData, weatherFile.Table);
                    Weather.WriteWeatherFile(weatherFile.Table, rainFileName, weatherFile.Latitude, weatherFile.Longitude,
                                             weatherFile.TAV, weatherFile.AMP);
                    filesCreated = new string[] { rainFileName };
                }

                if (filesCreated.Length > 0)
                {
                    simulation.WeatherFileName = Path.GetFileName(filesCreated[0]);

                    // Set the simulation end date to the end date of the weather file. This will avoid
                    // problems where SILO hasn't been updated for a while.
                    ApsimTextFile weatherFile = new ApsimTextFile();
                    try
                    {
                        weatherFile.Open(filesCreated[0]);
                        simulation.EndDate = weatherFile.LastDate;
                    }
                    finally
                    {
                        weatherFile.Close();
                    }
                }

                if (!allSimulationsAreSingleSeason)
                {
                    APSIMSpecification.Factor factor = new APSIMSpecification.Factor();
                    factor.Name                    = "Met";
                    factor.ComponentPath           = "/Simulations/" + simulation.Name + "/Met";
                    factor.ComponentVariableName   = "filename";
                    factor.ComponentVariableValues = filesCreated;
                    if (simulation.Factors == null)
                    {
                        simulation.Factors = new List <APSIMSpecification.Factor>();
                    }
                    simulation.Factors.Add(factor);
                }
            }
        }
예제 #9
0
        /// <summary>Creates a base APSIM simulation spec for the Yield Prophet spec.</summary>
        /// <param name="yieldProphet">The yield prophet specification.</param>
        /// <returns>The created APSIM simulation spec.</returns>
        private static APSIMSpecification CreateBaseSimulation(Paddock paddock)
        {
            Paddock copyOfPaddock = paddock; // XmlUtilities.Clone(paddock) as JobsService.Paddock;

            copyOfPaddock.ObservedData = paddock.ObservedData;

            APSIMSpecification shortSimulation = new APSIMSpecification();

            shortSimulation.Name            = "Base";
            shortSimulation.WeatherFileName = shortSimulation.Name + ".met";

            // Start date of simulation should be the earliest of ResetDate, SowDate and StartSeasonDate
            Sow sow = YieldProphetUtility.GetCropBeingSown(paddock.Management);

            if (sow == null)
            {
                throw new Exception("No sowing specified for paddock: " + paddock.Name);
            }

            if (sow.Date == DateTime.MinValue)
            {
                throw new Exception("No sowing DATE specified for paddock: " + paddock.Name);
            }

            if (sow.Crop == null || sow.Crop == "" || sow.Crop == "None")
            {
                throw new Exception("No sowing CROP specified for paddock: " + paddock.Name);
            }

            shortSimulation.StartDate = DateTime.MaxValue;
            if (paddock.SoilWaterSampleDate != DateTime.MinValue &&
                paddock.SoilWaterSampleDate < shortSimulation.StartDate)
            {
                shortSimulation.StartDate = paddock.SoilWaterSampleDate;
            }
            if (paddock.SoilNitrogenSampleDate != DateTime.MinValue &&
                paddock.SoilNitrogenSampleDate < shortSimulation.StartDate)
            {
                shortSimulation.StartDate = paddock.SoilNitrogenSampleDate;
            }
            if (sow != null && sow.Date < shortSimulation.StartDate && sow.Date != DateTime.MinValue)
            {
                shortSimulation.StartDate = sow.Date;
            }
            if (paddock.StartSeasonDate < shortSimulation.StartDate)
            {
                shortSimulation.StartDate = paddock.StartSeasonDate;
            }

            if (paddock.LongtermStartYear == 0)
            {
                shortSimulation.LongtermStartYear = 1957;
            }
            else
            {
                shortSimulation.LongtermStartYear = paddock.LongtermStartYear;
            }

            if (paddock.RunType == Paddock.RunTypeEnum.SingleSeason)
            {
                shortSimulation.EndDate = copyOfPaddock.NowDate.AddDays(-1);
                if ((shortSimulation.EndDate - shortSimulation.StartDate).Days > 360)
                {
                    shortSimulation.EndDate = shortSimulation.StartDate.AddDays(360);
                }
            }
            else if (paddock.RunType == Paddock.RunTypeEnum.LongTermPatched)
            {
                shortSimulation.EndDate = shortSimulation.StartDate.AddDays(360);
            }
            else if (paddock.RunType == Paddock.RunTypeEnum.LongTerm)
            {
                // Sow opp reports.
                shortSimulation.StartDate = new DateTime(shortSimulation.LongtermStartYear, 1, 1);
                shortSimulation.EndDate   = copyOfPaddock.NowDate.AddDays(-1);
            }
            shortSimulation.NowDate = copyOfPaddock.NowDate.AddDays(-1);
            if (shortSimulation.NowDate == DateTime.MinValue)
            {
                shortSimulation.NowDate = DateTime.Now;
            }
            shortSimulation.DailyOutput   = paddock.DailyOutput;
            shortSimulation.MonthlyOutput = paddock.MonthlyOutput;
            shortSimulation.YearlyOutput  = paddock.YearlyOutput;
            shortSimulation.ObservedData  = copyOfPaddock.ObservedData;
            shortSimulation.Soil          = copyOfPaddock.Soil;
            shortSimulation.SoilPath      = copyOfPaddock.SoilPath;
            shortSimulation.Samples       = new List <APSIM.Shared.Soils.Sample>();
            shortSimulation.Samples.AddRange(copyOfPaddock.Samples);
            shortSimulation.InitTotalWater    = copyOfPaddock.InitTotalWater;
            shortSimulation.InitTotalNitrogen = copyOfPaddock.InitTotalNitrogen;
            shortSimulation.StationNumber     = copyOfPaddock.StationNumber;
            shortSimulation.StubbleMass       = copyOfPaddock.StubbleMass;
            shortSimulation.StubbleType       = copyOfPaddock.StubbleType;
            shortSimulation.Management        = new List <Management>();
            shortSimulation.Management.AddRange(copyOfPaddock.Management);
            shortSimulation.UseEC          = paddock.UseEC;
            shortSimulation.WriteDepthFile = false;
            if (paddock.RunType == Paddock.RunTypeEnum.LongTermPatched)
            {
                shortSimulation.RunType = APSIMSpecification.RunTypeEnum.LongTermPatched;
            }
            else
            {
                shortSimulation.RunType = APSIMSpecification.RunTypeEnum.Normal;
            }
            shortSimulation.DecileDate          = paddock.StartSeasonDate;
            shortSimulation.NUnlimited          = paddock.NUnlimited;
            shortSimulation.NUnlimitedFromToday = paddock.NUnlimitedFromToday;
            shortSimulation.WriteDepthFile      = paddock.WriteDepthFile;
            shortSimulation.Next10DaysDry       = paddock.Next10DaysDry;
            AddResetDatesToManagement(copyOfPaddock, shortSimulation);

            // Do a stable sort on management actions.
            shortSimulation.Management = shortSimulation.Management.OrderBy(m => m.Date).ToList();

            if (paddock.RunType == Paddock.RunTypeEnum.LongTerm)
            {
                foreach (Management man in shortSimulation.Management)
                {
                    man.IsEveryYear = true;
                }
            }
            return(shortSimulation);
        }