| import numpy as np
|
|
|
| from ..entities.soilProfile import SoilProfile
|
|
|
|
|
| from typing import TYPE_CHECKING, Tuple
|
|
|
| if TYPE_CHECKING:
|
|
|
| from aquacrop.entities.soilProfile import SoilProfile
|
| from numpy import ndarray
|
|
|
| def infiltration(
|
| prof: "SoilProfile",
|
| NewCond_SurfaceStorage: float,
|
| NewCond_th_fc_Adj: "ndarray",
|
| NewCond_th: "ndarray",
|
| Infl: float,
|
| Irr: float,
|
| IrrMngt_AppEff: float,
|
| FieldMngt_Bunds: bool,
|
| FieldMngt_zBund: float,
|
| FluxOut: "ndarray",
|
| DeepPerc0: float,
|
| Runoff0: float,
|
| growing_season: bool,
|
| ) -> Tuple["ndarray", float, float, float, float, "ndarray"]:
|
| """
|
| Function to infiltrate incoming water (rainfall and irrigation)
|
|
|
| <a href="https://www.fao.org/3/BR248E/br248e.pdf#page=51" target="_blank">Reference Manual: drainage calculations</a> (pg. 42-65)
|
|
|
|
|
|
|
| Arguments:
|
|
|
|
|
|
|
| prof (SoilProfile): Soil object containing soil paramaters
|
|
|
| NewCond_SurfaceStorage (float): surface storage
|
|
|
| NewCond_th_fc_Adj (ndarray): water content at field capacity
|
|
|
| NewCond_th (ndarray): soil water content
|
|
|
| Infl (float): Infiltration so far
|
|
|
| Irr (float): Irrigation on current day
|
|
|
| IrrMngt_AppEff (float`: irrigation application efficiency
|
|
|
| FieldMngt (FieldMngtStruct): field management params
|
|
|
| FluxOut (np.array): flux of water out of each compartment
|
|
|
| DeepPerc0 (float): initial Deep Percolation
|
|
|
| Runoff0 (float): initial Surface Runoff
|
|
|
| growing_season (bool): is growing season (True or Flase)
|
|
|
|
|
| Returns:
|
|
|
| NewCond_th (nunpy.darray): updated soil water content
|
|
|
| NewCond_SurfaceStorage (float): updated surface storage
|
|
|
| DeepPerc (float): Total Deep Percolation
|
|
|
| RunoffTot (float): Total surface Runoff
|
|
|
| Infl (float): Infiltration on current day
|
|
|
| FluxOut (numpy.array): flux of water out of each compartment
|
|
|
|
|
|
|
|
|
| """
|
|
|
|
|
|
|
| InitCond_SurfaceStorage = NewCond_SurfaceStorage*1
|
| InitCond_th_fc_Adj = NewCond_th_fc_Adj*1
|
| InitCond_th = NewCond_th*1
|
|
|
| thnew = NewCond_th*1.
|
|
|
| Soil_nComp = thnew.shape[0]
|
|
|
| Infl = max(Infl,0.)
|
|
|
|
|
|
|
| if growing_season == True:
|
| Infl = Infl + (Irr * (IrrMngt_AppEff / 100))
|
|
|
| assert Infl >= 0
|
|
|
|
|
| if FieldMngt_Bunds:
|
|
|
| if FieldMngt_zBund > 0.001:
|
|
|
| InflTot = Infl + NewCond_SurfaceStorage
|
| if InflTot > 0:
|
|
|
| if InflTot > prof.Ksat[0]:
|
|
|
|
|
| ToStore = prof.Ksat[0]
|
|
|
| NewCond_SurfaceStorage = InflTot - prof.Ksat[0]
|
| else:
|
|
|
| ToStore = InflTot
|
|
|
| NewCond_SurfaceStorage = 0
|
|
|
|
|
| if NewCond_SurfaceStorage > FieldMngt_zBund:
|
|
|
| RunoffIni = NewCond_SurfaceStorage - FieldMngt_zBund
|
|
|
| NewCond_SurfaceStorage = FieldMngt_zBund * 1
|
| else:
|
|
|
| RunoffIni = 0
|
|
|
| else:
|
|
|
| ToStore = 0
|
| RunoffIni = 0
|
|
|
| elif FieldMngt_Bunds == False:
|
|
|
| if Infl > prof.Ksat[0]:
|
|
|
|
|
| ToStore = prof.Ksat[0]
|
|
|
| RunoffIni = Infl - prof.Ksat[0]
|
| else:
|
|
|
| ToStore = Infl
|
| RunoffIni = 0
|
|
|
|
|
| NewCond_SurfaceStorage = 0
|
|
|
|
|
| RunoffIni = RunoffIni + InitCond_SurfaceStorage
|
|
|
|
|
| ii = -1
|
| Runoff = 0
|
|
|
| if ToStore > 0:
|
| while (ToStore > 0) and (ii < Soil_nComp - 1):
|
|
|
| ii = ii + 1
|
|
|
|
|
|
|
| dthdtS = prof.tau[ii] * (prof.th_s[ii] - prof.th_fc[ii])
|
|
|
| factor = prof.Ksat[ii] / (dthdtS * 1000 * prof.dz[ii])
|
|
|
|
|
| dthdt0 = ToStore / (1000 * prof.dz[ii])
|
|
|
|
|
| if dthdt0 < dthdtS:
|
|
|
| if dthdt0 <= 0:
|
| theta0 = InitCond_th_fc_Adj[ii]
|
| else:
|
| A = 1 + (
|
| (dthdt0 * (np.exp(prof.th_s[ii] - prof.th_fc[ii]) - 1))
|
| / (prof.tau[ii] * (prof.th_s[ii] - prof.th_fc[ii]))
|
| )
|
|
|
| theta0 = prof.th_fc[ii] + np.log(A)
|
|
|
|
|
| if theta0 > prof.th_s[ii]:
|
| theta0 = prof.th_s[ii]
|
| elif theta0 <= InitCond_th_fc_Adj[ii]:
|
| theta0 = InitCond_th_fc_Adj[ii]
|
| dthdt0 = 0
|
|
|
| else:
|
|
|
| theta0 = prof.th_s[ii]
|
| dthdt0 = dthdtS
|
|
|
|
|
| drainmax = factor * dthdt0 * 1000 * prof.dz[ii]
|
|
|
| drainage = drainmax + FluxOut[ii]
|
|
|
| if drainage > prof.Ksat[ii]:
|
| drainmax = prof.Ksat[ii] - FluxOut[ii]
|
|
|
|
|
| diff = theta0 - InitCond_th[ii]
|
|
|
| if diff > 0:
|
|
|
| thnew[ii] = thnew[ii] + (ToStore / (1000 * prof.dz[ii]))
|
| if thnew[ii] > theta0:
|
|
|
| ToStore = (thnew[ii] - theta0) * 1000 * prof.dz[ii]
|
| thnew[ii] = theta0
|
| else:
|
|
|
| ToStore = 0
|
|
|
|
|
|
|
| FluxOut[ii] = FluxOut[ii] + ToStore
|
|
|
|
|
| excess = ToStore - drainmax
|
| if excess < 0:
|
| excess = 0
|
|
|
|
|
| ToStore = ToStore - excess
|
|
|
|
|
| if excess > 0:
|
| precomp = ii + 1
|
| while (excess > 0) and (precomp != 0):
|
|
|
|
|
|
|
| precomp = precomp - 1
|
|
|
|
|
|
|
| FluxOut[precomp] = FluxOut[precomp] - excess
|
|
|
| thnew[precomp] = thnew[precomp] + (excess / (prof.dz[precomp] * 1000))
|
|
|
| if thnew[precomp] > prof.th_s[precomp]:
|
|
|
| excess = (thnew[precomp] - prof.th_s[precomp]) * 1000 * prof.dz[precomp]
|
|
|
| thnew[precomp] = prof.th_s[precomp]
|
| else:
|
|
|
| excess = 0
|
|
|
| if excess > 0:
|
|
|
| Runoff = Runoff + excess
|
|
|
|
|
|
|
| DeepPerc = ToStore
|
| else:
|
|
|
| DeepPerc = 0
|
| Runoff = 0
|
|
|
|
|
| Runoff = Runoff + RunoffIni
|
|
|
|
|
| if Runoff > RunoffIni:
|
| if FieldMngt_Bunds:
|
| if FieldMngt_zBund > 0.001:
|
|
|
| NewCond_SurfaceStorage = NewCond_SurfaceStorage + (Runoff - RunoffIni)
|
|
|
| if NewCond_SurfaceStorage > FieldMngt_zBund:
|
|
|
| Runoff = RunoffIni + (NewCond_SurfaceStorage - FieldMngt_zBund)
|
|
|
| NewCond_SurfaceStorage = FieldMngt_zBund
|
| else:
|
|
|
| Runoff = RunoffIni
|
|
|
|
|
| NewCond_th = thnew
|
|
|
|
|
| DeepPerc = DeepPerc + DeepPerc0
|
| Infl = Infl - Runoff
|
| RunoffTot = Runoff + Runoff0
|
|
|
| return NewCond_th,NewCond_SurfaceStorage, DeepPerc, RunoffTot, Infl, FluxOut
|
|
|