|
|
| import os
|
| import numpy as np
|
|
|
| from ..entities.totalAvailableWater import TAW
|
| from ..entities.moistureDepletion import Dr
|
|
|
| from ..entities.waterStressCoefficients import Ksw
|
| from .adjust_CCx import adjust_CCx
|
|
|
|
|
| from .water_stress import water_stress
|
| from .root_zone_water import root_zone_water
|
| from .cc_development import cc_development
|
| from .update_CCx_CDC import update_CCx_CDC
|
| from .cc_required_time import cc_required_time
|
|
|
|
|
| from typing import NamedTuple, Tuple, TYPE_CHECKING
|
|
|
| if TYPE_CHECKING:
|
|
|
| from aquacrop.entities.initParamVariables import InitialCondition
|
| from aquacrop.entities.soilProfile import SoilProfile
|
| from aquacrop.entities.crop import CropStruct
|
|
|
| def canopy_cover(
|
| Crop: "CropStruct",
|
| prof: "SoilProfile",
|
| Soil_zTop: float,
|
| InitCond: "InitialCondition",
|
| gdd: float,
|
| et0: float,
|
| growing_season: bool,
|
| ):
|
|
|
|
|
| """
|
| Function to simulate canopy growth/decline
|
|
|
| <a href="https://www.fao.org/3/BR248E/br248e.pdf#page=30" target="_blank">Reference Manual: canopy_cover equations</a> (pg. 21-33)
|
|
|
|
|
| Arguments:
|
|
|
| Crop (CropStruct): Crop object
|
|
|
| prof (SoilProfile): SoilProfile object
|
|
|
| Soil_zTop (float): top soil depth
|
|
|
| InitCond (InitialCondition): InitCond object
|
|
|
| gdd (float): Growing Degree Days
|
|
|
| et0 (float): reference evapotranspiration
|
|
|
| growing_season (bool): is it currently within the growing season (True, Flase)
|
|
|
| Returns:
|
|
|
| NewCond (InitialCondition): updated InitCond object
|
|
|
|
|
| """
|
|
|
|
|
|
|
| InitCond_CC_NS = InitCond.canopy_cover_ns
|
| InitCond_CC = InitCond.canopy_cover
|
| InitCond_ProtectedSeed = InitCond.protected_seed
|
| InitCond_CCxAct = InitCond.ccx_act
|
| InitCond_CropDead = InitCond.crop_dead
|
| InitCond_tEarlySen = InitCond.t_early_sen
|
| InitCond_CCxW = InitCond.ccx_w
|
|
|
|
|
| NewCond = InitCond
|
| NewCond.cc_prev = InitCond.canopy_cover
|
|
|
|
|
| if growing_season == True:
|
|
|
| taw = TAW()
|
| root_zone_depletion = Dr()
|
|
|
| _, root_zone_depletion.Zt, root_zone_depletion.Rz, taw.Zt, taw.Rz, _,_,_,_,_,_ = root_zone_water(
|
| prof,
|
| float(NewCond.z_root),
|
| NewCond.th,
|
| Soil_zTop,
|
| float(Crop.Zmin),
|
| Crop.Aer,
|
| )
|
|
|
|
|
|
|
|
|
| if (root_zone_depletion.Rz / taw.Rz) <= (root_zone_depletion.Zt / taw.Zt):
|
|
|
| root_zone_depletion = root_zone_depletion.Rz
|
| taw = taw.Rz
|
| else:
|
|
|
| root_zone_depletion = root_zone_depletion.Zt
|
| taw = taw.Zt
|
|
|
|
|
| beta = True
|
| water_stress_coef = Ksw()
|
| water_stress_coef.exp, water_stress_coef.sto, water_stress_coef.sen, water_stress_coef.pol, water_stress_coef.sto_lin = water_stress(
|
| Crop.p_up,
|
| Crop.p_lo,
|
| Crop.ETadj,
|
| Crop.beta,
|
| Crop.fshape_w,
|
| NewCond.t_early_sen,
|
| root_zone_depletion,
|
| taw,
|
| et0,
|
| beta,
|
| )
|
|
|
|
|
|
|
|
|
| if Crop.CalendarType == 1:
|
| dtCC = 1
|
| tCCadj = NewCond.dap - NewCond.delayed_cds
|
| elif Crop.CalendarType == 2:
|
| dtCC = gdd
|
| tCCadj = NewCond.gdd_cum - NewCond.delayed_gdds
|
|
|
|
|
| if (tCCadj < Crop.Emergence) or (round(tCCadj) > Crop.Maturity):
|
|
|
|
|
| NewCond.canopy_cover_ns = 0
|
|
|
| elif tCCadj < Crop.CanopyDevEnd:
|
|
|
| if InitCond_CC_NS <= Crop.CC0:
|
|
|
| NewCond.canopy_cover_ns = Crop.CC0 * np.exp(Crop.CGC * dtCC)
|
|
|
| else:
|
|
|
| tmp_tCC = tCCadj - Crop.Emergence
|
| NewCond.canopy_cover_ns = cc_development(
|
| Crop.CC0, 0.98 * Crop.CCx, Crop.CGC, Crop.CDC, tmp_tCC, "Growth", Crop.CCx
|
| )
|
|
|
|
|
| NewCond.ccx_act_ns = NewCond.canopy_cover_ns
|
| elif tCCadj > Crop.CanopyDevEnd:
|
|
|
|
|
| NewCond.ccx_w_ns = NewCond.ccx_act_ns
|
| if tCCadj < Crop.Senescence:
|
|
|
| NewCond.canopy_cover_ns = InitCond_CC_NS
|
|
|
| NewCond.ccx_act_ns = NewCond.canopy_cover_ns
|
| else:
|
|
|
| tmp_tCC = tCCadj - Crop.Senescence
|
| NewCond.canopy_cover_ns = cc_development(
|
| Crop.CC0,
|
| NewCond.ccx_act_ns,
|
| Crop.CGC,
|
| Crop.CDC,
|
| tmp_tCC,
|
| "Decline",
|
| NewCond.ccx_act_ns,
|
| )
|
|
|
|
|
| if (tCCadj < Crop.Emergence) or (round(tCCadj) > Crop.Maturity):
|
|
|
|
|
| NewCond.canopy_cover = 0
|
| NewCond.cc0_adj = Crop.CC0
|
| elif tCCadj < Crop.CanopyDevEnd:
|
|
|
| if InitCond_CC <= NewCond.cc0_adj or (
|
| (InitCond_ProtectedSeed == True) and (InitCond_CC <= (1.25 * NewCond.cc0_adj))
|
| ):
|
|
|
|
|
| if InitCond_ProtectedSeed == True:
|
| tmp_tCC = tCCadj - Crop.Emergence
|
| NewCond.canopy_cover = cc_development(
|
| Crop.CC0, Crop.CCx, Crop.CGC, Crop.CDC, tmp_tCC, "Growth", Crop.CCx
|
| )
|
|
|
| if NewCond.canopy_cover > (1.25 * NewCond.cc0_adj):
|
|
|
|
|
| NewCond.protected_seed = False
|
|
|
| else:
|
| NewCond.canopy_cover = NewCond.cc0_adj * np.exp(Crop.CGC * dtCC)
|
|
|
| else:
|
|
|
| if InitCond_CC < (0.9799 * Crop.CCx):
|
|
|
|
|
| CGCadj = Crop.CGC * water_stress_coef.exp
|
| if CGCadj > 0:
|
|
|
|
|
| CCXadj = adjust_CCx(
|
| InitCond_CC,
|
| NewCond.cc0_adj,
|
| Crop.CCx,
|
| CGCadj,
|
| Crop.CDC,
|
| dtCC,
|
| tCCadj,
|
| Crop.CanopyDevEnd,
|
| Crop.CCx,
|
| )
|
| if CCXadj < 0:
|
|
|
| NewCond.canopy_cover = InitCond_CC
|
| elif abs(InitCond_CC - (0.9799 * Crop.CCx)) < 0.001:
|
|
|
|
|
| tmp_tCC = tCCadj - Crop.Emergence
|
| NewCond.canopy_cover = cc_development(
|
| Crop.CC0, Crop.CCx, Crop.CGC, Crop.CDC, tmp_tCC, "Growth", Crop.CCx
|
| )
|
| else:
|
|
|
|
|
|
|
| tReq = cc_required_time(
|
| InitCond_CC, NewCond.cc0_adj, CCXadj, CGCadj, Crop.CDC, "CGC"
|
| )
|
| if tReq > 0:
|
|
|
|
|
| tmp_tCC = tReq + dtCC
|
|
|
| NewCond.canopy_cover = cc_development(
|
| NewCond.cc0_adj,
|
| CCXadj,
|
| CGCadj,
|
| Crop.CDC,
|
| tmp_tCC,
|
| "Growth",
|
| Crop.CCx,
|
| )
|
|
|
|
|
| else:
|
|
|
| NewCond.canopy_cover = InitCond_CC
|
|
|
| else:
|
|
|
| NewCond.canopy_cover = InitCond_CC
|
|
|
| if NewCond.canopy_cover > NewCond.cc0_adj:
|
| NewCond.cc0_adj = Crop.CC0
|
| else:
|
| NewCond.cc0_adj = NewCond.canopy_cover
|
|
|
| else:
|
|
|
| tmp_tCC = tCCadj - Crop.Emergence
|
| NewCond.canopy_cover = cc_development(
|
| Crop.CC0, Crop.CCx, Crop.CGC, Crop.CDC, tmp_tCC, "Growth", Crop.CCx
|
| )
|
| NewCond.cc0_adj = Crop.CC0
|
|
|
| if NewCond.canopy_cover > InitCond_CCxAct:
|
|
|
| NewCond.ccx_act = NewCond.canopy_cover
|
|
|
| elif tCCadj > Crop.CanopyDevEnd:
|
|
|
| if tCCadj < Crop.Senescence:
|
|
|
| NewCond.canopy_cover = InitCond_CC
|
| if NewCond.canopy_cover > InitCond_CCxAct:
|
|
|
|
|
| NewCond.ccx_act = NewCond.canopy_cover
|
|
|
| else:
|
|
|
|
|
|
|
| CDCadj = Crop.CDC * ((NewCond.ccx_act + 2.29) / (Crop.CCx + 2.29))
|
|
|
| tmp_tCC = tCCadj - Crop.Senescence
|
| NewCond.canopy_cover = cc_development(
|
| NewCond.cc0_adj,
|
| NewCond.ccx_act,
|
| Crop.CGC,
|
| CDCadj,
|
| tmp_tCC,
|
| "Decline",
|
| NewCond.ccx_act,
|
| )
|
|
|
|
|
| if (NewCond.canopy_cover < 0.001) and (InitCond_CropDead == False):
|
|
|
| NewCond.canopy_cover = 0
|
| NewCond.crop_dead = True
|
|
|
|
|
| if tCCadj >= Crop.Emergence:
|
| if (tCCadj < Crop.Senescence) or (InitCond_tEarlySen > 0):
|
|
|
|
|
| if (water_stress_coef.sen < 1) and (InitCond_ProtectedSeed == False):
|
|
|
|
|
| NewCond.premat_senes = True
|
| if InitCond_tEarlySen == 0:
|
|
|
| NewCond.ccx_early_sen = InitCond_CC
|
|
|
|
|
| NewCond.t_early_sen = InitCond_tEarlySen + dtCC
|
|
|
| beta = False
|
|
|
| water_stress_coef = Ksw()
|
| water_stress_coef.exp, water_stress_coef.sto, water_stress_coef.sen, water_stress_coef.pol, water_stress_coef.sto_lin = water_stress(
|
| Crop.p_up,
|
| Crop.p_lo,
|
| Crop.ETadj,
|
| Crop.beta,
|
| Crop.fshape_w,
|
| NewCond.t_early_sen,
|
| root_zone_depletion,
|
| taw,
|
| et0,
|
| beta,
|
| )
|
|
|
|
|
| if water_stress_coef.sen > 0.99999:
|
| CDCadj = 0.0001
|
| else:
|
| CDCadj = (1 - (water_stress_coef.sen ** 8)) * Crop.CDC
|
|
|
|
|
| if NewCond.ccx_early_sen < 0.001:
|
| CCsen = 0
|
| else:
|
|
|
|
|
| tReq = (np.log(1 + (1 - InitCond_CC / NewCond.ccx_early_sen) / 0.05)) / (
|
| (CDCadj * 3.33) / (NewCond.ccx_early_sen + 2.29)
|
| )
|
|
|
| tmp_tCC = tReq + dtCC
|
|
|
| CCsen = NewCond.ccx_early_sen * (
|
| 1
|
| - 0.05
|
| * (
|
| np.exp(tmp_tCC * ((CDCadj * 3.33) / (NewCond.ccx_early_sen + 2.29)))
|
| - 1
|
| )
|
| )
|
| if CCsen < 0:
|
| CCsen = 0
|
|
|
|
|
| if tCCadj < Crop.Senescence:
|
|
|
| if CCsen > Crop.CCx:
|
| CCsen = Crop.CCx
|
|
|
|
|
| NewCond.canopy_cover = CCsen
|
| if NewCond.canopy_cover > InitCond_CC:
|
| NewCond.canopy_cover = InitCond_CC
|
|
|
|
|
|
|
| NewCond.ccx_act = NewCond.canopy_cover
|
|
|
|
|
| if NewCond.canopy_cover < Crop.CC0:
|
| NewCond.cc0_adj = NewCond.canopy_cover
|
| else:
|
| NewCond.cc0_adj = Crop.CC0
|
|
|
| else:
|
|
|
|
|
| if CCsen < NewCond.canopy_cover:
|
| NewCond.canopy_cover = CCsen
|
|
|
|
|
| if (NewCond.canopy_cover < 0.001) and (InitCond_CropDead == False):
|
|
|
| NewCond.canopy_cover = 0
|
| NewCond.crop_dead = True
|
|
|
| else:
|
|
|
| NewCond.premat_senes = False
|
| if (tCCadj > Crop.Senescence) and (InitCond_tEarlySen > 0):
|
|
|
|
|
| tmp_tCC = tCCadj - dtCC - Crop.Senescence
|
| CCXadj, CDCadj = update_CCx_CDC(InitCond_CC, Crop.CDC, Crop.CCx, tmp_tCC)
|
| NewCond.ccx_act = CCXadj
|
|
|
| tmp_tCC = tCCadj - Crop.Senescence
|
| NewCond.canopy_cover = cc_development(
|
| NewCond.cc0_adj, CCXadj, Crop.CGC, CDCadj, tmp_tCC, "Decline", CCXadj
|
| )
|
|
|
| if (NewCond.canopy_cover < 0.001) and (InitCond_CropDead == False):
|
| NewCond.canopy_cover = 0
|
| NewCond.crop_dead = True
|
|
|
|
|
| NewCond.t_early_sen = 0
|
|
|
|
|
| if NewCond.canopy_cover > InitCond_CCxW:
|
| NewCond.ccx_w = NewCond.canopy_cover
|
|
|
|
|
|
|
| if NewCond.canopy_cover_ns < NewCond.canopy_cover:
|
| NewCond.canopy_cover_ns = NewCond.canopy_cover
|
| if tCCadj < Crop.CanopyDevEnd:
|
| NewCond.ccx_act_ns = NewCond.canopy_cover_ns
|
|
|
|
|
| NewCond.canopy_cover_adj = (1.72 * NewCond.canopy_cover) - (NewCond.canopy_cover ** 2) + (0.3 * (NewCond.canopy_cover ** 3))
|
|
|
| NewCond.canopy_cover_adj_ns = (
|
| (1.72 * NewCond.canopy_cover_ns) - (NewCond.canopy_cover_ns ** 2) + (0.3 * (NewCond.canopy_cover_ns ** 3))
|
| )
|
|
|
| else:
|
|
|
| NewCond.canopy_cover = 0
|
| NewCond.canopy_cover_adj = 0
|
| NewCond.canopy_cover_ns = 0
|
| NewCond.canopy_cover_adj_ns = 0
|
| NewCond.ccx_w = 0
|
| NewCond.ccx_act = 0
|
| NewCond.ccx_w_ns = 0
|
| NewCond.ccx_act_ns = 0
|
|
|
| return NewCond
|
|
|
|
|