Skip to content

Sewer application: measurements behind design choices

Measurements that justify choices in src/noodl/apps/sewer/. The code states the choice and the reasoning; the numbers live here so they can be re-measured. The figures were taken on the development workstation (Windows 11, CPU, PyTorch float64 unless stated) and move with hardware; only their ordering is a claim.

Dense versus sparse head solve

DENSE_SOLVE_MAX_JUNCTIONS = 128 in dynwave.py: up to this many junctions the head solve uses the dense LU (linear_solver="direct"), above it the layer's "auto" (SciPy sparse LU).

Time per pass in ms, dense / sparse, on the binary trees of benchmarks/sewer_dynwave_speed.py:

Junctions Dense Sparse
63 17.6 18.3
127 18.5 19.3
255 21.4 20.2

Reproduce: python benchmarks/sewer_dynwave_speed.py. The crossover sits between 127 and 255 junctions; the dense path avoids SuperLU's per-call conversion on small networks.

Wall slope (K_SWITCH)

The normal-flow slope switch's wall (DynamicWaveConduit) is capped at K_SWITCH times the smaller end junction's grounding. Observed on the drain-down of the tree in tests/apps/sewer/test_dynwave.py (_drain):

  • at 10 x the grounding the head solve failed (50 Newton iterations at t = 520 s);
  • at 1 x it converges.

The heads bound the flow residual of that switch only through the wall slope over the junction's grounding, so a heads-only convergence test stopped a pass short of the fixed point: a flow residual of 3e-5 m3/s was seen. That is why iterate_flow_tol is judged alongside the heads.

Leak law precision

The leak law is built directly as PowerLaw(..., kind="leak") in air.py and not through Orifice, which casts to torch.get_default_dtype() (float32 in this repository). Verification check C1's residual floor, with the leak coefficient in each precision (two residual statistics of the check):

Precision Residuals
float32 leak branch 1.352e-12 / 1.855e-11
float64 leak branch 4.518e-13 / 6.141e-12

Measured when the headspace model was built; the check is the one named C1 in tests/apps/sewer/test_air.py.

Storage quasi-steady agreement

SewerHydraulics storage sweep under constant inflow reaches the quasi-steady solution: relative agreement 5.7e-15 after 200 steps of 60 s. Reproduce with tests/apps/sewer/test_hydraulics.py::test_storage_reaches_the_quasi_steady_fixed_point (the test asserts a tolerance; print the relative difference to see the figure).