Skip to content

Commit 8f2eedf

Browse files
Add documentation to the GetLinearSVVariables function.
1 parent 836a034 commit 8f2eedf

File tree

1 file changed

+175
-2
lines changed

1 file changed

+175
-2
lines changed

src/rtctools_channel_flow/calculate_parameters.py

Lines changed: 175 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,40 @@ def IdzFun(q, n, B, m, Sb, Y0, L, shape):
579579

580580

581581
class GetLinearSVVariables:
582+
583+
"""
584+
Pre-compute steady-state and linearized shallow-water (Saint-Venant) variables
585+
for a 1D open-channel flow in a rectangular cross-section.
586+
587+
This helper class sets up arrays at staggered nodes (Q- and H-points) commonly
588+
used in finite-difference schemes for open-channel hydraulics. Given nominal
589+
flow and geometry along the reach, it computes:
590+
- Geometric arrays (top width, area, wetted perimeter, hydraulic radius),
591+
- Kinematic/dynamic arrays (velocity, Froude number, friction slope),
592+
- Auxiliary coefficients (delta, kappa, f2, gamma) used in linearized models.
593+
594+
**Grid and staggering**
595+
- There are `n_level_nodes` water-level (H) nodes along the reach (including
596+
both ends). Discharge (Q) points are located in a staggered manner, resulting
597+
in `2*n_level_nodes - 1` interlaced positions for mixed variables.
598+
- Spatial step: `dx = length / (n_level_nodes - 1)`
599+
600+
**Assumptions**
601+
- Rectangular channel cross-section with constant top width `width` along x.
602+
- Linearly varying nominal depth from downstream (`y_nominal_down`) to upstream
603+
(`y_nominal`), constructed via `np.linspace`.
604+
- Uniform nominal discharge `q_nominal` (replicated across Q-points).
605+
- Hydrostatic pressure distribution and 1D Saint-Venant framework.
606+
- Friction modeled via a Chezy/Manning-like term condensed into
607+
`friction_coefficient` (dimensionless here; ensure consistency with your model).
608+
- Gravitational acceleration is fixed to `g = 9.80665 m/s²`.
609+
610+
**Units (recommended)**
611+
- length, h_b_up, h_b_down, y_nominal, y_nominal_down, width : meters [m]
612+
- q_nominal : cubic meters per second [m³/s]
613+
- friction_coefficient : dimensionless (model-dependent)
614+
"""
615+
582616
def __init__(
583617
self,
584618
n_level_nodes=4,
@@ -591,6 +625,39 @@ def __init__(
591625
y_nominal_down=0,
592626
friction_coefficient=0,
593627
):
628+
629+
"""
630+
Initialize channel and nominal-flow parameters.
631+
632+
Parameters
633+
----------
634+
n_level_nodes : int, default=4
635+
Number of water level (H) nodes along the channel, including both ends.
636+
Must be >= 2 to form at least one segment.
637+
length : float, default=0.0
638+
Channel reach length [m].
639+
h_b_up : float, default=0.0
640+
Upstream bed elevation [m].
641+
h_b_down : float, default=0.0
642+
Downstream bed elevation [m].
643+
q_nominal : float, default=0.0
644+
Nominal discharge, assumed uniform across Q-points [m³/s].
645+
width : float, default=0.0
646+
Channel top width (rectangular section) [m].
647+
y_nominal : float, default=0.0
648+
Nominal *upstream* flow depth [m].
649+
y_nominal_down : float, default=0.0
650+
Nominal *downstream* flow depth [m].
651+
friction_coefficient : float, default=0.0
652+
Friction coefficient (dimensionless). Interpretation depends on your
653+
chosen friction law; ensure consistency across the model.
654+
655+
Notes
656+
-----
657+
This constructor only stores inputs. Call :meth:`getVariables` to compute
658+
all derived arrays.
659+
"""
660+
594661
self.n_level_nodes = n_level_nodes
595662
self.length = length
596663
self.h_b_up = h_b_up
@@ -602,6 +669,82 @@ def __init__(
602669
self.friction_coefficient = friction_coefficient
603670

604671
def getVariables(self):
672+
673+
"""
674+
Compute and store all derived steady/linearized arrays in-place.
675+
676+
After calling this method, the following attributes are created:
677+
678+
Geometry / base fields
679+
----------------------
680+
q0 : list[float], length n_level_nodes + 1
681+
Nominal discharge at Q-points (staggered), replicated from `q_nominal`.
682+
t0 : list[float], length n_level_nodes
683+
Channel top width at H-nodes (constant = `width` for rectangular).
684+
y0 : np.ndarray, length n_level_nodes
685+
Nominal water depth at H-nodes, linearly interpolated from
686+
downstream (`y_nominal_down`) to upstream (`y_nominal`).
687+
a0 : list[float], length n_level_nodes
688+
Wetted area at H-nodes. For rectangular section: `a0 = t0 * y0`.
689+
p0 : list[float], length n_level_nodes
690+
Wetted perimeter at H-nodes. Rectangular: `p0 = t0 + 2*y0`.
691+
r : list[float], length n_level_nodes
692+
Hydraulic radius at H-nodes: `r = a0 / p0`.
693+
694+
Kinematics / dynamics (staggered)
695+
---------------------------------
696+
v0 : list[float], length 2*n_level_nodes - 1
697+
Velocity at staggered Q/H points. Computed via discharge and
698+
adjacent areas depending on the location (Q vs H points).
699+
sf : list[float], length 2*n_level_nodes - 1
700+
Friction slope at staggered points. Uses squared discharge and
701+
a composite term with area and hydraulic radius.
702+
c0 : list[float], length n_level_nodes + 1
703+
Gravity-wave celerity at Q-points (staggered): `c0 = sqrt(g * y)`.
704+
f0 : list[float], length 2*n_level_nodes - 1
705+
Local Froude number at staggered points: `f0 = v0 / c0` (interpolated
706+
where needed).
707+
dydx : list[float], length 2*n_level_nodes - 1
708+
Water-surface slope at staggered points from gradually-varied flow:
709+
`dydx = (s_b - sf) / (1 - f0^2)`, where `s_b` is bed slope.
710+
711+
Linearization auxiliaries
712+
-------------------------
713+
delta : list[float], length n_level_nodes + 1
714+
Array used in linearized momentum relations, coefficient of the
715+
discharge term; set to zeros if
716+
`q_nominal == 0` to avoid division by zero, otherwise computed from
717+
`v0`, `s_b`, and `dydx`.
718+
kappa : list[float], length n_level_nodes
719+
Coefficient derived from linearization for rectangular cross-sections:
720+
`kappa = 7/3 - (4*a0)/(3*t0*p0) * 2` (the final `* 2` reflects the
721+
PDE coefficient due to rectangular geometry).
722+
f2 : list[float], length n_level_nodes
723+
Froude number: `f2 = v0(H)^2 * t0 / (g * a0)`, where `v0(H)`
724+
is taken at the H-indexed staggered position (even index).
725+
gamma : list[float], length n_level_nodes
726+
Coefficient of the water level term, coming from the
727+
Froude-related contributions, and bed slope. Computed at H-nodes.
728+
729+
Notes
730+
-----
731+
- Gravitational acceleration is set to `g = 9.80665 m/s²`.
732+
- Bed slope: `s_b = (h_b_up - h_b_down) / length`.
733+
- Spatial step: `dx = length / (n_level_nodes - 1)`.
734+
- This function does not return a value; it populates instance attributes.
735+
- If `q_nominal == 0`, `delta` is set to a zero array (to prevent division
736+
by zero in `v0` terms).
737+
- The detailed description of this linearization of the Saint-Venant equations
738+
can be found in Litrico, X., & Fromion, V. (2009). Modeling and control of
739+
hydrosystems. London: Springer London.
740+
741+
Raises
742+
------
743+
ZeroDivisionError
744+
If `length == 0` or `n_level_nodes < 2`, divisions by zero may occur.
745+
Ensure inputs are physically meaningful before calling.
746+
"""
747+
605748
s_b = (self.h_b_up - self.h_b_down) / self.length
606749
g_n = 9.80665
607750
dx = self.length / (self.n_level_nodes - 1)
@@ -745,6 +888,38 @@ def getVariables(self):
745888

746889

747890
class GetIDZVariables:
891+
892+
"""
893+
Compute IDZ (Integrator Delay Zero) model variables for a 1D open‑channel flow
894+
segment, based on nominal discharge, geometry, slope, and friction.
895+
896+
This class wraps a call to an external function `IdzFun`, which performs
897+
the core IDZ hydraulic computations and returns:
898+
899+
- Linearized model coefficients: p11, p12, p21, p22
900+
- Upstream/Downstream amplification factors: Au, Ad
901+
- Travel times: tu_hat, td_hat
902+
- Additional geometric outputs: yn, x2 (not stored here)
903+
904+
The class stores the key IDZ coefficients and mean delay time.
905+
906+
**Intended use**
907+
----------------
908+
Instantiate, then call :meth:`getVariables`:
909+
910+
>>> model = GetIDZVariables(length=5000, h_b_up=3, h_b_down=2,
911+
q_nominal=50, width=20, y_nominal=2,
912+
side_slope=2, friction_coefficient=0.03)
913+
>>> model.getVariables()
914+
>>> model.Delay_in_hour, model.p11, model.p12
915+
916+
Notes
917+
-----
918+
- The computation relies on the function `IdzFun`, which must be available
919+
in the current namespace.
920+
- This class stores only a subset of the results produced by `IdzFun`.
921+
"""
922+
748923
def __init__(
749924
self,
750925
length=0,
@@ -797,5 +972,3 @@ def getVariables(self):
797972
self.p22 = p22_inf_hat
798973

799974

800-
# Test function
801-
# res = IdzFun(2.7, 0.02, 7.0, 1.5, 0.0001, 2.1, 7000, 0)

0 commit comments

Comments
 (0)