diff --git a/.CI/checkHTMLDoc/checkTags.py b/.CI/checkHTMLDoc/checkTags.py index 614be21..95ff380 100644 --- a/.CI/checkHTMLDoc/checkTags.py +++ b/.CI/checkHTMLDoc/checkTags.py @@ -19,7 +19,7 @@ VOID_TAGS = ('area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr') # Tags that should not be used -AVOIDABLE_TAGS = ('b', 'i', 'h1', 'h2', 'h3', 'h6', 'figure', 'figcaption') +AVOIDABLE_TAGS = ('b', 'i', 'h1', 'h2', 'h3', 'h6') def _checkFileTags(file_name): """ diff --git a/OpenHPL/Examples/Gate.mo b/OpenHPL/Examples/Gate.mo new file mode 100644 index 0000000..52e27e4 --- /dev/null +++ b/OpenHPL/Examples/Gate.mo @@ -0,0 +1,94 @@ +within OpenHPL.Examples; +model Gate "Usage of the tainter gate" + extends Modelica.Icons.Example; + inner Data data(SteadyState = true, Vdot_0 = 75) annotation ( + Placement(transformation(extent = {{-100, 80}, {-80, 100}}))); + Modelica.Blocks.Sources.Ramp gateOpening( + height=0, + duration=1000, + offset=1, + startTime=500) annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Waterway.Reservoir upstream( + constantLevel=false, + useLevel=true, + L=10, + W=10) annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Waterway.Reservoir downstream( + h_0=4, + constantLevel=false, + useLevel=true, + L=10, + W=10) annotation (Placement(transformation( + extent={{-10,10},{10,-10}}, + rotation=180, + origin={30,50}))); + Waterway.Gate_HR gate_HR(W=16.5, T=5.6) annotation (Placement(transformation(extent={{-10,40},{10,60}}))); + Modelica.Blocks.Sources.Ramp down_level( + height=0, + duration=1000, + offset=3, + startTime=500) annotation (Placement(transformation(extent={{80,-10},{60,10}}))); + Waterway.Reservoir upstream1( + constantLevel=false, + useLevel=true, + L=10, + W=10) annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Waterway.Reservoir downstream1( + h_0=4, + constantLevel=false, + useLevel=true, + L=10, + W=10) annotation (Placement(transformation( + extent={{-10,10},{10,-10}}, + rotation=180, + origin={30,0}))); + Waterway.Gate gate( + sluice=false, + b=16.5, + r=8.5, + h_h=5.6) annotation (Placement(transformation(extent={{-8,-10},{12,10}}))); + Waterway.Reservoir upstream2( + constantLevel=false, + useLevel=true, + L=10, + W=10) annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Waterway.Reservoir downstream2( + h_0=4, + constantLevel=false, + useLevel=true, + L=10, + W=10) annotation (Placement(transformation( + extent={{-10,10},{10,-10}}, + rotation=180, + origin={30,-50}))); + Waterway.Gate gate_sluice( + sluice=true, + b=16.5, + r=8.5, + h_h=5.6) annotation (Placement(transformation(extent={{-10,-60},{10,-40}}))); + Modelica.Blocks.Sources.Ramp up_level( + height=0, + duration=1000, + offset=5, + startTime=500) annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); +equation + connect(upstream.o, gate_HR.i) annotation (Line(points={{-20,50},{-10,50}}, color={0,128,255})); + connect(gate_HR.o, downstream.o) annotation (Line(points={{10,50},{20,50}}, color={0,128,255})); + connect(gateOpening.y, gate_HR.B) annotation (Line(points={{-19,80},{0,80},{0,62}}, color={0,0,127})); + connect(down_level.y, downstream.level) annotation (Line(points={{59,0},{54,0},{54,56},{42,56}}, color={0,0,127})); + connect(upstream1.o, gate.i) annotation (Line(points={{-20,0},{-8,0}}, color={0,128,255})); + connect(gate.o, downstream1.o) annotation (Line(points={{12,0},{20,0}}, color={0,128,255})); + connect(gateOpening.y, gate.a) annotation (Line(points={{-19,80},{-14,80},{-14,22},{2,22},{2,12}}, + color={0,0,127})); + connect(upstream2.o, gate_sluice.i) annotation (Line(points={{-20,-50},{-10,-50}}, color={0,128,255})); + connect(gate_sluice.o, downstream2.o) annotation (Line(points={{10,-50},{20,-50}}, color={0,128,255})); + connect(gateOpening.y, gate_sluice.a) annotation (Line(points={{-19,80},{-14,80},{-14,-28},{0,-28},{0,-38}}, + color={0,0,127})); + connect(downstream1.level, down_level.y) annotation (Line(points={{42,6},{54,6},{54,0},{59,0}}, color={0,0,127})); + connect(downstream2.level, down_level.y) annotation (Line(points={{42,-44},{54,-44},{54,0},{59,0}}, color={0,0,127})); + connect(up_level.y, upstream.level) annotation (Line(points={{-59,0},{-52,0},{-52,56},{-42,56}}, color={0,0,127})); + connect(upstream1.level, up_level.y) annotation (Line(points={{-42,6},{-52,6},{-52,0},{-59,0}}, color={0,0,127})); + connect(upstream2.level, up_level.y) annotation (Line(points={{-42,-44},{-52,-44},{-52,0},{-59,0}}, color={0,0,127})); + annotation ( + experiment(StopTime=2000, Interval=0.4)); +end Gate; diff --git a/OpenHPL/Examples/package.order b/OpenHPL/Examples/package.order index 7f0f9f9..9ecdaf2 100644 --- a/OpenHPL/Examples/package.order +++ b/OpenHPL/Examples/package.order @@ -7,4 +7,5 @@ DetailedGen DetailedGenFrancis PowerSystemSimple VolumeFlowSource +Gate WithOpenIPSL diff --git a/OpenHPL/Icons/Gate.mo b/OpenHPL/Icons/Gate.mo new file mode 100644 index 0000000..17e5b94 --- /dev/null +++ b/OpenHPL/Icons/Gate.mo @@ -0,0 +1,55 @@ +within OpenHPL.Icons; +partial class Gate "Icons for the gate" + parameter Boolean sluice=false "if true, gate is of type sluice gate, otherwise it is a radial/tainter gate type" annotation (Dialog(group="Type"), choices(checkBox=true)); + annotation (Icon(graphics={ + Rectangle( + extent={{-46,-60},{100,-72}}, + lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Rectangle( + visible = sluice, + extent={{-46,0},{-4,-60}}, + lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Rectangle( + visible = sluice, + extent={{-4,20},{4,-60}}, + lineColor={0,0,0}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-100,0},{-46,-72}}, + lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Ellipse( + visible = not sluice, + extent={{-60,140},{220,-140}}, + lineColor={135,135,135}, + startAngle=155, + endAngle=196, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-100,-72},{100,-80}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Forward), + Rectangle(extent={{-100,100},{100,-100}}, lineColor={0,0,0}), + Text( + lineColor={28,108,200}, + extent={{-90,100},{90,60}}, + textString="%name", + textStyle={TextStyle.Bold}), + Ellipse( + extent={{-2,-4},{2,-8}}, + lineColor={0,0,0}, + fillColor={0,0,0}, + fillPattern=FillPattern.Solid), + Line( + points={{0,-6},{0,100}}, + color={0,0,0}, + pattern=LinePattern.Dash)})); +end Gate; diff --git a/OpenHPL/Icons/package.order b/OpenHPL/Icons/package.order index f98bf83..7c45fcf 100644 --- a/OpenHPL/Icons/package.order +++ b/OpenHPL/Icons/package.order @@ -7,6 +7,7 @@ Surge Fitting DraftTube OpenChannel +Gate ElectroMech Turbine Generator diff --git a/OpenHPL/Resources/Images/TainterGate-backedup.png b/OpenHPL/Resources/Images/TainterGate-backedup.png new file mode 100644 index 0000000..3728460 Binary files /dev/null and b/OpenHPL/Resources/Images/TainterGate-backedup.png differ diff --git a/OpenHPL/Resources/Images/TainterGate-freeflow.png b/OpenHPL/Resources/Images/TainterGate-freeflow.png new file mode 100644 index 0000000..ba2310c Binary files /dev/null and b/OpenHPL/Resources/Images/TainterGate-freeflow.png differ diff --git a/OpenHPL/Resources/Images/TainterGate.png b/OpenHPL/Resources/Images/TainterGate.png new file mode 100644 index 0000000..3e20bb4 Binary files /dev/null and b/OpenHPL/Resources/Images/TainterGate.png differ diff --git a/OpenHPL/UsersGuide/References.mo b/OpenHPL/UsersGuide/References.mo index 545d75b..f376ab7 100644 --- a/OpenHPL/UsersGuide/References.mo +++ b/OpenHPL/UsersGuide/References.mo @@ -3,6 +3,11 @@ model References "References" extends Modelica.Icons.References; annotation (Documentation(info="
+
[Bollrich2019]
+

