Skip to content

Water distribution: catalogue

Pressurised water networks: pipes, pumps, valves, tanks and demand (EPANET .inp reader). How the pieces fit together: Water distribution. Every application is set up the same way; see Using noodl.

Import from noodl.apps.water. The full reference, with every parameter, is in the API reference.

Set-up

Build the model and its starting state and inputs.

Name What it does How to call it
build_model Assemble the water model and return (model, state, drivers). build_model(net, *, headloss=None, pda=None, p_min=None, p_req=None, exponent=None, quality=None, coupling='pingpong', dt=None, friction='composite', pipe_form=None, tank_mode='explicit')
initial_drivers build_model's driver template (copied), then values by name (see noodl.refs.drivers_from), then demand: {junction: m3/s withdrawn}, positive, stored as the negative nodal source the head solve takes. initial_drivers(model, *, values=None, demand=None)
initial_state All-zero state, dispatching on each layer's quantity (the app convention), tank levels from the network file; then values by node, tank or pump name (see noodl.refs.state_from): initial_state(model, values={"water.tank_level": {"T1": 4.0}}). initial_state(model, *, values=None)

Network components

Descriptions of the physical objects a network is built from.

Name What it does How to call it
Control One LINK <id> OPEN\|CLOSED IF NODE <tank> BELOW\|ABOVE <level> line. Control(link, status, node, test, level)
Junction A junction: elevation (m) and base demand (m3/s, withdrawn), optionally scaled by a time pattern. Junction(name, elevation, demand=0.0, pattern=None)
Pump A pump from u to v on a head-flow curve (by name), at relative speed. Pump(name, u, v, curve, power=None, speed=1.0)
Reservoir A fixed-head node: total head (m), optionally varied by a time pattern. Reservoir(name, head, pattern=None)
Tank A cylindrical tank: bottom elevation, initial, minimum and maximum water levels and diameter (all m); its level is carried across steps by TankLevels. Tank(name, elevation, init_level, min_level, max_level, diameter)
Valve A valve from u to v: diameter (m), EPANET kind (for example TCV) and its setting (TCV: a loss coefficient; FCV: a flow, m3/s; PBV: a head drop, m), with a minor-loss coefficient. A GPV's setting is its head-loss curve (a curves key). Valve(name, u, v, diameter, kind, setting, minor_loss=0.0, curve=None)
WaterNetwork A pressurised distribution network, in SI, with everything the builder needs. WaterNetwork(junctions, reservoirs=(), tanks=(), pipes=(), pumps=(), valves=(), curves=<factory>, patterns=<factory>, controls=(), demand_pattern=None, pattern_timestep=3600.0, hydraulic_timestep=3600.0, report_timestep=3600.0, duration=0.0, headloss='H-W', options=<factory>, notes=<factory>)
WaterOptions [OPTIONS] keys that change the physics, with EPANET 2.2's own defaults. WaterOptions(demand_model='DDA', minimum_pressure=0.0, required_pressure=0.1, pressure_exponent=0.5, specific_gravity=1.0, viscosity=1.0, flow_units=None)
WaterPipe A pipe from u to v: length and diameter (m), roughness (in the network's head-loss formula's units), a minor-loss coefficient and its status. WaterPipe(name, u, v, length, diameter, roughness, minor_loss=0.0, status='OPEN')

Constitutive laws

The relation between the flow through an edge and the potential difference across it.

