From b67cb2b86cb4beb10b1e8105d9a93f0f0dd001a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjarne=20B=C3=B8rresen?= Date: Fri, 30 Jan 2026 13:25:22 +0100 Subject: [PATCH 1/4] Updated BaseValve and Turbine model --- OpenHPL/ElectroMech/BaseClasses/BaseValve.mo | 110 ++++++++----------- OpenHPL/ElectroMech/Turbines/Turbine.mo | 22 +++- 2 files changed, 63 insertions(+), 69 deletions(-) diff --git a/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo b/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo index a15067ee..642e03d1 100644 --- a/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo +++ b/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo @@ -1,76 +1,52 @@ within OpenHPL.ElectroMech.BaseClasses; partial model BaseValve "Simple hydraulic valve (base class)" - outer Data data "Using standard class with global parameters"; - extends OpenHPL.Interfaces.TwoContacts; - + extends OpenHPL.Interfaces.TwoContacts; + outer OpenHPL.Data data "Using standard class with global parameters"; + // parameter Boolean ValveCapacity = true "If checked the valve capacity C_v should be specified, - otherwise specify the nominal values (net head and flow rate)" - annotation (Dialog(group = "Nominal values"), choices(checkBox = true)); - parameter Real C_v = 1 "Valve capacity" - annotation (Dialog(group = "Nominal values", enable = ValveCapacity)); - parameter SI.Height H_n = 100 "Nominal net head" - annotation (Dialog(group = "Nominal values", enable = not ValveCapacity)); - parameter SI.VolumeFlowRate Vdot_n = 3 "Nominal flow rate" - annotation (Dialog(group = "Nominal values", enable = not ValveCapacity)); - parameter SI.PerUnit u_n = 0.95 "Nominal opening" - annotation (Dialog(group = "Nominal values", enable = not ValveCapacity)); - parameter Boolean ConstEfficiency = true "If checked the constant efficiency eta_h is used, - otherwise specify lookup table for efficiency" - annotation (Dialog(group = "Efficiency data"), choices(checkBox = true)); - parameter SI.Efficiency eta_h = 0.9 "Hydraulic efficiency" - annotation (Dialog(group = "Efficiency data", enable = ConstEfficiency)); - parameter Real lookup_table[:, :] = [0, 0.4; 0.2, 0.7; 0.5, 0.9; 0.95, 0.95; 1.0, 0.93] - "Look-up table for the turbine/valve efficiency, described by a table matrix, - where the first column is a pu value of the guide vane opening, - and the second column is a pu value of the turbine efficiency." - annotation (Dialog(group = "Efficiency data", enable = not ConstEfficiency)); - parameter Boolean WaterCompress = false "If checked, the water is compressible" - annotation (Dialog(tab = "Advanced"), choices(checkBox = true)); - - SI.Pressure dp "Pressure drop"; - SI.EnergyFlowRate Kdot_i_tr "Kinetic energy flow"; - SI.MassFlowRate mdot "Mass flow rate"; - SI.VolumeFlowRate Vdot "Flow rate"; - Real C_v_ "Valve capacity"; - - output SI.EnergyFlowRate Wdot_s "Valve power"; - Modelica.Blocks.Tables.CombiTable1Dv look_up_table(table=lookup_table); + otherwise specify the nominal values (net head and flow rate)" annotation( + Dialog(group = "Nominal values"), + choices(checkBox = true)); + parameter Real C_v = 1 "Valve capacity" annotation( + Dialog(group = "Nominal values", enable = ValveCapacity)); + parameter Modelica.Units.SI.Height H_n = 100 "Nominal net head" annotation( + Dialog(group = "Nominal values", enable = not ValveCapacity)); + parameter Modelica.Units.SI.VolumeFlowRate Vdot_n = 3 "Nominal flow rate" annotation( + Dialog(group = "Nominal values", enable = not ValveCapacity)); + parameter Modelica.Units.SI.PerUnit u_n = 1.00 "Nominal opening" annotation( + Dialog(group = "Nominal values", enable = not ValveCapacity)); + parameter Real alpha=1.00 "Exponent of closing curve (if different from 1, the closing law will be non-linear)" annotation(Dialog(tab="Advanced", group = "Closing law")); + // + Modelica.Units.SI.Pressure dp "Pressure drop"; + Modelica.Units.SI.MassFlowRate mdot "Mass flow rate"; + Modelica.Units.SI.VolumeFlowRate Vdot "Flow rate"; protected - Modelica.Blocks.Interfaces.RealInput u(min=0, max=1) - "=1: completely open, =0: completely closed" - annotation (Placement(transformation( - origin={0,70}, - extent={{-10,-10},{10,10}}, - rotation=270), iconTransformation( - extent={{-20,-20},{20,20}}, - rotation=270, - origin={0,80}))); + parameter Real C_v_ = if ValveCapacity then C_v else Vdot_n/sqrt(H_n*data.g*data.rho)/u_n "Define 'valve capacity' based on the nominal values"; + Modelica.Blocks.Interfaces.RealInput u(min = 0, max = 1) "=1: completely open, =0: completely closed" annotation( + Placement(transformation(origin = {0, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 270), iconTransformation(extent = {{-20, -20}, {20, 20}}, rotation = 270, origin = {0, 80}))); + constant Real epsilon = 5.0e-5 "Constant to ensure robust expression for dp vs flow. Trial and error to find suitable value."; equation - i.mdot+o.mdot=0; + i.mdot + o.mdot = 0; mdot = i.mdot; - Vdot = if WaterCompress then mdot / (data.rho * (1 + data.beta * (i.p - data.p_a))) else mdot / data.rho - "Checking for water compressibility"; - look_up_table.u[1] = u "Link the valve opening"; - C_v_ = if ValveCapacity then C_v else Vdot_n/sqrt(H_n*data.g*data.rho/data.p_a)/u_n - "Define 'valve capacity' base on the nominal values"; - dp = Vdot ^ 2 * data.p_a / (C_v_ * max(1e-6, u)) ^ 2 "Valve equation for pressure drop"; + Vdot = mdot/data.rho; + dp*(C_v_*max(epsilon, u^alpha))^2 = Vdot*abs(Vdot) "Valve equation for pressure drop"; dp = i.p - o.p "Link the pressure drop to the ports"; - Kdot_i_tr = dp * Vdot "Energy balance"; - if ConstEfficiency then - Wdot_s = eta_h * Kdot_i_tr; - else - Wdot_s = look_up_table.y[1] * Kdot_i_tr; - end if; - -annotation ( - Documentation(info="

-This is a simple model of hydraulic valve. -The model can use a constant efficiency or varying -efficiency from a lookup-table. -

-

-This model is based on the energy balance of a valve. -The valve capacity can either be specified + annotation ( + Documentation(info= "

+This is a partial, simple model of hydraulic valve.  

This model is based on the energy balance of a valve. +

+Specifically:
+dp*f(opening)=v|v| +
+The function f(opening) is expressed as:
+(C_v_*max(epsilon, u^alpha))^2 +
+When alpha is 1, this implies a linear relation between closing and head loss. +
+

The valve capacity can either be specified directly by the user by specifying C_v or it will be calculated from the nominal head H_n and nominal flow rate Vdot_n.

@@ -82,5 +58,5 @@ The valve power is defined as the product of the valve power and valve efficienc Besides hydraulic input and output, there is an input u for controlling the valve opening.

-")); +")); end BaseValve; diff --git a/OpenHPL/ElectroMech/Turbines/Turbine.mo b/OpenHPL/ElectroMech/Turbines/Turbine.mo index 38806bbb..a0c0a29e 100644 --- a/OpenHPL/ElectroMech/Turbines/Turbine.mo +++ b/OpenHPL/ElectroMech/Turbines/Turbine.mo @@ -4,10 +4,28 @@ model Turbine "Simple turbine model with mechanical connectors" extends BaseClasses.Power2Torque(power(y=Wdot_s)); extends Interfaces.TurbineContacts; extends Icons.Turbine; - + // Modelica.Blocks.Math.Feedback lossCorrection annotation (Placement(transformation(extent={{-50,70},{-30,90}}))); + parameter Boolean ConstEfficiency = true "If checked the constant efficiency eta_h is used, + otherwise specify lookup table for efficiency" + annotation (Dialog(group = "Efficiency data"), choices(checkBox = true)); + parameter SI.Efficiency eta_h = 0.9 "Hydraulic efficiency" + annotation (Dialog(group = "Efficiency data", enable = ConstEfficiency)); + parameter Real lookup_tablee[:, :] = [0, 0.4; 0.2, 0.7; 0.5, 0.9; 0.95, 0.95; 1.0, 0.93] "Look-up table for the turbine/valve efficiency, described by a table matrix, where the first column is a pu value of the guide vane opening, and the second column is a pu value of the turbine efficiency." annotation (Dialog(group = "Efficiency data", enable = not ConstEfficiency)); + + Modelica.Blocks.Tables.CombiTable1Dv look_up_table(table = lookup_tablee, smoothness = Modelica.Blocks.Types.Smoothness.ContinuousDerivative, extrapolation = Modelica.Blocks.Types.Extrapolation.LastTwoPoints) annotation(Placement(transformation(origin = {-76, -74}, extent={{-10,-10},{10,10}}))); + output Modelica.Units.SI.EnergyFlowRate Wdot_s "Turbine power"; +protected + Modelica.Units.SI.EnergyFlowRate Kdot_i_tr "gross hydraulic power"; equation - + look_up_table.u[1] = u "Link the valve opening"; + if ConstEfficiency then + Wdot_s = eta_h * Kdot_i_tr; + else + Wdot_s = look_up_table.y[1] * Kdot_i_tr; + end if; + Kdot_i_tr = dp * Vdot "Energy balance"; + // connect(P_out, lossCorrection.y) annotation (Line( points={{40,110},{40,80},{-31,80}}, color={0,0,127}, From 0a6972786354a3120390548092bc6953d7c5ec8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjarne=20B=C3=B8rresen?= Date: Fri, 30 Jan 2026 13:56:19 +0100 Subject: [PATCH 2/4] Updated .gitignore to exlcude latex intermediate files --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index 87be2d8a..64ceb384 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,12 @@ OpenHPL/Resources/Documents/UsersGuide_src/auto/ OpenHPL/Resources/Documents/Nomenclature.html *.html + + +# LaTeX intermdeiate documnts +*.aux +*.bbl +*.blg +*.log +*.synctex.gz +*.toc \ No newline at end of file From d16cd91a732178d2770ff71df6835b4862d90adc Mon Sep 17 00:00:00 2001 From: Dietmar Winkler Date: Mon, 2 Feb 2026 07:46:39 +0100 Subject: [PATCH 3/4] BaseValve: Code and documentation clean up. --- OpenHPL/ElectroMech/BaseClasses/BaseValve.mo | 75 +++++++++++--------- OpenHPL/Examples/SimpleValve.mo | 4 +- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo b/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo index 642e03d1..389a0b21 100644 --- a/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo +++ b/OpenHPL/ElectroMech/BaseClasses/BaseValve.mo @@ -2,50 +2,61 @@ within OpenHPL.ElectroMech.BaseClasses; partial model BaseValve "Simple hydraulic valve (base class)" extends OpenHPL.Interfaces.TwoContacts; outer OpenHPL.Data data "Using standard class with global parameters"; - // - parameter Boolean ValveCapacity = true "If checked the valve capacity C_v should be specified, - otherwise specify the nominal values (net head and flow rate)" annotation( - Dialog(group = "Nominal values"), - choices(checkBox = true)); - parameter Real C_v = 1 "Valve capacity" annotation( - Dialog(group = "Nominal values", enable = ValveCapacity)); - parameter Modelica.Units.SI.Height H_n = 100 "Nominal net head" annotation( - Dialog(group = "Nominal values", enable = not ValveCapacity)); - parameter Modelica.Units.SI.VolumeFlowRate Vdot_n = 3 "Nominal flow rate" annotation( - Dialog(group = "Nominal values", enable = not ValveCapacity)); - parameter Modelica.Units.SI.PerUnit u_n = 1.00 "Nominal opening" annotation( - Dialog(group = "Nominal values", enable = not ValveCapacity)); - parameter Real alpha=1.00 "Exponent of closing curve (if different from 1, the closing law will be non-linear)" annotation(Dialog(tab="Advanced", group = "Closing law")); - // - Modelica.Units.SI.Pressure dp "Pressure drop"; - Modelica.Units.SI.MassFlowRate mdot "Mass flow rate"; - Modelica.Units.SI.VolumeFlowRate Vdot "Flow rate"; + + parameter Boolean ValveCapacity = true + "If checked, the valve capacity C_v should be specified, + otherwise specify the nominal values (net head and flow rate at nominal opening)" + annotation (Dialog(group = "Nominal values"), choices(checkBox = true)); + parameter Real C_v = 1 "Valve capacity" + annotation (Dialog(group = "Nominal values", enable = ValveCapacity)); + parameter SI.Height H_n = 100 "Nominal net head" + annotation (Dialog(group = "Nominal values", enable = not ValveCapacity)); + parameter SI.VolumeFlowRate Vdot_n = 3 "Nominal volume flow rate" + annotation (Dialog(group = "Nominal values", enable = not ValveCapacity)); + parameter SI.PerUnit u_n = 1 "Nominal opening" + annotation (Dialog(group = "Nominal values", enable = not ValveCapacity)); + parameter Real alpha=1 "Exponent of closing curve (if different from 1, the closing law will be non-linear)" annotation(Dialog(tab="Advanced", group = "Closing law")); + + SI.Pressure dp "Pressure drop"; + SI.MassFlowRate mdot "Mass flow rate"; + SI.VolumeFlowRate Vdot "Volume flow rate"; + protected - parameter Real C_v_ = if ValveCapacity then C_v else Vdot_n/sqrt(H_n*data.g*data.rho)/u_n "Define 'valve capacity' based on the nominal values"; - Modelica.Blocks.Interfaces.RealInput u(min = 0, max = 1) "=1: completely open, =0: completely closed" annotation( - Placement(transformation(origin = {0, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 270), iconTransformation(extent = {{-20, -20}, {20, 20}}, rotation = 270, origin = {0, 80}))); + parameter Real C_v_ = if ValveCapacity then C_v else Vdot_n/sqrt(H_n*data.g*data.rho)/u_n + "Define 'valve capacity' based on the nominal values"; + Modelica.Blocks.Interfaces.RealInput u(min = 0, max = 1) "=1: completely open, =0: completely closed" + annotation (Placement(transformation(origin = {0, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 270), iconTransformation(extent = {{-20, -20}, {20, 20}}, rotation = 270, origin = {0, 80}))); constant Real epsilon = 5.0e-5 "Constant to ensure robust expression for dp vs flow. Trial and error to find suitable value."; + equation i.mdot + o.mdot = 0; mdot = i.mdot; Vdot = mdot/data.rho; dp*(C_v_*max(epsilon, u^alpha))^2 = Vdot*abs(Vdot) "Valve equation for pressure drop"; dp = i.p - o.p "Link the pressure drop to the ports"; - annotation ( - Documentation(info= "

-This is a partial, simple model of hydraulic valve.  

This model is based on the energy balance of a valve. -

    + annotation ( Documentation(info=" +

    +This is a partial, simple model of hydraulic valve.  

    This model is based on the energy balance of a valve. +

    +
    • Mass flow is equal at innflow and outflow
    • The head loss and pressure difference is proportional to square of velocity
    -Specifically:
    +

    +Specifically: +

    +
     dp*f(opening)=v|v|
    -
    -The function f(opening) is expressed as:
    +
    +

    +The function f(opening) is expressed as: +

    +
     (C_v_*max(epsilon, u^alpha))^2
    -
    -When alpha is 1, this implies a linear relation between closing and head loss. -
    +
    +

    +When alpha is 1, this implies a linear relation between closing and head loss. +

    The valve capacity can either be specified directly by the user by specifying C_v or it will be calculated from the nominal head H_n and nominal flow rate Vdot_n. @@ -58,5 +69,5 @@ The valve power is defined as the product of the valve power and valve efficienc Besides hydraulic input and output, there is an input u for controlling the valve opening.

    -")); +")); end BaseValve; diff --git a/OpenHPL/Examples/SimpleValve.mo b/OpenHPL/Examples/SimpleValve.mo index bcf5d959..ad860bec 100644 --- a/OpenHPL/Examples/SimpleValve.mo +++ b/OpenHPL/Examples/SimpleValve.mo @@ -34,9 +34,7 @@ model SimpleValve "Model of a hydropower system with a simple turbine turbine" extent={{-10,-10},{10,10}}))); Waterway.Valve valve( ValveCapacity=false, - C_v=1, - ConstEfficiency=false, - WaterCompress=false) annotation (Placement(transformation(extent={{20,20},{40,40}}))); + C_v=1) annotation (Placement(transformation(extent={{20,20},{40,40}}))); equation connect(reservoir.o, intake.i) annotation ( Line(points={{-80,30},{-70,30}}, color = {28, 108, 200})); From 5bac08143fc28c7825788b2438b274c66740d7b2 Mon Sep 17 00:00:00 2001 From: Dietmar Winkler Date: Mon, 2 Feb 2026 08:02:01 +0100 Subject: [PATCH 4/4] Turbine: Code clean up. --- OpenHPL/ElectroMech/Turbines/Turbine.mo | 33 ++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/OpenHPL/ElectroMech/Turbines/Turbine.mo b/OpenHPL/ElectroMech/Turbines/Turbine.mo index a0c0a29e..6934b22c 100644 --- a/OpenHPL/ElectroMech/Turbines/Turbine.mo +++ b/OpenHPL/ElectroMech/Turbines/Turbine.mo @@ -4,19 +4,24 @@ model Turbine "Simple turbine model with mechanical connectors" extends BaseClasses.Power2Torque(power(y=Wdot_s)); extends Interfaces.TurbineContacts; extends Icons.Turbine; - // - Modelica.Blocks.Math.Feedback lossCorrection annotation (Placement(transformation(extent={{-50,70},{-30,90}}))); - parameter Boolean ConstEfficiency = true "If checked the constant efficiency eta_h is used, - otherwise specify lookup table for efficiency" + + parameter Boolean ConstEfficiency = true + "If checked the constant efficiency eta_h is used, + otherwise specify lookup table for efficiency" annotation (Dialog(group = "Efficiency data"), choices(checkBox = true)); parameter SI.Efficiency eta_h = 0.9 "Hydraulic efficiency" annotation (Dialog(group = "Efficiency data", enable = ConstEfficiency)); - parameter Real lookup_tablee[:, :] = [0, 0.4; 0.2, 0.7; 0.5, 0.9; 0.95, 0.95; 1.0, 0.93] "Look-up table for the turbine/valve efficiency, described by a table matrix, where the first column is a pu value of the guide vane opening, and the second column is a pu value of the turbine efficiency." annotation (Dialog(group = "Efficiency data", enable = not ConstEfficiency)); - - Modelica.Blocks.Tables.CombiTable1Dv look_up_table(table = lookup_tablee, smoothness = Modelica.Blocks.Types.Smoothness.ContinuousDerivative, extrapolation = Modelica.Blocks.Types.Extrapolation.LastTwoPoints) annotation(Placement(transformation(origin = {-76, -74}, extent={{-10,-10},{10,10}}))); + parameter Real lookup_table[:, :] = [0, 0.4; 0.2, 0.7; 0.5, 0.9; 0.95, 0.95; 1.0, 0.93] + "Look-up table for the turbine/valve efficiency, described by a table matrix, where the first column is a pu value of the guide vane opening, and the second column is a pu value of the turbine efficiency." + annotation (Dialog(group = "Efficiency data", enable = not ConstEfficiency)); + Modelica.Blocks.Math.Feedback lossCorrection + annotation (Placement(transformation(extent={{-50,70},{-30,90}}))); + Modelica.Blocks.Tables.CombiTable1Dv look_up_table(table = lookup_table, smoothness = Modelica.Blocks.Types.Smoothness.ContinuousDerivative, extrapolation = Modelica.Blocks.Types.Extrapolation.LastTwoPoints) annotation(Placement(transformation(origin = {-76, -74}, extent={{-10,-10},{10,10}}))); output Modelica.Units.SI.EnergyFlowRate Wdot_s "Turbine power"; + protected - Modelica.Units.SI.EnergyFlowRate Kdot_i_tr "gross hydraulic power"; + SI.EnergyFlowRate Kdot_i_tr "Gross hydraulic power"; + equation look_up_table.u[1] = u "Link the valve opening"; if ConstEfficiency then @@ -25,17 +30,17 @@ equation Wdot_s = look_up_table.y[1] * Kdot_i_tr; end if; Kdot_i_tr = dp * Vdot "Energy balance"; - // + connect(P_out, lossCorrection.y) annotation (Line( points={{40,110},{40,80},{-31,80}}, color={0,0,127}, pattern=LinePattern.Dash)); connect(lossCorrection.u1, power.y) annotation (Line(points={{-48,80},{-88,80},{-88,30},{-81,30}},color={0,0,127})); - connect(frictionLoss.power, lossCorrection.u2) annotation (Line(points={{-1,12},{-40,12},{-40,72}}, - color={0,0,127})); - connect(u_t, u) annotation (Line(points={{-80,120},{-80,90},{0,90},{0,70}}, color={0,0,127})); + connect(frictionLoss.power, lossCorrection.u2) annotation (Line(points={{-1,12},{-40,12},{-40,72}},color={0,0,127})); + connect(u_t, u) annotation (Line(points={{-80,120},{-80,90},{0,90},{0,70}},color={0,0,127})); annotation ( - Documentation(info="

    + Documentation(info=" +

    This is a simple model of the turbine that give possibilities for simplified modelling of the turbine unit. The model can use a constant efficiency or varying efficiency from a lookup-table. @@ -69,5 +74,5 @@ there are inputs as the control signal for the valve opening and also output as textString="P"), Text( extent={{-96,100},{-60,80}}, textColor={0,0,0}, - textString="GVO")})); + textString="Opening")})); end Turbine;