APSIMInitiative / APSIM710

APSIM
https://www.apsim.info
29 stars 46 forks source link

How to capture length of individual phenology stages using a tracker and yearly output? #2185

Open LenLon opened 1 year ago

LenLon commented 1 year ago

Hey everyone,

I am currently looking into capturing the length of individual phenology stages (in days) using the maize model and a gridded implementation of APSIM. I can get by by using daily outputs and then just counting the days from the stage_name variable output, but daily outputs mean I increase the size of my outputs tremendously and APSIM runs a lot slower too (I think).

Is there a way to set up a tracker to just do that for me and give me an output (one for each phenology stage) at harvest? There are the DeltaTT variables, but they only seem to track when the phenology stage changes.. maybe there could also be a tracker that queries the date when an event happens? I know the arguments on sowing and at harvest exist, but maybe there is something akin to on_phenology_stage_change ;)

peter-devoil commented 1 year ago

Yes, and no...

a) all the apsim crops have different names for phenological stages, and writing something that works across all crops is tricky.

b) the maize (and most others) module will publish an event called X when phenological phase X is entered. So, you can write some tracker logic like

value of maize.DaysAfterSowing on maize.end_of_juvenile as EJ_Days

and then report EJ_Days later. If you're running a longish simulation, beware of "stale" tracker variables if you're reporting a crop that fails (ie doesnt reach phase X). They'll only be (re)set when the event occurs.

LenLon commented 1 year ago

Oh wow, that's really helpful!

I'll try and implement this and some additional logic that tracks the plant status, so I know when a plant has failed. I assume there is an event for plant death as well?

And where would I find these events? Are they printed in the .sum files?

PS: I am also imagining I could capture not only growing season temperatures, but also temperatures per phenology stage then.. as in

mean of maxt on end_of_day from maize.end_of_juvenile to maize.end_of_floral_initiation as MeanStageTemp

or something similar?

peter-devoil commented 1 year ago

There isnt a plant death event, but there's some logic to test for it bundled in with the harvest rule (... or maize.plant_status = 'dead')

These stages are defined in a configuration file. Note that there's no a "end_of_X" for each stage X, the event X occurs when the plant enters the phase X.

And yes, you can capture any variable in the system.

LenLon commented 1 year ago

Thanks a lot! This has all been very useful. Now one more thing:

I want to capture 2 cropping seasons (bimodal rainfall regime) in one zone. I have made two manager modules for sowing, but APSIM gives me no way of "labelling" the resulting yields either as season 1 or season 2. I'm sure there is a way to track this, but I have found no documentation on this either.

peter-devoil commented 1 year ago

For sure, there's always "one more" :)

A simple approach is to add a variable to one of your managers that represents which manager module has sown that crop. When either manager is sowing, it sets that variable. So, look for the lines that sow the crop, and add a variable

...
   maize sow plants =2.2, sowing_depth = 100, cultivar = sc401, row_spacing = 0.9, tiller_no_fertile = 1 (), skip = solid
   season_name = 'season1'
...

you may want to set season_name in the initialisation somewhere. The variable will remain set until the next sowing.

Reporting this is trivial in a harvest report (just add another column), but is trickier in an annual report - where you'd have to track it with the tracker component at each harvest, and report two sets of crop variables. In that case you could publish an event to the system that the tracker is listening for:

   act_mods season1
   maize harvest

(act_mods is a manager shorthand for active modules) - and the tracker:

value of maize.yield on season1 as season1_yield
LenLon commented 1 year ago

As of right now it seems APSIM reports yields (and everything else in my My Variables list) with every harvest, so I already get two outputs per year or one per season. I'd just like APSIM to also report a new column with the season name (1 or 2) for easier splitting of the data for analysis later.

I have added a parameter as suggested in the sowing with intercropping manager process code:

if ('[crop]' = 'sorghum') then [crop] sow plants =[density], sowing_depth = [depth], cultivar = [cultivar1], row_spacing = [row_spacing], tiller_no_fertile = [ftn] (), skip = [skiprow] else [crop] sow cultivar = [cultivar1], plants = [density] (plants/m2), sowing_depth = [depth], row_spacing = [row_spacing], season_name = 'season_1' endif

and initialised it under the init ribbon of the same node using

season_name = 'season_1'

The same for the second sowing with intercropping manager node for the second season, just with season_2 as the value.

I have added the act_mods season1 event to my first sowing with intercropping manager node, and I just want the tracker to save the value of season_name at that event (which should be season_1, right?) using:

value of season_name on season1 as season

Now my simulation fails with this error:

`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! APSIM Fatal Error

 Cannot parse float from string "season_2"
 Component name: paddock.tracker
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

`

Is it trying to save a number from a string here? I also tried to just report season_name directly under My Variables, but it just prints season_2 everytime for all harvest :(

Thank you so much for the input provided so far.

peter-devoil commented 1 year ago

You want that extra bit on its own line, not as an extra bit to the crop module's sowing.

What happens here is that you create a "manager variable" that other modules ask for - particularly the report module, but also other manager components.

When the second manager does its sowing thing, it asks the system for any variable called "season_name". When the first manager says "I've got it", the second manager writes to the first managers variable, instead of making a second "season_name" in the system.