gwsource.traveltime#
Eulerian mean travel time (backward) and mean age (forward) under full mixing.
Water volume and residence time
-------------------------------
The water volume of cell i is V_i = porosity_i x area_i x saturated thickness_i (FlowStep
.saturated_thickness: DATA-SAT x (top - bot), or from heads; confined cells fully saturated; see
gwsource.mf6io). A fully mixed cell is a well-mixed reservoir: the time a parcel spends in it is
exponentially distributed with mean tau_i = V_i / O_i (backward; O_i = gross outflow) or
tau_i = V_i / I_i (forward; I_i = gross inflow); the two are equal when the cell budget closes.
Cells with O_i = 0 (or I_i = 0) have no residence time (NaN) and take no part.
Package nodes of a network step (gwsource.network) have their own water volume
(FlowStep.fixed_volume: SFR reach, lake, MAW well or UZF cell volume from the package budget's
STORAGE VOLUME), so the identities below hold over cells and package nodes alike.
Backward: mean travel time to a destination group
-------------------------------------------------
Let T be the time from a parcel entering cell i until it leaves the model, and D the event
"it leaves through a sink term of the destination group". Under full mixing the residence time
R_i in cell i is independent of the route by which the parcel leaves it, so with
m_i = E[T 1_D] (the capture-weighted expected time) and P_ij = q_ij / O_i:
m_i = E[R_i] P(D) + sum_j P_ij m_j => (I - P) m = tau o F
the same matrix as the backward solve (I - P) F = S D, factorised once (BackwardResult.factor)
and reused with one extra right-hand side per group. The conditional mean travel time is
mean_time_i = m_i / F_i (NaN where F_i <= fraction_threshold)
It is the mean time from entering cell i (from a neighbour or a source term) until leaving the
model through a destination sink term, and it includes the residence in the cell where the
water leaves (for a well, its own cell). mean_time_to_exit_cell removes that last residence:
x solves (I - P) x = tau o (S D) (the expected residence in the cell of exit, weighted by the
probability of exiting there through the destination), and (m - x) / F is the mean time until
the water enters the cell through whose sink term it leaves. Particle trackers that stop
particles on entering a sink cell (MF6 PRT, MODPATH) measure the latter.
Exact identity (backward). Multiply row i of the m-equation by O_i (tau_i O_i = V_i) and sum
over all cells; the intercell terms cancel exactly as in the closure identity
(gwsource.diagnostics), leaving, with Src_i the source total and r_i = I_i - O_i the residual:
sum_i Src_i m_i - sum_i r_i m_i = sum_i V_i F_i
Since sum_i Src_i F_i - sum_i r_i F_i = Q_D (destination inflow), the flux-weighted mean
travel time of all water reaching the destination, sum Src m / sum Src F, equals
sum V F / Q_D up to the residual terms: the water volume that ends at the destination divided
by the destination inflow (a turnover time). For mean_time_to_exit_cell the right-hand side
is sum V F - sum_i tau_i d_i (d_i the destination sink flow in cell i).
Forward: mean age of water from a source group
----------------------------------------------
With Q_ij = q_ji / I_i, tau_i = V_i / I_i and G the source fraction, n_i = E[A 1_S] (A the age
of water leaving cell i since it entered the model, 1_S that it entered through the source
group) satisfies (I - Q) n = tau o G, with the forward matrix. mean_time_i = n_i / G_i is the
mean age of the water in cell i (equal to that of the water leaving it, under full mixing) that
came from the group, including its residence in cell i. Identity, with Snk_i the sink total:
sum_i Snk_i n_i + sum_i r_i n_i = sum_i V_i G_i
so the flux-weighted mean age at all sinks of the water from the group is sum V G / Q_S.
These are means over the mixed distribution, not first advective arrivals: they complement
particle tracking for time-of-travel zone criteria rather than replacing it.
- class gwsource.traveltime.TravelTimeResult(mode, fraction_threshold, water_volume, residence_time, weighted_time, mean_time, mean_time_to_exit_cell, group_volume, group_inflow, mean_transit_time, flux_weighted_time, exit_cell_time=None)[source]#
Bases:
objectPer-group mean travel times (backward) or ages (forward); arrays have one value per cell. weighted_time: m (backward) or n (forward), the fraction-weighted expected time. mean_time: m / F or n / G where the fraction exceeds fraction_threshold, NaN elsewhere. mean_time_to_exit_cell: backward only, (m - x) / F (see module docstring); exit_cell_time holds x. water_volume, residence_time: per cell (residence time NaN where O or I is 0). group_volume: sum V F (sum V G), the water volume that ends at (came from) the group. group_inflow: destination (source) inflow Q of the group. mean_transit_time: group_volume / group_inflow. flux_weighted_time: sum Src m / sum Src F (backward) or sum Snk n / sum Snk G (forward), the flux-weighted mean over all water entering (leaving) the model; equal to mean_transit_time up to the budget residual.
- gwsource.traveltime.cell_porosity(porosity, n_cells)[source]#
Return porosity as a per-cell array from a scalar or an array of the grid's size.
- gwsource.traveltime.water_volume(step, porosity)[source]#
Return V = porosity x area x saturated thickness per cell (0 in inactive cells). Nodes with a fixed volume (package nodes of a network step) take it instead. porosity may also be a dict {model: per-cell porosity} for a network step.
- gwsource.traveltime.residence_time(volume, throughflow)[source]#
Return tau = V / throughflow, NaN where the throughflow is 0.
- gwsource.traveltime.travel_time(step, result, porosity, fraction_threshold=1e-10)[source]#
Return mean travel times (BackwardResult) or mean ages (ForwardResult) of every group. porosity: scalar or one value per cell (required; there is no default). The result must be a gross-accounting trace of this step; its factorisation is reused when it has one.
- Parameters:
step (FlowStep)
result (BackwardResult | ForwardResult)
fraction_threshold (float)
- Return type:
- gwsource.traveltime.travel_time_closure(step, result, tt, group)[source]#
Return the identity sum Src m - sum r m = sum V F (backward) or its forward analogue. Forward: sum Snk n + sum r n = sum V G. Check.error is zero to round-off.
- Parameters:
step (FlowStep)
result (BackwardResult | ForwardResult)
tt (TravelTimeResult)
group (str)
- Return type:
- gwsource.traveltime.exit_cell_closure(step, result, tt, group)[source]#
Return sum Src (m - x) - sum r (m - x) = sum V F - sum tau d (backward only).
- Parameters:
step (FlowStep)
result (BackwardResult)
tt (TravelTimeResult)
group (str)
- Return type: