Source code for pcse.crop.lintul_cassava.phenology

# -*- coding: utf-8 -*-
# Herman Berghuijs (herman.berghuijs@wur.nl), Allard de Wit (allard.dewit@wur.nl), Tom Schut (tom.schut@wur.nl)
# February 2026
import datetime

from pcse.traitlets import Float, Instance, Enum
from pcse.base import ParamTemplate, RatesTemplate, SimulationObject, StatesTemplate
from pcse import signals

[docs] class phenology(SimulationObject): """Class to simulate phenology This class simulates the phenology of the crop from its emergence. Phenology is quantified as a temperature sum. The crop emerges if 1) the soil moisture content is above the permanent wilting point and 2) the crop is sown and fulfilled the thermal requirement to emergence after it has been planted. **Simulation parameters** ================= ============================================== ====== =========================== Name Description Type Unit ================= ============================================== ====== =========================== OPTEMERGTSUM Temperature sum from sowing to emergence in absence of water stress SCr |C| d TBASE Temperature below which there is no development possible SCr |C| SMW Soil moisture content at permanent wilting point. SCr cm3 water cm-3 soil ================= ============================================== ====== =========================== **State variables** ================= ============================================== ====== =========================== Name Description Pbl Unit ================= ============================================== ====== =========================== TSUM Temperature sum from sowing. Y |C| d TSUMCROP Temperature sum from emergence Y |C| d ================= ============================================== ====== =========================== **Rate variables** ================= ============================================== ====== =========================== Name Description Pbl Unit ================= ============================================== ====== =========================== RTSUM Rate of increase of temperature sum from sowing. N |C| RTSUMCROP Rate of increase of temperature sum from emergence N |C| ================= ============================================== ====== =========================== **Auxillary variables** ================= ============================================== ====== =========================== Name Description Pbl Unit ================= ============================================== ====== =========================== EMERG Indicates whether (=1) or not (=0) the crop has been emerged. Y - DTEFF Effective temperature for development Y |C| ================= ============================================== ====== =========================== """ class Parameters(ParamTemplate): OPTEMERGTSUM = Float() TBASE = Float() SMW = Float() CROP_START_TYPE = Enum(["sowing", "emergence"]) CROP_END_TYPE = Enum(["maturity", "harvest", "earliest"]) class RateVariables(RatesTemplate): RTSUM = Float() RTSUMCROP = Float() DTEFF = Float() class StateVariables(StatesTemplate): EMERG = Float() TSUM = Float() TSUMCROP = Float() DOS = Instance(datetime.date) # Day of sowing DOE = Instance(datetime.date) # Day of emergence DOH = Instance(datetime.date) # Day of harvest def initialize(self, day, kiosk, parameters): EMERG = 0. TSUM = 0. TSUMCROP = 0. self.kiosk = kiosk self.params = self.Parameters(parameters) self.rates = self.RateVariables(kiosk, publish = ["DTEFF"]) self.states = self.StateVariables( kiosk, publish=["EMERG", "TSUM", "TSUMCROP"], EMERG = EMERG, TSUM = TSUM, TSUMCROP = TSUMCROP, DOS=day, DOE=None, DOH=None ) self._connect_signal(self._on_CROP_FINISH, signal=signals.crop_finish) def calc_rates(self, day, drv, delt=1): k = self.kiosk p = self.params r = self.rates s = self.states DTEFF = max(0, drv.TEMP - p.TBASE) # Deg. C : effective daily temperature # -----------------------------------------EMERGENCE-----------------------------------------------# # emergence occurs (1) when the temperature sum exceeds the temperature sum needed for emergence. And (2) # when enough water is available in the soil. if (k.SM-p.SMW >= 0) & (k.TSUM-p.OPTEMERGTSUM >= 0): emerg1 = 1 else: emerg1 = 0 # once the crop is established is does not disappear again if s.TSUMCROP > 0: emerg2 = 1 else: emerg2 = 0 EMERG = max(emerg1, emerg2) # (-) RTSUM = DTEFF / delt # Emergence of the crop is used to calculate the temperature sum of the crop. RTSUMCROP = DTEFF * EMERG # Deg. C r.DTEFF = DTEFF r.RTSUM = RTSUM r.RTSUMCROP = RTSUMCROP s.EMERG = EMERG def integrate(self, day, delt = 1): r = self.rates s = self.states s.TSUM += r.RTSUM s.TSUMCROP += r.RTSUMCROP if s.EMERG > 0 and s.DOE is None: s.DOE = day #--------------------------------------------------------------------------- def _on_CROP_FINISH(self, day, finish_type=None): """Handler for setting day of harvest (DOH). Although DOH is not strictly related to phenology (but to management) this is the most logical place to put it. """ if finish_type in ['harvest', 'earliest']: self._for_finalize["DOH"] = day