import {withDownload, fmt, pearson} from "../assets/js/dl.js"
treatments = FileAttachment("data/module1/treatments.csv").csv({typed: true})
final = FileAttachment("data/module1/final.csv").csv({typed: true})
gsim = FileAttachment("data/module1/growth_sim.csv").csv({typed: true})
gobs = FileAttachment("data/module1/growth_obs.csv").csv({typed: true})
stats = FileAttachment("data/module1/stats.csv").csv({typed: true})
weather = FileAttachment("data/module1/weather.csv").csv({typed: true})
stages = FileAttachment("data/module1/stages.csv").csv({typed: true})
coef = FileAttachment("data/module1/coefficients.csv").csv({typed: true})
potential = FileAttachment("data/module1/potential.csv").csv({typed: true})
potGrowth = FileAttachment("data/module1/potential_growth.csv").csv({typed: true})
sensCul = FileAttachment("data/module1/sens_cultivar.csv").csv({typed: true})
sensCulG = FileAttachment("data/module1/sens_cultivar_growth.csv").csv({typed: true})
sensPd = FileAttachment("data/module1/sens_pdate.csv").csv({typed: true})
sensPdG = FileAttachment("data/module1/sens_pdate_growth.csv").csv({typed: true})
sensCoef = FileAttachment("data/module1/sens_coef.csv").csv({typed: true})
sensCoefG = FileAttachment("data/module1/sens_coef_growth.csv").csv({typed: true})
runInfo = FileAttachment("data/module1/run_info.csv").csv()
csmMods = FileAttachment("data/module1/csm_modules.csv").csv({typed: true})
csmPlants = FileAttachment("data/module1/csm_plant_models.csv").csv({typed: true})
tfun = FileAttachment("data/module1/cropgro_temperature.csv").csv({typed: true})
eco = coef[0]
// built at runtime so Quarto does not rewrite the .ipynb link to the rendered page
dlLinks = html`<a href="${"../notebooks/module1" + ".ipynb"}" download>download .ipynb</a>, helper <a href="../notebooks/learnlib.py" download>learnlib.py</a>`
W = Math.min(width, 860)
trtName = new Map(treatments.map(d => [d.TRNO, `T${d.TRNO} ${d.water}, ${d.nitrogen} N`]))Module 1: running a crop model, phenology, sensitivity and potential production
DSSAT training, module 1 of 6. Follows day 1 of the course, with code instead of the DSSAT shell
How to use this module. Read this page for the ideas; every chart here comes from the notebook module 1 notebook (), which runs the DSSAT engine and writes the small data files the charts read. The page itself never runs the engine. The runs on this build were made on with model .
What you will learn
- What a crop simulation model does, and what an experiment (FileX) and its treatments are.
- How to run DSSAT on an existing experiment and compare its results with field measurements.
- How the maize model decides when the crop flowers and matures (phenology, thermal time).
- How to change one input at a time (sensitivity analysis) and read the result.
- How to set up the simplest experiment, potential production, in which only weather, CO2 and the cultivar limit the crop.
The topics follow the first day of the 2018 International Training Program on DSSAT in Chiang Mai (syllabus). The course used the DSSAT shell and its tools (XBuild, the Sensitivity Analysis tool, GBuild); here each of those steps is a few lines of Python, using xdssat’s modules and the stock DSSAT engine, version 4.8.
0. DSSAT and its Cropping System Model
Where DSSAT comes from
The course opened with the history of crop modelling and of DSSAT. In outline, as its first lecture told it:
| When | What |
|---|---|
| Late 1960s | Crop simulation starts with Dutch (C. T. de Wit) and US researchers, who wanted to predict growth and yield to design management and quantify the effect of weather |
| 1982 to 1993 | The IBSNAT project (International Benchmark Sites Network for Agrotechnology Transfer), based at the University of Hawaii and funded by USAID, builds a network of researchers, data standards and DSSAT itself |
| 1983 | The minimum data set for running crop models is defined (module 2) |
| 1985 to 1986 | DSSAT is named (1985) and first released (1986) with maize, wheat, soybean and peanut. Its models came from CERES-Maize and CERES-Wheat and from SOYGRO and PNUTGRO, each until then a separate program with its own soil, weather and management code |
| December 1993 to October 2014 | ICASA (International Consortium for Agricultural Systems Applications) carries the work on, joining IBSNAT with the Dutch systems effort, and maintains the data standards |
| From 2004 | The Cropping System Model replaces the separate programs with one modular engine (Jones et al. 2003) |
| 2012 onwards | The DSSAT Foundation develops and distributes DSSAT (dssat.net) |
The separate programs were hard to keep compatible, to maintain and to extend to new crops, which the course gave as the reason DSSAT was created. The Cropping System Model later joined them into one modular engine with shared soil, weather and management modules (Jones et al. 2003), and that engine is what every page of this site runs.
Today DSSAT centres on one program, the Cropping System Model (CSM): a single Fortran engine built from modules for the weather, the soil (water, nitrogen, carbon, temperature), the exchange between soil, plant and atmosphere (SPAM), management, and a family of plant models that share one interface (Jones et al. 2003). Counting the source code of the engine used on this site shows how the work is divided:
The plant part alone holds model families, from CERES (cereals) and CROPGRO (grain legumes and more) to models for potato, sugarcane, cassava and pineapple:
Counted by the module 1 notebook in DSSAT/dssat-csm-os at the commit pinned on this site (folders Plant, Soil, SPAM, Weather, Management, InputModule, Utilities, CSM_Main; files ending .for or .f90).
The same engine serves very different questions. The course listed diagnosing yield gaps, precision agriculture, water, irrigation and soil fertility management, plant breeding and genotype by environment interactions, gene-based modelling, yield prediction, and the effects of climate variability and climate change; the DSSAT Foundation’s own list today is similar (About DSSAT). Module 6 returns to these applications and what each one needs.
1. A crop model, an experiment, a treatment
DSSAT’s Cropping System Model grows a crop one day at a time (Jones et al. 2003). Each day it reads the weather (radiation, temperature, rain), works out how far the crop has developed, how much it has grown, and how much water and nitrogen the roots took from each soil layer. Its inputs are the weather, the soil profile, the cultivar’s genetic coefficients and the management: planting, irrigation, fertilizer.
A useful way to think about what limits a crop is the hierarchy of production levels (Ittersum and Rabbinge 1997). Potential yield is set by radiation, temperature, CO2 and the cultivar alone. Attainable (water- and nutrient-limited) yield is lower where water or nitrogen run short. Actual yield is lower still where weeds, pests and diseases reduce it. DSSAT simulates the first two levels; this module starts with real treatments and ends with the potential.
The example is a maize experiment from Gainesville, Florida, in 1982 (UFGA8201, cultivar McCurdy 84aa), one of the example experiments shipped with DSSAT (DSSAT Foundation 2026). It has six treatments: every combination of three water regimes and two nitrogen rates. In the experiment file each treatment is a row that picks one level of each factor (cultivar, field, initial conditions, planting, irrigation, fertilizer, simulation controls).
2. Running the model and checking it against the field
The notebook copies the experiment, its weather and soil files and the field measurements into a short work folder and runs the engine on all six treatments. The engine writes one summary row per treatment and daily time series. The field data come in two files: end-of-season values (FileA) and samples taken during the season (FileT).
Across the six treatments, simulated grain yield ranges from to kg/ha against to kg/ha measured. The model ranks the treatments the way the field did: the rainfed plots yield least, and the irrigated high-N plot most. It does not separate the two rainfed treatments: with too little water, extra nitrogen makes no simulated difference to grain.
Growth during the season
Pick a variable; the lines are the daily simulation, the dots the field samples.
GBuild’s Statistics option reports how far the simulation is from the samples. The notebook computes the same two numbers: the root mean square error (RMSE, in the variable’s units) and Willmott’s index of agreement d, which is 1 for a perfect match and has no units (Willmott 1981). For \(n\) pairs of observed \(O_i\) and simulated \(S_i\) values, with \(\bar O\) the mean of the observations:
\[ \begin{gathered} \mathrm{RMSE} = \sqrt{\frac{1}{n}\sum_{i=1}^{n} (S_i - O_i)^2} \\[4pt] d = 1 - \frac{\sum_i (S_i - O_i)^2}{\sum_i \left(|S_i - \bar O| + |O_i - \bar O|\right)^2} \end{gathered} \]
3. Phenology: when does the crop flower?
Development (moving through life stages) is not the same as growth (adding mass). A crop that develops fast has a short life; that does not make it bigger. Temperature drives development in all crops; day length matters for some cultivars.
CERES-Maize counts development in thermal time, degree-days above a base temperature. Each day adds DTT degree-days; each phase ends when its requirement is met. For maize: emergence, the end of the juvenile phase after P1 degree-days, a floral induction phase that day length can slow (P2), tassel initiation, silking, grain filling for P5 degree-days, and maturity.
How one day’s DTT is computed is set in the engine’s Fortran (MZ_PHENOL.for, lines 437-517). The base temperature TBASE is °C here and the optimum TOPT is °C; both come from the ecotype file MZCER048.ECO. Try it: the function below is a direct port of the air-temperature branches (the engine uses an estimated soil temperature while the plant has 10 leaves or fewer, when its growing point is still near the ground; that branch is left out here). With \(T_{base}\), the optimum \(T_{opt}\) and the day’s \(T_{max}\) and \(T_{min}\):
\[ \begin{gathered} DTT = \begin{cases} 0 & T_{max} < T_{base} \\ T_{opt} - T_{base} & T_{min} > T_{opt} \\ DTT_{hourly} & T_{min} < T_{base} \text{ or } T_{max} > T_{opt} \\ \dfrac{T_{max} + T_{min}}{2} - T_{base} & \text{otherwise} \end{cases} \\[6pt] DTT_{hourly} = \frac{1}{24}\sum_{h=1}^{24} \left(\min\left(\max(T_h, T_{base}), T_{opt}\right) - T_{base}\right) \end{gathered} \]
with hourly temperatures from a sine curve, \(T_h = \frac{T_{max} + T_{min}}{2} + \frac{T_{max} - T_{min}}{2}\,\sin\!\left(\frac{3.14\,h}{12}\right)\). A phase ends on the day its sum reaches the cultivar’s requirement, \(\sum DTT \ge P1\) for the juvenile phase.
With a wide daily range, part of the day is below TBASE or above TOPT even when the mean is not; the hourly sine curve gives those hours less (or no) thermal time, so the curve bends before it reaches the cap. Above TOPT the rate does not fall: the model has no penalty for heat in this function.
Over the 1982 season, the thermal time adds up like this (air-temperature branches only, so slightly different from the engine’s own sum early in the season). The vertical lines are the stage changes the engine simulated for treatment 4:
Stage numbers are the PlantGro GSTD values of treatment 4. For CERES-Maize GSTD is the phenology stage ISTAGE once the plant has leaves (MZ_GROSUB.for:1847-1851); each line marks the day a stage begins, named after the stage comments in MZ_PHENOL.for (lines 647-875). McCurdy 84aa: P1 = °C-day, P2 = d/h, P5 = °C-day (engine’s MZCER048.CUL).
Temperature responses in CROPGRO
CERES-Maize uses one base temperature and one optimum. CROPGRO, the model of the grain legumes in module 2, uses a four-point function instead: no development below a base TB, a rise to a first optimum TO1, a plateau to a second optimum TO2, and a decline to zero at a maximum TM,
\[ f(T) = \begin{cases} 0 & T \le T_B \text{ or } T \ge T_M \\ \dfrac{T - T_B}{T_{O1} - T_B} & T_B < T < T_{O1} \\ 1 & T_{O1} \le T \le T_{O2} \\ 1 - \dfrac{T - T_{O2}}{T_M - T_{O2}} & T_{O2} < T < T_M \end{cases} \]
(UTILS.for:353-358, curve type LIN, called in PHENOL.for:237). Soybean’s species file sets one function for each of three phases of development:
Values from the engine’s SBGRO048.SPE (phenology parameters): TB , TO1 , TO2 , TM °C for this phase. CROPGRO applies the function to hourly temperatures.
4. Potential production
Now the simplest experiment: water and nitrogen are not simulated at all (WATER and NITRO switched to N in the simulation controls), so only weather, CO2 and the cultivar limit growth. In the DSSAT shell this is a new FileX made in XBuild. In the notebook it is built from treatment 4 of UFGA8201 with filex.build_filex, keeping the same field, cultivar and planting date. With the water switch off, DSSAT skips the soil water balance (SPAM.for:269); with the N switch off, CERES-Maize has no N stress (MZ_GROSUB.for:2059).
The potential run (measured CO2) gives kg/ha. The irrigated high-N treatment reached of it in the model; the rainfed treatments . Water, not nitrogen, made the largest difference in this season.
CO2. DSSAT can take CO2 from a measured series (option M, Mauna Loa) or use a fixed value (option D, 380 ppm from CO2048.WDA), see CO2VAL.for. The 1982 series averages ppm over the season; with 380 ppm the potential yield is kg/ha, more: a small effect for a ppm difference.
5. Sensitivity analysis: one thing at a time
The Sensitivity Analysis tool changes one input and reruns. All runs below are potential production, so that water and nitrogen do not blur the effect.
Cultivars
Six maize cultivars from the engine’s cultivar file, from a short to a long juvenile phase (P1):
A longer juvenile phase delays anthesis (from to days after planting here) and builds more leaf area, but the highest yield is not the latest cultivar: yield also depends on grain filling (P5, G2, G3), and McCurdy 84aa has the longest grain filling of the six. A potential yield like this belongs to a cultivar at one place in one year; it is not a fixed property of the cultivar.
Planting date
Pick a planting date; 26 February is the experiment’s own date, the others follow in steps of two weeks.
Planted : anthesis after days, maturity after days, potential yield kg/ha; mean temperature over the season °C and mean radiation MJ/m²/day. Later plantings grow in warmer weather, so they accumulate thermal time faster and mature sooner. Yield does not follow a simple line over the six dates; the notebook has the daily weather to dig into why.
One genetic coefficient
Change P1 (thermal time of the juvenile phase) or P5 (thermal time of grain filling) of McCurdy 84aa. The notebook writes a copy of the cultivar file with the new value into each run folder; the engine reads the local file first, so its own file is never changed.
With = : anthesis days after planting, maturity , potential yield kg/ha. P5 lengthens grain filling without moving anthesis, and yield rises with it. P1 moves both dates, and yield is highest at P1 = with kg/ha, not at either end of the range; the notebook’s daily weather is the place to look for why.
From one field to a grid: xdssat
Every experiment above is one field. xdssat runs the same engine, unchanged, for every 0.1° weather cell of a region, one simulation per cell, season and water regime. In the rice case study that is cells of Java over 30 years (current run: ). Phenology is where the grid shows its first pattern: the same cultivar, planted by the same rule, takes longer to mature where nights are cooler, because thermal time accumulates more slowly (section 3).
Across the cells with irrigated wet-season rice, season length and night temperature correlate at r = , from to days. The case study’s Science page shows what that does to the simulated yield.
Self-test
- Which treatment of UFGA8201 is closest to potential production, and why is it not exactly equal?
- The model gives the same grain yield to both rainfed treatments. What does that tell you about which factor limited them?
- In the cultivar comparison, why does the cultivar with the most leaf area not give the most grain?
- Change the CO2 option in the notebook to
W(CO2 from the weather file). What happens, and why? - Add a planting date in July in the notebook. Predict anthesis and maturity first, then run it.
Where this goes next
Module 2 adds growth processes, weather files and cultivar coefficients; module 3 turns the water balance on. The plan for all six modules is on the training overview.
References
DSSAT Foundation. 2026. DSSAT-CSM Example Data (Dssat-Csm-Data), Commit 99c95b3. https://github.com/DSSAT/dssat-csm-data.
Ittersum, M. K. van, and R. Rabbinge. 1997. “Concepts in Production Ecology for Analysis and Quantification of Agricultural Input-Output Combinations.” Field Crops Research 52 (3): 197–208. https://doi.org/10.1016/S0378-4290(97)00037-3.
Jones, J. W., G. Hoogenboom, C. H. Porter, et al. 2003. “The DSSAT Cropping System Model.” European Journal of Agronomy 18 (3–4): 235–65. https://doi.org/10.1016/S1161-0301(02)00107-7.
Willmott, Cort J. 1981. “On the Validation of Models.” Physical Geography 2 (2): 184–94. https://doi.org/10.1080/02723646.1981.10642213.