Gerhard Bollrich: "Technische Hydromechanik 1 (eBook)", + Book, Beuth Verlag GmbH, 2019, + 8th Edition, ISBN 978-3-410-29170-1.

+
[Hinna2021]

Jonas Tveit Hinna: "Modelica model of transient pipe flow in hydraulic laboratory systems using the method of characteristics", diff --git a/OpenHPL/Waterway/Gate.mo b/OpenHPL/Waterway/Gate.mo new file mode 100644 index 0000000..7d03e40 --- /dev/null +++ b/OpenHPL/Waterway/Gate.mo @@ -0,0 +1,153 @@ +within OpenHPL.Waterway; +model Gate "Model of a sluice or tainter gate based on [Bollrich2019]" + outer Data data "Using standard class with system parameters"; + extends Icons.Gate; + extends OpenHPL.Interfaces.ContactPort; + import Modelica.Units.Conversions.to_deg; + parameter SI.Height b "Width of the gate" annotation (Dialog(group="Common")); + parameter SI.Length r "Radius of the gate arm" annotation (Dialog(enable=not sluice, group="Radial/Tainter")); + parameter SI.Height h_h "Height of the hinge above gate bottom" annotation (Dialog(group="Radial/Tainter", enable=not sluice)); + SI.Height h_0 "Inlet water level"; + SI.Height h_2 "Outlet water level"; + SI.Height h_2_limit "Limit of free flow"; + SI.Area A = a*b "Area of the physical gate opening"; + SI.VolumeFlowRate Vdot "Volume flow rate through the gate"; + Real mu_A "Discharge coefficient"; + Real psi "Contraction coefficient"; + //Real psi90 "Contraction coefficient for vertical gate"; + Real chi "Back-up coefficient"; + SI.Angle alpha = C.pi/2 - asin((h_h-a)/r) "Edge angle of the gate"; + Real x,y,z; + Real h0_a = h_0/a; + Real h2_a = h_2/a; + Modelica.Blocks.Interfaces.RealInput a "Opening of the gate [m]" annotation (Placement(transformation( + extent={{-20,-20},{20,20}}, + rotation=270, + origin={0,120}))); +equation + mu_A = psi/sqrt(1+psi*a/h_0); + if sluice then + psi = 1 / (1+ 0.64 * sqrt(1-(a/h_0)^2)) "Sluice gate, i.e. alpha = 90 deg"; + else + psi = 1.3 - 0.8 * sqrt(1 - ((to_deg(alpha)-205)/220)^2) "Normally only valid for a/h_0 --> 0"; + end if; + x = (1-2*psi*a/h_0*(1-psi*a/max(C.small,h_2)))^2; + y = x+z-1; + z = (h_2/h_0)^2; + + h_2_limit = a*psi/2*(sqrt(1+16/(psi*(1+psi*a/h_0)) * (h_0/a))-1); + + if h_2 >= h_2_limit then + chi = sqrt((1+psi*a/h_0) * ((1-2*psi*a/h_0 * (1-psi*a/h_2))- + sqrt((1-2*psi*a/h_0*(1-psi*a/max(C.small,h_2)))^2 + (h_2/h_0)^2 - 1))) "Backed-up flow"; + else + chi = 1 "Free flow"; + end if; + + Vdot = chi * mu_A * A * sqrt(2*data.g*h_0) "Volume flow rate through the gate"; + mdot = Vdot * data.rho "Mass flow rate through the gate"; + i.p = h_0 * data.g * data.rho + data.p_a "Inlet water pressure"; + o.p = h_2 * data.g * data.rho + data.p_a "Outlet water pressure"; + annotation (Documentation(info=" +

Implementation

+

+The calculation of the flow through the gate is approximated for two different regions and is based +on [Bollrich2019]. +Equation numbers and figure numbers given below are in sync with the numbers of [Bollrich2019]. +

+
Free flowing
+ + + + + +
+ \"TainterGate +
Fig. 8.13: Free flow through the tainter gate (source: + [Bollrich2019], page 376)
+

+The free flow can be calculated with: + +$$Q_A = \\mu_A \\cdot A \\cdot \\sqrt{2g\\cdot h_0} \\tag{8.24} $$ +(valid for gate opening higher than the downstream water level) +

+

+With +

+
Opening area
+
$$ A = a\\cdot b $$
+
Discharge coefficient
+
$$ \\mu_A = \\frac{\\psi}{\\sqrt{1+\\frac{\\psi\\cdot a}{h_0}}} \\tag{8.23}$$
+
Contraction coefficient sluice gate (\\(\\alpha=90^\\circ\\))
+
$$ \\psi_{90^\\circ}= \\frac{1}{1+0.64\\cdot \\sqrt{1-(a/h_0)^2}} \\tag{8.25}$$
+
Contraction coefficient radial gate (for \\(a/h_0 \\rightarrow 0\\))
+
$$ \\psi_0(\\alpha)= 1.3 -0.8\\cdot\\sqrt{1-\\left(\\frac{\\alpha -205^\\circ}{220^\\circ}\\right)^2} \\tag{8.25a}$$
+
The edge angle \\(\\alpha\\) of the gate
+
$$ \\alpha = \\left( \\frac{\\pi}{2} - \\arcsin(\\frac{h_h-a}{r})\\right) \\cdot \\frac{180^\\circ}{\\pi} $$
+
+
+With: +
    +
  • \\(a \\ldots\\) Vertical gate opening
  • +
  • \\(h_h \\ldots\\) Height of the hinge above gate bottom\"
  • +
  • \\(r \\ldots\\) Radius of the gate arm
  • +
