The model (what's real data vs. what's simplified scaffolding)
Real, from the catalog (verbatim, not invented): OnlyCSharp.Data.Catalogs.Agriculture.CropYield —
13 crops' ky (FAO-33 Table 25 yield-response factor), potentialYieldTHa, harvestIndex,
rueGPerMJ (radiation-use efficiency), extinctionCoeff (Beer-Lambert k), maxLai,
baseTempC + gddToAnthesis + gddToMaturity (thermal-time phenology), and
depletionFractionP (FAO-56 Table 22). Cite: FAO-33, FAO-56, Sinclair & Muchow (1999). Plus
OnlyCSharp.Data.Catalogs.Agriculture.SeedCatalog — germination cardinal temperatures
(GermTempMinC/OptC/MaxC, Covell et al. 1986 broken-linear rate model) and real
SpacingInRowCm/SpacingBetweenRowCm row geometry, cross-referenced by species where the
40-crop catalog has a matching entry (see per-plot "seed source" badge).
Real solar geometry (per the addendum): solar declination via the Cooper (1969) approximation
δ = 23.44°·sin(360/365·(N+284)); day length via
hours = 24/π·acos(-tan(lat)·tan(δ)); extraterrestrial radiation Ra via the standard
FAO-56 (Allen et al. 1998, eq. 21) formula from declination + sunset-hour-angle + inverse earth-sun distance —
all computed for the fixed Ames, Iowa latitude (42.03°N), for the real calendar date starting 1999-01-01.
Documented simplifications (explicitly allowed by the brief): seasonal temperature is a
sinusoid phase-lagged ~30 days behind the solstice (the standard real-world thermal-lag phenomenon) rather than
a physical energy-balance model; surface solar radiation Rs = Ra × clear-sky transmissivity (a
constant per climate profile, standing in for full Angstrom–Prescott sunshine-hour data); precipitation is a
seasonal-mean + deterministic day-to-day pseudo-random pattern (not real weather-station records); reference
evapotranspiration ET0 is a simplified radiation+temperature proxy (not full Penman–Monteith);
intercepted PAR assumes the standard Monteith (1977) 50% PAR fraction of solar radiation; soil available-water
capacity (0.15 mm/mm, loam) and the FAO-56 dual-Kc curve shape are generic defaults (the catalog
doesn't carry per-crop Kc or soil AWC). Where a crop has no SeedCatalog match (Soybean/Sorghum/Potato/Rice/
Cotton/Barley/Sugarcane), spacing/germination use a same-species-typical sane default, flagged in the seed badge.
The Ky story — why timing matters
FAO-33's Doorenbos & Kassam relation is 1 − Ya/Ym = Ky × (1 − ETa/ETm) — the SAME relative
water deficit costs more or less yield depending on when in the season it happens. The catalog stores
one whole-season Ky per crop; this sim recovers the classic stage-timing effect by weighting each
day's ET deficit by how sensitive that growth stage is (Doorenbos & Kassam's well-established qualitative
ordering — flowering is always the most sensitive stage) before folding it into the season-long ratio:
Stage Sensitivity weight Why
Germinating / dormant 0.2 little transpiring leaf area yet
Vegetative 0.5 can compensate with more growth later
Flowering (anthesis) 1.8 — peak pollen viability / grain-set is water-critical and irreversible
Yield formation 1.0 grain/tuber fill still sensitive
Ripening 0.3 yield is largely already set
Season-end: weightedRelDeficit = Σ(weight·(ETc−ETa)) / Σ(weight·ETc), then
Ya = min(biomass×HI, Ym) × clamp(1 − Ky×weightedRelDeficit, 0, 1). A dry spell during flowering
therefore costs far more yield than the identical dry spell during vegetative growth — pick a crop, sow it, and
toggle a plot's irrigation off during flowering to see it live.
Showcasing OnlyCSharp.Data.Catalogs.Agriculture.CropYield and
OnlyCSharp.Data.Catalogs.Agriculture.SeedCatalog. Self-contained, zero dependencies, runs from
file://. Test hook: window.__farm.