HydPy-GA (base model)¶
The HydPy-GA base model provides features to implement infiltration methods based on Green & Ampt-like wetting fronts.
Method Features¶
- class hydpy.models.ga.ga_model.Model[source]¶
Bases:
AdHocModel
HydPy-GA (base model).
- The following “run methods” are called in the given sequence during each simulation step:
Calc_SurfaceWaterSupply_V1
Take rainfall as the possible supply for infiltration through the soil’s surface.Calc_SoilWaterSupply_V1
Take capillary rise as the possible supply for water additions through the soil’s bottom.Calc_Demand_V1
Take evaporation as the demand for extracting water from the soil’s surface and body.Perform_GARTO_V1
Perform the GARTO algorithm for the numerical substeps and aggregate their results.Calc_TotalInfiltration_V1
Calculate the average infiltration from all soil compartments.Calc_TotalPercolation_V1
Calculate the average percolation from all soil compartments.Calc_TotalSoilWaterAddition_V1
Calculate the average soil water addition to all soil compartments.Calc_TotalWithdrawal_V1
Calculate the average withdrawal from all soil compartments.Calc_TotalSurfaceRunoff_V1
Calculate the average surface runoff from all soil compartments.
- The following interface methods are available to main models using the defined model as a submodel:
Set_InitialSurfaceWater_V1
Set the given initial surface water depth for the selected soil compartment.Set_ActualSurfaceWater_V1
Set the given actual surface water depth for the selected soil compartment.Set_SoilWaterSupply_V1
Set the (potential) water supply to the soil’s body.Set_SoilWaterDemand_V1
Set the (potential) water withdrawal from the soil’s surface and body.Execute_Infiltration_V1
Calculate infiltration (and percolation).Add_SoilWater_V1
Add the (direct) soil water supply to the soil’s body.Remove_SoilWater_V1
Remove the water demand from the soil’s body and eventually from the soil’s surface.Get_Infiltration_V1
Get the current infiltration to the selected soil compartment.Get_Percolation_V1
Get the current percolation from the selected soil compartment.Get_SoilWaterAddition_V1
Get the current soil water addition to the selected soil compartment.Get_SoilWaterRemoval_V1
Get the current soil (and surface water) withdrawal from the selected soil compartment.Get_SoilWaterContent_V1
Get the current soil water content of the selected soil compartment.
- The following “additional methods” might be called by one or more of the other methods or are meant to be directly called by the user:
Return_RelativeMoisture_V1
Calculate and return the relative soil water content for the given bin-soil combination.Return_Conductivity_V1
Based on the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966), calculate and return the conductivity for the given bin-soil combination.Return_CapillaryDrive_V1
Based on the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966), calculate and return the capillary drive between the water contents of the given bins for the defined soil.Return_DryDepth_V1
Calculate and return the “dry depth”.Return_LastActiveBin_V1
Find the index of the last active bin (that either contains a wetting front or uniform moisture over the complete soil depth).Active_Bin_V1
Activate a bin to the right of the bin with the given index.Percolate_FilledBin_V1
Calculate the percolation of water through the filled first bin due to gravitational forcing.Shift_Front_V1
Increase the selected bin’s wetting front depth without modifying its relative moisture following a variation of the Talbot-Ogden equation (Talbot and Ogden, 2008).Redistribute_Front_V1
Modify the selected bin’s wetting front depth and relative moisture content based on a Green & Ampt redistribution equation.Infiltrate_WettingFrontBins_V1
Process infiltration into the wetting front bins.Merge_FrontDepthOvershootings_V1
Merge those neighbour bins where the wetting front’s depth of the right neighbour exceeds the wetting front’s depth of the left neighbour.Merge_SoilDepthOvershootings_V1
Merge bins with wetting front depth larger than soil depth with their left neighbour bins and add their water excess to percolation.Water_AllBins_V1
Water the soil’s body by (potentially) adding water to all active bins.Withdraw_AllBins_V1
Take withdrawal from the available surface water and (potentially) from all active bins.
- REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()¶
- class hydpy.models.ga.ga_model.Calc_SurfaceWaterSupply_V1[source]¶
Bases:
Method
Take rainfall as the possible supply for infiltration through the soil’s surface.
- Requires the control parameter:
- Requires the input sequence:
- Calculates the flux sequence:
- Basic equation:
\(SurfaceWaterSupply = Rainfall\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> inputs.rainfall = 2.0 >>> model.calc_surfacewatersupply_v1() >>> fluxes.surfacewatersupply surfacewatersupply(2.0, 2.0)
- class hydpy.models.ga.ga_model.Calc_SoilWaterSupply_V1[source]¶
Bases:
Method
Take capillary rise as the possible supply for water additions through the soil’s bottom.
- Requires the control parameter:
- Requires the input sequence:
- Calculates the flux sequence:
- Basic equation:
\(SoilWaterSupply = CapillaryRise\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> inputs.capillaryrise = 2.0 >>> model.calc_soilwatersupply_v1() >>> fluxes.soilwatersupply soilwatersupply(2.0, 2.0)
- class hydpy.models.ga.ga_model.Calc_Demand_V1[source]¶
Bases:
Method
- Take evaporation as the demand for extracting water from the soil’s surface and
body.
- Requires the control parameter:
- Requires the input sequence:
- Calculates the flux sequence:
- Basic equation:
\(Demand = Evaporation\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> inputs.evaporation = 2.0 >>> model.calc_demand_v1() >>> fluxes.demand demand(2.0, 2.0)
- class hydpy.models.ga.ga_model.Return_RelativeMoisture_V1[source]¶
Bases:
Method
Calculate and return the relative soil water content for the given bin-soil combination.
- Required by the methods:
Infiltrate_WettingFrontBins_V1
Percolate_FilledBin_V1
Redistribute_Front_V1
Return_CapillaryDrive_V1
Return_Conductivity_V1
Shift_Front_V1
- Requires the control parameters:
- Requires the state sequence:
- Basic equation (Lai et al. (2015), equation 11):
\(RelativeMoisture = \frac{FrontMoisture - ResidualMoisture}{SaturationMoisture - ResidualMoisture}\)
Method
Return_RelativeMoisture_V1
prevents returning values smaller than zero or larger than one that might arise due to violations of the residualor saturation water content.Examples:
>>> from hydpy.models.ga import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(2) >>> nmbbins(5) >>> residualmoisture(0.1, 0.2) >>> saturationmoisture(0.5, 0.8) >>> states.moisture = [[0.0, 0.0], ... [0.1, 0.2], ... [0.3, 0.65], ... [0.5, 0.8], ... [1.0, 1.0]] >>> from hydpy import round_ >>> for soil in range(2): ... for bin_ in range(5): ... print(f"soil: {soil}, bin: {bin_} -> relativemoisture ", end="") ... round_(model.return_relativemoisture_v1(bin_, soil)) soil: 0, bin: 0 -> relativemoisture 0.0 soil: 0, bin: 1 -> relativemoisture 0.0 soil: 0, bin: 2 -> relativemoisture 0.5 soil: 0, bin: 3 -> relativemoisture 1.0 soil: 0, bin: 4 -> relativemoisture 1.0 soil: 1, bin: 0 -> relativemoisture 0.0 soil: 1, bin: 1 -> relativemoisture 0.0 soil: 1, bin: 2 -> relativemoisture 0.75 soil: 1, bin: 3 -> relativemoisture 1.0 soil: 1, bin: 4 -> relativemoisture 1.0
- class hydpy.models.ga.ga_model.Return_Conductivity_V1[source]¶
Bases:
Method
Based on the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966), calculate and return the conductivity for the given bin-soil combination.
- Required by the methods:
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Percolate_FilledBin_V1
Perform_GARTO_V1
Redistribute_Front_V1
Shift_Front_V1
- Required submethod:
- Requires the control parameters:
ResidualMoisture
SaturationMoisture
SaturatedConductivity
PoreSizeDistribution
- Requires the state sequence:
- Basic equation (Lai et al. (2015), equation 11):
\(Conductivity = SaturatedConductivity \cdot RelativeMoisture^{3 + 2 / PoreSizeDistribution}\)
Examples:
>>> from hydpy.models.ga import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(2) >>> nmbbins(3) >>> residualmoisture(0.1, 0.2) >>> saturationmoisture(0.5, 0.8) >>> poresizedistribution(0.3, 0.4) >>> saturatedconductivity(10.0, 20.0) >>> states.moisture = [[0.1, 0.0], ... [0.3, 0.5], ... [0.5, 1.0]] >>> from hydpy import round_ >>> for soil in range(2): ... for bin_ in range(3): ... print(f"soil: {soil}, bin: {bin_} -> conductivity ", end="") ... round_(model.return_conductivity_v1(bin_, soil)) soil: 0, bin: 0 -> conductivity 0.0 soil: 0, bin: 1 -> conductivity 0.012304 soil: 0, bin: 2 -> conductivity 10.0 soil: 1, bin: 0 -> conductivity 0.0 soil: 1, bin: 1 -> conductivity 0.078125 soil: 1, bin: 2 -> conductivity 20.0
- class hydpy.models.ga.ga_model.Return_CapillaryDrive_V1[source]¶
Bases:
Method
Based on the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966), calculate and return the capillary drive between the water contents of the given bins for the defined soil.
- Required by the methods:
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Perform_GARTO_V1
Redistribute_Front_V1
Shift_Front_V1
- Required submethod:
- Requires the control parameters:
ResidualMoisture
SaturationMoisture
AirEntryPotential
PoreSizeDistribution
- Requires the state sequence:
- Basic equation (Lai et al. (2015), equation 11):
\(CapillaryDrive_{bin1,bin2} = \frac{AirEntryPotential}{3 \cdot PoreSizeDistribution + 1} \cdot \begin{cases} RelativeMoisture_{bin2}^{3 + 1 / PoreSizeDistribution} - RelativeMoisture_{bin1}^{3 + 1 / PoreSizeDistribution} &|\ Moisture_{bin2} < SaturationMoisture \\ 3 \cdot PoreSizeDistribution + 2 - RelativeMoisture_{bin1}^{3 + 1 / PoreSizeDistribution} &|\ Moisture_{bin2} = SaturationMoisture \end{cases}\)
Examples:
>>> from hydpy.models.ga import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(2) >>> nmbbins(3) >>> residualmoisture(0.1, 0.2) >>> saturationmoisture(0.5, 0.8) >>> airentrypotential(0.1, 0.2) >>> poresizedistribution(0.3, 0.4) >>> saturatedconductivity(10.0, 20.0) >>> states.moisture = [[0.1, 0.0], ... [0.3, 0.5], ... [0.5, 1.0]] >>> from hydpy import round_ >>> for soil in range(2): ... for bin_ in range(2): ... print(f"soil: {soil}, bin: {bin_} -> capillarydrive ", end="") ... round_(model.return_capillarydrive_v1(bin_, bin_ + 1, soil)) soil: 0, bin: 0 -> capillarydrive 0.000653 soil: 0, bin: 1 -> capillarydrive 0.151979 soil: 1, bin: 0 -> capillarydrive 0.002009 soil: 1, bin: 1 -> capillarydrive 0.2889
- class hydpy.models.ga.ga_model.Percolate_FilledBin_V1[source]¶
Bases:
Method
Calculate the percolation of water through the filled first bin due to gravitational forcing.
- Required by the methods:
- Required submethods:
- Requires the control parameters:
DT
SoilDepth
ResidualMoisture
SaturationMoisture
SaturatedConductivity
PoreSizeDistribution
- Requires the state sequence:
- Updates the flux sequence:
- Updates the state sequence:
- Updates the aide sequence:
- Basic equation:
\(Percolation = DT \cdot Conductivity\)
Example:
For simplicity, we make each soil compartment’s first (and only) bin saturated so that actual conductivity equals saturated conductivity:
>>> from hydpy.models.ga import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(3) >>> nmbbins(2) >>> dt(0.5) >>> soildepth(100.0, 200.0, 300.0) >>> residualmoisture(0.1) >>> saturationmoisture(0.5) >>> poresizedistribution(0.3) >>> saturatedconductivity(6.0, 8.0, 10.0) >>> states.moisture = 0.5 >>> aides.actualsurfacewater = 2.0, 4.0, 6.0 >>> fluxes.percolation = 1.0 >>> for soil in range(3): ... model.percolate_filledbin_v1(soil) >>> aides.actualsurfacewater actualsurfacewater(0.0, 0.0, 1.0) >>> fluxes.percolation percolation(3.0, 5.0, 6.0)
By the way,
Percolate_FilledBin_V1
sets the first bin’s front depth to the respective soil compartment’s depth:>>> states.frontdepth frontdepth([[100.0, 200.0, 300.0], [nan, nan, nan]])
- class hydpy.models.ga.ga_model.Return_DryDepth_V1[source]¶
Bases:
Method
Calculate and return the “dry depth”.
- Required by the methods:
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Perform_GARTO_V1
Redistribute_Front_V1
Shift_Front_V1
- Requires the control parameters:
- Requires the derived parameter:
- Requires the state sequence:
- Basic equations (Lai et al. (2015), equation 7, modified, see issue 89):
:math:` frac{tau + sqrt{tau^2 + 4 cdot tau cdot EffectiveCapillarySuction}}{2}`
:math:` tau = DT cdot frac{SaturatedConductivity}{SaturationMoisture - FrontMoisture}`
Example:
>>> from hydpy.models.ga import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(3) >>> nmbbins(2) >>> dt(0.5) >>> residualmoisture(0.1, 0.2, 0.2) >>> saturationmoisture(0.5, 0.8, 0.8) >>> poresizedistribution(0.3, 0.4, 0.4) >>> saturatedconductivity(10.0, 20.0, 20.0) >>> airentrypotential(0.1, 0.2, 0.2) >>> derived.effectivecapillarysuction.update() >>> states.moisture = [[0.3, 0.5, 0.8], [nan, nan, nan]] >>> from hydpy import round_ >>> for soil in range(3): ... round_(model.return_drydepth_v1(soil)) 25.151711 33.621747 inf
- class hydpy.models.ga.ga_model.Return_LastActiveBin_V1[source]¶
Bases:
Method
Find the index of the last active bin (that either contains a wetting front or uniform moisture over the complete soil depth).
- Required by the methods:
- Requires the control parameter:
- Requires the state sequence:
Example:
>>> from hydpy.models.ga import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(3) >>> nmbbins(3) >>> states.moisture = [[0.1, 0.1, 0.1], ... [0.1, 0.5, 0.5], ... [0.1, 1.0, 0.1]] >>> for soil in range(3): ... print(f"soil: {soil} -> bin: {model.return_lastactivebin_v1(soil)}") soil: 0 -> bin: 0 soil: 1 -> bin: 2 soil: 2 -> bin: 1
- class hydpy.models.ga.ga_model.Active_Bin_V1[source]¶
Bases:
Method
Activate a bin to the right of the bin with the given index.
- Required by the method:
- Requires the control parameters:
- Requires the derived parameter:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
We need to activate another bin if the current last bin’s moisture decreases and rainfall intensity exceeds saturated conductivity.
- Basic equations (related to Lai et al. (2015)):
\(MoistureChange_{bin+1} = \frac{ActualSurfaceWater - DT \cdot 2 \cdot Conductivity_{bin}}{DryDepth}\)
\(Moisture_{bin+1} = Moisture_{bin} + MoistureChange_{bin+1}\)
\(Infiltration_{bin+1} = DT \cdot SaturatedConductivity \cdot \left( \frac{EffectiveCapillarySuction}{DryDepth} + 1 \right)\)
\(FrontDepth_{bin+1} = \frac{Infiltration_{bin+1}}{MoistureChange_{bin+1}}\)
The calculation of infiltration and the new front depth follows equation 4 of Lai et al. (2015), except for using \(Moisture_{bin}\) instead of \(ResidualMoisture\) and \(Moisture_{bin+1}\) instead of \(SaturationMoisture\). Regarding the moisture change, Lai et al. (2015) does not seem to mention the given basic equation explicitly.
Examples:
Method
Active_Bin_V1
is a little complicated, so we perform multiple test calculations considering different special cases. We use the following setting for all these test calculations.>>> from hydpy.models.ga_garto import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(1) >>> nmbbins(3) >>> dt(0.25) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(1000.0) >>> residualmoisture(0.1) >>> saturationmoisture(0.5) >>> airentrypotential(0.1) >>> poresizedistribution(0.3) >>> saturatedconductivity(10.0) >>> derived.soilareafraction.update() >>> derived.effectivecapillarysuction.update()
We define a test function that applies
Active_Bin_V1
for a definable initial surface water depth. The function checks that the water volume remains unchanged, prints the moisture change, the resulting moisture state, and the depth of the new active front (as calculated byActive_Bin_V1
), and additionally prints the related infiltration (whichActive_Bin_V1
does not calculate on its own):>>> from hydpy.core.objecttools import repr_, repr_values >>> def check(actualsurfacewater): ... states.moisture = [[0.1], [0.3], [0.1]] ... states.frontdepth = [[1000.0], [500.0], [0.0]] ... logs.moisturechange = [[nan], [-inf], [nan]] ... aides.actualsurfacewater = actualsurfacewater ... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... model.active_bin_v1(1, 0) ... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... assert old_volume == new_volume ... infiltration = actualsurfacewater - aides.actualsurfacewater[0] ... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"infiltration: {repr_(infiltration)}") ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
The first example deals with a moderate rainfall intensity (a relatively small surface water depth), where everything works as described by the basic equations defined above:
>>> check(actualsurfacewater=1.0) moisturechange: nan, -inf, 0.155311 moisture: 0.1, 0.3, 0.455311 infiltration: 1.0 frontdepth: 1000.0, 500.0, 6.438686
For high rainfall intensities, the calculated moisture change could result in the actual moisture exceeding the saturation moisture. In such cases,
Active_Bin_V1
corrects the moisture but leaves the moisture change as is:ToDo: clip the moisture change?
>>> check(actualsurfacewater=5.0) moisturechange: nan, -inf, 0.780401 moisture: 0.1, 0.3, 0.5 infiltration: 2.55963 frontdepth: 1000.0, 500.0, 12.798152
A particularity of method
Active_Bin_V1
is to set the moisture change to its highest possible value if the original moisture change (following the basic equation) is negative. Such situations can arise when the pre-existing active fronts have already infiltrated a significant amount of the rainfall available for the given numerical timestep:ToDo: set the moisture change to zero?
>>> check(actualsurfacewater=0.001) moisturechange: nan, -inf, 0.2 moisture: 0.1, 0.3, 0.5 infiltration: 0.001 frontdepth: 1000.0, 500.0, 0.005
Even for zero remaining surface water,
Active_Bin_V1
activates a bin and sets its moisture value to the saturation value (without calculating any infiltration):>>> check(actualsurfacewater=0.0) moisturechange: nan, -inf, 0.2 moisture: 0.1, 0.3, 0.5 infiltration: 0.0 frontdepth: 1000.0, 500.0, 0.0
A very special case is when the initially calculated moisture change (following the basic equation) is zero. Only then,
Active_Bin_V1
refrains from activating another bin:Active_Bin_V1
checks if the initially calculated moisture change (following the basic equation) is zero. Only then does it refrain from activating another bin:>>> actualsurfacewater=control.dt * 2.0 * model.return_conductivity_v1(1, 0) >>> check(actualsurfacewater=actualsurfacewater) moisturechange: nan, -inf, 0.0 moisture: 0.1, 0.3, 0.1 infiltration: 0.0 frontdepth: 1000.0, 500.0, 0.0
The following two examples illustrate highly deviating ways of front activation around the “zero moisture change” case (the second example also shows that infiltration becomes restricted when the front depth would otherwise overshoot the soil depth):
>>> check(actualsurfacewater=actualsurfacewater-1e-5) moisturechange: nan, -inf, 0.2 moisture: 0.1, 0.3, 0.5 infiltration: 0.006142 frontdepth: 1000.0, 500.0, 0.03071
>>> check(actualsurfacewater=actualsurfacewater+1e-5) moisturechange: nan, -inf, 0.000002 moisture: 0.1, 0.3, 0.300002 infiltration: 0.001563 frontdepth: 1000.0, 500.0, 1000.0
- class hydpy.models.ga.ga_model.Shift_Front_V1[source]¶
Bases:
Method
Increase the selected bin’s wetting front depth without modifying its relative moisture following a variation of the Talbot-Ogden equation (Talbot and Ogden, 2008).
- Required by the method:
- Required submethods:
Return_RelativeMoisture_V1
Return_LastActiveBin_V1
Return_DryDepth_V1
Return_Conductivity_V1
Return_CapillaryDrive_V1
- Requires the control parameters:
DT
NmbBins
SoilDepth
ResidualMoisture
SaturationMoisture
SaturatedConductivity
AirEntryPotential
PoreSizeDistribution
- Requires the derived parameter:
- Requires the aide sequence:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
Method
Shift_Front_V1
applies for active wetting front bins that are not the last active bin or that are saturated (Moisture
equalsSaturationMoisture
). The latter holds only for periods with rainfall intensity exceeding saturated conductivity.- Basic equation (Lai et al. (2015), equation 8, modified):
\(FrontDepth_{bin, new} = FrontDepth_{bin, old} + DT \cdot \frac{Conductivity_{bin-1} - Conductivity_{bin}} {Moisture_{bin} - Moisture_{bin-1}} \cdot \left(1 + \frac{CapillaryDrive_{0, LastActiveBin} + InitialSurfaceWater}{FrontDepth_{bin}} \right)\)
Note the used equation deviates from equation 8 of Lai et al. (2015) in adding the initial surface water depth to the effective capillary drive, which increases infiltration. Using
InitialSurfaceWater
instead ofActualSurfaceWater
assures the bin processing order does not affect the individual infiltration rates.Examples:
For comparison, we perform the following examples similar to those of method
Active_Bin_V1
. The general setting is identical, except that we initialise one more bin:>>> from hydpy.models.ga_garto import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(1) >>> nmbbins(4) >>> dt(0.25) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(1000.0) >>> residualmoisture(0.1) >>> saturationmoisture(0.5) >>> airentrypotential(0.1) >>> poresizedistribution(0.3) >>> saturatedconductivity(10.0) >>> derived.soilareafraction.update() >>> derived.effectivecapillarysuction.update()
The test function also behaves similarly but allows for more modifications of the initial states, supports selecting the considered bin, and applies
Shift_Front_V1
instead ofActive_Bin_V1
:>>> from hydpy.core.objecttools import repr_, repr_values >>> def check( ... bin_, initialsurfacewater, actualsurfacewater, frontdepth, moisture ... ): ... states.moisture = [[m] for m in moisture] ... states.frontdepth = [[fd] for fd in frontdepth] ... logs.moisturechange = nan ... aides.initialsurfacewater = initialsurfacewater ... aides.actualsurfacewater = actualsurfacewater ... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... model.shift_front_v1(bin_, 0) ... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... assert old_volume == new_volume ... infiltration = actualsurfacewater - aides.actualsurfacewater[0] ... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"infiltration: {repr_(infiltration)}") ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
Shift_Front_V1
is to be applied on non-last active wetting front bins and the last bin if it is saturated. We start with demonstrating its functionality for the latter case.The first example is standard so far that the given basic equation applies without additional restrictions and initial and actual surface water depths are identical. 2.75 mm of the available surface water infiltrate and shift the wetting front by about 13.75 mm:
>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=10.0, ... frontdepth=[1000.0, 500.0, 100.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1]) moisturechange: nan, nan, nan, nan moisture: 0.1, 0.3, 0.5, 0.1 infiltration: 2.750428 frontdepth: 1000.0, 500.0, 113.752138, 0.0
Next, we decrease the amount of available surface water to 1 mm but let the initial surface water depth at 10 mm. Thus, the potential infiltration stays as is, but the actual infiltration reduces to 1 mm (and the front shift to 5 mm):
>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=1.0, ... frontdepth=[1000.0, 500.0, 100.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1]) moisturechange: nan, nan, nan, nan moisture: 0.1, 0.3, 0.5, 0.1 infiltration: 1.0 frontdepth: 1000.0, 500.0, 105.0, 0.0
For small or zero initial front depths,
Shift_Front_V1
uses the methodReturn_DryDepth_V1
to advance the front instead of the basic equation:>>> from hydpy import round_ >>> round_(model.return_drydepth_v1(0)) 6.399076 >>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=10.0, ... frontdepth=[1000.0, 500.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1]) moisturechange: nan, nan, nan, nan moisture: 0.1, 0.3, 0.5, 0.1 infiltration: 1.279815 frontdepth: 1000.0, 500.0, 6.399076, 0.0
Shift_Front_V1
prevents a wetting front from overshooting the soil depth but not the depth of other fronts:>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=10.0, ... frontdepth=[1000.0, 999.0, 998.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1]) moisturechange: nan, nan, nan, nan moisture: 0.1, 0.3, 0.5, 0.1 infiltration: 0.4 frontdepth: 1000.0, 999.0, 1000.0, 0.0
In principle,
Shift_Front_V1
works for the active, non-last bins as described above:>>> check(bin_=1, initialsurfacewater=10.0, actualsurfacewater=1.0, ... frontdepth=[1000.0, 300.0, 200.0, 100.0], ... moisture=[0.2, 0.3, 0.4, 0.5]) moisturechange: nan, nan, nan, nan moisture: 0.2, 0.3, 0.4, 0.5 infiltration: 0.003176 frontdepth: 1000.0, 300.031762, 200.0, 100.0
However, for these bins, it also applies to rain-free periods. Then, its front shifts as usual while keeping its relative moisture. As the considered bin cannot (completely) take the corrensponding absolute moisture decrease from the surface, it takes water from the last active bin instead, decreasing its depth but not its relative moisture:
>>> check(bin_=1, initialsurfacewater=0.0, actualsurfacewater=0.0, ... frontdepth=[1000.0, 300.0, 200.0, 100.0], ... moisture=[0.2, 0.3, 0.4, 0.5]) moisturechange: nan, nan, nan, nan moisture: 0.2, 0.3, 0.4, 0.5 infiltration: 0.0 frontdepth: 1000.0, 300.030738, 200.0, 99.969262
If the last active bin does not contain enough water, the second-last bin must help out:
>>> check(bin_=1, initialsurfacewater=0.0, actualsurfacewater=0.0, ... frontdepth=[1000.0, 300.0, 200.0, 0.01], ... moisture=[0.2, 0.3, 0.4, 0.5]) moisturechange: nan, nan, nan, 0.0 moisture: 0.2, 0.3, 0.4, 0.2 infiltration: 0.0 frontdepth: 1000.0, 300.030738, 199.979262, 0.0
If all bins that possess higher relative moisture than the considered bin do not contain enough water, the shift of the wetting front becomes restricted:
>>> check(bin_=1, initialsurfacewater=0.0, actualsurfacewater=0.0, ... frontdepth=[1000.0, 300.0, 0.02, 0.01], ... moisture=[0.2, 0.3, 0.4, 0.5]) moisturechange: nan, nan, 0.0, 0.0 moisture: 0.2, 0.3, 0.2, 0.2 infiltration: 0.0 frontdepth: 1000.0, 300.03, 0.0, 0.0
All examples above show that
Shift_Front_V1
never modifiesMoistureChange
, except when deactivating a bin. Then, it sets the moisture change to zero.
- class hydpy.models.ga.ga_model.Redistribute_Front_V1[source]¶
Bases:
Method
Modify the selected bin’s wetting front depth and relative moisture content based on a Green & Ampt redistribution equation.
- Required by the method:
- Required submethods:
Return_RelativeMoisture_V1
Return_DryDepth_V1
Return_Conductivity_V1
Return_CapillaryDrive_V1
- Requires the control parameters:
NmbBins
DT
SoilDepth
ResidualMoisture
SaturationMoisture
SaturatedConductivity
AirEntryPotential
PoreSizeDistribution
- Requires the derived parameter:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
Redistribute_Front_V1
applies for the last active wetting front bin when rainfall intensity does not exceed saturated conductivity.- Basic equations (Lai et al. (2015), equation 6)
\(p = \cases{1.7 &| ActualSurfaceWater = 0 \\ 1.0 &| ActualSurfaceWater > 0}\)
\(MoistureChange_{bin} = \frac{1}{FrontDepth_{bin}} \cdot \left( ActualSurfaceWater - DT \cdot \left( Conductivity_{bin} - \frac{p \cdot SaturatedConductivity \cdot CapillaryDrive_{bin-1,bin}} {FrontDepth_{bin}} \right) \right)\)
\(Moisture_{bin,old} = Moisture_{bin,new} + MoistureChange_{bin}\)
\(Infiltration_{bin} = DT \cdot SaturatedConductivity \cdot \left( 1 + \frac{EffectiveCapillarySuction}{FrontDepth_{bin}} \right)\)
\(FrontDepth_{bin,new} = \frac{Infiltration_{bin} + FrontDepth_{bin,old} \cdot (Moisture_{bin,old} - Moisture_{bin-1})} {Moisture_{bin,new} - Moisture_{bin-1}}\)
Lai et al. (2015) define only the calculation of the moisture change explicitly. The infiltration calculation and the corresponding shift of the wetting front depth rest on the GARTO source code provided by the authors. One might have expected to use \(Conductivity_{bin}\) and \(CapillaryDrive_{bin-1,bin}\) instead of \(SaturatedConductivity\) and \(EffectiveCapillarySuction\). There is a remark of the authors (possibly concerning the \(CapillaryDrive_{bin-1,bin}\) vs \(EffectiveCapillarySuction\) issue only) that oscillations in infiltration rates might show up otherwise. Maybe we can discuss this with the authors or investigate ourselves in more detail later.
If the bin’s initial front depth is zero, the basic equations for calculating moisture change and infiltration become obsolete.
Redistribute_Front_V1
then proceeds as follows:\(MoistureChange_{bin} = (ActualSurfaceWater - DT \cdot Conductivity_{bin-1}) / DryDepth\)
\(Infiltration_{bin} = DT \cdot SaturatedConductivity \cdot \left( 1 + \frac{EffectiveCapillarySuction}{DryDepth} \right)\)
Examples:
For comparison, we perform the following examples similar to those of method
Shift_Front_V1
. The general setting is identical:>>> from hydpy.models.ga_garto import * >>> simulationstep("1h") >>> parameterstep("1h") >>> nmbsoils(1) >>> nmbbins(4) >>> dt(0.25) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(1000.0) >>> residualmoisture(0.1) >>> saturationmoisture(0.5) >>> airentrypotential(0.1) >>> poresizedistribution(0.3) >>> saturatedconductivity(10.0) >>> derived.soilareafraction.update() >>> derived.effectivecapillarysuction.update()
The test function behaves similarly. However it neglects the initial surface water depth, which is not a relevant input to
Redistribute_Front_V1
, and considers percolation, whichRedistribute_Front_V1
might update when deactivating surface wetting fronts:>>> from hydpy.core.objecttools import repr_, repr_values >>> def check(bin_, actualsurfacewater, frontdepth, moisture): ... states.moisture = [[m] for m in moisture] ... states.frontdepth = [[fd] for fd in frontdepth] ... logs.moisturechange = nan ... aides.actualsurfacewater = actualsurfacewater ... fluxes.percolation[0] = 0.0 ... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... model.redistribute_front_v1(bin_, 0) ... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... assert old_volume == new_volume + fluxes.percolation[0] ... infiltration = actualsurfacewater - aides.actualsurfacewater[0] ... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"infiltration: {repr_(infiltration)}") ... print(f"percolation: {repr_(fluxes.percolation[0])}") ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
In the first example, the given basic equations apply without modifications. Due to missing surface water, relative moisture decreases. Consequently, the front’s depth increases to keep the bin’s total water volume:
>>> check(bin_=2, actualsurfacewater=0.0, ... frontdepth=[1000.0, 500.0, 100.0, 0.0], ... moisture=[0.1, 0.3, 0.4, 0.1]) moisturechange: nan, nan, -0.001553, nan moisture: 0.1, 0.3, 0.398447, 0.1 infiltration: 0.0 percolation: 0.0 frontdepth: 1000.0, 500.0, 101.57736, 0.0
With enough available surface water, the bin’s relative soil moisture increases. In the following example, this moisture increase outweighs the actual infiltration. So the front depth must must decrease to keep the absolute water volume.
>>> check(bin_=2, actualsurfacewater=5.0, ... frontdepth=[1000.0, 500.0, 100.0, 0.0], ... moisture=[0.1, 0.3, 0.4, 0.1]) moisturechange: nan, nan, 0.048449, nan moisture: 0.1, 0.3, 0.448449, 0.1 infiltration: 2.503816 percolation: 0.0 frontdepth: 1000.0, 500.0, 84.229985, 0.0
For zero initial front depth,
Redistribute_Front_V1
prefers the alternative equations for calculating moisture change and infiltration defined above:>>> check(bin_=2, actualsurfacewater=0.5, ... frontdepth=[1000.0, 500.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.4, 0.1]) moisturechange: nan, nan, 0.077656, nan moisture: 0.1, 0.3, 0.477656, 0.1 infiltration: 0.5 percolation: 0.0 frontdepth: 1000.0, 500.0, 2.814434, 0.0
Redistribute_Front_V1
ensures the updated moisture content does not exceed the saturation content, even if the calculated moisture change suggests so:ToDo: clip moisture change?
>>> check(bin_=2, actualsurfacewater=20.0, ... frontdepth=[1000.0, 500.0, 100.0, 0.0], ... moisture=[0.1, 0.3, 0.4, 0.1]) moisturechange: nan, nan, 0.198449, nan moisture: 0.1, 0.3, 0.5, 0.1 infiltration: 2.503816 percolation: 0.0 frontdepth: 1000.0, 500.0, 62.519079, 0.0
A moisture decrease that would result in falling below the moisture value of the left neighbour bin causes the deactivation of the affected bin. If the left neighbour contains an active wetting front,
Redistribute_Front_V1
adds the remaining soil water and infiltration to this bin by increasing its front depth:- ToDo: What if the front depth of the left neigbour bin exceeds soil depth
afterwards?
>>> check(bin_=2, actualsurfacewater=0.001, ... frontdepth=[1000.0, 500.0, 100.0, 0.0], ... moisture=[0.1, 0.3, 0.30001, 0.1]) moisturechange: nan, nan, 0.0, nan moisture: 0.1, 0.3, 0.1, 0.1 infiltration: 0.001 percolation: 0.0 frontdepth: 1000.0, 500.01, 0.0, 0.0
If the left neighbour is the first, completely “filled” bin, the remaining soil water and infiltration increase its moisture content:
>>> soildepth(500.0) >>> check(bin_=1, actualsurfacewater=0.001, ... frontdepth=[500.0, 100.0, 0.0, 0.0], ... moisture=[0.3, 0.30001, 0.1, 0.1]) moisturechange: nan, 0.0, nan, nan moisture: 0.300004, 0.300004, 0.300004, 0.300004 infiltration: 0.001 percolation: 0.0 frontdepth: 500.0, 0.0, 0.0, 0.0
- ToDo: In the original GARTO code, the remaining soil water and infiltration
become percolation. However, when evaporation interferes with the original equations, this simplification can result in percolation rates larger than saturated conductivity. We observed this in the continuous event example, where percolation was 20 mm/h (the rainfall rate) in the 21st hour despite a saturated conductivity of 13.2 mm/h. For our assumption, the percolation rate is 12.8 mm/h. Nevertheless, we should keep this deviation from the original implementation in mind for a while; in case it brings unexpected side effects in future applications.
- class hydpy.models.ga.ga_model.Infiltrate_WettingFrontBins_V1[source]¶
Bases:
Method
Process infiltration into the wetting front bins.
- Required by the methods:
- Required submethods:
Return_RelativeMoisture_V1
Return_DryDepth_V1
Return_Conductivity_V1
Return_CapillaryDrive_V1
Active_Bin_V1
Shift_Front_V1
Redistribute_Front_V1
- Requires the control parameters:
NmbBins
DT
SoilDepth
ResidualMoisture
SaturationMoisture
SaturatedConductivity
AirEntryPotential
PoreSizeDistribution
- Requires the derived parameter:
- Requires the aide sequence:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
Infiltrate_WettingFrontBins_V1
does not perform any calculations itself but selects the proper submethods to do so. It either does nothing (if the filled bin is saturated) or callsRedistribute_Front_V1
,Shift_Front_V1
, orActive_Bin_V1
(primarily depending on the initial surface water depth and the current moisture contents).Infiltrate_WettingFrontBins_V1
is specifically designed forga_garto
.Examples:
Instead of triggering actual calculations, we try to show how
Infiltrate_WettingFrontBins_V1
selects the mentioned methods based on mocking them. Therefore, we must import the model in pure Python mode:>>> from hydpy.core.importtools import reverse_model_wildcard_import >>> reverse_model_wildcard_import() >>> from hydpy import pub, print_vector >>> with pub.options.usecython(False): ... from hydpy.models.ga import * ... simulationstep("1h") ... parameterstep("1h")
We define only those parameters required for selecting the proper methods:
>>> nmbsoils(1) >>> nmbbins(5) >>> dt(0.25) >>> saturationmoisture(0.6) >>> saturatedconductivity(10.0)
The following test function prepares the initial surface water depth, the (current) relative moisture, and the (previous) moisture change. Afterwards, it replaces the mentioned methods with mocks, invokes
Infiltrate_WettingFrontBins_V1
, and prints the passed arguments of all mock calls:>>> from unittest.mock import patch >>> def check(initialsurfacewater, moisture, moisturechange): ... states.moisture = [[m] for m in moisture] ... logs.moisturechange = [[mc] for mc in moisturechange] ... aides.initialsurfacewater = initialsurfacewater ... with patch.object( ... model, "redistribute_front_v1" ... ) as redistribute_front_v1, patch.object( ... model, "shift_front_v1" ... ) as shift_front_v1, patch.object( ... model, "active_bin_v1" ... ) as active_bin_v1: ... model.infiltrate_wettingfrontbins_v1(0) ... for mock in (shift_front_v1, redistribute_front_v1, active_bin_v1): ... if mock.called: ... print(mock._extract_mock_name(), end=": ") ... print_vector([str(call)[4:] for call in mock.mock_calls])
If the first (filled) bin is saturated,
Infiltrate_WettingFrontBins_V1
does nothing:>>> check(initialsurfacewater=20.0, ... moisture=[0.6, 0.6, 0.6, 0.6, 0.6], ... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
If a wetting front bin is saturated,
Infiltrate_WettingFrontBins_V1
calls eitherShift_Front_V1
orRedistribute_Front_V1
, depending on whether the surface water depth (rainfall intensity) exceeds saturated conductivity or not:>>> check(initialsurfacewater=20.0, ... moisture=[0.1, 0.6, 0.6, 0.6, 0.6], ... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0]) shift_front_v1: (1, 0)
>>> check(initialsurfacewater=2.0, ... moisture=[0.1, 0.6, 0.6, 0.6, 0.6], ... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0]) redistribute_front_v1: (1, 0)
If all bins are active,
Infiltrate_WettingFrontBins_V1
callsShift_Front_V1
for all bins except for the last one, for which it callsRedistribute_Front_V1
:>>> check(initialsurfacewater=2.0, ... moisture=[0.1, 0.2, 0.3, 0.4, 0.5], ... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0]) shift_front_v1: (1, 0), (2, 0), (3, 0) redistribute_front_v1: (4, 0)
If there is at least one inactivated bin and the last active bin is not saturated,
Infiltrate_WettingFrontBins_V1
either callsActive_Bin_V1
to activate a new bin right to it or callsRedistribute_Front_V1
, depending on whether rainfall intensity exceeds saturated conductivity and the active bin’s relative moisture decreased previously or not:>>> check(initialsurfacewater=20.0, ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.0, 0.0, 0.0, -1.0, 0.0]) shift_front_v1: (1, 0), (2, 0) active_bin_v1: (3, 0)
>>> check(initialsurfacewater=2.0, ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.0, 0.0, 0.0, -1.0, 0.0]) shift_front_v1: (1, 0), (2, 0) redistribute_front_v1: (3, 0)
>>> check(initialsurfacewater=20.0, ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0]) shift_front_v1: (1, 0), (2, 0) redistribute_front_v1: (3, 0)
>>> check(initialsurfacewater=2.0, ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0]) shift_front_v1: (1, 0), (2, 0) redistribute_front_v1: (3, 0)
>>> reverse_model_wildcard_import()
- class hydpy.models.ga.ga_model.Merge_FrontDepthOvershootings_V1[source]¶
Bases:
Method
Merge those neighbour bins where the wetting front’s depth of the right neighbour exceeds the wetting front’s depth of the left neighbour.
- Required by the methods:
- Requires the control parameter:
- Updates the state sequences:
- Updates the log sequence:
Examples:
For comparison, we perform the following examples similar to those of method
Active_Bin_V1
. However, in contrast toActive_Bin_V1
,Merge_FrontDepthOvershootings_V1
only needs to know the number of available bins and their current states only, making the general set-up much shorter:>>> from hydpy.models.ga_garto import * >>> parameterstep() >>> nmbsoils(1) >>> nmbbins(5) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(1000.0) >>> derived.soilareafraction.update()
Instead of accepting different values for the actual surface water depth, the test function here allows defining the respective front’s depth, moisture and moisture change:
>>> from hydpy.core.objecttools import repr_, repr_values >>> def check(frontdepth, moisture, moisturechange): ... states.frontdepth = [[fd] for fd in frontdepth] ... states.moisture = [[m] for m in moisture] ... logs.moisturechange = [[mc] for mc in moisturechange] ... old_volume = round(model.watercontent, 12) ... model.merge_frontdepthovershootings_v1(0) ... new_volume = round(model.watercontent, 12) ... assert old_volume == new_volume ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
Nothing happens as long as all bins have smaller front depths than their left neighbours. Note that
Merge_FrontDepthOvershootings_V1
also becomes active only if relative moisture increases from left to right. Hence, in the following example, there is no merging of the two inactive bins, which (as usual) both have zero front depths:>>> check(frontdepth=[1000.0, 500.0, 100.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1, 0.1], ... moisturechange=[0.2, 0.4, 0.6, 0.0, 0.0]) frontdepth: 1000.0, 500.0, 100.0, 0.0, 0.0 moisture: 0.1, 0.3, 0.5, 0.1, 0.1 moisturechange: 0.2, 0.4, 0.6, 0.0, 0.0
For equal depths,
Merge_FrontDepthOvershootings_V1
deactivates the left neighbour bin and sets the moisture change of the left neighbour to zero:>>> check(frontdepth=[1000.0, 500.0, 500.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1, 0.1], ... moisturechange=[0.2, 0.4, 0.6, 0.0, 0.0]) frontdepth: 1000.0, 500.0, 0.0, 0.0, 0.0 moisture: 0.1, 0.5, 0.1, 0.1, 0.1 moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
In case of an overshooting,
Merge_FrontDepthOvershootings_V1
must add the (additional) water content of the (deactivated) right neighbour to the (preserved) left neighbour:>>> check(frontdepth=[1000.0, 500.0, 600.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.5, 0.1, 0.1], ... moisturechange=[0.2, 0.4, 0.6, 0.0, 0.0]) frontdepth: 1000.0, 550.0, 0.0, 0.0, 0.0 moisture: 0.1, 0.5, 0.1, 0.1, 0.1 moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
All right neighbours of a deactivated bin move (at least) one place to the left:
>>> check(frontdepth=[1000.0, 500.0, 600.0, 400.0, 0.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.2, 0.4, 0.6, 0.8, 0.0]) frontdepth: 1000.0, 550.0, 400.0, 0.0, 0.0 moisture: 0.1, 0.3, 0.4, 0.1, 0.1 moisturechange: 0.2, 0.0, 0.8, 0.0, 0.0
If the last bin is active, it gets properly deactivated:
>>> check(frontdepth=[1000.0, 500.0, 600.0, 400.0, 300.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.5], ... moisturechange=[0.2, 0.4, 0.6, 0.8, 1.0]) frontdepth: 1000.0, 550.0, 400.0, 300.0, 0.0 moisture: 0.1, 0.3, 0.4, 0.5, 0.1 moisturechange: 0.2, 0.0, 0.8, 1.0, 0.0
The two last examples demonstrate that the underlying algorithm works stably in case multiple mergings are necessary:
>>> check(frontdepth=[1000.0, 500.0, 600.0, 700.0, 0.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.2, 0.4, 0.6, 0.8, 0.0]) frontdepth: 1000.0, 600.0, 0.0, 0.0, 0.0 moisture: 0.1, 0.4, 0.1, 0.1, 0.1 moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
>>> check(frontdepth=[1000.0, 500.0, 600.0, 400.0, 500.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.5], ... moisturechange=[0.2, 0.4, 0.6, 0.8, 1.0]) frontdepth: 1000.0, 550.0, 450.0, 0.0, 0.0 moisture: 0.1, 0.3, 0.5, 0.1, 0.1 moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
- class hydpy.models.ga.ga_model.Merge_SoilDepthOvershootings_V1[source]¶
Bases:
Method
Merge bins with wetting front depth larger than soil depth with their left neighbour bins and add their water excess to percolation.
- Required by the methods:
- Requires the control parameters:
- Updates the flux sequence:
- Updates the state sequences:
- Updates the log sequence:
Merge_SoilDepthOvershootings_V1
assumes proper sorting of wetting front depths (decreasing from left to right), as ensured byMerge_FrontDepthOvershootings_V1
.Examples:
For comparison, we perform the following examples similar to those of the related method
Merge_FrontDepthOvershootings_V1
. The general setting is identical:>>> from hydpy.models.ga_garto import * >>> parameterstep() >>> nmbsoils(1) >>> nmbbins(5) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(1000.0) >>> derived.soilareafraction.update()
The test function is similar but must also consider percolation:
>>> from hydpy.core.objecttools import repr_, repr_values >>> def check(frontdepth, moisture, moisturechange): ... states.frontdepth = [[fd] for fd in frontdepth] ... states.moisture = [[m] for m in moisture] ... logs.moisturechange = [[mc] for mc in moisturechange] ... fluxes.percolation = 0.0 ... old_volume = round(model.watercontent, 12) ... model.merge_soildepthovershootings_v1(0) ... new_volume = round(model.watercontent + fluxes.percolation[0], 12) ... assert old_volume == new_volume ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}") ... print(f"percolation: {repr_(fluxes.percolation[0])}")
Nothing happens as long as all bins have smaller front depths than their left neighbours. Note that
Merge_SoilDepthOvershootings_V1
also becomes active only if relative moisture increases from left to right. Hence, in the following example, there is no merging of the two inactive bins, which (as usual) both have zero front depths:>>> check(frontdepth=[1000.0, 900.0, 800.0, 0.0, 0.0], ... moisture=[0.1, 0.2, 0.3, 0.1, 0.1], ... moisturechange=[0.0, 1.0, 2.0, 0.0, 0.0]) frontdepth: 1000.0, 900.0, 800.0, 0.0, 0.0 moisture: 0.1, 0.2, 0.3, 0.1, 0.1 moisturechange: 0.0, 1.0, 2.0, 0.0, 0.0 percolation: 0.0
If a single front’s depth reaches the soil bottom exactly,
Merge_SoilDepthOvershootings_V1
deactivates the affected bin and takes its relative moisture value as the new initial moisture:>>> check(frontdepth=[1000.0, 1000.0, 0.0, 0.0, 0.0], ... moisture=[0.1, 0.2, 0.1, 0.1, 0.1], ... moisturechange=[0.0, 1.0, 0.0, 0.0, 0.0]) frontdepth: 1000.0, 0.0, 0.0, 0.0, 0.0 moisture: 0.2, 0.2, 0.2, 0.2, 0.2 moisturechange: 0.0, 0.0, 0.0, 0.0, 0.0 percolation: 0.0
Parts of the front lying below the soil’s bottom become percolation:
>>> check(frontdepth=[1000.0, 1100.0, 0.0, 0.0, 0.0], ... moisture=[0.1, 0.2, 0.1, 0.1, 0.1], ... moisturechange=[0.0, 1.0, 0.0, 0.0, 0.0]) frontdepth: 1000.0, 0.0, 0.0, 0.0, 0.0 moisture: 0.2, 0.2, 0.2, 0.2, 0.2 moisturechange: 0.0, 0.0, 0.0, 0.0, 0.0 percolation: 10.0
All remaining active wetting front bins move (at least) one place to the left:
>>> check(frontdepth=[1000.0, 1100.0, 800.0, 700.0, 600.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.5], ... moisturechange=[0.0, 1.0, 2.0, 3.0, 4.0]) frontdepth: 1000.0, 800.0, 700.0, 600.0, 0.0 moisture: 0.2, 0.3, 0.4, 0.5, 0.2 moisturechange: 0.0, 2.0, 3.0, 4.0, 0.0 percolation: 10.0
The two last examples demonstrate that the underlying algorithm works stably in case multiple mergings are necessary:
>>> check(frontdepth=[1000.0, 1200.0, 1100.0, 700.0, 0.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.1], ... moisturechange=[0.0, 1.0, 2.0, 3.0, 0.0]) frontdepth: 1000.0, 700.0, 0.0, 0.0, 0.0 moisture: 0.3, 0.4, 0.3, 0.3, 0.3 moisturechange: 0.0, 3.0, 0.0, 0.0, 0.0 percolation: 30.0
>>> check(frontdepth=[1000.0, 1200.0, 1200.0, 1100.0, 1100.0], ... moisture=[0.1, 0.2, 0.3, 0.4, 0.5], ... moisturechange=[0.0, 1.0, 2.0, 3.0, 4.0]) frontdepth: 1000.0, 0.0, 0.0, 0.0, 0.0 moisture: 0.5, 0.5, 0.5, 0.5, 0.5 moisturechange: 0.0, 0.0, 0.0, 0.0, 0.0 percolation: 60.0
- class hydpy.models.ga.ga_model.Water_AllBins_V1[source]¶
Bases:
Method
Water the soil’s body by (potentially) adding water to all active bins.
- Required by the methods:
- Requires the control parameters:
- Updates the flux sequence:
- Updates the state sequences:
- Updates the log sequence:
The soil water addition calculated by
Water_AllBins_V1
equals the defined soil water supply, except adding the complete supply would exceed the saturation water content.Note that the caller needs to pass the supply as a method parameter, which allows him to decide whether to add everything in one simulation step or multiple numerical substeps.
Examples:
We prepare a single shallow soil compartment divided into four bins:
>>> from hydpy.models.ga_garto import * >>> simulationstep("1d") >>> parameterstep("1d") >>> nmbsoils(1) >>> nmbbins(4) >>> dt(0.5) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(100.0) >>> saturationmoisture(0.5) >>> derived.soilareafraction.update()
The following test function works similar to the one defined for demonstrating
Active_Bin_V1
but considers the soil water addition instead of infiltration:>>> from hydpy.core.objecttools import repr_, repr_values >>> def check(soilwatersupply, moisture, frontdepth): ... fluxes.soilwatersupply[0] = soilwatersupply ... states.moisture = [[m] for m in moisture] ... states.frontdepth = [[fd] for fd in frontdepth] ... logs.moisturechange = [[1.0], [2.0], [3.0], [4.0]] ... fluxes.soilwateraddition[0] = 0.0 ... old_volume = round(model.watercontent, 12) ... model.water_allbins_v1(0, soilwatersupply) ... new_volume = round(model.watercontent, 12) ... assert old_volume + fluxes.soilwateraddition[0] == new_volume ... print(f"soilwatersupply: {repr_(fluxes.soilwatersupply[0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}") ... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}") ... print(f"soilwateraddition: {repr_(fluxes.soilwateraddition[0])}")
For zero soil water supply,
Water_AllBins_V1
does nothing:>>> check(soilwatersupply=0.0, ... moisture=[0.1, 0.3, 0.1, 0.1], ... frontdepth=[100.0, 50.0, 0.0, 0.0]) soilwatersupply: 0.0 moisture: 0.1, 0.3, 0.1, 0.1 frontdepth: 100.0, 50.0, 0.0, 0.0 moisturechange: 1.0, 2.0, 3.0, 4.0 soilwateraddition: 0.0
Water_AllBins_V1
tries to add the supply to the dryest bin by increasing its relative moisture content:>>> check(soilwatersupply=5.0, ... moisture=[0.1, 0.3, 0.1, 0.1], ... frontdepth=[100.0, 50.0, 0.0, 0.0]) soilwatersupply: 5.0 moisture: 0.2, 0.3, 0.2, 0.2 frontdepth: 100.0, 50.0, 0.0, 0.0 moisturechange: 0.0, 2.0, 3.0, 4.0 soilwateraddition: 5.0
If a bin is not the last active bin, its highest possible moisture content is restricted by the relative moisture value of its right neighbour bin. If two bins get the same moisture, one of them becomes obsolete, so we can remove it and shift all its right neighbours one place to the left:
>>> check(soilwatersupply=10.0, ... moisture=[0.1, 0.3, 0.1, 0.1], ... frontdepth=[100.0, 50.0, 0.0, 0.0]) soilwatersupply: 10.0 moisture: 0.3, 0.3, 0.3, 0.3 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 3.0, 4.0, 0.0 soilwateraddition: 10.0
If the first bin cannot take enough water,
Water_AllBins_V1
updates the front depth and increases the water content of the second bin:>>> check(soilwatersupply=20.0, ... moisture=[0.1, 0.3, 0.1, 0.1], ... frontdepth=[100.0, 50.0, 0.0, 0.0]) soilwatersupply: 20.0 moisture: 0.4, 0.4, 0.4, 0.4 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 3.0, 4.0, 0.0 soilwateraddition: 20.0
However, no bin can possess relative moisture higher than indicated by saturation moisture:
>>> check(soilwatersupply=40.0, ... moisture=[0.1, 0.3, 0.1, 0.1], ... frontdepth=[100.0, 50.0, 0.0, 0.0]) soilwatersupply: 40.0 moisture: 0.5, 0.5, 0.5, 0.5 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 3.0, 4.0, 0.0 soilwateraddition: 30.0
Water_AllBins_V1
deactivates multiple bins when necessary:>>> check(soilwatersupply=40.0, ... moisture=[0.1, 0.3, 0.5, 0.1], ... frontdepth=[100.0, 50.0, 0.0, 0.0]) soilwatersupply: 40.0 moisture: 0.5, 0.5, 0.5, 0.5 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 4.0, 0.0, 0.0 soilwateraddition: 30.0
>>> check(soilwatersupply=10.0, ... moisture=[0.1, 0.2, 0.3, 0.4], ... frontdepth=[100.0, 75.0, 50.0, 25.0]) soilwatersupply: 10.0 moisture: 0.333333, 0.4, 0.333333, 0.333333 frontdepth: 100.0, 25.0, 0.0, 0.0 moisturechange: 0.0, 4.0, 0.0, 0.0 soilwateraddition: 10.0
>>> check(soilwatersupply=30.0, ... moisture=[0.1, 0.2, 0.3, 0.4], ... frontdepth=[100.0, 75.0, 50.0, 25.0]) soilwatersupply: 30.0 moisture: 0.5, 0.5, 0.5, 0.5 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 0.0, 0.0, 0.0 soilwateraddition: 25.0
The last two examples demonstrate, similar to the first example, that
Water_AllBins_V1
adjusts the relative moisture value of all non-active bins after increasing the moisture of the first bin:>>> check(soilwatersupply=10.0, ... moisture=[0.1, 0.1, 0.1, 0.1], ... frontdepth=[100.0, 0.0, 0.0, 0.0]) soilwatersupply: 10.0 moisture: 0.2, 0.2, 0.2, 0.2 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 2.0, 3.0, 4.0 soilwateraddition: 10.0
>>> check(soilwatersupply=50.0, ... moisture=[0.1, 0.1, 0.1, 0.1], ... frontdepth=[100.0, 0.0, 0.0, 0.0]) soilwatersupply: 50.0 moisture: 0.5, 0.5, 0.5, 0.5 frontdepth: 100.0, 0.0, 0.0, 0.0 moisturechange: 0.0, 2.0, 3.0, 4.0 soilwateraddition: 40.0
- class hydpy.models.ga.ga_model.Withdraw_AllBins_V1[source]¶
Bases:
Method
Take withdrawal from the available surface water and (potentially) from all active bins.
- Required by the methods:
- Requires the control parameters:
- Updates the flux sequence:
- Updates the state sequences:
- Updates the aide sequence:
The withdrawal calculated by
Withdraw_AllBins_V1
equals the defined demand, except no water exceeding the residual moisture is left. Hence, for example, actual evaporation is more suitable for specifying the demand than potential evaporation.Note that the caller needs to pass the demand as a method parameter, which allows him to decide whether to subtract everything in one simulation step or multiple numerical substeps.
Examples:
We prepare a single shallow soil compartment divided into four bins:
>>> from hydpy.models.ga_garto import * >>> simulationstep("1d") >>> parameterstep("1d") >>> nmbsoils(1) >>> nmbbins(4) >>> dt(0.5) >>> sealed(False) >>> soilarea(1.0) >>> soildepth(100.0) >>> residualmoisture(0.1) >>> derived.soilareafraction.update()
The following test function works similar to the one defined for demonstrating
Active_Bin_V1
but considers the withdrawal instead of infiltration:>>> from hydpy.core.objecttools import repr_, repr_values >>> def check(demand, actualsurfacewater, frontdepth, moisture): ... states.moisture = [[m] for m in moisture] ... states.frontdepth = [[fd] for fd in frontdepth] ... logs.moisturechange = nan ... aides.actualsurfacewater = actualsurfacewater ... fluxes.withdrawal[0] = 0.0 ... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... model.withdraw_allbins_v1(0, control.dt * demand) ... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12) ... assert old_volume == new_volume + fluxes.withdrawal[0] ... print(f"withdrawal: {repr_(fluxes.withdrawal[0])}") ... print(f"actualsurfacewater: {repr_(aides.actualsurfacewater[0])}") ... print(f"moisture: {repr_values(states.moisture[:, 0])}") ... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
For zero demand,
Withdraw_AllBins_V1
does nothing:>>> check(demand=0.0, actualsurfacewater=20.0, ... frontdepth=[100.0, 50.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.1, 0.1]) withdrawal: 0.0 actualsurfacewater: 20.0 moisture: 0.1, 0.3, 0.1, 0.1 frontdepth: 100.0, 50.0, 0.0, 0.0
If possible,
Withdraw_AllBins_V1
withdraws only surface water:>>> check(demand=10.0, actualsurfacewater=20.0, ... frontdepth=[100.0, 50.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.1, 0.1]) withdrawal: 5.0 actualsurfacewater: 15.0 moisture: 0.1, 0.3, 0.1, 0.1 frontdepth: 100.0, 50.0, 0.0, 0.0
If no surface water is available,
Withdraw_AllBins_V1
tries to take all withdrawal from the wettest bin by reducing its relative moisture content:>>> check(demand=10.0, actualsurfacewater=0.0, ... frontdepth=[100.0, 50.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.1, 0.1]) withdrawal: 5.0 actualsurfacewater: 0.0 moisture: 0.1, 0.2, 0.1, 0.1 frontdepth: 100.0, 50.0, 0.0, 0.0
The following example shows that
Withdraw_AllBins_V1
still prefers surface water over soil water if the demand exceeds the available surface water:>>> check(demand=10.0, actualsurfacewater=2.5, ... frontdepth=[100.0, 50.0, 0.0, 0.0], ... moisture=[0.1, 0.3, 0.1, 0.1]) withdrawal: 5.0 actualsurfacewater: 0.0 moisture: 0.1, 0.25, 0.1, 0.1 frontdepth: 100.0, 50.0, 0.0, 0.0
If the wettest bin does not contain enough water,
Withdraw_AllBins_V1
proceeds from right to left in taking the remaining demand:>>> check(demand=10.0, actualsurfacewater=0.0, ... frontdepth=[100.0, 75.0, 50.0, 25.0], ... moisture=[0.1, 0.2, 0.3, 0.4]) withdrawal: 5.0 actualsurfacewater: 0.0 moisture: 0.1, 0.2, 0.25, 0.1 frontdepth: 100.0, 75.0, 50.0, 0.0
However,
Withdraw_AllBins_V1
never takes more water than indicated by soil’s residual moisture:>>> check(demand=40.0, actualsurfacewater=0.0, ... frontdepth=[100.0, 75.0, 50.0, 25.0], ... moisture=[0.1, 0.2, 0.3, 0.4]) withdrawal: 15.0 actualsurfacewater: 0.0 moisture: 0.1, 0.1, 0.1, 0.1 frontdepth: 100.0, 0.0, 0.0, 0.0
The last two examples show that
Withdraw_AllBins_V1
can also take water from the filled bin (if it is not already dry, as in the previous example):>>> check(demand=10.0, actualsurfacewater=0.0, ... frontdepth=[100.0, 0.0, 0.0, 0.0], ... moisture=[0.2, 0.2, 0.2, 0.2]) withdrawal: 5.0 actualsurfacewater: 0.0 moisture: 0.15, 0.2, 0.2, 0.2 frontdepth: 100.0, 0.0, 0.0, 0.0
>>> check(demand=40.0, actualsurfacewater=0.0, ... frontdepth=[100.0, 0.0, 0.0, 0.0], ... moisture=[0.2, 0.2, 0.2, 0.2]) withdrawal: 10.0 actualsurfacewater: 0.0 moisture: 0.1, 0.2, 0.2, 0.2 frontdepth: 100.0, 0.0, 0.0, 0.0
As the last examples show,
Withdraw_AllBins_V1
does not update the other bins’ moisture after removing water from the filled bin, which is surprising but agrees with the author’s GARTO source code and gave better results for shallow soils in some comparisons.
- class hydpy.models.ga.ga_model.Perform_GARTO_V1[source]¶
Bases:
Method
Perform the GARTO algorithm for the numerical substeps and aggregate their results.
- Required submethods:
Return_LastActiveBin_V1
Return_Conductivity_V1
Return_DryDepth_V1
Return_CapillaryDrive_V1
Percolate_FilledBin_V1
Infiltrate_WettingFrontBins_V1
Merge_FrontDepthOvershootings_V1
Merge_SoilDepthOvershootings_V1
Water_AllBins_V1
Withdraw_AllBins_V1
- Requires the control parameters:
NmbSoils
NmbBins
DT
SoilDepth
Sealed
ResidualMoisture
SaturationMoisture
SaturatedConductivity
AirEntryPotential
PoreSizeDistribution
- Requires the derived parameters:
- Requires the flux sequences:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequences:
- Calculates the flux sequences:
Infiltration
Percolation
SoilWaterAddition
Withdrawal
SurfaceRunoff
Method
Perform_GARTO_V1
executes its submethodsPercolate_FilledBin_V1
,Infiltrate_WettingFrontBins_V1
,Merge_FrontDepthOvershootings_V1
,Merge_SoilDepthOvershootings_V1
,Water_AllBins_V1
, andWithdraw_AllBins_V1
in the order of mentioning on all non-sealed soil compartments. Additionally, it converts surface water that cannot infiltrate (or evaporate) during a numerical substep immediately to surface runoff (no ponding). So, it provides all core functionalities of application modelga_garto
, and the explanations and test results forga_garto
essentially apply toPerform_GARTO_V1
, too.
- class hydpy.models.ga.ga_model.Calc_TotalInfiltration_V1[source]¶
Bases:
Method
Calculate the average infiltration from all soil compartments.
- Requires the control parameter:
- Requires the derived parameter:
- Requires the flux sequence:
- Calculates the flux sequence:
- Basic equation:
\(TotalInfiltration = \sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot Infiltration_i\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> derived.soilareafraction(0.8, 0.2) >>> fluxes.infiltration = 1.0, 2.0 >>> model.calc_totalinfiltration_v1() >>> fluxes.totalinfiltration totalinfiltration(1.2)
- class hydpy.models.ga.ga_model.Calc_TotalPercolation_V1[source]¶
Bases:
Method
Calculate the average percolation from all soil compartments.
- Requires the control parameter:
- Requires the derived parameter:
- Requires the flux sequence:
- Calculates the flux sequence:
- Basic equation:
\(TotalPercolation = \sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot Percolation_i\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> derived.soilareafraction(0.8, 0.2) >>> fluxes.percolation = 1.0, 2.0 >>> model.calc_totalpercolation_v1() >>> fluxes.totalpercolation totalpercolation(1.2)
- class hydpy.models.ga.ga_model.Calc_TotalSoilWaterAddition_V1[source]¶
Bases:
Method
Calculate the average soil water addition to all soil compartments.
- Requires the control parameter:
- Requires the derived parameter:
- Requires the flux sequence:
- Calculates the flux sequence:
- Basic equation:
\(TotalSoilWaterAddition = \sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot SoilWaterAddition_i\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> derived.soilareafraction(0.8, 0.2) >>> fluxes.soilwateraddition = 1.0, 2.0 >>> model.calc_totalsoilwateraddition_v1() >>> fluxes.totalsoilwateraddition totalsoilwateraddition(1.2)
- class hydpy.models.ga.ga_model.Calc_TotalWithdrawal_V1[source]¶
Bases:
Method
Calculate the average withdrawal from all soil compartments.
- Requires the control parameter:
- Requires the derived parameter:
- Requires the flux sequence:
- Calculates the flux sequence:
- Basic equation:
\(TotalWithdrawal = \sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot Withdrawal_i\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> derived.soilareafraction(0.8, 0.2) >>> fluxes.withdrawal = 1.0, 2.0 >>> model.calc_totalwithdrawal_v1() >>> fluxes.totalwithdrawal totalwithdrawal(1.2)
- class hydpy.models.ga.ga_model.Calc_TotalSurfaceRunoff_V1[source]¶
Bases:
Method
Calculate the average surface runoff from all soil compartments.
- Requires the control parameter:
- Requires the derived parameter:
- Requires the flux sequence:
- Calculates the flux sequence:
- Basic equation:
\(TotalSurfaceRunoff = \sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot SurfaceRunoff_i\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> derived.soilareafraction(0.8, 0.2) >>> fluxes.surfacerunoff = 1.0, 2.0 >>> model.calc_totalsurfacerunoff_v1() >>> fluxes.totalsurfacerunoff totalsurfacerunoff(1.2)
- class hydpy.models.ga.ga_model.Set_InitialSurfaceWater_V1[source]¶
Bases:
Method
Set the given initial surface water depth for the selected soil compartment.
- Requires the control parameter:
- Calculates the aide sequence:
Example:
Note that
Set_InitialSurfaceWater_V1
multiplies the given value withDT
to adjust it to the numerical substep width:>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> dt.value = 0.5 >>> model.set_initialsurfacewater_v1(0, 2.0) >>> model.set_initialsurfacewater_v1(1, 4.0) >>> aides.initialsurfacewater initialsurfacewater(1.0, 2.0)
- class hydpy.models.ga.ga_model.Set_ActualSurfaceWater_V1[source]¶
Bases:
Method
Set the given actual surface water depth for the selected soil compartment.
- Requires the control parameter:
- Calculates the aide sequence:
Example:
Note that
Set_ActualSurfaceWater_V1
multiplies the given value withDT
to adjust it to the numerical substep width:>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> dt.value = 0.5 >>> model.set_actualsurfacewater_v1(0, 2.0) >>> model.set_actualsurfacewater_v1(1, 4.0) >>> aides.actualsurfacewater actualsurfacewater(1.0, 2.0)
- class hydpy.models.ga.ga_model.Set_SoilWaterSupply_V1[source]¶
Bases:
Method
Set the (potential) water supply to the soil’s body.
- Calculates the flux sequence:
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> model.set_soilwatersupply_v1(0, 2.0) >>> model.set_soilwatersupply_v1(1, 4.0) >>> fluxes.soilwatersupply soilwatersupply(2.0, 4.0)
- class hydpy.models.ga.ga_model.Set_SoilWaterDemand_V1[source]¶
Bases:
Method
Set the (potential) water withdrawal from the soil’s surface and body.
- Calculates the flux sequence:
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> model.set_soilwaterdemand_v1(0, 2.0) >>> model.set_soilwaterdemand_v1(1, 4.0) >>> fluxes.demand demand(2.0, 4.0)
- class hydpy.models.ga.ga_model.Execute_Infiltration_V1[source]¶
Bases:
Method
Calculate infiltration (and percolation).
- Required submethods:
Return_LastActiveBin_V1
Return_Conductivity_V1
Return_DryDepth_V1
Return_CapillaryDrive_V1
Percolate_FilledBin_V1
Infiltrate_WettingFrontBins_V1
Merge_FrontDepthOvershootings_V1
Merge_SoilDepthOvershootings_V1
- Requires the control parameters:
NmbBins
DT
SoilDepth
ResidualMoisture
SaturationMoisture
SaturatedConductivity
AirEntryPotential
PoreSizeDistribution
- Requires the derived parameters:
- Requires the aide sequence:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
- Calculates the flux sequences:
The interface method
Execute_Infiltration_V1
subsequently executes the GARTO methodsPercolate_FilledBin_V1
,Infiltrate_WettingFrontBins_V1
,Merge_FrontDepthOvershootings_V1
, andMerge_SoilDepthOvershootings_V1
for all numerical substeps.
- class hydpy.models.ga.ga_model.Add_SoilWater_V1[source]¶
Bases:
Method
Add the (direct) soil water supply to the soil’s body.
- Required submethod:
- Requires the control parameters:
- Requires the flux sequence:
- Updates the state sequences:
- Updates the log sequence:
- Calculates the flux sequence:
The interface method
Add_SoilWater_V1
only callsWithdraw_AllBins_V1
.
- class hydpy.models.ga.ga_model.Remove_SoilWater_V1[source]¶
Bases:
Method
Remove the water demand from the soil’s body and eventually from the soil’s surface.
- Required submethod:
- Requires the control parameters:
- Requires the flux sequence:
- Updates the state sequences:
- Updates the aide sequence:
- Calculates the flux sequence:
The interface method
Remove_SoilWater_V1
only callsWithdraw_AllBins_V1
. Hence, whetherRemove_SoilWater_V1
can remove surface water depends on the order the different interface methods are applied and is thus a decision of the calling model.
- class hydpy.models.ga.ga_model.Get_Infiltration_V1[source]¶
Bases:
Method
Get the current infiltration to the selected soil compartment.
- Calculates the flux sequence:
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> fluxes.infiltration = 2.0, 4.0 >>> from hydpy import round_ >>> round_(model.get_infiltration_v1(0)) 2.0 >>> round_(model.get_infiltration_v1(1)) 4.0
- class hydpy.models.ga.ga_model.Get_Percolation_V1[source]¶
Bases:
Method
Get the current percolation from the selected soil compartment.
- Calculates the flux sequence:
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> fluxes.percolation = 2.0, 4.0 >>> from hydpy import round_ >>> round_(model.get_percolation_v1(0)) 2.0 >>> round_(model.get_percolation_v1(1)) 4.0
- class hydpy.models.ga.ga_model.Get_SoilWaterAddition_V1[source]¶
Bases:
Method
Get the current soil water addition to the selected soil compartment.
- Calculates the flux sequence:
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> fluxes.soilwateraddition = 2.0, 4.0 >>> from hydpy import round_ >>> round_(model.get_soilwateraddition_v1(0)) 2.0 >>> round_(model.get_soilwateraddition_v1(1)) 4.0
- class hydpy.models.ga.ga_model.Get_SoilWaterRemoval_V1[source]¶
Bases:
Method
Get the current soil (and surface water) withdrawal from the selected soil compartment.
- Calculates the flux sequence:
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> fluxes.withdrawal = 2.0, 4.0 >>> from hydpy import round_ >>> round_(model.get_soilwaterremoval_v1(0)) 2.0 >>> round_(model.get_soilwaterremoval_v1(1)) 4.0
- class hydpy.models.ga.ga_model.Get_SoilWaterContent_V1[source]¶
Bases:
Method
Get the current soil water content of the selected soil compartment.
- Requires the control parameters:
- Requires the state sequences:
- Basic equation:
\(SoilWaterContent = Moisture_1 \cdot SoilDepth + \sum_{i=2}^{NmbBins} (Moisture_i - Moisture_{i-1}) \cdot FrontDepth_i\)
Example:
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(3) >>> nmbbins(4) >>> sealed(False, False, True) >>> soilarea(1.0, 2.0, 3.0) >>> soildepth(100.0, 200, nan) >>> residualmoisture(0.1, 0.2, nan) >>> saturationmoisture(0.5, 0.8, nan) >>> states.moisture = [[0.3, 0.2, nan], ... [0.3, 0.3, nan], ... [0.3, 0.5, nan], ... [0.3, 0.8, nan]] >>> states.frontdepth = [[100.0, 200.0, nan], ... [0.0, 150.0, nan], ... [0.0, 100.0, nan], ... [0.0, 50.0, nan]] >>> from hydpy import round_ >>> round_(model.get_soilwatercontent_v1(0)) 30.0 >>> round_(model.get_soilwatercontent_v1(1)) 90.0 >>> round_(model.get_soilwatercontent_v1(2)) 0.0
- class hydpy.models.ga.ga_model.BaseModel[source]¶
Bases:
AdHocModel
General base class for GARTO-like Green-Ampt models.
- check_waterbalance(initial_conditions: dict[str, dict[str, dict[str, float | ndarray[Any, dtype[float64]]]]]) float [source]¶
Determine the water balance error of the previous simulation run in mm.
Method
check_waterbalance()
calculates the balance error as follows:\(\sum_{t=t0}^{t1} \big( Rainfall_t - TotalPercolation_t + TotalSoilWaterAddition_t - TotalWithdrawal_t - Percolation_t \big) +b\big( WaterVolume_{t0} - WaterVolume_{t1} \big)\)
The returned error should always be in scale with numerical precision so that it does not affect the simulation results in any relevant manner.
Pick the required initial conditions before starting the simulation via property
conditions
. See the integration tests of the application modelga_garto
for some examples.
- property watercontents: ndarray[Any, dtype[float64]]¶
The unique water content of each soil compartment in mm.
Property
watercontents
generally returns zero values for sealed soil compartments:>>> from hydpy.models.ga_garto import * >>> parameterstep() >>> nmbsoils(3) >>> nmbbins(4) >>> sealed(False, False, True) >>> soilarea(1.0, 2.0, 3.0) >>> soildepth(100.0, 200, nan) >>> residualmoisture(0.1, 0.2, nan) >>> saturationmoisture(0.5, 0.8, nan) >>> derived.soilareafraction.update() >>> states.moisture = [[0.3, 0.2, nan], ... [0.3, 0.3, nan], ... [0.3, 0.5, nan], ... [0.3, 0.8, nan]] >>> states.frontdepth = [[100.0, 200.0, nan], ... [0.0, 150.0, nan], ... [0.0, 100.0, nan], ... [0.0, 50.0, nan]] >>> from hydpy import print_vector >>> print_vector(model.watercontents) 30.0, 90.0, 0.0
- property watercontent: float¶
The average water content of all soil compartments in mm.
Property
watercontent
includes sealed soil compartments in the average, which is why the presence of sealing reduces the returned value:>>> from hydpy.models.ga_garto import * >>> parameterstep() >>> nmbsoils(3) >>> nmbbins(4) >>> sealed(False, False, True) >>> soilarea(1.0, 2.0, 3.0) >>> soildepth(100.0, 200, nan) >>> residualmoisture(0.1, 0.2, nan) >>> saturationmoisture(0.5, 0.8, nan) >>> derived.soilareafraction.update() >>> states.moisture = [[0.3, 0.2, nan], ... [0.3, 0.3, nan], ... [0.3, 0.5, nan], ... [0.3, 0.8, nan]] >>> states.frontdepth = [[100.0, 200.0, nan], ... [0.0, 150.0, nan], ... [0.0, 100.0, nan], ... [0.0, 50.0, nan]] >>> from hydpy import round_ >>> round_(model.watercontent) 35.0
>>> soilarea(1.0, 2.0, 0.0) >>> derived.soilareafraction.update() >>> round_(model.watercontent) 70.0
- REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()¶
- class hydpy.models.ga.ga_model.Base_SoilModel_V1[source]¶
Bases:
BaseModel
,SoilModel_V1
Base class for HydPy-GA models that comply with the
SoilModel_V1
submodel interface.- prepare_nmbzones¶
Set the number of soil compartments.
>>> from hydpy.models.ga_garto_submodel1 import * >>> parameterstep() >>> model.prepare_nmbzones(2) >>> nmbsoils nmbsoils(2)
- REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()¶
- cymodel: CyModelProtocol | None¶
- parameters: parametertools.Parameters¶
- sequences: sequencetools.Sequences¶
- masks: masktools.Masks¶
Parameter Features¶
Control parameters¶
- class hydpy.models.ga.ControlParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
SubParameters
Control parameters of model ga.
- The following classes are selected:
NmbSoils()
The number of separately modelled soil compartments in the subbasin [-].NmbBins()
The number of available bins for each soil compartment [-].DT()
The length of the numerical substeps [T].Sealed()
Flag indicating if a (soil) compartment is sealed for infiltration [-].SoilArea()
The area of each soil compartment [km²].SoilDepth()
Depth of the considered soil domains [mm].ResidualMoisture()
Relative residual water content [-].SaturationMoisture()
Relative saturation water content [-].SaturatedConductivity()
Saturated hydraulic conductivity [mm/T].PoreSizeDistribution()
Pore-size distribution parameter [-].AirEntryPotential()
Air entry potential [mm].
- class hydpy.models.ga.ga_control.NmbSoils(subvars: SubParameters)[source]¶
Bases:
Parameter
The number of separately modelled soil compartments in the subbasin [-].
- class hydpy.models.ga.ga_control.NmbBins(subvars: SubParameters)[source]¶
Bases:
Parameter
The number of available bins for each soil compartment [-].
- Required by the methods:
Add_SoilWater_V1
Execute_Infiltration_V1
Get_SoilWaterContent_V1
Infiltrate_WettingFrontBins_V1
Merge_FrontDepthOvershootings_V1
Merge_SoilDepthOvershootings_V1
Perform_GARTO_V1
Redistribute_Front_V1
Remove_SoilWater_V1
Return_LastActiveBin_V1
Shift_Front_V1
Water_AllBins_V1
Withdraw_AllBins_V1
Each soil compartment consists of multiple bins. Bins are the “places” where we model individual wetting fronts with different relative moisture values. Hence,
NmbBins
determines the maximum number of wetting fronts we can simulate simultaneously.The first bin is unique, as it is always “filled” (as if its wetting front covers the considered soil column completely). Hence, for a single 1-front Green & Ampt calculation, one must prepare (at least) two bins. Then, the first bin handles the initial soil moisture, while the second bin handles the wetting front’s moisture and depth.
- class hydpy.models.ga.ga_control.DT(subvars: SubParameters)[source]¶
Bases:
Parameter
The length of the numerical substeps [T].
- Required by the methods:
Active_Bin_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Percolate_FilledBin_V1
Perform_GARTO_V1
Redistribute_Front_V1
Return_DryDepth_V1
Set_ActualSurfaceWater_V1
Set_InitialSurfaceWater_V1
Shift_Front_V1
- trim(lower=None, upper=None) bool [source]¶
Adjust
DT
when necessary, so the simulation period is an integer multiple.Assume we want to perform a simulation over intervals of 30 minutes but define
DT
in hours:>>> from hydpy.models.ga import * >>> simulationstep("30m") >>> parameterstep("1h")
A tenth of an hour then is a fifth of the simulation interval:
>>> dt(0.1) >>> dt dt(0.1) >>> dt.value 0.2
The numerical substeps cannot be longer than the simulation intervals:
>>> dt(1.0) >>> dt dt(0.5)
Zero or negative values are also impossible, of course. The chosen minimum numerical stepsize is one second:
>>> dt(0.0) >>> dt dt(0.000278) >>> from hydpy import pub >>> with pub.options.parameterstep("1s"): ... dt dt(1.0)
When necessary, values within the allowed range are reduced to ensure the simulation interval is an integer multiple:
>>> dt(0.3) >>> dt dt(0.25)
- class hydpy.models.ga.ga_control.Sealed(subvars: SubParameters)[source]¶
Bases:
Parameter
Flag indicating if a (soil) compartment is sealed for infiltration [-].
- Required by the methods:
- class hydpy.models.ga.ga_control.SoilArea(subvars: SubParameters)[source]¶
Bases:
Parameter
The area of each soil compartment [km²].
- class hydpy.models.ga.ga_control.SoilDepth(subvars: SubParameters)[source]¶
Bases:
Parameter
Depth of the considered soil domains [mm].
- class hydpy.models.ga.ga_control.ResidualMoisture(subvars: SubParameters)[source]¶
Bases:
Parameter
Relative residual water content [-].
- Required by the methods:
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Percolate_FilledBin_V1
Perform_GARTO_V1
Redistribute_Front_V1
Remove_SoilWater_V1
Return_CapillaryDrive_V1
Return_Conductivity_V1
Return_RelativeMoisture_V1
Shift_Front_V1
Withdraw_AllBins_V1
- trim(lower=None, upper=None) bool [source]¶
Trim
ResidualMoisture
following \(0 \leq ResidualMoisture \leq SaturationMoisture \leq 1\).>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(5) >>> residualmoisture(-0.5, 0.0, 0.5, 1.0, 1.5) >>> residualmoisture residualmoisture(0.0, 0.0, 0.5, 1.0, 1.0)
>>> saturationmoisture.values = 0.4, 0.5, 0.6, 0.7, 0.8 >>> residualmoisture(0.6) >>> residualmoisture residualmoisture(0.4, 0.5, 0.6, 0.6, 0.6)
- class hydpy.models.ga.ga_control.SaturationMoisture(subvars: SubParameters)[source]¶
Bases:
Parameter
Relative saturation water content [-].
- Required by the methods:
Active_Bin_V1
Add_SoilWater_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Percolate_FilledBin_V1
Perform_GARTO_V1
Redistribute_Front_V1
Return_CapillaryDrive_V1
Return_Conductivity_V1
Return_DryDepth_V1
Return_RelativeMoisture_V1
Shift_Front_V1
Water_AllBins_V1
- trim(lower=None, upper=None) bool [source]¶
Trim
SaturationMoisture
following \(0 \leq ResidualMoisture \leq SaturationMoisture \leq 1\).>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(5) >>> saturationmoisture(-0.5, 0.0, 0.5, 1.0, 1.5) >>> saturationmoisture saturationmoisture(0.0, 0.0, 0.5, 1.0, 1.0)
>>> residualmoisture.values = 0.2, 0.3, 0.4, 0.5, 0.6 >>> saturationmoisture(0.4) >>> saturationmoisture saturationmoisture(0.4, 0.4, 0.4, 0.5, 0.6)
- class hydpy.models.ga.ga_control.SaturatedConductivity(subvars: SubParameters)[source]¶
Bases:
Parameter
Saturated hydraulic conductivity [mm/T].
- class hydpy.models.ga.ga_control.PoreSizeDistribution(subvars: SubParameters)[source]¶
Bases:
Parameter
Pore-size distribution parameter [-].
- class hydpy.models.ga.ga_control.AirEntryPotential(subvars: SubParameters)[source]¶
Bases:
Parameter
Air entry potential [mm].
Derived parameters¶
- class hydpy.models.ga.DerivedParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
SubParameters
Derived parameters of model ga.
- The following classes are selected:
NmbSubsteps()
The number of numerical substeps in each simulation step [-].SoilAreaFraction()
The area fraction of each soil compartment [-].EffectiveCapillarySuction()
The effective capillary suction according to the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966) [mm].
- class hydpy.models.ga.ga_derived.NmbSubsteps(subvars: SubParameters)[source]¶
Bases:
Parameter
The number of numerical substeps in each simulation step [-].
- Required by the methods:
- class hydpy.models.ga.ga_derived.SoilAreaFraction(subvars: SubParameters)[source]¶
Bases:
Parameter
The area fraction of each soil compartment [-].
- Required by the methods:
Calc_TotalInfiltration_V1
Calc_TotalPercolation_V1
Calc_TotalSoilWaterAddition_V1
Calc_TotalSurfaceRunoff_V1
Calc_TotalWithdrawal_V1
- update() None [source]¶
Calculate the fractions based on \(SoilAreaFraction_i = SoilArea_i / \Sigma SoilArea\).
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(5) >>> soilarea(10.0, 40.0, 20.0, 25.0, 5.0) >>> derived.soilareafraction.update() >>> derived.soilareafraction soilareafraction(0.1, 0.4, 0.2, 0.25, 0.05)
- class hydpy.models.ga.ga_derived.EffectiveCapillarySuction(subvars: SubParameters)[source]¶
Bases:
Parameter
The effective capillary suction according to the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966) [mm].
- Required by the methods:
Active_Bin_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Perform_GARTO_V1
Redistribute_Front_V1
Return_DryDepth_V1
Shift_Front_V1
- update() None [source]¶
Calculate the effective capillary suction based on the current values of
AirEntryPotential
andPoreSizeDistribution
.The used equation follows equation 13 of Lai et al. (2015) if setting the initial equal to the residual water content:
\(EffectiveCapillarySuction = AirEntryPotential \cdot \frac{3 \cdot PoreSizeDistribution + 2}{3 \cdot PoreSizeDistribution + 1}\)
Sequence Features¶
Input sequences¶
- class hydpy.models.ga.InputSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
InputSequences
Input sequences of model ga.
- The following classes are selected:
Rainfall()
Rainfall [mm/T].CapillaryRise()
Capillary rise [mm/T].Evaporation()
Evaporation [mm/T].
- class hydpy.models.ga.ga_inputs.Rainfall(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
InputSequence
Rainfall [mm/T].
- Required by the method:
- STANDARD_NAME: ClassVar[StandardInputNames] = 'precipitation'¶
- class hydpy.models.ga.ga_inputs.CapillaryRise(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
InputSequence
Capillary rise [mm/T].
- Required by the method:
- STANDARD_NAME: ClassVar[StandardInputNames] = 'capillary_rise'¶
- class hydpy.models.ga.ga_inputs.Evaporation(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
InputSequence
Evaporation [mm/T].
- Required by the method:
- STANDARD_NAME: ClassVar[StandardInputNames] = 'evapotranspiration'¶
Flux sequences¶
- class hydpy.models.ga.FluxSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
FluxSequences
Flux sequences of model ga.
- The following classes are selected:
SurfaceWaterSupply()
Water supply to the soil’s surface [mm/T].SoilWaterSupply()
Water supply to the soil’s body (e.g., capillary rise) [mm/T].Demand()
(Potential) water withdrawal from the soil’s surface and body [mm/T].Infiltration()
Infiltration through the soil’s surface [mm/T].Percolation()
Percolation through the soil’s bottom [mm/T].SoilWaterAddition()
Actual addition of soil water due to processes like capillary rise [mm/T].Withdrawal()
Withdrawal from the soil’s surface or body (e.g. due to evaporation) [mm/T].SurfaceRunoff()
Surface runoff [mm/T].TotalInfiltration()
Average infiltration of the whole subbasin [mm/T].TotalPercolation()
Average percolation of the whole subbasin [mm/T].TotalSoilWaterAddition()
Average soil water addition to the whole subbasin [mm/T].TotalWithdrawal()
Average withdrawal of the whole subbasin [mm/T].TotalSurfaceRunoff()
Average surface runoff of the whole subbasin [mm/T].
- class hydpy.models.ga.ga_fluxes.SurfaceWaterSupply(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Water supply to the soil’s surface [mm/T].
- Calculated by the method:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.SoilWaterSupply(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Water supply to the soil’s body (e.g., capillary rise) [mm/T].
- Calculated by the methods:
- Required by the methods:
- class hydpy.models.ga.ga_fluxes.Demand(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
(Potential) water withdrawal from the soil’s surface and body [mm/T].
- Calculated by the methods:
- Required by the methods:
- class hydpy.models.ga.ga_fluxes.Infiltration(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Infiltration through the soil’s surface [mm/T].
- Calculated by the methods:
Execute_Infiltration_V1
Get_Infiltration_V1
Perform_GARTO_V1
- Required by the method:
- class hydpy.models.ga.ga_fluxes.Percolation(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Percolation through the soil’s bottom [mm/T].
- Calculated by the methods:
- Updated by the methods:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.SoilWaterAddition(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Actual addition of soil water due to processes like capillary rise [mm/T].
- Calculated by the methods:
- Updated by the method:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.Withdrawal(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Withdrawal from the soil’s surface or body (e.g. due to evaporation) [mm/T].
- Calculated by the methods:
Get_SoilWaterRemoval_V1
Perform_GARTO_V1
Remove_SoilWater_V1
- Updated by the method:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.SurfaceRunoff(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Surface runoff [mm/T].
- Calculated by the methods:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.TotalInfiltration(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Average infiltration of the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalPercolation(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Average percolation of the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalSoilWaterAddition(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Average soil water addition to the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalWithdrawal(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Average withdrawal of the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalSurfaceRunoff(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
FluxSequence
Average surface runoff of the whole subbasin [mm/T].
- Calculated by the method:
State sequences¶
- class hydpy.models.ga.StateSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
StateSequences
State sequences of model ga.
- The following classes are selected:
Moisture()
The relative soil moisture of each bin (within the wetting front) [-].FrontDepth()
The depth of the wetting front in each bin [-].
- class hydpy.models.ga.ga_states.Moisture(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
StateSequence
The relative soil moisture of each bin (within the wetting front) [-].
- Updated by the methods:
Active_Bin_V1
Add_SoilWater_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Merge_FrontDepthOvershootings_V1
Merge_SoilDepthOvershootings_V1
Perform_GARTO_V1
Redistribute_Front_V1
Remove_SoilWater_V1
Shift_Front_V1
Water_AllBins_V1
Withdraw_AllBins_V1
- Required by the methods:
Get_SoilWaterContent_V1
Percolate_FilledBin_V1
Return_CapillaryDrive_V1
Return_Conductivity_V1
Return_DryDepth_V1
Return_LastActiveBin_V1
Return_RelativeMoisture_V1
The current moisture of inactive bins usually equals the “initial moisture” of the first “filled” bin. However, withdrawal (e.g. due to evaporation) can result in moisture values of inactive bins larger than the initial moisture.
ToDo: What is the reason behind this behaviour? Can we change it?
- trim(lower=None, upper=None) bool [source]¶
Trim the relative moisture following \(ResidualMoisture \leq Moisture \leq SaturationMoisture\).
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> nmbbins(5) >>> residualmoisture(0.2, 0.4) >>> saturationmoisture(0.8, 0.6) >>> states.moisture([[0.0, 0.0], ... [0.2, 0.4], ... [0.5, 0.5], ... [0.8, 0.6], ... [1.0, 1.0]]) >>> states.moisture moisture([[0.2, 0.4], [0.2, 0.4], [0.5, 0.5], [0.8, 0.6], [0.8, 0.6]])
- class hydpy.models.ga.ga_states.FrontDepth(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
StateSequence
The depth of the wetting front in each bin [-].
- Updated by the methods:
Active_Bin_V1
Add_SoilWater_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Merge_FrontDepthOvershootings_V1
Merge_SoilDepthOvershootings_V1
Percolate_FilledBin_V1
Perform_GARTO_V1
Redistribute_Front_V1
Remove_SoilWater_V1
Shift_Front_V1
Water_AllBins_V1
Withdraw_AllBins_V1
- Required by the method:
The current wetting front depth of inactive bins is zero. But zero front depth does not necessarily mean a bin is inactive.
- trim(lower=None, upper=None) bool [source]¶
Trim the wetting front depth following \(0 \leq FrontDepth \leq SoilDepth\).
>>> from hydpy.models.ga import * >>> parameterstep() >>> nmbsoils(2) >>> nmbbins(5) >>> soildepth(100.0, 500.0) >>> states.frontdepth([[-10.0, -10.0], ... [0.0, 0.0], ... [50.0, 250.0], ... [100.0, 500.0], ... [110.0, 510.0]]) >>> states.frontdepth frontdepth([[0.0, 0.0], [0.0, 0.0], [50.0, 250.0], [100.0, 500.0], [100.0, 500.0]])
Log sequences¶
- class hydpy.models.ga.LogSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
LogSequences
Log sequences of model ga.
- The following classes are selected:
MoistureChange()
The (last) change in soil moisture of each bin [-].
- class hydpy.models.ga.ga_logs.MoistureChange(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LogSequence
The (last) change in soil moisture of each bin [-].
- Updated by the methods:
Active_Bin_V1
Add_SoilWater_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Merge_FrontDepthOvershootings_V1
Merge_SoilDepthOvershootings_V1
Perform_GARTO_V1
Redistribute_Front_V1
Shift_Front_V1
Water_AllBins_V1
Some methods of
ga_garto
take the direction of the last moisture change as a marker for a bin’s state:ToDo: Would constants like “INACTIVE” or “REDISTRIBUTION” simplify the methods?
Aide sequences¶
- class hydpy.models.ga.AideSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
AideSequences
Aide sequences of model ga.
- The following classes are selected:
InitialSurfaceWater()
The initial surface water depth at the beginning of a numerical substep [mm].ActualSurfaceWater()
The actual surface water depth [mm].
- class hydpy.models.ga.ga_aides.InitialSurfaceWater(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
AideSequence
The initial surface water depth at the beginning of a numerical substep [mm].
- Calculated by the method:
- Updated by the method:
- Required by the methods:
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Shift_Front_V1
- class hydpy.models.ga.ga_aides.ActualSurfaceWater(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
AideSequence
The actual surface water depth [mm].
- Calculated by the method:
- Updated by the methods:
Active_Bin_V1
Execute_Infiltration_V1
Infiltrate_WettingFrontBins_V1
Percolate_FilledBin_V1
Perform_GARTO_V1
Redistribute_Front_V1
Remove_SoilWater_V1
Shift_Front_V1
Withdraw_AllBins_V1
- class hydpy.models.ga.AideSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
AideSequences
Aide sequences of model ga.
- The following classes are selected:
InitialSurfaceWater()
The initial surface water depth at the beginning of a numerical substep [mm].ActualSurfaceWater()
The actual surface water depth [mm].
- class hydpy.models.ga.ControlParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
SubParameters
Control parameters of model ga.
- The following classes are selected:
NmbSoils()
The number of separately modelled soil compartments in the subbasin [-].NmbBins()
The number of available bins for each soil compartment [-].DT()
The length of the numerical substeps [T].Sealed()
Flag indicating if a (soil) compartment is sealed for infiltration [-].SoilArea()
The area of each soil compartment [km²].SoilDepth()
Depth of the considered soil domains [mm].ResidualMoisture()
Relative residual water content [-].SaturationMoisture()
Relative saturation water content [-].SaturatedConductivity()
Saturated hydraulic conductivity [mm/T].PoreSizeDistribution()
Pore-size distribution parameter [-].AirEntryPotential()
Air entry potential [mm].
- class hydpy.models.ga.DerivedParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
SubParameters
Derived parameters of model ga.
- The following classes are selected:
NmbSubsteps()
The number of numerical substeps in each simulation step [-].SoilAreaFraction()
The area fraction of each soil compartment [-].EffectiveCapillarySuction()
The effective capillary suction according to the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966) [mm].
- class hydpy.models.ga.FluxSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
FluxSequences
Flux sequences of model ga.
- The following classes are selected:
SurfaceWaterSupply()
Water supply to the soil’s surface [mm/T].SoilWaterSupply()
Water supply to the soil’s body (e.g., capillary rise) [mm/T].Demand()
(Potential) water withdrawal from the soil’s surface and body [mm/T].Infiltration()
Infiltration through the soil’s surface [mm/T].Percolation()
Percolation through the soil’s bottom [mm/T].SoilWaterAddition()
Actual addition of soil water due to processes like capillary rise [mm/T].Withdrawal()
Withdrawal from the soil’s surface or body (e.g. due to evaporation) [mm/T].SurfaceRunoff()
Surface runoff [mm/T].TotalInfiltration()
Average infiltration of the whole subbasin [mm/T].TotalPercolation()
Average percolation of the whole subbasin [mm/T].TotalSoilWaterAddition()
Average soil water addition to the whole subbasin [mm/T].TotalWithdrawal()
Average withdrawal of the whole subbasin [mm/T].TotalSurfaceRunoff()
Average surface runoff of the whole subbasin [mm/T].
- class hydpy.models.ga.InputSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
InputSequences
Input sequences of model ga.
- The following classes are selected:
Rainfall()
Rainfall [mm/T].CapillaryRise()
Capillary rise [mm/T].Evaporation()
Evaporation [mm/T].
- class hydpy.models.ga.LogSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
LogSequences
Log sequences of model ga.
- The following classes are selected:
MoistureChange()
The (last) change in soil moisture of each bin [-].
- class hydpy.models.ga.StateSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
StateSequences
State sequences of model ga.
- The following classes are selected:
Moisture()
The relative soil moisture of each bin (within the wetting front) [-].FrontDepth()
The depth of the wetting front in each bin [-].