-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Implementing GARTO #89
Comments
The application range of the original Green & Ampt infiltration method is somewhat limited. One assumption is that heavy rainfall occurs in a single period without interruptions, which is invalid for continuous hydrological simulations. Hence, we need to implement one of the available GA extensions. After some pretests, we decided on (first) implementing (parts of) the GARTO method. Like other Green & Ampt with Redistribution (GAR) approaches, GARTO supports the simulation of multiple wetting fronts (of current and past rainfall events) and the redistribution of already existing fronts in the absence of rainfall. Thankfully, two of its authors, Fred L. Ogden and Cary A. Talbot, provided their source code (written in C), which helped a lot in developing the first Python-based prototype. GARTO allows including interactions with a shallow groundwater table. I think, at least for now, there is no need for us to implement this functionality as well. The last decision brings up the topic of finding a good name. First, I thought about naming the new model family HydPy-Inf or similar. However, the name inf of the corresponding base model would collide with NumPy's constant for infinity. More importantly, I think it might prove a bad idea to group Green & Ampt-like methods and other infiltration methods due to the propagation of a variable number of wetting fronts requiring a very different implementation of "normal" state-space-based approaches (relying on the water content of a fixed number of buckets). So, I propose the more precise model family name HydPy-GA. Possible names for the new application model (both from the documentation and source code perspective):
I would favour HydPy-GA (GARTO). The name is a little redundant but still nicely short. ga_garto also reads well. However, the name is an exaggeration, for we do not implement the shallow dynamic water table (for now). My first idea for clarifying the current HydPy implementation only models surface water infiltration (and neglects groundwater rise) is HydPy-GA (GARTO-S) / ga_gartos. The analysis performed by the authors lets us expect that GARTO is computationally much faster than numerical approximations of Richards' original equation. However, we can be sure it is computationally much more demanding than simple scalar bucket approaches. For now, I will strictly follow the provided C source code and implement a fixed numerical step size (explicit Euler method) without any error control. With promising results but too long computation times for our projects, we could revisit this decision later and implement at least simple adaptive error control (e.g. halved stepsize after tolerance violations) or possibly use a more efficient solver (which, I am afraid, would require special handling of the numerous discontinuities, resulting in a massive amount of work; maybe discontinuity locking?). |
The variables' names should be self-explanatory. My suggestions:
Note that following this suggestion, ActualSurfaceWater and InitialSurfaceWater are two aide sequences instead of one state sequence called SurfaceWater. The idea is not to mix interception evaporation losses with infiltration losses. At the start of each numerical substep, rainfall becomes surface water. Next, infiltration removes as much water as possible from this reservoir. In case of infiltration excess, the remaining water becomes surface runoff. Hence, ActualSurfaceWater becomes zero at the end of each numerical substep. If we want to allow a certain ponding level, we must do so with the help of another model. For the desired coupling with HydPy-L, this means that GARTO is responsible for calculating the infiltration and the (potential) surface runoff only and that HydPy-L would model the ponding (or use another submodel for this purpose). Despite being an input factor, I try to handle Evapotranspiration as actual evapotranspiration instead of potential evapotranspiration. This way, the user or the calling model can decide on the method for adjusting evapotranspiration to the actual soil moisture. (What about other soil water losses, e.g. due to lateral outflow (interflow)? Just handle them as additional evapotranspiration? Or find a better, more general name for Evapotranspiration? To be discussed in issue #91. Evapotranspiration is not discussed in the GARTO paper but has been added to the C code later, which allows for taking evaporation before infiltration or from surface water by uncommenting some code lines. I think we should decide on the option that is computationally most efficient and/or allows for the easiest coupling with HydPy-L. Also to be discussed in #91. |
I will leave parameter DT as a primary control parameter for now. Later, if we decide on an adaptive integration algorithm, we can move it to the more hidden solver parameters or even remove it from users' access. For now, its |
I will name the soil and bin index variables s and b in all methods (local variables). |
IMPORTANT: I am afraid GARTO might recalculate Conductivity multiple times for the same bin and numeric time step. Hence, a single call of Calc_Conductivity_V1 might not be enough. A added the arguments s and b to avoid unnecessary recalculations. However, additional calls to Calc_Conductivity_V1 increase complexity. I postpone checking if recalculations actually occur (and if, in which situations) until all integration tests are ready. |
One point puzzling me: I calculate the "dry depth" using with (local variable) and (derived parameter) I think this agrees with the C code. However, the paper uses Does this mean that the C code always calculates the dry depth for the residual moisture ( Maybe this relates to the question of what to do when the moisture of the most-left bin changes (for example, due to evaporation). Still need to think this through...
No, not really: we still use the moisture of the leftmost bin for calculating |
All vectors have the length Based on these considerations: Why not put nan-values in all inactive bins? I think this would clarify each bin's current state and relevance. I am not sure about the terms I should use in the documentation. The paper is a little more abstract and does not use words like "bin". And the C code is not entirely consistent, as it names the first entry "saturated bin" (also "completely saturated domain"). "Saturated" also seems a little misleading, as we might be speaking of the driest part of the moisture domain. I will try it with the following naming conventions:
|
While fixing a few bugs in my code, I encountered the following difference to the C implementation (I hope, I use it correctly): The hourly rainfall values: 4.0, 0.0, 5.0, 0.0, 0.0, 3.0, 0.0 [cm/h] Everything else is pretty standard, except that I set the soil depth to only 0.1 m. In Python, rain infiltrates completely (and partly becomes evaporation and groundwater recharge). For the heaviest event, C runs into This brings up the questions, why the states of both implementations evolve differently (maybe A related question I did not think of so far: If I am correct, shallow soils should always show higher infiltration rates than deep soils with otherwise equal characteristics, because their infiltration fronts cannot become that large, don't they? Do we have to think about restricting the bottom's permeability later for coupling with HydPy-L? |
Not necessarily, as GARTO does neglect capillary drive for the filled bin (I think due to the soil water front touching the ground water). We need to decide on a proper lower boundary assumption for coupling with HydPy-l later. |
After lots of debugging, I found the reason for the different behaviour. It relates to removing water from the filled bin due to evaporation. In the C-implementation, the moisture of the bins stays as is (possibly saturated). In the current Python implementation, I set their moisture values to the new first bin's value. Both operations do not introduce any water volume errors due to dealing with the relative moisture and zero front depth. However, in the next numerical substep, the C-implementation selects the method for pure front shifts (t_o_advance_front) due to saturation, while the Python implementation selects the redistribution method (gar_infiltrate_redistribute). Only t_o_advance_front contains a restriction that prevents overshooting. I suppose t_o_advance_front tends to slightly underestimate infiltration (due to neglecting percolation during the remaining subperiod where the discussed bin is filled), and gar_infiltrate_redistribute tends to (vastly) overestimate infiltration (due to applying capillary forcing during the whole numerical substep). So, I prefer the approach of the C implementation. However, later refactorings which make such hidden dependencies more explicit would be helpful. Two questions are still open:
|
I get the following discontinuous infiltration rates when I let the water evaporate from the soil only (both in the C and the Python implementation): If I allow taking water from the soil's surface first (if available), the rates look much better: So, I go for the latter approach without investigating the reason for the discontinuous rates in the first case. In both cases, evaporation takes place after infiltration and thus takes the remaining surface water only. |
An example for what might happen if one does not prepare enough bins: 4 bins: The most convenient approach seems to automatically extend the number of available bins when necessary during simulation. So far, reallocating arrays is something we prevent entirely during simulations for computational efficiency. It seems a good idea for the given problem, as reallocations should rarely happen. But it might require significant implementation efforts (Python vs C, multiple sequences, related time series objects). |
One thing I do not fully understand is how |
Method |
|
Overshooting the soil's bottom results in percolation (or groundwater recharge), which is more due to numerical inaccuracy than GARTO's concept. In some cases, the related errors seem to be negligible. However, during front redistribution, I found very significant overestimations of percolation when considering evaporation. I hope I fixed it well, but I added the following remark in case not:
Generally, I left more To-Do remarks than usual in a (potential) master branch model. But I expect we need to fine-tune the model later anyhow (when coupling it to other models). |
I added a method named We require this method for coupling GARTO to LARSIM's capillary rise option. Nevertheless, I think adding it to the stand-alone GARTO model is beneficial - at least for testing, which is more straightforward for the stand-alone model than the submodel. Conceptually, everything seems clear. But technically, I am not 100 % certain everything will always run smoothly. As for |
A reminder: in HydPy-L, soil evaporation can be negative. Hence, the coupling of HydPy-L to the GARTO submodel now deals with such cases. However, the GARTO submodel always assumes positive soil evaporation inputs. Maybe, we should change this later? |
We currently aim to support LARSIM-like simulations with HydPy-L that better take infiltration excess into account via a Green & Ampt (GA) infiltration approach. However, HydPy-L is already very complex, and a GA approach suitable for continuous simulations is not too simple either. So, combining the equations of both models is something we should avoid. Instead, we strive for an independently usable GA model that allows for coupling with HydPy-L (and, at best, other "complete" hydrological models like HydPy-H). Unfortunately, this is beyond HydPy's current modularisation functionalities. Extending these functionalities will be non-trivial, but we think it will pay off very soon due to ways to keep our application models smaller and increase the users' flexibility in combining different model modules.
This necessary work will touch on many topics and require many decisions. Hence, we split the discussion into three issues that separately deal with the GA methodology itself (#89), the general approach to couple "complete" application models like HydPy-L with "submodels" like GA (#90), and the specific coupling interface for HydPy-L and GA (#91).
The text was updated successfully, but these errors were encountered: