Using an Existing Cropbox Model

This tutorial will teach you how to use an existing Cropbox model. For this tutorial, we will be importing and utilizing a Cropbox model from a julia package called SimpleCrop.

Installing a Cropbox Model

Often times, the Cropbox model that you want to use will be part of a Julia package.

If the package you want to install is under the official Julia package registry, you can simply install the package using the following command.

using Pkg
Pkg.add("SimpleCrop")

You can also install any Julia package using a GitHub link.

using Pkg
Pkg.add("https://github.com/cropbox/SimpleCrop.jl")

Importing a Cropbox Model

To start using a Julia package containing your desired model, you must first load the package into your environment.

This can be done by using this simple command.

using SimpleCrop

Let's not forget to load Cropbox as well.

using Cropbox

Inspecting the Model

The model is implemented as a system named Model defined in SimpleCrop module. We can inspect the model with the @look macro, which will show us all the variables in the system.

@look SimpleCrop.Model
[doc]

[system]
Model
  context
  config
  DATE
  DOY
  DOYP (planting_day_of_year)
  TMAX (maximum_temperature)
  TMIN (minimum_temperature)
  TMN (mean_temperature)
  PAR (photosynthetically_active_radiation)
  SWFAC (soil_water_stress_factor)
  EMP1 (LAI_coeff1)
  EMP2 (LAI_coeff2)
  Fc (canopy_fraction)
  sla (specific_leaf_area)
  INTOT (duration_of_reproductive_stage)
  LAI0 (initial_leaf_area_index)
  Lfmax (maximum_leaf_number)
  N0 (initial_leaf_number)
  nb (LAI_coeff)
  p1 (leaf_senescence_rate)
  PD (plant_density)
  rm (maximum_leaf_appearance_rate)
  tb (base_temperature)
  W0 (initial_plant_dry_matter)
  Wc0 (initial_canopy_dry_matter)
  Wr0 (initial_root_dry_matter)
  PT (photosynthesis_reduction_factor_for_temp)
  RUE (radiation_use_efficiency)
  Pg (potential_growth_rate)
  ROWSPC (row_spacing)
  Y1 (canopy_light_extinction_coeff)
  P (planted)
  VP (vegetative_phase)
  RP (reproductive_phase)
  FL (development_phase_code)
  dN (leaf_number_increase)
  N (leaf_number)
  di (daily_accumulated_temperature)
  INT (accumulated_temperature_during_reproductive_stage)
  _a
  dLAI1
  dLAI2
  dLAI (leaf_area_index_increase)
  LAI (leaf_area_index)
  E (CH2O_conversion_efficiency)
  dW
  W (plant_dry_matter)
  Wc (canopy_dry_matter)
  Wr (root_dry_matter)
  Wf (fruit_dry_matter)
  endsim (end_of_simulation)
  Δt (timestep)
  SRAD (solar_radiation)
  RAIN (rainfall)
  calendar
  _i (irrigation_data)
  IRR
  CN (runoff_curve_number)
  DP (soil_profile_depth)
  DRNp (daily_drainage)
  WPp (soil_water_portion_at_wilting_point)
  FCp (soil_water_portion_at_field_capacity)
  STp (soil_water_portion_at_saturation)
  SWC0 (initial_soil_water_content)
  WP (soil_water_content_at_wilting_point)
  FC (soil_water_content_at_field_capacity)
  ST (soil_water_content_at_saturation)
  S (potential_maximum_soil_moisture_retention_after_runoff)
  POTINF (potential_infiltration)
  ROF (runoff)
  INF (infiltration)
  THE (soil_water_content_threshold)
  TRAIN (cumulative_rainfall)
  TIRR (cumulative_irrigation)
  TESa (cumulative_soil_evaporation)
  TEPa (cumulative_plant_transpiration)
  TROF (cumulative_runoff)
  TDRN (cumulative_vertical_drainage)
  TINF (cumulative_infiltration)
  DRN (vertical_drainage)
  αs (soil_albedo)
  αc (crop_albedo)
  ALB (surface_albedo)
  Tmed
  EEQ (equilibrium_evaporation)
  f
  ETp (potential_evapotranspiration)
  ESp (potential_soil_evaporation)
  EPp (potential_plant_transpiration)
  _a
  ESa (soil_evaporation)
  EPa (plant_transpiration)
  dSWC
  dROF_extra
  dSWC_ADJ
  SWC_ADJ
  SWC (soil_water_content)
  ΔSWC (storage_change)
  Fi
  Fo
  WATBAL
  CHECK
  SWFAC1 (drought_stress_factor)
  WTABLE (water_table_thickness)
  DWT (water_table_depth)
  STRESS_DEPTH (water_table_depth_threshold)
  SWFAC2 (excess_stress_factor)
  _w (weather_data)

