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:
AdHocModelHydPy-GA (base model).
- The following “run methods” are called in the given sequence during each simulation step:
Calc_SurfaceWaterSupply_V1Take rainfall as the possible supply for infiltration through the soil’s surface.Calc_SoilWaterSupply_V1Take capillary rise as the possible supply for water additions through the soil’s bottom.Calc_Demand_V1Take evaporation as the demand for extracting water from the soil’s surface and body.Perform_GARTO_V1Perform the GARTO algorithm for the numerical substeps and aggregate their results.Calc_TotalInfiltration_V1Calculate the average infiltration from all soil compartments.Calc_TotalPercolation_V1Calculate the average percolation from all soil compartments.Calc_TotalSoilWaterAddition_V1Calculate the average soil water addition to all soil compartments.Calc_TotalWithdrawal_V1Calculate the average withdrawal from all soil compartments.Calc_TotalSurfaceRunoff_V1Calculate 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_V1Set the given initial surface water depth for the selected soil compartment.Set_ActualSurfaceWater_V1Set the given actual surface water depth for the selected soil compartment.Set_SoilWaterSupply_V1Set the (potential) water supply to the soil’s body.Set_SoilWaterDemand_V1Set the (potential) water withdrawal from the soil’s surface and body.Execute_Infiltration_V1Calculate infiltration (and percolation).Add_SoilWater_V1Add the (direct) soil water supply to the soil’s body.Remove_SoilWater_V1Remove the water demand from the soil’s body and eventually from the soil’s surface.Get_Infiltration_V1Get the current infiltration to the selected soil compartment.Get_Percolation_V1Get the current percolation from the selected soil compartment.Get_SoilWaterAddition_V1Get the current soil water addition to the selected soil compartment.Get_SoilWaterRemoval_V1Get the current soil (and surface water) withdrawal from the selected soil compartment.Get_SoilWaterContent_V1Get 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_V1Calculate and return the relative soil water content for the given bin-soil combination.Return_Conductivity_V1Based 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_V1Based 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_V1Calculate and return the “dry depth”.Return_LastActiveBin_V1Find the index of the last active bin (that either contains a wetting front or uniform moisture over the complete soil depth).Active_Bin_V1Activate a bin to the right of the bin with the given index.Percolate_FilledBin_V1Calculate the percolation of water through the filled first bin due to gravitational forcing.Shift_Front_V1Increase 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_V1Modify the selected bin’s wetting front depth and relative moisture content based on a Green & Ampt redistribution equation.Infiltrate_WettingFrontBins_V1Process infiltration into the wetting front bins.Merge_FrontDepthOvershootings_V1Merge 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_V1Merge bins with wetting front depth larger than soil depth with their left neighbour bins and add their water excess to percolation.Water_AllBins_V1Water the soil’s body by (potentially) adding water to all active bins.Withdraw_AllBins_V1Take 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:
MethodTake 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:
MethodTake 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:
MethodCalculate and return the relative soil water content for the given bin-soil combination.
- Required by the methods:
Infiltrate_WettingFrontBins_V1Percolate_FilledBin_V1Redistribute_Front_V1Return_CapillaryDrive_V1Return_Conductivity_V1Shift_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_V1prevents 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:
MethodBased 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_V1Infiltrate_WettingFrontBins_V1Percolate_FilledBin_V1Perform_GARTO_V1Redistribute_Front_V1Shift_Front_V1- Required submethod:
- Requires the control parameters:
ResidualMoistureSaturationMoistureSaturatedConductivityPoreSizeDistribution- 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:
MethodBased 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_V1Infiltrate_WettingFrontBins_V1Perform_GARTO_V1Redistribute_Front_V1Shift_Front_V1- Required submethod:
- Requires the control parameters:
ResidualMoistureSaturationMoistureAirEntryPotentialPoreSizeDistribution- 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:
MethodCalculate the percolation of water through the filled first bin due to gravitational forcing.
- Required by the methods:
- Required submethods:
- Requires the control parameters:
DTSoilDepthResidualMoistureSaturationMoistureSaturatedConductivityPoreSizeDistribution- 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_V1sets 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:
MethodCalculate and return the “dry depth”.
- Required by the methods:
Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Perform_GARTO_V1Redistribute_Front_V1Shift_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:
MethodFind 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:
MethodActivate 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_V1is 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_V1for 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_V1does 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_V1corrects 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_V1is 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_V1activates 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_V1refrains from activating another bin:Active_Bin_V1checks 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:
MethodIncrease 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_V1Return_LastActiveBin_V1Return_DryDepth_V1Return_Conductivity_V1Return_CapillaryDrive_V1- Requires the control parameters:
DTNmbBinsSoilDepthResidualMoistureSaturationMoistureSaturatedConductivityAirEntryPotentialPoreSizeDistribution- Requires the derived parameter:
- Requires the aide sequence:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
Method
Shift_Front_V1applies for active wetting front bins that are not the last active bin or that are saturated (MoistureequalsSaturationMoisture). 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
InitialSurfaceWaterinstead ofActualSurfaceWaterassures 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_V1instead 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_V1is 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_V1uses the methodReturn_DryDepth_V1to 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_V1prevents 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_V1works 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_V1never 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:
MethodModify 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_V1Return_DryDepth_V1Return_Conductivity_V1Return_CapillaryDrive_V1- Requires the control parameters:
NmbBinsDTSoilDepthResidualMoistureSaturationMoistureSaturatedConductivityAirEntryPotentialPoreSizeDistribution- Requires the derived parameter:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
Redistribute_Front_V1applies 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_V1then 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_V1might 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_V1prefers 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_V1ensures 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_V1adds 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:
MethodProcess infiltration into the wetting front bins.
- Required by the methods:
- Required submethods:
Return_RelativeMoisture_V1Return_DryDepth_V1Return_Conductivity_V1Return_CapillaryDrive_V1Active_Bin_V1Shift_Front_V1Redistribute_Front_V1- Requires the control parameters:
NmbBinsDTSoilDepthResidualMoistureSaturationMoistureSaturatedConductivityAirEntryPotentialPoreSizeDistribution- Requires the derived parameter:
- Requires the aide sequence:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequence:
Infiltrate_WettingFrontBins_V1does 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_V1is specifically designed forga_garto.Examples:
Instead of triggering actual calculations, we try to show how
Infiltrate_WettingFrontBins_V1selects 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_V1does 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_V1calls eitherShift_Front_V1orRedistribute_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_V1callsShift_Front_V1for 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_V1either callsActive_Bin_V1to 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:
MethodMerge 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_V1only 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_V1also 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_V1deactivates 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_V1must 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:
MethodMerge 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_V1assumes 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_V1also 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_V1deactivates 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:
MethodWater 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_V1equals 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_V1but 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_V1does 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_V1tries 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_V1updates 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_V1deactivates 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_V1adjusts 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:
MethodTake 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_V1equals 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_V1but 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_V1does 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_V1withdraws 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_V1tries 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_V1still 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_V1proceeds 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_V1never 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_V1can 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_V1does 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:
MethodPerform the GARTO algorithm for the numerical substeps and aggregate their results.
- Required submethods:
Return_LastActiveBin_V1Return_Conductivity_V1Return_DryDepth_V1Return_CapillaryDrive_V1Percolate_FilledBin_V1Infiltrate_WettingFrontBins_V1Merge_FrontDepthOvershootings_V1Merge_SoilDepthOvershootings_V1Water_AllBins_V1Withdraw_AllBins_V1- Requires the control parameters:
NmbSoilsNmbBinsDTSoilDepthSealedResidualMoistureSaturationMoistureSaturatedConductivityAirEntryPotentialPoreSizeDistribution- Requires the derived parameters:
- Requires the flux sequences:
- Updates the state sequences:
- Updates the log sequence:
- Updates the aide sequences:
- Calculates the flux sequences:
InfiltrationPercolationSoilWaterAdditionWithdrawalSurfaceRunoff
Method
Perform_GARTO_V1executes its submethodsPercolate_FilledBin_V1,Infiltrate_WettingFrontBins_V1,Merge_FrontDepthOvershootings_V1,Merge_SoilDepthOvershootings_V1,Water_AllBins_V1, andWithdraw_AllBins_V1in 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_gartoessentially apply toPerform_GARTO_V1, too.
- class hydpy.models.ga.ga_model.Calc_TotalInfiltration_V1[source]¶
Bases:
MethodCalculate 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:
MethodCalculate 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:
MethodCalculate 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:
MethodCalculate 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:
MethodCalculate 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:
MethodSet the given initial surface water depth for the selected soil compartment.
- Requires the control parameter:
- Calculates the aide sequence:
Example:
Note that
Set_InitialSurfaceWater_V1multiplies the given value withDTto 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:
MethodSet the given actual surface water depth for the selected soil compartment.
- Requires the control parameter:
- Calculates the aide sequence:
Example:
Note that
Set_ActualSurfaceWater_V1multiplies the given value withDTto 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:
MethodSet 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:
MethodSet 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:
MethodCalculate infiltration (and percolation).
- Required submethods:
Return_LastActiveBin_V1Return_Conductivity_V1Return_DryDepth_V1Return_CapillaryDrive_V1Percolate_FilledBin_V1Infiltrate_WettingFrontBins_V1Merge_FrontDepthOvershootings_V1Merge_SoilDepthOvershootings_V1- Requires the control parameters:
NmbBinsDTSoilDepthResidualMoistureSaturationMoistureSaturatedConductivityAirEntryPotentialPoreSizeDistribution- 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_V1subsequently executes the GARTO methodsPercolate_FilledBin_V1,Infiltrate_WettingFrontBins_V1,Merge_FrontDepthOvershootings_V1, andMerge_SoilDepthOvershootings_V1for all numerical substeps.
- class hydpy.models.ga.ga_model.Add_SoilWater_V1[source]¶
Bases:
MethodAdd 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_V1only callsWithdraw_AllBins_V1.
- class hydpy.models.ga.ga_model.Remove_SoilWater_V1[source]¶
Bases:
MethodRemove 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_V1only callsWithdraw_AllBins_V1. Hence, whetherRemove_SoilWater_V1can 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:
MethodGet 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:
MethodGet 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:
MethodGet 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:
MethodGet 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:
MethodGet 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:
AdHocModelGeneral base class for GARTO-like Green-Ampt models.
- check_waterbalance(initial_conditions: dict[str, dict[str, dict[str, float | ndarray[tuple[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_gartofor some examples.
- property watercontents: ndarray[tuple[Any, ...], dtype[float64]]¶
The unique water content of each soil compartment in mm.
Property
watercontentsgenerally 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
watercontentincludes 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_V1Base class for HydPy-GA models that comply with the
SoilModel_V1submodel 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:
SubParametersControl 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:
ParameterThe number of separately modelled soil compartments in the subbasin [-].
- class hydpy.models.ga.ga_control.NmbBins(subvars: SubParameters)[source]¶
Bases:
ParameterThe number of available bins for each soil compartment [-].
- Required by the methods:
Add_SoilWater_V1Execute_Infiltration_V1Get_SoilWaterContent_V1Infiltrate_WettingFrontBins_V1Merge_FrontDepthOvershootings_V1Merge_SoilDepthOvershootings_V1Perform_GARTO_V1Redistribute_Front_V1Remove_SoilWater_V1Return_LastActiveBin_V1Shift_Front_V1Water_AllBins_V1Withdraw_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,
NmbBinsdetermines 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:
ParameterThe length of the numerical substeps [T].
- Required by the methods:
Active_Bin_V1Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Percolate_FilledBin_V1Perform_GARTO_V1Redistribute_Front_V1Return_DryDepth_V1Set_ActualSurfaceWater_V1Set_InitialSurfaceWater_V1Shift_Front_V1
- trim(lower=None, upper=None) bool[source]¶
Adjust
DTwhen necessary, so the simulation period is an integer multiple.Assume we want to perform a simulation over intervals of 30 minutes but define
DTin 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:
ParameterFlag indicating if a (soil) compartment is sealed for infiltration [-].
- Required by the methods:
- class hydpy.models.ga.ga_control.SoilArea(subvars: SubParameters)[source]¶
Bases:
ParameterThe area of each soil compartment [km²].
- class hydpy.models.ga.ga_control.SoilDepth(subvars: SubParameters)[source]¶
Bases:
ParameterDepth of the considered soil domains [mm].
- class hydpy.models.ga.ga_control.ResidualMoisture(subvars: SubParameters)[source]¶
Bases:
ParameterRelative residual water content [-].
- Required by the methods:
Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Percolate_FilledBin_V1Perform_GARTO_V1Redistribute_Front_V1Remove_SoilWater_V1Return_CapillaryDrive_V1Return_Conductivity_V1Return_RelativeMoisture_V1Shift_Front_V1Withdraw_AllBins_V1
- trim(lower=None, upper=None) bool[source]¶
Trim
ResidualMoisturefollowing \(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:
ParameterRelative saturation water content [-].
- Required by the methods:
Active_Bin_V1Add_SoilWater_V1Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Percolate_FilledBin_V1Perform_GARTO_V1Redistribute_Front_V1Return_CapillaryDrive_V1Return_Conductivity_V1Return_DryDepth_V1Return_RelativeMoisture_V1Shift_Front_V1Water_AllBins_V1
- trim(lower=None, upper=None) bool[source]¶
Trim
SaturationMoisturefollowing \(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:
ParameterSaturated hydraulic conductivity [mm/T].
- class hydpy.models.ga.ga_control.PoreSizeDistribution(subvars: SubParameters)[source]¶
Bases:
ParameterPore-size distribution parameter [-].
- class hydpy.models.ga.ga_control.AirEntryPotential(subvars: SubParameters)[source]¶
Bases:
ParameterAir entry potential [mm].
Derived parameters¶
- class hydpy.models.ga.DerivedParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)
Bases:
SubParametersDerived 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:
ParameterThe number of numerical substeps in each simulation step [-].
- Required by the methods:
- class hydpy.models.ga.ga_derived.SoilAreaFraction(subvars: SubParameters)[source]¶
Bases:
ParameterThe area fraction of each soil compartment [-].
- Required by the methods:
Calc_TotalInfiltration_V1Calc_TotalPercolation_V1Calc_TotalSoilWaterAddition_V1Calc_TotalSurfaceRunoff_V1Calc_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:
ParameterThe effective capillary suction according to the Brooks-Corey soil moisture characteristic model (Brooks and Corey, 1966) [mm].
- update() None[source]¶
Calculate the effective capillary suction based on the current values of
AirEntryPotentialandPoreSizeDistribution.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:
InputSequencesInput 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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
InputSequenceRainfall [mm/T].
- Required by the method:
- STANDARD_NAME: ClassVar[StandardInputNames] = 'precipitation'¶
- class hydpy.models.ga.ga_inputs.CapillaryRise(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
InputSequenceCapillary rise [mm/T].
- Required by the method:
- STANDARD_NAME: ClassVar[StandardInputNames] = 'capillary_rise'¶
- class hydpy.models.ga.ga_inputs.Evaporation(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
InputSequenceEvaporation [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:
FluxSequencesFlux 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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceWater supply to the soil’s surface [mm/T].
- Calculated by the method:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.SoilWaterSupply(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceWater 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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceInfiltration through the soil’s surface [mm/T].
- Calculated by the methods:
Execute_Infiltration_V1Get_Infiltration_V1Perform_GARTO_V1- Required by the method:
- class hydpy.models.ga.ga_fluxes.Percolation(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequencePercolation 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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceActual 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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceWithdrawal from the soil’s surface or body (e.g. due to evaporation) [mm/T].
- Calculated by the methods:
Get_SoilWaterRemoval_V1Perform_GARTO_V1Remove_SoilWater_V1- Updated by the method:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.SurfaceRunoff(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceSurface runoff [mm/T].
- Calculated by the methods:
- Required by the method:
- class hydpy.models.ga.ga_fluxes.TotalInfiltration(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceAverage infiltration of the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalPercolation(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceAverage percolation of the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalSoilWaterAddition(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceAverage soil water addition to the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalWithdrawal(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceAverage withdrawal of the whole subbasin [mm/T].
- Calculated by the method:
- class hydpy.models.ga.ga_fluxes.TotalSurfaceRunoff(subvars: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
FluxSequenceAverage 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:
StateSequencesState 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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
StateSequenceThe relative soil moisture of each bin (within the wetting front) [-].
- Updated by the methods:
Active_Bin_V1Add_SoilWater_V1Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Merge_FrontDepthOvershootings_V1Merge_SoilDepthOvershootings_V1Perform_GARTO_V1Redistribute_Front_V1Remove_SoilWater_V1Shift_Front_V1Water_AllBins_V1Withdraw_AllBins_V1- Required by the methods:
Get_SoilWaterContent_V1Percolate_FilledBin_V1Return_CapillaryDrive_V1Return_Conductivity_V1Return_DryDepth_V1Return_LastActiveBin_V1Return_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: ModelIOSequences[ModelIOSequence, FastAccessIOSequence])[source]¶
Bases:
StateSequenceThe depth of the wetting front in each bin [-].
- Updated by the methods:
Active_Bin_V1Add_SoilWater_V1Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Merge_FrontDepthOvershootings_V1Merge_SoilDepthOvershootings_V1Percolate_FilledBin_V1Perform_GARTO_V1Redistribute_Front_V1Remove_SoilWater_V1Shift_Front_V1Water_AllBins_V1Withdraw_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:
LogSequencesLog 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:
LogSequenceThe (last) change in soil moisture of each bin [-].
Some methods of
ga_gartotake 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:
AideSequencesAide 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:
AideSequenceThe 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_V1Infiltrate_WettingFrontBins_V1Shift_Front_V1
- class hydpy.models.ga.ga_aides.ActualSurfaceWater(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
AideSequenceThe actual surface water depth [mm].
- Calculated by the method:
- Updated by the methods:
Active_Bin_V1Execute_Infiltration_V1Infiltrate_WettingFrontBins_V1Percolate_FilledBin_V1Perform_GARTO_V1Redistribute_Front_V1Remove_SoilWater_V1Shift_Front_V1Withdraw_AllBins_V1
- class hydpy.models.ga.AideSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
AideSequencesAide 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:
SubParametersControl 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:
SubParametersDerived 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:
FluxSequencesFlux 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:
InputSequencesInput 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:
LogSequencesLog 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:
StateSequencesState 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 [-].