SimpleCrop.jl
SimpleCrop.jl is an implementation of SimpleCrop model which was introduced as an example of how DSSAT models were structured in a modular approach. The original model was coded in Fortran and here reimplemented in a domain-specific language based on Julia using Cropbox framework.
Installation
using Pkg
Pkg.add("SimpleCrop")
Getting Started
using Cropbox
using SimpleCrop
The model is implemented as a system named Model
defined in SimpleCrop
module.
parameters(SimpleCrop.Model; alias = true)
Config for 1 system:
Model | ||
weather_data | = | nothing |
planting_day_of_year | = | 121 d |
LAI_coeff1 | = | 0.104 m² |
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⁻¹ |
plant_density | = | 5.0 m⁻² |
maximum_leaf_appearance_rate | = | 0.1 d⁻¹ |
base_temperature | = | 10.0 °C |
initial_plant_dry_matter | = | 0.3 g m⁻² |
initial_canopy_dry_matter | = | 0.045 g m⁻² |
initial_root_dry_matter | = | 0.255 g m⁻² |
radiation_use_efficiency | = | 2.1 g MJ⁻¹ |
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⁻¹ |
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 |
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 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)
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)
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)
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)
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)
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)
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)
The resulting soil water content (SWC
) is shown here.
visualize(r, :DATE, :SWC; ylim = (0, 400), kind = :line)
Which, in turn, determines soil water stress factor (SWFAC
) in this model.
visualize(r, :DATE, [:SWFAC, :SWFAC1, :SWFAC2]; ylim = (0, 1), kind = :line)
For more information about using the framework such as simulate()
and visualize()
functions, please refer to the Cropbox documentation.