Below is a step‐by‐step explanation of how exfil.c
in EPA SWMM5 processes exfiltration for storage units. The main idea is to handle infiltration (seepage) from the base and sloped banks of a storage node into the surrounding soil—using either a simple constant exfiltration rate or a Green‐Ampt approach.
1. Overview: Storage Node Exfiltration in SWMM
-
Storage nodes can lose water through their bottom and sidewalls. This is called exfiltration.
-
SWMM provides the option for:
- Constant infiltration (Ksat) – If you only specify a saturated hydraulic conductivity.
- Green–Ampt infiltration – If you provide suction head, saturated hydraulic conductivity, and initial moisture deficit (IMD).
-
The Green-Ampt formulation is the same as used for subcatchments, except it’s applied to the bottom and bank areas of a storage node.
2. Key Data Structures
-
TExfil
- Found in
exfil.h
, this struct holds twoTGrnAmpt
objects:btmExfil
: infiltration parameters for the bottom of the storage unit.bankExfil
: infiltration parameters for the banks (sloped side).
- Also stores
btmArea
,bankMinDepth
,bankMaxDepth
,bankMaxArea
—the geometry parameters describing the bottom area and side areas.
- Found in
-
Storage[k].exfil
- Each storage node
k
has an optional pointerexfil
to aTExfil
. If non-NULL, we can compute infiltration through it.
- Each storage node
-
TGrnAmpt
- Data structure for Green-Ampt infiltration parameters (suction head, Ks, IMDmax), plus state variables tracking how much infiltration has occurred so far.
3. Function-by-Function Explanation
3.1 exfil_readStorageParams(...)
int exfil_readStorageParams(int k, char* tok[], int ntoks, int n)
- Reads exfiltration parameters from an input line for storage node
k
. - Tokens might contain:
- Just one value (Ksat).
- Or three values (suction head, Ksat, IMDmax) for Green-Ampt infiltration.
- Steps:
- Checks how many tokens remain after
n
. - If only one token, it interprets it as the saturated conductivity
Ksat
. - Else, it reads three tokens as
suction head
,Ksat
, andIMDmax
. - If
Ksat = 0.0
, no exfiltration is created (returns 0). - Otherwise, it calls
createStorageExfil(...)
to actually build aTExfil
object and store these parameters.
- Checks how many tokens remain after
Why: This parses the user’s input for infiltration/exfiltration parameters and decides if infiltration is constant or if we use a Green-Ampt approach.
3.2 exfil_initState(...)
void exfil_initState(int k)
-
Called at the start of a simulation (or re-initialization) for a storage node
k
. -
What it does:
-
If
Storage[k].exfil
is not NULL, it callsgrnampt_initState
on bothbtmExfil
andbankExfil
to reset infiltration states (like cumulative infiltration, wetting front depth, etc.). -
Determines the geometry of the bottom area and bank area depending on the storage shape:
-
TABULAR
shape:- Uses the user-defined “Storage Curve” in
Curve[i]
. - Looks up area at 0 ft depth to get the bottom area.
- Then scans the table entries to find the “bank” min depth, max depth, and max area.
- Converts these from user units to internal units.
- Uses the user-defined “Storage Curve” in
-
FUNCTIONAL
shape:btmArea = Storage[k].a0
plus optionallya1
ifa2 = 0.0
.- No real max depth or max area, so sets them to
BIG
.
-
CYLINDRICAL
,CONICAL
,PYRAMIDAL
shapes:btmArea = a0
, sets bank depth/area toBIG
.
-
-
-
Why: This sets up the baseline geometry—bottom area used for infiltration, plus the range of depths/areas for the “banks” infiltration.
3.3 exfil_getLoss(...)
double exfil_getLoss(TExfil* exfil, double tStep, double depth, double area)
- Main infiltration logic: how much water exfiltrates (cfs) in the current time step.
- Steps:
- Bottom infiltration:
- If
IMDmax == 0
, we assume a constant infiltration rate =Ksat * Adjust.hydconFactor
.Adjust.hydconFactor
is a monthly/temperature adjustment for hydraulic conductivity.
- Else, calls
grnampt_getInfil(...)
with the bottom infiltration parameters to get the infiltration rate (ft/s). - Multiply that infiltration rate by
exfil->btmArea
to get a flow (cfs).
- If
- Bank infiltration (for side slopes):
- Only if water depth >
exfil->bankMinDepth
. - The bank area is
min(area, exfil->bankMaxArea) - btmArea
.- i.e., total water surface area minus the bottom area, but capped at
bankMaxArea
.
- i.e., total water surface area minus the bottom area, but capped at
- If
IMDmax == 0
, infiltration is just area × Ksat. - Else, we approximate the average depth above the bank using either:
- If actual depth >
bankMaxDepth
, we dodepth = depth - bankMaxDepth + (bankMaxDepth - bankMinDepth)/2
. - If below top of bank,
depth = (depth - bankMinDepth)/2
.
- If actual depth >
- Then calls
grnampt_getInfil(...)
again withbankExfil
parameters and multiplies by the side bank area.
- Only if water depth >
- Returns the total exfiltration rate (cfs).
- Bottom infiltration:
Why: A storage node can have infiltration from both the bottom and the side banks, and the code uses Green-Ampt or constant infiltration to estimate these losses.
3.4 createStorageExfil(...)
int createStorageExfil(int k, double x[])
- Builds a new
TExfil
object for storage nodek
. - Steps:
- Allocates memory for
TExfil
if not already created. - Allocates two
TGrnAmpt
objects: one for bottom infiltration, one for bank infiltration. - Calls
grnampt_setParams(...)
on both with the arrayx[]
(suction head, Ksat, IMDmax). - If memory allocation fails, sets error code.
- Allocates memory for
- Why: This is how SWMM sets up the infiltration (exfiltration) mechanism for a particular storage node.
4. Putting It All Together
- Reading Input: The user’s input line for a storage node might say “Green-Ampt parameters” or just a single Ksat. SWMM calls
exfil_readStorageParams(...)
, which might create aTExfil
if Ksat > 0. - Initialization: During
exfil_initState(...)
, we determine the bottom area and potential bank area for infiltration, set initial infiltration states to zero, etc. - Every Time Step:
- For each storage node with an
exfil
object, SWMM callsexfil_getLoss(...)
to compute infiltration outflow. - That infiltration rate is subtracted from the water volume in the node, thus lowering the node’s depth over time.
- For each storage node with an
The net effect is that storage nodes in SWMM can slowly lose water into the ground, either with a constant infiltration or a Green–Ampt infiltration approach that depends on soil suction, conductivity, and moisture deficit—applied separately to bottom and bank areas.
5. Key Highlights & Design Choices
-
Two Infiltration Regions
- Bottom: Horizontal infiltration area.
- Banks: Sloped infiltration area, which might vary with water depth.
-
Green‐Ampt vs. Constant
- If
IMDmax == 0.0
, infiltration is simply constantKsat × area
. - Otherwise, the modified Green–Ampt approach is used.
- If
-
Monthly/Temperature Adjustments
Adjust.hydconFactor
is a multiplier that can be changed monthly in SWMM’s advanced settings (e.g., water temperature effect on viscosity/conductivity).
-
Shapes
- For
TABULAR
storage shapes, the curve can show how cross-sectional area increases with depth—this code identifies the “bottom area” at depth = 0 and the portion of the surface area that could be considered “bank.”
- For
-
Performance
- Everything is done each time step for each storage node. This approach is straightforward but must be carefully handled if many storage nodes exist.
Overall, exfil.c
is the part of SWMM that converts infiltration input parameters into actual water losses from storage nodes, integrating a Green‐Ampt infiltration model (or a simpler Ksat-based approach) into the dynamic routing of stored water.
No comments:
Post a Comment