gwsource.assemble#

Assemble the linear systems of backward and forward tracing from a FlowStep.

Gross accounting (default). For cell i, with q_ij >= 0 the intercell flow i→j and
q_k the external terms (positive into the cell):
    O_i = sum_j q_ij + sum_{k in i, q_k<0} |q_k|      (total outflow)
    I_i = sum_j q_ji + sum_{k in i, q_k>0} q_k        (total inflow)
    r_i = I_i - O_i                                   (budget residual, reported only)
Backward: F_i - sum_j (q_ij/O_i) F_j = sum_{k in D, q_k<0} |q_k| / O_i
Forward:  G_i - sum_j (q_ji/I_i) G_j = sum_{k in S, q_k>0} q_k / I_i
Cells with O_i = 0 (backward) or I_i = 0 (forward) get an identity row and zero right-hand side.

Strong sinks (TraceConfig.strong_sinks, backward only). A strong-sink cell is absorbing: its
water leaves through its sink terms only, none goes on to its neighbours. With Snk_i the sum of
its sink outflows its row is F_i = sum_{k in D, q_k<0} |q_k| / Snk_i, so its water is split
among the sink groups by their flows.

Net accounting (the reference method, Foley & Black 2013 [FB13]). Edges only:
    s_i = O^edges_i - I^edges_i,   T_i = I^edges_i + max(s_i, 0)
Destination cells are absorbing (f = 1, their out-edges ignored); elsewhere
    f_i = sum_j q_ij f_j / T_i.
Strong-sink cells outside the destination are absorbing with f = 0 (their water goes to their
own sinks).
Forward net mode is the same on the reversed graph with source cells fixed at g = 1.

Net group inflow. Summing the row equations T_i f_i = sum_j q_ij f_j over the cells outside the
destination group D gives, with s+ = max(s, 0),
    sum_i f_i s+_i = sum_{d in D} T_d - sum_{D->D} q - sum_{D->not D} q_ij f_j
and in forward mode, with S the source group and s- = max(-s, 0),
    sum_i g_i s-_i = sum_{s in S} T_s - sum_{S->S} q - sum_{not S->S} q_ji g_j.
The throughflow sum of the fixed cells counts twice the water passing from one fixed cell to
another and the water that leaves the group and comes back (with share f_j or g_j). The net
destination (source) inflow is the throughflow sum less these two terms (net_double_count), so
it counts each passage once and equals the net volume from (to). It depends on the solved
fractions just outside the group, not on the budget alone. With the solved fractions, volume
from (to) minus the net inflow is exactly the sum of the un-normalised row residuals over the
cells outside the group (gwsource.diagnostics).

Matrices are written in "dependency" form: row i of (I - P) refers to the cells whose values
cell i depends on (downstream cells in backward mode, upstream cells in forward mode).
class gwsource.assemble.Edges(src, dst, q)[source]#

Bases: object

Directed intercell flows src→dst with q > 0.
Parameters:
subset(keep)[source]#
Return the edges where keep is True.
Parameters:

keep (ndarray)

Return type:

Edges

class gwsource.assemble.CellBudget(edge_out, edge_in, source, sink)[source]#

Bases: object

Per-cell gross flow totals (all non-negative except the residual).
Parameters:
property outflow: ndarray#
Total outflow O = intercell outflow + sink terms.
property inflow: ndarray#
Total inflow I = intercell inflow + source terms.
property residual: ndarray#
Budget residual r = I - O.
gwsource.assemble.flow_edges(step)[source]#
Return the directed positive-flow edges from the off-diagonal FLOW-JA-FACE entries.
Parameters:

step (FlowStep)

Return type:

Edges

gwsource.assemble.term_totals(step, mask=None)[source]#
Return per-cell (source, sink) totals of the external terms (optionally masked).
Parameters:
Return type:

tuple[ndarray, ndarray]

gwsource.assemble.cell_budget(step, edges=None)[source]#
Return the per-cell gross budget of a FlowStep (edges from flow_edges(step) if not given).
Parameters:
Return type:

CellBudget

gwsource.assemble.system_matrix(n, row, col, q, norm, fixed=None)[source]#
Return I - P with P[row, col] = q / norm[row]; rows with norm 0, or fixed, are identity.
Parameters:
Return type:

csr_matrix

gwsource.assemble.group_term_flows(step, groups, sign)[source]#
Return (cells, groups) totals of |q| over each group's selected terms of the given sign.
Parameters:
Return type:

ndarray

gwsource.assemble.gross_backward_system(step, edges, budget, groups, strong=None)[source]#
Return (I - P, S D) for gross backward tracing; one right-hand-side column per group.

strong: optional mask of strong-sink cells; their rows are F_i = d_i / Snk_i (module doc).
Parameters:
Return type:

tuple[csr_matrix, ndarray]

gwsource.assemble.gross_forward_system(step, edges, budget, groups)[source]#
Return (I - Q, R T) for gross forward tracing; one right-hand-side column per group.
Parameters:
Return type:

tuple[csr_matrix, ndarray]

gwsource.assemble.net_balance(n, edges)[source]#
Return (s, T): net source s = O^edges - I^edges and throughflow T = I^edges + max(s, 0).
Parameters:
Return type:

tuple[ndarray, ndarray]

gwsource.assemble.net_system(n, edges, fixed, throughflow, backward, absorbing=None)[source]#
Return (matrix, rhs) of net-mode tracing with the fixed cells set to 1.

absorbing: optional mask of further cells set to 0 (strong sinks outside the destination).
Parameters:
Return type:

tuple[csr_matrix, ndarray]

gwsource.assemble.net_double_count(edges, fixed, fraction, backward=True)[source]#
Return the water the fixed cells' T sum counts twice: (inside, boundary x f) (module doc).
Parameters:
Return type:

tuple[float, float]

gwsource.assemble.absorbing_edges(edges, fixed, backward)[source]#
Return the edges left once the fixed cells absorb (backward: drop their out-edges).
Parameters:
Return type:

Edges