Least-cost pipe sizing for water distribution and transmission networks, inside QGIS.
Reads and writes EPANET .inp models and has its own steady-state hydraulic solver, so
nothing else needs to be installed.
.inp independently in EPANET
or your usual package, and check the result against the codes and standards that govern your
project. Every design must be reviewed and accepted by a qualified engineer who takes responsibility
for it. The software is provided without warranty of any kind - see LICENSE.You give it a network (an EPANET model), a catalogue of pipes you can actually buy with their rates, and the design rules (minimum pressure, maximum velocity, loading scenarios). It returns the cheapest set of diameters that satisfies every rule in every scenario.
.inp file of the optimised network.
As soon as a run finishes, <your model>_optimised.inp is written next to the model
you loaded - the original file untouched, the same node and pipe IDs, the same patterns, curves,
controls and coordinates, only the diameters (and roughness, if you asked for the catalogue values)
replaced by the optimised ones. Open it in EPANET, WaterGEMS or back in QGIS and it runs straight
away. Use Save optimised .inp... on the Results tab to write it anywhere else, or to
export one of the alternative designs instead of the best one. Switch the automatic write off with
the checkbox on the Optimise tab if you do not want it.Alongside the model you also get a bill of quantities, an HTML report, CSV tables and styled map layers.
<model>_design.gpkg next to the .inp file: nodes and
pipes.| Attribute | Meaning |
|---|---|
opt_mode | size = the optimiser chooses the diameter;
fixed = the pipe stays as it is in the model (existing mains, pumps, valves). |
opt_group | Pipes with the same group name are forced to the same diameter (a single main split into several links, staged contracts, symmetric branches). |
min_dn / max_dn | Allowed DN range for that pipe. |
materials | Comma separated materials the pipe may use
(e.g. DI,MS) - empty means any. |
check_p (1 = pressure is checked here), and
pmin_m / pmax_m per-node overrides.Each row is a size you are willing to lay: material, DN, internal diameter, roughness (Hazen-Williams C, Darcy-Weisbach ks, Manning n - the one matching the model's head-loss formula is used) and the unit rate per metre. Presets are provided for DI K9, HDPE PE100 PN10, PVC-U PN10, steel, and the two research benchmark networks.
Uncheck Use to keep a size in the table but exclude it from this run. "Use the catalogue roughness" replaces the roughness of every sized pipe with the value of the chosen material; switch it off to keep the roughness already in the model.
The small table under the catalogue restricts each material to a DN range, which is how most schemes are actually specified: HDPE up to DN300, ductile iron from DN300 to DN1000, mild steel above DN1000. One row per material, blank = no limit:
| Material | Min DN | Max DN |
|---|---|---|
HDPE-PN6 | 300 | |
DI-K7 | 300 | 1000 |
MS | 1000 |
Fill from catalogue puts one row in for every material in the table above, keeping any
ranges you have already typed. Sizes outside their material's range are removed from the catalogue
before the run, so they cannot turn up in the design, the map or the bill of quantities, and
the log says how many were dropped. A material with no row is unrestricted. The per-pipe
materials attribute on the pipe layer still applies on top of this, so you can also say
"this particular main must be DI" and get the intersection of the two rules.
Save CSV... writes the table below; Load CSV... reads it back. One row per size, one header row, comma separated. The header names are what matter - column order is free, extra columns are ignored, the names are case-insensitive, and a file saved from Excel (with a BOM) loads fine.
| Column | Meaning | If left empty |
|---|---|---|
use | 1 = offer this size to the optimiser, 0 = keep the row but skip it.
true/false, yes/no also work. | used |
material | Short material code - DI, HDPE,
MS... This is the string the pipe layer's materials attribute matches
against. | PIPE |
dn | Nominal size, the label only. Used for grouping and for the
min_dn / max_dn limits on the pipe layer. | copies
id_mm |
id_mm | Internal diameter in mm. This is the number the hydraulics actually use - for plastics it is the bore, not the OD. | copies dn |
hw_c | Hazen-Williams C. | 130 |
dw_ks_mm | Darcy-Weisbach roughness ks in mm. | 0.1 |
cm_n | Chezy-Manning n. | 0.012 |
unit_cost | Rate per metre laid, in your currency. | 0 |
pn | Class or pressure rating, a label only (K9,
PN10). | blank |
Only the roughness column matching the model's head-loss formula is read: hw_c for
Hazen-Williams, dw_ks_mm for Darcy-Weisbach, cm_n for Chezy-Manning. The
other two can hold anything.
use,material,dn,id_mm,hw_c,dw_ks_mm,cm_n,unit_cost,pn 1,DI,100,100,140,0.1,0.012,85,K9 1,DI,150,150,140,0.1,0.012,120,K9 1,HDPE,110,97.4,145,0.02,0.009,24,PN10 0,PVC,160,144.6,150,0.01,0.009,34,PN10
| Setting | Notes |
|---|---|
| Minimum residual pressure | Checked at every junction (or only at junctions with demand). Per-node overrides win. |
| Maximum pressure | 0 = no limit. Sizing can rarely fix a high static head - use PRVs. |
| Maximum / minimum velocity | 0 = no limit. Velocities are checked in every scenario. |
| Max head-loss gradient | m per km; a common transmission-main criterion. Pipes shorter than 2 m are ignored here. |
| Diameters must not increase downstream | Telescoping rule for branched mains. |
The first setting on this tab chooses the formula used for every hydraulic calculation,
exactly like the Friction Method in WaterGEMS' calculation options. Leave it on
As in the model to use whatever the .inp specifies, or force one of:
| Formula | Roughness column used | Typical values |
|---|---|---|
| Hazen-Williams | hw_c - the C value | 140 DI/MS lined, 150 HDPE, 100 old iron |
| Darcy-Weisbach | dw_ks_mm - ks in mm | 0.1 lined, 0.02 plastic, 1-3 old iron |
| Chezy-Manning | cm_n - Manning n | 0.011-0.012 lined, 0.009 plastic |
| Modified Hazen-Williams | mhw_cr - the coefficient CR |
~0.95 DI/MS lined, ~1.02 plastic, ~0.88 older iron |
Modified Hazen-Williams is the Jain, Mohan & Khanna (1978) form used by the CPHEEO
manual and by WaterGEMS:
V = 143.534 CR R0.6575 S0.5525, which rearranges to
hf = 1.005×10-3 L Q1.81 / (CR1.81
D4.81). Note that CR is a coefficient near 1.0 and is not a
Hazen-Williams C. If your catalogue CSV has no mhw_cr column, a CR is derived
for each size from its hw_c, which puts C=140 at about CR=0.95 and C=150 at
about 1.02.
Changing the formula changes what the roughness number means, so the numbers have to change with it, and a design sized under one formula is not the design you get under another. Two things happen automatically when you switch:
.inp always carries the formula you chose: the
HEADLOSS option is rewritten and every pipe roughness is re-expressed in the new
units. Without that the file would hold C values under a Darcy-Weisbach header and EPANET would
silently compute nonsense..inp says HEADLOSS H-W and each pipe's CR is
translated into the Hazen-Williams C that loses the same head at that pipe's own governing design
flow. Because the match is made at the operating point rather than at a nominal velocity, EPANET
reproduces the design to about a millimetre - but it is still a translation, and the
[TITLE] block of every such file carries a warning saying so. The diameters, which are
what you are buying, are the Modified Hazen-Williams design and are not altered.Scenarios are loading cases - every design must satisfy all of the enabled ones: peak hour (demand factor), fire flow at one or more nodes with a lower residual pressure, minimum tank level, a future demand factor, and so on. Empty cells fall back to the global criteria. "Add fire-flow scenario from selected nodes" builds one scenario per selected node.
| Method | When |
|---|---|
| Automatic | Exact MILP if the network is a tree, otherwise the search. |
| Least cost - search | Memetic GA + spanning-tree MILP seeding + iterated local search. For looped networks. |
| Least cost - exact MILP | Branched networks, control valves included: HiGHS proves the global optimum for the catalogue and scenarios given. Requires SciPy (shipped with QGIS). |
| Trade-off curve (Pareto) | NSGA-II: a curve of designs, cost against the Todini resilience index (spare energy in the network) or against the pressure deficit if the budget is fixed. |
Split pipe (exact method only) allows two diameters within one pipe - the classic way to squeeze the last few percent out of a transmission main. The exported .inp then contains the two sub-pipes with a new node between them.
When you press Run optimisation the plugin first sizes every pipe at the largest size that pipe is allowed - which is not always the largest size in the catalogue, because per-pipe DN limits and the material limits by diameter can cap it - and checks the targets against that. If they still cannot be met, no search can help, so it says so and offers to stop rather than spending the whole time limit to return an infeasible design.
The message separates the two faults, because they need opposite fixes:
Nodes with no open path to a source at all are reported separately - that is a model fault (a closed link or a valve status), not a sizing one. The full node lists go to the run log, where they can be copied out.
Set a time limit (the search always uses it fully), optionally several independent runs, and a seed if you need reproducible results. Analyse current design runs the hydraulics of the model as it stands and shows where it fails - a good first step.
Write the optimised .inp when the run finishes (on by default) saves
<model>_optimised.inp beside your model the moment a design is found, so the sized
EPANET model exists even if you close the dialog immediately. The path is echoed in the log and at
the top of the result summary.
The table lists the best design and the alternatives found (or the Pareto front). Selecting a row shows its summary. The buttons:
new_dn, new_id_mm,
q_lps, v_ms... to your own pipe layer.Branched networks. In a tree the flow in every pipe is fixed by the demands, so the head at each node is a linear function of the diameter choice. The least-cost design is then a mixed-integer linear program which HiGHS solves to a proven global optimum - no tuning, no random seed, and a certificate that nothing cheaper exists for that catalogue. With split pipes the same model becomes a pure LP (the Karmeli / Alperovits-Shamir formulation).
A control valve breaks the chain of pipe head losses that ties a node back to its source, so the pressure behind one is not a simple function of the diameters above it. The exact solver handles this rather than refusing the network:
Valves that are simply open, or throttled to a fixed setting (TCV, GPV, PBV), need none of this: on a tree their flow is fixed, so their loss is just a constant on the path.
Every design still goes through the full non-linear solver afterwards. If a valve does not end up in the state it was designed for, that check catches it and the run says so.
Looped networks. Flows depend on the diameters, so the problem is non-convex and no solver can prove optimality in practice. This plugin uses three ingredients together:
On the two standard research benchmarks it reaches the best solutions published in the literature: 419,000 on the Two-Loop network and 6,081,087 on Hanoi (Hazen-Williams as EPANET computes it), typically in well under two minutes.
The built-in solver is a Global Gradient Algorithm (Todini & Pilati) implementation that follows EPANET 2.2 conventions: Hazen-Williams, Darcy-Weisbach (Swamee-Jain with the EPANET transitional interpolation) and Chezy-Manning; minor losses; check valves; pumps (single-point, three-point, multi-point and constant-power curves); PRV, PSV, FCV and TCV valves; reservoirs and tanks as fixed heads. It was verified against EPANET (through WNTR) on the EPANET example networks and on the 3,356-node Net6 and 964-node KY4 models - heads agree to millimetres.
Each formula was checked separately against EPANET on single pipes spanning DN80-2000, 0.5-2 m/s and the usual roughness range: Hazen-Williams agrees to 0.001 %, Chezy-Manning to 0.08 % and Darcy-Weisbach to 0.06 % (a constant offset from EPANET's own friction-factor rounding). The Chezy-Manning coefficient is calibrated against EPANET rather than taken from the textbook form, which is about 1 % out.
The design check is steady state: demand patterns, controls and rules are not simulated (they are preserved unchanged in the exported .inp). Model each critical condition as its own scenario.