+
+ +
Backed-up discharge
+ + + + + +
+ \"TainterGate +
Fig. 8.16: Backed-up flow through the tainter gate (source: + [Bollrich2019], page 379)
+

+$$Q_A = \\chi \\cdot \\mu_A \\cdot A \\cdot \\sqrt{2g\\cdot h_0} \\tag{8.29} $$ + +With +

+
+
Back-up coefficient
+
$$ \\chi = \\sqrt{ + \\left( + 1 + \\frac{\\psi\\cdot a}{h_0} + \\right) \\cdot + \\left\\{ + \\left[ + 1 - 2\\cdot\\frac{\\psi\\cdot a}{h_0} \\cdot + \\left( + 1-\\frac{\\psi\\cdot a}{h_2} + \\right) + \\right] + - \\sqrt{ + \\left[ + 1 - 2 \\cdot \\frac{\\psi\\cdot a}{h_0} \\cdot + \\left( + 1-\\frac{\\psi\\cdot a}{h_2} + \\right) + \\right]^2 + + + \\left( + \\frac{h_2}{h_0} + \\right)^2 + - 1 + } + \\right\\} + } \\tag{8.28}$$
+
+ +
Boundary between free and backed-up flow
+

+The boundary of the height of the water level \\(h_2\\) behind the gate from which on the calculation switches to the backed-up flow (8.29) can be derived from: + +$$ \\frac{h_2^*}{a} = \\frac{\\psi}{2} \\cdot \\left( \\sqrt{ 1 + \\frac{16}{\\psi\\cdot\\left(1+\\frac{\\psi\\cdot a}{h_0}\\right)}\\cdot\\frac{h_0}{a}} - 1 \\right) \\tag{8.26}$$ + +So when \\(\\frac{h_2}{a} \\geq \\frac{h_2^*}{a}\\) then we have back-up flow. +

