civilpy.water_resources package
Open-channel and pipe hydraulics, bridge scour, and ODOT culvert headwall standards.
Submodules
civilpy.water_resources.hydraulics module
ODOT standard culvert headwall and wing-wall lookup tables.
OhioCulvertDesign encapsulates ODOT standard-drawing dimensions,
reinforcement, and concrete quantities for box-culvert headwalls and
wing-walls, keyed by headwall type, design height, and span.
- class civilpy.water_resources.hydraulics.OhioCulvertDesign(hw_type='A', des_h='6.5', span=14, wall_theta='All')[source]
Bases:
objectODOT standard culvert headwall and wing-wall design lookup table.
Encapsulates the Ohio DOT standard drawings for box culvert headwall and wing-wall dimensions, reinforcement sizes, and concrete quantities. Dimensions are keyed by headwall type, design height, and culvert span.
- Headwall_Dimensions
Nested dimension and reinforcement lookup keyed by headwall type → design height → property.
- Type:
civilpy.water_resources.open_channel module
Open-channel flow for rectangular channels: critical/normal depth, Froude number, and the specific-energy curve with alternate depths — the diagram from every hydraulics course.
US units: ft, cfs; Manning with the 1.486 conversion.
Examples
>>> ch = RectangularChannel(width=10, n=0.013, slope=0.002)
>>> round(ch.critical_depth(q=200), 3)
2.316
>>> yn = ch.normal_depth(q=200)
>>> ch.froude(q=200, y=yn) < 1.0 # mild slope -> subcritical
True
- class civilpy.water_resources.open_channel.RectangularChannel(width: float, n: float = 0.013, slope: float = 0.001)[source]
Bases:
object- alternate_depths(q: float, energy: float, tol: float = 1e-08) tuple[float, float][source]
The sub- and supercritical depths sharing the given specific energy (raises if E is below the critical minimum).
- classify_profile(q: float, y: float) str[source]
Gradually-varied-flow profile class (M1, M2, S3, …) for a flow depth
y: slope letter from normal vs. critical depth, zone number from whereysits relative to both.
- friction_slope(q: float, y: float) float[source]
Sf from Manning’s equation at depth
y— the slope that would makeythe normal depth forq.
- gvf_profile(q: float, y_control: float, length: float, n_steps: int = 400, upstream: bool | None = None)[source]
Gradually-varied water-surface profile from a control depth, integrating dy/dx = (S0 - Sf)/(1 - Fr^2) with RK4.
y_controlis the known depth (e.g. pool elevation behind a dam for M1, the brink for M2); integration marcheslengthft upstream for subcritical controls and downstream for supercritical (override withupstream). Returns(x, y)arrays with x positive downstream of the control (so an upstream march has negative stations) — integration stops early if the depth reaches critical, where GVF theory breaks down.
- normal_depth(q: float, tol: float = 1e-08) float[source]
Solve Manning for the uniform-flow depth by bisection.
- plot_gvf_profile(q: float, y_control: float, length: float, ax=None, n_steps: int = 400, upstream: bool | None = None)[source]
Water-surface profile sketch: channel bottom on its slope, the GVF surface, normal and critical depth lines, the energy grade line, and the profile classification (M1, S2, …). Returns the figure.
civilpy.water_resources.pipe_flow module
Pressure-pipe energy and hydraulic grade lines.
A PipeProfile is a chain of pipe segments leaving a reservoir
(or any known energy elevation). Each segment carries Darcy-Weisbach
friction (h_f = f L/D * V^2/2g) plus a lumped minor-loss coefficient
applied at its entrance, so fittings, bends, entrances, and expansions
land where they occur. The EGL steps down at each minor loss and slopes
down along each run; the HGL hangs one velocity head below it — the
classic profile sketch, including the sub-atmospheric warning zone where
the HGL dips below the pipe.
US units: ft, cfs; diameters in inches.
Examples
A 12-in line, 500 ft long, f = 0.02, square entrance (K = 0.5), running 4 cfs out of a reservoir at El. 250:
>>> p = PipeProfile([PipeSegment(500.0, 12.0, f=0.02, k_minor=0.5)],
... node_elevations_ft=[200.0, 180.0],
... source_energy_ft=250.0, q_cfs=4.0)
>>> round(p.velocity_fps(0), 2)
5.09
>>> round(p.total_head_loss(), 2) # friction + entrance
4.23
>>> round(p.egl_at_end(), 2)
245.77
- class civilpy.water_resources.pipe_flow.PipeProfile(segments, node_elevations_ft, source_energy_ft: float, q_cfs: float)[source]
Bases:
objectA reservoir-fed pipe chain with its EGL/HGL profile.
node_elevations_ftare the pipe centerline elevations at each segment end (len(segments) + 1values);source_energy_ftis the starting energy elevation (reservoir water surface).- grade_lines()[source]
Stations and grade-line elevations:
(x, egl, hgl, z_pipe)arrays with two points per segment so minor losses show as vertical EGL drops.
- low_pressure_stations()[source]
(station, margin) pairs where the HGL falls below the pipe — sub-atmospheric pressure, the cavitation/air-binding warning.
civilpy.water_resources.scour module
Bridge scour by the FHWA HEC-18 method.
Implements the local pier-scour (CSU) equation, the contraction-scour
equations (live-bed Laursen and clear-water), and the supporting critical-
velocity and correction-factor relationships from FHWA HEC-18, Evaluating
Scour at Bridges (5th ed., 2012). The bed grain size these equations
need – D50 and D95 – is exactly what a particle-size analysis on a boring
log provides, so pier_scour_from_boring() reads it straight from a
Borehole.
US customary units throughout: lengths in feet, velocities in ft/s, discharge in cubic feet per second, grain sizes in millimetres (converted internally), angles in degrees.
- civilpy.water_resources.scour.G_FT_S2 = 32.2
Gravitational acceleration, ft/s^2.
- civilpy.water_resources.scour.KU_CLEARWATER = 0.0077
Clear-water contraction-scour coefficient Ku, English (HEC-18 Eq. 6.4).
- civilpy.water_resources.scour.KU_CRITICAL_VELOCITY = 11.17
Critical-velocity coefficient Ku, English units (HEC-18 Eq. 6.1).
- civilpy.water_resources.scour.MM_PER_FT = 304.8
Millimetres per foot.
- civilpy.water_resources.scour.PIER_SHAPE_K1 = {'cylinder': 1.0, 'group': 1.0, 'round': 1.0, 'sharp': 0.9, 'square': 1.1}
Pier nose shape factor K1 (HEC-18 Table 7.1).
- class civilpy.water_resources.scour.PierScourResult(scour_depth_ft: float, froude: float, k1: float, k2: float, k3: float, k4: float, d50_mm: float | None = None, d95_mm: float | None = None)[source]
Bases:
objectLocal pier scour with the correction factors that produced it.
- civilpy.water_resources.scour.angle_of_attack_factor(pier_length_ft: float, pier_width_ft: float, skew_deg: float) float[source]
Flow angle-of-attack correction K2 (HEC-18 Eq. 7.2): K2 = (cos theta + (L/a) sin theta)^0.65.
- civilpy.water_resources.scour.armoring_factor_k4(approach_velocity_fps: float, depth_ft: float, pier_width_ft: float, d50_mm: float, d95_mm: float) float[source]
Coarse-bed armoring correction K4 (HEC-18 Eqs. 7.3-7.6).
Applies only when the bed is coarse (D50 >= 2 mm and D95 >= 20 mm); otherwise K4 = 1.0. K4 = 0.4 (VR)^0.15 with a floor of 0.4, where the velocity ratio VR uses the approach velocity for incipient motion at the pier for D50 and D95.
- civilpy.water_resources.scour.clear_water_contraction_scour(contracted_discharge_cfs: float, contracted_width_ft: float, d50_mm: float, existing_depth_ft: float) float[source]
Clear-water contraction scour depth ys (ft), Laursen (HEC-18 Eq. 6.4): y2 = [Ku Q^2 / (Dm^(2/3) W^2)]^(3/7), Dm = 1.25 D50, Ku = 0.0077 (English, Dm in feet); ys = y2 - y0.
- civilpy.water_resources.scour.critical_velocity(depth_ft: float, d50_mm: float) float[source]
Critical (incipient-motion) velocity Vc (ft/s) for bed material of median size
d50_mmat flow depthdepth_ft(HEC-18 Eq. 6.1): Vc = Ku y^(1/6) D50^(1/3), Ku = 11.17 (English), D50 in feet.
- civilpy.water_resources.scour.froude_number(velocity_fps: float, depth_ft: float) float[source]
Froude number Fr = V / sqrt(g y).
- civilpy.water_resources.scour.live_bed_contraction_scour(approach_depth_ft: float, approach_discharge_cfs: float, contracted_discharge_cfs: float, approach_width_ft: float, contracted_width_ft: float, existing_depth_ft: float, k1: float = 0.64) float[source]
Live-bed contraction scour depth ys (ft), Laursen (HEC-18 Eq. 6.2): y2/y1 = (Q2/Q1)^(6/7) (W1/W2)^k1, ys = y2 - y0.
k1is the bed-transport-mode exponent (0.59-0.69; 0.64 default).
- civilpy.water_resources.scour.pier_scour_csu(approach_velocity_fps: float, approach_depth_ft: float, pier_width_ft: float, k1: float = 1.0, k2: float = 1.0, k3: float = 1.1, k4: float = 1.0) float[source]
Local pier scour depth ys (ft) by the CSU equation (HEC-18 Eq. 7.1):
ys = 2.0 K1 K2 K3 K4 y1 (a/y1)^0.65 Fr1^0.43
K1 nose shape, K2 angle of attack, K3 bed condition (1.1 typical plane bed), K4 coarse-bed armoring.
- civilpy.water_resources.scour.pier_scour_from_boring(borehole, streambed_depth_ft: float, approach_velocity_fps: float, approach_depth_ft: float, pier_width_ft: float, pier_length_ft: float | None = None, skew_deg: float = 0.0, shape: str = 'round', k3: float = 1.1) PierScourResult[source]
Local pier scour using the bed gradation from a boring log.
Reads D50 (and D95 for armoring) from the particle-size analysis nearest
streambed_depth_ftinboreholeand applies the CSU equation. K1 comes fromshape(HEC-18 Table 7.1), K2 from the pier geometry andskew_degwhenpier_length_ftis given, and K4 from coarse-bed armoring when the gradation is coarse enough.
Module contents
Water resources engineering package.
Open-channel hydraulics (open_channel),
pressurized pipe flow (pipe_flow), bridge
scour (scour), and ODOT culvert headwall
standards (hydraulics).