Name What it does How to call it
BreakerValve A pressure breaker valve (PBV): EPANET 2.2's pbvcoeff (hydcoeffs.c). BreakerValve(setting, minor, *, kind='pbv')
CompositeDarcyWeisbach
also EpanetDarcyWeisbach
Composite Darcy-Weisbach pipe: Hagen-Poiseuille, Dunlop's cubic, then Swamee-Jain. CompositeDarcyWeisbach(length, diameter, roughness, *, minor_loss=0.0, nu=1.02193344e-06, cfs_per_m3s=None, scale=1.0, rtol=1e-15, max_iter=100, kind='pipe', learnable=False)
FlowControlledPipe A pipe in its resistance form, dp = scale h(q), with the flow an unknown of the layer (build_model's pipe_form="flow"): pipe is the pipe's potential-form law (HazenWilliams or CompositeDarcyWeisbach), whose head_loss gives h. FlowControlledPipe(pipe, *, gradient_floor=0.0, kind='pipe')
FlowControlledPump A pump in its head-gain form, phi_discharge - phi_suction = gain(q), with the flow an unknown of the layer, as EPANET's and wntr's own solvers write it. pump is the pump's PumpCurve, whose head_gain gives the gain (with gradient_floor, EPANET's RQtol, and closed_slope, its CBIG, both in the layer's potential per m^3/s). build_model writes every pump in this form, whatever the pipe_form. FlowControlledPump(pump, *, gradient_floor, closed_slope, kind='pump')
GeneralPurposeValve A general purpose valve (GPV): EPANET 2.2's gpvcoeff (hydcoeffs.c). GeneralPurposeValve(flows, heads, n_points, *, kind='gpv')
HazenWilliams h_L = K q^1.852 + m q^2 with K = 10.666829500036 C^-1.852 d^-4.871 L. HazenWilliams(length, diameter, roughness, *, minor_loss=0.0, dp_transition=1e-09, kind='pipe', learnable=False)
MinorLoss h = m q \|q\| with m = K / (2 g A^2): a throttle control valve (TCV) or any pure minor-loss link. Inverted in closed form, q = sign(h) sqrt(\|h\| / m), with the same laminar blend and both-branch safe substitution as HazenWilliams. MinorLoss(setting, diameter, *, dp_transition=1e-09, kind='valve', learnable=False)
PumpCurve Constant-speed pump on its own edge kind: h_gain = w^2 (h0 - r (q/w)^n). PumpCurve(h0, r, n=2.0, *, speed=1.0, dp_transition=1e-06, status_key=None, kind='pump', learnable=False)
TankStorage A cylindrical tank as storage (build_model(tank_mode="storage")): an edge from the tank's node to a datum at head 0, so that dp is the tank's head times scale and the edge's flow is the net inflow into the tank. The volume above the datum changes by A dH, so in a step of dt. TankStorage(area, head0, *, scale=1.0, kind='tank')

Closures

Functions of the state that compute drivers each step (densities, flows, levels).

Name What it does How to call it
TankLevels Tank levels, simple controls and the boundary heads they prescribe. TankLevels(net, tanks, controls, pump_names, *, dt, reservoir_heads, tank_first_index, head_scale=1.0)

Sources

Nodal sources and withdrawals.

Name What it does How to call it
PressureDrivenDemand The Wagner demand function as a NodeSource (withdrawal, positive OUT). PressureDrivenDemand(nodes, q_required, elevation, *, p_min=0.0, p_req=0.0, exponent=0.5, learnable=False)

Files

Readers and writers of other tools' file formats.

Name What it does How to call it
read_epanet_inp Read the documented subset of an EPANET 2.2 .inp into a WaterNetwork, in SI. read_epanet_inp(path)

Functions

Calculations and helpers.

Name What it does How to call it
link_table One row per link: flow (m3/s), head loss (m) and velocity (m/s); optionally to CSV. link_table(model, state, names=None, *, path=None)
pressure_head Pressure head (m) at every node: the solved head minus the node's elevation. pressure_head(model, state, elevations=None)
composite_friction_factor
also epanet_friction_factor
Composite friction factor for Re > 2000: (f, df/dq). composite_friction_factor(q, e, s)
tank_inflow Net inflow (m3/s) at every tank node, from the layer's solved branch flows. tank_inflow(model, state)
tank_levels Every tank's level (m above its bottom) in state, in either tank_mode. tank_levels(model, state)
three_point_curve EPANET's single-point pump-curve fit: (h0, r, n) for h = h0 - r q^n. three_point_curve(q_design, h_design)
to_kilopascal Metres of head -> kPa, at rho = 998.2 kg/m3 and g = 9.80665 m/s2. to_kilopascal(head)
twoloop The committed hand-made SI fixture (tests/data/water/twoloop_si.inp). twoloop()
water_step One step of dt (s) of a model built with tank_mode="storage": Model.step with water_steady's Newton defaults and pump check, the tank levels stepped implicitly (TankStorage, integration "backward_euler" or "trapezoidal"; trapezoidal needs a step-start state whose tank flows are solved, not the build's zeros). The level controls act on the step-start levels, as EPANET's do. water_step(model, state, drivers, dt, *, integration='backward_euler', **solve_kwargs)
water_steady The quasi-steady state: one Model.steady with tight Newton tolerances. water_steady(model, state, drivers, **solve_kwargs)

Constants and tables

Named values and option tables.

Name Value
DW_SI 0.0826
EPANET_QCF table of 10 entries: CFS, GPM, MGD, IMGD, AFD, LPS, LPM, MLD, ...
FLOW_UNITS table of 10 entries: CFS, GPM, MGD, IMGD, AFD, LPS, LPM, MLD, ...
G 9.80665
HW_SI 10.666829500036