APSIMInitiative / ApsimX

ApsimX is the next generation of APSIM
http://www.apsim.info
Other
129 stars 159 forks source link

Harvesting rule for potato long-term factorials #3008

Closed JJguri closed 5 years ago

JJguri commented 5 years ago

I had an issue related with the harvesting rule using a long-term factorial with potato. Because the harvesting rule was set at maturity, during years were the crop does not achieve this phenological stage, it never is harvested. Therefore, I have added a rule for an alternatively harvesting at fixed date as follow:

if (Phenology.CurrentPhaseName == "Maturity" or Clock.Today == "15-Apr") { Potato.Harvest(); Potato.EndCrop();

However, I got the following error:

System.Exception: Unable to compile "Harvesting" ---> System.Exception: ) expected. Line number: 23 Embedded statement cannot be a declaration or labeled statement. Line number: 23 ; expected. Line number: 23 Invalid expression term '.'. Line number: 23 ; expected. Line number: 23 ; expected. Line number: 23 Invalid expression term ')'. Line number: 23 ; expected. Line number: 23 at APSIM.Shared.Utilities.ReflectionUtilities.CompileTextToAssembly(String code, String assemblyFileName) at Models.Manager.RebuildScriptModel(List`1 errors) --- End of inner exception stack trace --- at Models.Manager.set_Code(String value) at UserInterface.Presenters.ManagerPresenter.BuildScript()

hol430 commented 5 years ago

the C# logical or operator is ||, so your if statement should probably read something like if (Phenology.CurrentPhaseName == "Maturity" || Clock.Today == "15-Apr")

JJguri commented 5 years ago

I modified the statement, however, the following error appeared: An object reference is required for the non-static field, method, or property 'Models.Clock.Today.get'.

hol430 commented 5 years ago

You will need a link to your clock. You should be able to get that by putting

[Link] Clock Clock;

with your other links, assuming that your clock is called Clock.

JJguri commented 5 years ago

Done, but still something is needed (please see attached)

untitled

hol430 commented 5 years ago

What I would recommend doing is adding a DateTime property to your script, and comparing that to Clock.Today. To do this, add something along the lines of:

[Description("Harvesting Date")]
public DateTime HarvestingDate { get; set; }

just beneath your links. You can then choose April 15 by going to the properties tab and typing 15-Apr into the cell next to Harvesting Date. Then, change your if statement to

if (Phenology.CurrentPhaseName == "Maturity" || Clock.Today == HarvestingDate)

The advantage of doing it this way is that you can easily change this date from the properties tab.

When typing the date into the properties tab, you may need to type it in the form dd/mm/yy - I'm not certain. I believe it may depend on your system's date settings. So if you're on Windows, just look in the bottom-right corner of the screen and use the same format that the date is in. In my case, it's dd/mm/yy.

date

JJguri commented 5 years ago

The script is already working, although I need to specify only day and month (dd-mmm) in the properties tab because it is a long-term simulation. I had added this in the script but I am not able to choose this format (dd-mmm) in the properties tab. The system’s date settings of my computer is the same like your computer. untitled

hol430 commented 5 years ago

What exactly isn't working? I was also unable to input in dd-mmm format, but putting the date in as dd/mm/yy seemed to work just fine.

hol430 commented 5 years ago

Never mind, I see the problem. What you can do is use one of our date utility methods, called CompareDates(). You will need to change your HarvestingDate to be of type string, rather than DateTime.

[Description("Harvesting Date (dd-MMM)")]
public string HarvestingDate { get; set; }

Then, you can write something like the following:

if (Phenology.CurrentPhaseName == "Maturity" || DateUtilities.DatesEqual(HarvestingDate, Clock.Today))
JJguri commented 5 years ago

In order to harvest the crop once a year, I need to put the harvest date in the dd-mmm instead dd-mm-yyyy format in the properties tab (see below), and I am not able to do that with the current script. Therefore, during years when the crop does not achieve maturity it is not harvested and the HarvestReport is not created. The script works well withouth errors and the simulation run.

image

JJguri commented 5 years ago

Done. Script and format date (dd-mmm) working well for simulations where the crop does not achieve maturity, where it is harvested each 15-Apr each year. However the following error (see below) appeared in the simulations where crop maturity is achieved, some conflict between Harvest and EndCrop. I would like the model prioritises the harvest at maturity during years when the crop is able to achieve this stage, otherwise, end of crop at fixed date (harvest) which is indicated in the properties tab.

System.Exception: ERROR in file: C:\Users\jjojeda\Dropbox\DATA\APSIM sim\Paper I_dean.apsimx Simulation name: Exp WaterIrr Weather91009 SoilBK EndCrop method called when no crop is planted. Either your planting rule is not working or your end crop is happening at the wrong time ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Exception: EndCrop method called when no crop is planted. Either your planting rule is not working or your end crop is happening at the wrong time at Models.PMF.Plant.EndCrop() at Models.Script.OnDoManagement(Object sender, EventArgs e) in c:\Users\jjojeda\AppData\Local\Temp\ApsimX\tmpB227.cs:line 32 at System.EventHandler.Invoke(Object sender, EventArgs e) at Models.Clock.OnDoCommence(Object sender, CommenceArgs e) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Models.Core.Events.Publish(String eventName, Object[] args) at Models.Core.Runners.RunSimulation.Run(CancellationTokenSource cancelToken) --- End of inner exception stack trace --- at Models.Core.Runners.RunSimulation.Run(CancellationTokenSource cancelToken) at APSIM.Shared.Utilities.JobRunnerAsync.<>c__DisplayClass10_0.b__0()

hol430 commented 5 years ago

EndCrop() should only be called once. To prevent it being called multiple times, you could check that the crop is alive:

if (Potato.IsAlive && (Phenology.CurrentPhaseName == "Maturity" || DateUtilities.DatesEqual(HarvestingDate, Clock.Today)))
JJguri commented 5 years ago

Everything running!

Just another comment: I have different source of climate data BoM and SILO. I would like to get a column as a part of my report that provide me that information. Can I read this info from the met file? Remember that each weather station to me is a level of a factor "weather" in the factorial, therefore, I am calling the met files from a folder, e.g. [Weather].FileName = Weather\91009.met, with one script.

hol430 commented 5 years ago

Not sure exactly which part of your weather data you want to report, but if you go to your report, type [Weather] and then type a period . you should some suggestions. You can move through this list with the arrow keys, type the first few letters to filter the results, and hit enter to insert the item into your report.