@look can also be used to inspect individual state variables.

@look SimpleCrop.Model.W
[doc]

[code]
  W(dW):plant_dry_matter ~ accumulate(u"g/m^2", init = W0, when = P)

The relationship between the variables in the model can be visualized using a dependency graph.

Cropbox.dependency(SimpleCrop.Model)
Example block output

If an arrow points from one variable to a second variable, then the value of the second variable depends on, or is calculated with, the value of the first.

We can view the values of all the parameters of the model with the following command.

parameters(SimpleCrop.Model; alias = true)

Config for 1 system:

Model
weather_data=nothing
planting_day_of_year=121 d
LAI_coeff1=0.104 m^2
LAI_coeff2=0.64
canopy_fraction=0.85
duration_of_reproductive_stage=300.0 d K
initial_leaf_area_index=0.013
maximum_leaf_number=12.0
initial_leaf_number=2.0
LAI_coeff=5.3
leaf_senescence_rate=0.03 g K^-1
plant_density=5.0 m^-2
maximum_leaf_appearance_rate=0.1 d^-1
base_temperature=10.0 °C
initial_plant_dry_matter=0.3 g m^-2
initial_canopy_dry_matter=0.045 g m^-2
initial_root_dry_matter=0.255 g m^-2
radiation_use_efficiency=2.1 g MJ^-1
row_spacing=60.0 cm
CH2O_conversion_efficiency=1.0
irrigation_data=nothing
runoff_curve_number=55
soil_profile_depth=145 cm
daily_drainage=0.1 d^-1
soil_water_portion_at_wilting_point=0.06
soil_water_portion_at_field_capacity=0.17
soil_water_portion_at_saturation=0.28
initial_soil_water_content=246.5 mm
soil_albedo=0.1
crop_albedo=0.2
water_table_depth_threshold=250 mm

Running a Simulation

As many parameters are already defined in the model, we only need to prepare time-series data for daily weather and irrigation, which are included in the package for convenience.

using CSV
using DataFrames
using Dates
using TimeZones

loaddata(f) = CSV.File(joinpath(dirname(pathof(SimpleCrop)), "../test/data", f)) |> DataFrame
config = @config (
    :Clock => :step => 1u"d",
    :Calendar => :init => ZonedDateTime(1987, 1, 1, tz"UTC"),
    :Weather => :weather_data => loaddata("weather.csv"),
    :SoilWater => :irrigation_data => loaddata("irrigation.csv"),
)

Let's run a simulation with the model using configuration we just created. Stop condition for simulation is defined in a flag variable named endsim which coincides with plant maturity or the end of reproductive stage.

r = simulate(SimpleCrop.Model; config, stop = :endsim)

Visualizing the Results

The output of simulation is now contained in a data frame from which we generate multiple plots. The number of leaf (N) went from initial_leaf_number (= 2) to maximum_leaf_number (= 12) as indicated in the default set of parameters.

visualize(r, :DATE, :N; ylim = (0, 15), kind = :line)
Example block output

Thermal degree days (INT) started accumulating from mid-August with the onset of reproductive stage until late-October when it reaches the maturity indicated by duration_of_reproductive_stage (= 300 K d).

visualize(r, :DATE, :INT; kind = :line)
Example block output

Assimilated carbon (W) was partitioned into multiple parts of the plant as shown in the plot of dry biomass.

visualize(r, :DATE, [:W, :Wc, :Wr, :Wf];
    names = ["Total", "Canopy", "Root", "Fruit"], kind = :line)
Example block output

Leaf area index (LAI) reached its peak at the end of vegetative stage then began declining throughout reproductive stage.

visualize(r, :DATE, :LAI; kind = :line)
Example block output

For soil water balance, here is a plot showing water runoff (ROF), infiltration (INF), and vertical drainage (DRN).

visualize(r, :DATE, [:ROF, :INF, :DRN]; kind = :line)
Example block output

Soil water status has influence on potential evapotranspiration (ETp), actual soil evaporation (ESa), and actual plant transpiration (ESp).

visualize(r, :DATE, [:ETp, :ESa, :EPa]; kind = :line)
Example block output

The resulting soil water content (SWC) is shown here.

visualize(r, :DATE, :SWC; ylim = (0, 400), kind = :line)
Example block output

Which, in turn, determines soil water stress factor (SWFAC) in this model.

visualize(r, :DATE, [:SWFAC, :SWFAC1, :SWFAC2]; ylim = (0, 1), kind = :line)
Example block output