| import numpy as np
|
|
|
| from ..entities.initParamVariables import InitialCondition
|
| from ..entities.modelConstants import ModelConstants
|
| from typing import Tuple, TYPE_CHECKING
|
|
|
| if TYPE_CHECKING:
|
|
|
| from aquacrop.entities.crop import Crop
|
| from aquacrop.entities.inititalWaterContent import InitialWaterContent
|
| from aquacrop.entities.clockStruct import ClockStruct
|
| from aquacrop.entities.paramStruct import ParamStruct
|
| from aquacrop.entities.initParamVariables import InitialCondition
|
|
|
|
|
| def read_model_initial_conditions(
|
| ParamStruct: "ParamStruct",
|
| ClockStruct: "ClockStruct",
|
| InitWC: "InitialWaterContent",
|
| crop: "Crop") -> Tuple["ParamStruct", "InitialCondition"]:
|
| """
|
| Function to set up initial model conditions
|
|
|
| Arguments:
|
|
|
| ParamStruct (ParamStruct): Contains model paramaters
|
|
|
| ClockStruct (ClockStruct): time paramaters
|
|
|
| InitWC (InitialWaterContent): initial water content
|
|
|
| crop (Crop): crop parameters
|
|
|
|
|
| Returns:
|
|
|
| ParamStruct (ParamStruct): updated ParamStruct object
|
|
|
| InitCond (InitialCondition): containing initial model conditions/counters
|
|
|
| """
|
|
|
|
|
|
|
|
|
|
|
| InitCond = InitialCondition(len(ParamStruct.Soil.profile))
|
|
|
|
|
|
|
|
|
| if ClockStruct.season_counter == -1:
|
| InitCond.z_root = 0.
|
| InitCond.cc0_adj = 0.
|
|
|
| elif ClockStruct.season_counter == 0:
|
| InitCond.z_root = ParamStruct.Seasonal_Crop_List[0].Zmin
|
| InitCond.cc0_adj = ParamStruct.Seasonal_Crop_List[0].CC0
|
|
|
|
|
| InitCond.HIfinal = crop.HI0
|
|
|
|
|
|
|
|
|
|
|
|
|
| if ClockStruct.season_counter == -1:
|
|
|
| if (ParamStruct.FallowFieldMngt.bunds) and (
|
| float(ParamStruct.FallowFieldMngt.z_bund) > 0.001
|
| ):
|
|
|
| InitCond.surface_storage = float(ParamStruct.FallowFieldMngt.bund_water)
|
| if InitCond.surface_storage > float(ParamStruct.FallowFieldMngt.z_bund):
|
| InitCond.surface_storage = float(ParamStruct.FallowFieldMngt.z_bund)
|
| else:
|
|
|
| InitCond.surface_storage = 0
|
|
|
| elif ClockStruct.season_counter == 0:
|
|
|
|
|
| FieldMngtTmp = ParamStruct.FieldMngt
|
| if (FieldMngtTmp.bunds) and (float(FieldMngtTmp.z_bund) > 0.001):
|
|
|
| InitCond.surface_storage = float(FieldMngtTmp.bund_water)
|
| if InitCond.surface_storage > float(FieldMngtTmp.z_bund):
|
| InitCond.surface_storage = float(FieldMngtTmp.z_bund)
|
| else:
|
|
|
| InitCond.surface_storage = 0
|
|
|
|
|
|
|
|
|
|
|
| profile = ParamStruct.Soil.profile
|
|
|
|
|
| if ParamStruct.water_table == 0:
|
|
|
| InitCond.z_gw = ModelConstants.NO_VALUE
|
| InitCond.wt_in_soil = False
|
|
|
| InitCond.th_fc_Adj = profile.th_fc.values
|
| elif ParamStruct.water_table == 1:
|
|
|
| InitCond.z_gw = float(ParamStruct.z_gw[ClockStruct.time_step_counter])
|
|
|
| zMid = profile.zMid
|
|
|
| if InitCond.z_gw >= 0:
|
| idx = zMid[zMid >= InitCond.z_gw].index
|
| if idx.shape[0] == 0:
|
| InitCond.wt_in_soil = False
|
| else:
|
| InitCond.wt_in_soil = True
|
| else:
|
| InitCond.wt_in_soil = False
|
|
|
|
|
| compi = int(len(profile)) - 1
|
| thfcAdj = np.zeros(compi + 1)
|
| while compi >= 0:
|
|
|
| compdf = profile.loc[compi]
|
| if compdf.th_fc <= 0.1:
|
| Xmax = 1
|
| else:
|
| if compdf.th_fc >= 0.3:
|
| Xmax = 2
|
| else:
|
| pF = 2 + 0.3 * (compdf.th_fc - 0.1) / 0.2
|
| Xmax = (np.exp(pF * np.log(10))) / 100
|
|
|
| if (InitCond.z_gw < 0) or ((InitCond.z_gw - zMid.iloc[compi]) >= Xmax):
|
| for ii in range(compi+1):
|
| compdfii = profile.loc[ii]
|
| thfcAdj[ii] = compdfii.th_fc
|
|
|
| compi = -1
|
| else:
|
| if compdf.th_fc >= compdf.th_s:
|
| thfcAdj[compi] = compdf.th_fc
|
| else:
|
| if zMid.iloc[compi] >= InitCond.z_gw:
|
| thfcAdj[compi] = compdf.th_s
|
| else:
|
| dV = compdf.th_s - compdf.th_fc
|
| dFC = (dV / (Xmax ** 2)) * ((zMid.iloc[compi] - (InitCond.z_gw - Xmax)) ** 2)
|
| thfcAdj[compi] = compdf.th_fc + dFC
|
|
|
| compi = compi - 1
|
|
|
|
|
| InitCond.th_fc_Adj = np.round(thfcAdj, 3)
|
|
|
| profile["th_fc_Adj"] = np.round(InitCond.th_fc_Adj, 3)
|
|
|
|
|
| ParamStruct.Soil.Hydrology = profile.groupby("Layer").mean().drop(["dz", "dzsum"], axis=1)
|
| ParamStruct.Soil.Hydrology["dz"] = profile.groupby("Layer").sum().dz
|
|
|
|
|
|
|
|
|
|
|
| typestr = InitWC.wc_type
|
| methodstr = InitWC.method
|
|
|
| depth_layer = InitWC.depth_layer
|
| datapoints = InitWC.value
|
|
|
| values = np.zeros(len(datapoints))
|
|
|
| hydf = ParamStruct.Soil.Hydrology
|
|
|
|
|
| if typestr == "Num":
|
|
|
| depth_layer = np.array(depth_layer, dtype=float)
|
| values = np.array(datapoints, dtype=float)
|
|
|
| elif typestr == "Pct":
|
|
|
|
|
| depth_layer = np.array(depth_layer, dtype=float)
|
| datapoints = np.array(datapoints, dtype=float)
|
|
|
| for ii in range(len(values)):
|
| if methodstr == "Depth":
|
| depth = depth_layer[ii]
|
| value = datapoints[ii]
|
|
|
|
|
| if depth < profile.dzsum.iloc[-1]:
|
| layer = profile.query(f"{depth}<dzsum").Layer.iloc[0]
|
| else:
|
| layer = profile.Layer.iloc[-1]
|
|
|
| compdf = hydf.loc[layer]
|
|
|
|
|
| values[ii] = compdf.th_wp + ((value / 100) * (compdf.th_fc - compdf.th_wp))
|
| elif methodstr == "Layer":
|
|
|
| layer = depth_layer[ii]
|
| value = datapoints[ii]
|
|
|
| compdf = hydf.loc[layer]
|
|
|
| values[ii] = compdf.th_wp + ((value / 100) * (compdf.th_fc - compdf.th_wp))
|
|
|
| elif typestr == "Prop":
|
|
|
|
|
| depth_layer = np.array(depth_layer, dtype=float)
|
| datapoints = np.array(datapoints, dtype=str)
|
|
|
| for ii in range(len(values)):
|
| if methodstr == "Depth":
|
|
|
| depth = depth_layer[ii]
|
| value = datapoints[ii]
|
|
|
|
|
| if depth < profile.dzsum.iloc[-1]:
|
| layer = profile.query(f"{depth}<dzsum").Layer.iloc[0]
|
| else:
|
| layer = profile.Layer.iloc[-1]
|
|
|
| compdf = hydf.loc[layer]
|
|
|
|
|
| if value == "SAT":
|
| values[ii] = compdf.th_s
|
| if value == "FC":
|
| values[ii] = compdf.th_fc
|
| if value == "WP":
|
| values[ii] = compdf.th_wp
|
|
|
| elif methodstr == "Layer":
|
|
|
| layer = depth_layer[ii]
|
| value = datapoints[ii]
|
|
|
| compdf = hydf.loc[layer]
|
|
|
| if value == "SAT":
|
| values[ii] = compdf.th_s
|
| if value == "FC":
|
| values[ii] = compdf.th_fc
|
| if value == "WP":
|
| values[ii] = compdf.th_wp
|
|
|
|
|
|
|
| thini = np.zeros(int(profile.shape[0]))
|
| if methodstr == "Layer":
|
| for ii in range(len(values)):
|
| layer = depth_layer[ii]
|
| value = values[ii]
|
|
|
| idx = profile.query(f"Layer=={int(layer)}").index
|
|
|
| thini[idx] = value
|
|
|
| InitCond.th = thini
|
|
|
| elif methodstr == "Depth":
|
| depths = depth_layer
|
|
|
|
|
| if depths[0] > 0:
|
| depths = np.append([0], depths)
|
| values = np.append([values[0]], values)
|
|
|
|
|
| if depths[-1] < ParamStruct.Soil.zSoil:
|
| depths = np.append(depths, [ParamStruct.Soil.zSoil])
|
| values = np.append(values, [values[-1]])
|
|
|
|
|
| SoilDepths = profile.dzsum.values
|
| comp_top = np.append([0], SoilDepths[:-1])
|
| comp_bot = SoilDepths
|
| comp_mid = (comp_top + comp_bot) / 2
|
|
|
| thini = np.interp(comp_mid, depths, values)
|
| InitCond.th = thini
|
|
|
|
|
|
|
|
|
| if ParamStruct.water_table == 1:
|
| if (typestr == "Prop") and (datapoints[-1] == "FC"):
|
| InitCond.th = InitCond.th_fc_Adj
|
|
|
|
|
|
|
| if InitCond.wt_in_soil is True:
|
|
|
| SoilDepths = profile.dzsum.values
|
| comp_top = np.append([0], SoilDepths[:-1])
|
| comp_bot = SoilDepths
|
| comp_mid = (comp_top + comp_bot) / 2
|
| idx = np.where(comp_mid >= InitCond.z_gw)[0][0]
|
| for ii in range(idx, len(profile)):
|
| layeri = profile.loc[ii].Layer
|
| InitCond.th[ii] = hydf.th_s.loc[layeri]
|
|
|
| InitCond.thini = InitCond.th
|
|
|
| ParamStruct.Soil.profile = profile
|
| ParamStruct.Soil.Hydrology = hydf
|
|
|
| return ParamStruct, InitCond
|
|
|
|
|