+")); +end Gate; diff --git a/OpenHPL/Waterway/Gate_HR.mo b/OpenHPL/Waterway/Gate_HR.mo new file mode 100644 index 0000000..ba2a46e --- /dev/null +++ b/OpenHPL/Waterway/Gate_HR.mo @@ -0,0 +1,87 @@ +within OpenHPL.Waterway; +model Gate_HR "Model of a tainter gate (HEC-RAS)" + outer Data data "Using standard class with system parameters"; + extends Icons.Gate(final sluice); + extends OpenHPL.Interfaces.ContactPort; + + parameter SI.Height W "Width of the gated spillway" + annotation (Dialog(group="Geometry")); + parameter SI.Height T "Trunnion height (from spillway crest to trunnion pivot point)" + annotation (Dialog(group="Geometry")); + parameter Real Cd = 0.7 "Discharge coefficient (typically ranges from 0.6 - 0.8)" + annotation (Dialog(group="Coefficients")); + parameter Real TE = 0.16 "Trunnion height exponent, typically about 0.16" + annotation (Dialog(group="Coefficients")); + parameter Real BE = 0.72 "Gate opening exponent, typically about 0.72" + annotation (Dialog(group="Coefficients")); + SI.Length H = h_i "Upstream Energy Head above the spillway crest"; + parameter Real HE = 0.62 "Head exponent, typically about 0.62" + annotation (Dialog(group="Coefficients")); + SI.Height h_i "Inlet water level"; + SI.Height h_o "Outlet water level"; + SI.VolumeFlowRate Vdot "Volume flow rate through the gate"; + Real H_ratio = h_o/h_i "Ratio of outlet to inlet height"; + + Modelica.Blocks.Interfaces.RealInput B "Height of gate opening [m]" annotation (Placement(transformation( + extent={{-20,-20},{20,20}}, + rotation=270, + origin={0,120}))); +protected + SI.VolumeFlowRate Vdot_free "Free base volume flow rate through the gate"; + SI.VolumeFlowRate Vdot_partial "Partially submerged base volume flow rate through the gate"; + SI.VolumeFlowRate Vdot_full "Fully submerged base volume flow rate through the gate"; + Real Cdx "Discharge coefficient tuned for a smooth transition between partially and fully submerged"; + +equation + Vdot_free = sqrt(2*data.g)* W * T^TE * B^BE * h_i^HE "Free flow condition"; + Vdot_partial = sqrt(2*data.g)* W * T^TE * B^BE * (3*(h_i-h_o))^HE "Partially submerged"; + Vdot_full = sqrt(2*data.g*(h_i-h_o))* W * B "Fully submerged"; + Cdx = Cd * Vdot_partial/Vdot_full; + if H_ratio <= 0.67 then + Vdot=Cd * Vdot_free "Free flow condition"; + elseif H_ratio <= 0.8 then + Vdot= Cd * Vdot_partial "Partially submerged"; + else + Vdot= Cdx * Vdot_full "Fully submerged"; + end if; + mdot = Vdot * data.rho "Mass flow rate through the gate"; + i.p = h_i * data.g * data.rho + data.p_a "Inlet water pressure"; + o.p = h_o * data.g * data.rho + data.p_a "Outlet water pressure"; + annotation (Documentation(info=" +

Background

+

+The Tainter Gate (also known as Radial Gate) is modelled based on a simplified calculation + as used in the HEC-RAS simulation software. +More specifically the following documentation is taken from the + +HEC-RAS Hydraulic Reference Manual on Radial Gates. +

+
+ +
Example Radial Gate with an Ogee Spillway Crest [HEC-RAS].
+
+

Implementation

+

+The calculation of the flow through the gate is approximated for three different regions: +

+
Free flowing
+

+$$Q = C_d W T^{T_E} B^{B_E} H^{H_E} \\sqrt{2g} \\tag{1} $$ +(valid for gate opening higher than the downstream water level) +

+
Partially submerged
+

+$$Q = C_d W T^{T_E} B^{B_E} (3H)^{H_E} \\sqrt{2g} \\tag{2} $$ +(valid for the region where the ratio of downstream water level to upstream water level (H_ratio = h_o/h_i) is between 0.67 and 0.8) +

+
Fully submerged
+

+$$Q = C_{dx} A \\sqrt{2gH} \\tag{3}$$ +(otherwise with Cdx being a discharge coefficient tuned for a smooth transition between partially and fully submerged) +

+

+Note: +The use of Cdx is different to the implementaion as done in HEC-RAS. This was done in order to have a smoother transition from the partially to fully submerged region. +

+")); +end Gate_HR; diff --git a/OpenHPL/Waterway/package.order b/OpenHPL/Waterway/package.order index 9c79a5a..c1f5c6f 100644 --- a/OpenHPL/Waterway/package.order +++ b/OpenHPL/Waterway/package.order @@ -6,6 +6,8 @@ Pipe PenstockKP SurgeTank Reservoir +Gate +Gate_HR RunOff_zones RunOff_zones_input VolumeFlowSource