diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/BaseLimiterWithLag.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/BaseLimiterWithLag.mo new file mode 100644 index 00000000000..157d029fc17 --- /dev/null +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/BaseLimiterWithLag.mo @@ -0,0 +1,134 @@ +within Dynawo.NonElectrical.Blocks.NonLinear.BaseClasses; + +/* +* Copyright (c) 2024, RTE (http://www.rte-france.com) +* See AUTHORS.txt +* All rights reserved. +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, you can obtain one at http://mozilla.org/MPL/2.0/. +* SPDX-License-Identifier: MPL-2.0 +* +* This file is part of Dynawo, an hybrid C++/Modelica open source suite +* of simulation tools for power systems. +*/ + +block BaseLimiterWithLag "Base block of limiter that enforces saturations only after they were violated without interruption during a given amount of time" + import Modelica.Constants; + import Dynawo.NonElectrical.Logs.Timeline; + import Dynawo.NonElectrical.Logs.TimelineKeys; + + extends Modelica.Blocks.Icons.Block; + + parameter Types.Time LagMax "Time lag before taking action when going above UMax"; + parameter Types.Time LagMin "Time lag before taking action when going below UMin"; + parameter Real UMax "Maximum allowed u"; + parameter Real UMin "Minimum allowed u"; + + Modelica.Blocks.Interfaces.RealInput u(start = u0) "Input signal connector" annotation( + Placement(transformation(extent={{-140,-20},{-100,20}}))); + Modelica.Blocks.Interfaces.RealOutput y(start = y0) "Output signal connector" annotation( + Placement(transformation(extent={{100,-10},{120,10}}))); + + discrete Types.Time tUMaxReached(start = tUMaxReached0) "Last time when u went above UMax"; + discrete Types.Time tUMinReached(start = tUMinReached0) "Last time when u went below UMin"; + + Boolean initSaturatedMax(start = (tUMaxReached0 == -Constants.inf)) "If true, simulation starts in max saturated mode"; + Boolean initSaturatedMin(start = (tUMinReached0 == -Constants.inf)) "If true, simulation starts in min saturated mode"; + + parameter Types.Time tUMaxReached0 "Initial time when u went above UMax"; + parameter Types.Time tUMinReached0 "Initial time when u went below UMin"; + parameter Real u0 "Initial input"; + parameter Real y0 "Initial output"; + +equation + when u > UMax then + tUMaxReached = if initSaturatedMax then -Constants.inf else time; + initSaturatedMax = false; + elsewhen u <= UMax then + tUMaxReached = Constants.inf; + initSaturatedMax = false; + end when; + + when u < UMin then + tUMinReached = if initSaturatedMin then -Constants.inf else time; + initSaturatedMin = false; + elsewhen u >= UMin then + tUMinReached = Constants.inf; + initSaturatedMin = false; + end when; + + annotation( + preferredView = "text", + Icon(coordinateSystem( + preserveAspectRatio=true, + extent={{-100,-100},{100,100}}), graphics={ + Line(points={{-80,-56},{-60,-56},{-60,-22},{38,-22},{38,-56},{66,-56}},color={0,0,192}), + Line(points={{-80,32},{18,32},{18,66},{38,66},{38,32},{66,32}},color={0,192,0}), + Line(points={{0,-90},{0,68}}, color={192,192,192}), + Polygon( + points={{0,90},{-8,68},{8,68},{0,90}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{-90,0},{68,0}}, color={192,192,192}), + Polygon( + points={{90,0},{68,-8},{68,8},{90,0}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{-80,-70},{-50,-70},{50,70},{80,70}}), + Text( + extent={{-150,-150},{150,-110}}, + lineColor={0,0,0}, + textString="uMax=%uMax"), + Text( + extent={{-150,150},{150,110}}, + textString="%name", + lineColor={0,0,255}), + Line( + visible=strict, + points={{50,70},{80,70}}, + color={255,0,0}), + Line( + visible=strict, + points={{-80,-70},{-50,-70}}, + color={255,0,0})}), + Diagram(coordinateSystem( + preserveAspectRatio=true, + extent={{-100,-100},{100,100}}), graphics={ + Line(points={{0,-60},{0,50}}, color={192,192,192}), + Polygon( + points={{0,60},{-5,50},{5,50},{0,60}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{-60,0},{50,0}}, color={192,192,192}), + Polygon( + points={{60,0},{50,-5},{50,5},{60,0}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{-50,-40},{-30,-40},{30,40},{50,40}}), + Text( + extent={{46,-6},{68,-18}}, + lineColor={128,128,128}, + textString="u"), + Text( + extent={{-30,70},{-5,50}}, + lineColor={128,128,128}, + textString="y"), + Text( + extent={{58,-54},{28,-42}}, + lineColor={128,128,128}, + textString="%delayTimes s"), + Text( + extent={{-58,-54},{-28,-42}}, + lineColor={128,128,128}, + textString="UMin"), + Text( + extent={{26,40},{66,56}}, + lineColor={128,128,128}, + textString="UMax")}), + Documentation(info = "There is no lag when switching from saturated to non-saturated mode.

The Boolean variable initSaturatedMax prevents tUMaxReached from being reset at initial time if the simulation starts in saturated mode. Thus, tUMaxReached is equal to minus infinity i.e. it is assumed that UMax was crossed long before the simulation.

The Boolean variable initSaturatedMin performs the same function with respect to tUMinReached and UMin.")); +end BaseLimiterWithLag; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/BaseLimiterWithLag_INIT.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/BaseLimiterWithLag_INIT.mo new file mode 100644 index 00000000000..828f062379b --- /dev/null +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/BaseLimiterWithLag_INIT.mo @@ -0,0 +1,49 @@ +within Dynawo.NonElectrical.Blocks.NonLinear.BaseClasses; + +/* +* Copyright (c) 2024, RTE (http://www.rte-france.com) +* See AUTHORS.txt +* All rights reserved. +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, you can obtain one at http://mozilla.org/MPL/2.0/. +* SPDX-License-Identifier: MPL-2.0 +* +* This file is part of Dynawo, an hybrid C++/Modelica open source suite +* of simulation tools for power systems. +*/ + +model BaseLimiterWithLag_INIT "Base initialization model for LimiterWithLag and LimiterAtCurrentValueWithLag" + import Modelica.Constants; + + extends AdditionalIcons.Init; + + parameter Real UMax "Maximum allowed u"; + parameter Real UMin "Minimum allowed u"; + + discrete Types.Time tUMaxReached0(start = Constants.inf) "Initial time when u went above UMax"; + discrete Types.Time tUMinReached0(start = Constants.inf) "Initial time when u went below UMin"; + + Real u0 "Initial input"; + Real y0 "Initial output, =y0LF if compliant with saturations"; + Real y0LF "Initial y from loadflow"; + +equation + u0 = y0LF; + + when u0 > UMax then + tUMaxReached0 = -Constants.inf; // Init in steadystate, UMax has been reached for a long time + elsewhen u0 <= UMax then + tUMaxReached0 = Constants.inf; + end when; + + when u0 < UMin then + tUMinReached0 = -Constants.inf; + elsewhen u0 >= UMin then + tUMinReached0 = Constants.inf; + end when; + + annotation( + preferredView = "text", + Documentation(info = "The input of this model is y0LF. This value will initialize the limiter input variable, but since it could be out the saturation bounds, the initial value kept for y is y0.

If u0 exceeds UMax, it is assumed that UMax has been crossed long before the simulation, hence tUMaxReached0 is equal to minus infinity.

The same assumption is made regarding UMin and tUMinReached0.
")); +end BaseLimiterWithLag_INIT; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/CMakeLists.txt b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/CMakeLists.txt index 89e8f2bca26..b3343cf0066 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/CMakeLists.txt +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/CMakeLists.txt @@ -11,6 +11,8 @@ set(MODEL_FILES package.mo package.order + BaseLimiterWithLag.mo + BaseLimiterWithLag_INIT.mo BasePulse.mo BaseRSFlipFlop.mo ) diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/package.order b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/package.order index 76720f004fa..dad38b4cdf3 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/package.order +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/BaseClasses/package.order @@ -1,2 +1,4 @@ +BaseLimiterWithLag +BaseLimiterWithLag_INIT BasePulse BaseRSFlipFlop diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/CMakeLists.txt b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/CMakeLists.txt index d5dfb14ed85..b9c991c6828 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/CMakeLists.txt +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/CMakeLists.txt @@ -23,6 +23,8 @@ set(MODEL_FILES LimitedFirstOrder.mo LimitedIntegrator.mo LimitedLeadLag.mo + LimiterAtCurrentValueWithLag.mo + LimiterAtCurrentValueWithLag_INIT.mo LimiterWithLag.mo LimiterWithLag_INIT.mo LimRateLimFirstOrder.mo diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterAtCurrentValueWithLag.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterAtCurrentValueWithLag.mo new file mode 100644 index 00000000000..b15e796d2c1 --- /dev/null +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterAtCurrentValueWithLag.mo @@ -0,0 +1,23 @@ +within Dynawo.NonElectrical.Blocks.NonLinear; + +/* +* Copyright (c) 2024, RTE (http://www.rte-france.com) +* See AUTHORS.txt +* All rights reserved. +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, you can obtain one at http://mozilla.org/MPL/2.0/. +* SPDX-License-Identifier: MPL-2.0 +* +* This file is part of Dynawo, an hybrid C++/Modelica open source suite +* of simulation tools for power systems. +*/ + +block LimiterAtCurrentValueWithLag "Limiter that enforces saturations only after they were violated without interruption during a given amount of time, the lower saturation value being its current value" + extends Dynawo.NonElectrical.Blocks.NonLinear.BaseClasses.BaseLimiterWithLag; + +equation + y = if (time - tUMinReached >= LagMin) then pre(y) elseif (time - tUMaxReached >= LagMax) then UMax else u; + + annotation(preferredView = "text"); +end LimiterAtCurrentValueWithLag; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterAtCurrentValueWithLag_INIT.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterAtCurrentValueWithLag_INIT.mo new file mode 100644 index 00000000000..8a6e829dbe2 --- /dev/null +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterAtCurrentValueWithLag_INIT.mo @@ -0,0 +1,25 @@ +within Dynawo.NonElectrical.Blocks.NonLinear; + +/* +* Copyright (c) 2024, RTE (http://www.rte-france.com) +* See AUTHORS.txt +* All rights reserved. +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, you can obtain one at http://mozilla.org/MPL/2.0/. +* SPDX-License-Identifier: MPL-2.0 +* +* This file is part of Dynawo, an hybrid C++/Modelica open source suite +* of simulation tools for power systems. +*/ + +model LimiterAtCurrentValueWithLag_INIT "Initialization model of LimiterAtCurrentValueWithLag" + extends Dynawo.NonElectrical.Blocks.NonLinear.BaseClasses.BaseLimiterWithLag_INIT; + +equation + y0 = if u0 > UMax then UMax else u0; + + annotation( + preferredView = "text", + Documentation(info = "In this model, y0 complies only with UMax.")); +end LimiterAtCurrentValueWithLag_INIT; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag.mo index bfa5066b941..7103668c1ce 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag.mo +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag.mo @@ -12,123 +12,11 @@ within Dynawo.NonElectrical.Blocks.NonLinear; * This file is part of Dynawo, an hybrid C++/Modelica open source time domain simulation tool for power systems. */ -block LimiterWithLag "Limiter that enforces saturations only after they were violated without interruption during a certain amount of time. No lag when switching from saturated to non saturated mode though" - import Modelica.Constants; - import Dynawo.NonElectrical.Logs.Timeline; - import Dynawo.NonElectrical.Logs.TimelineKeys; - - extends Modelica.Blocks.Icons.Block; - - parameter Real UMin "Minimum allowed u"; - parameter Real UMax "Maximum allowed u"; - parameter Types.Time LagMin "Time lag before taking action when going below uMin"; - parameter Types.Time LagMax "Time lag before taking action when going above uMax"; - - Modelica.Blocks.Interfaces.RealInput u(start = u0) "Input signal connector" annotation(Placement( - transformation(extent={{-140,-20},{-100,20}}))); - Modelica.Blocks.Interfaces.RealOutput y(start = y0) "Output signal connector" annotation(Placement( - transformation(extent={{100,-10},{120,10}}))); - - discrete Types.Time tUMinReached(start = tUMinReached0) "Last time when u went below EfdMin"; - discrete Types.Time tUMaxReached(start = tUMaxReached0) "Last time when u went above EfdMax"; - - parameter Real u0 "Initial input"; - parameter Real y0 "Initial output"; - parameter Types.Time tUMinReached0 "Initial time when u went below UMin"; - parameter Types.Time tUMaxReached0 "Initial time when u went above UMax"; - - Boolean initSaturatedMin(start = (tUMinReached0 == - Constants.inf) ) "Whether we start in min saturated mode. Boolean used to prevent the model from resetting tUMinReached when in saturated mode at the beginning of the simulation"; - Boolean initSaturatedMax(start = (tUMaxReached0 == - Constants.inf) ) "Whether we start in max saturated mode. Boolean used to prevent the model from resetting tUMaxReached when in saturated mode at the beginning of the simulation"; +block LimiterWithLag "Limiter that enforces saturations only after they were violated without interruption during a given amount of time" + extends Dynawo.NonElectrical.Blocks.NonLinear.BaseClasses.BaseLimiterWithLag; equation - y = if (time - tUMinReached >= LagMin) then UMin else if (time - tUMaxReached >= LagMax) then UMax else u; - - // Assessing that u is within limits - when (u < UMin) then - tUMinReached = if initSaturatedMin then - Constants.inf else time; // If we start in saturated state, tUMinReached should not be reset to time at time = 0 because we assume that u crossed UMin a long time ago - initSaturatedMin = false; // For the next when triggerings, back to classic behaviour - elsewhen (u >= UMin) then - tUMinReached = Constants.inf; - initSaturatedMin = false; - end when; - - when (u > UMax) then - tUMaxReached = if initSaturatedMax then - Constants.inf else time; // If we start in saturated state, tUMaxReached should not be reset to time at time = 0 because we assume that u crossed UMax a long time ago - initSaturatedMax = false; // For the next when triggerings, back to classic behaviour - elsewhen (u <= UMax) then - tUMaxReached = Constants.inf; - initSaturatedMax = false; - end when; + y = if (time - tUMinReached >= LagMin) then UMin elseif (time - tUMaxReached >= LagMax) then UMax else u; - annotation(preferredView = "text", - Icon(coordinateSystem( - preserveAspectRatio=true, - extent={{-100,-100},{100,100}}), graphics={ - Line(points={{-80,-56},{-60,-56},{-60,-22},{38,-22},{38,-56},{66,-56}},color={0,0,192}), - Line(points={{-80,32},{18,32},{18,66},{38,66},{38,32},{66,32}},color={0,192,0}), - Line(points={{0,-90},{0,68}}, color={192,192,192}), - Polygon( - points={{0,90},{-8,68},{8,68},{0,90}}, - lineColor={192,192,192}, - fillColor={192,192,192}, - fillPattern=FillPattern.Solid), - Line(points={{-90,0},{68,0}}, color={192,192,192}), - Polygon( - points={{90,0},{68,-8},{68,8},{90,0}}, - lineColor={192,192,192}, - fillColor={192,192,192}, - fillPattern=FillPattern.Solid), - Line(points={{-80,-70},{-50,-70},{50,70},{80,70}}), - Text( - extent={{-150,-150},{150,-110}}, - lineColor={0,0,0}, - textString="uMax=%uMax"), - Text( - extent={{-150,150},{150,110}}, - textString="%name", - lineColor={0,0,255}), - Line( - visible=strict, - points={{50,70},{80,70}}, - color={255,0,0}), - Line( - visible=strict, - points={{-80,-70},{-50,-70}}, - color={255,0,0})}), - Diagram(coordinateSystem( - preserveAspectRatio=true, - extent={{-100,-100},{100,100}}), graphics={ - Line(points={{0,-60},{0,50}}, color={192,192,192}), - Polygon( - points={{0,60},{-5,50},{5,50},{0,60}}, - lineColor={192,192,192}, - fillColor={192,192,192}, - fillPattern=FillPattern.Solid), - Line(points={{-60,0},{50,0}}, color={192,192,192}), - Polygon( - points={{60,0},{50,-5},{50,5},{60,0}}, - lineColor={192,192,192}, - fillColor={192,192,192}, - fillPattern=FillPattern.Solid), - Line(points={{-50,-40},{-30,-40},{30,40},{50,40}}), - Text( - extent={{46,-6},{68,-18}}, - lineColor={128,128,128}, - textString="u"), - Text( - extent={{-30,70},{-5,50}}, - lineColor={128,128,128}, - textString="y"), - Text( - extent={{58,-54},{28,-42}}, - lineColor={128,128,128}, - textString="%delayTimes s"), - Text( - extent={{-58,-54},{-28,-42}}, - lineColor={128,128,128}, - textString="uMin"), - Text( - extent={{26,40},{66,56}}, - lineColor={128,128,128}, - textString="uMax")})); + annotation(preferredView = "text"); end LimiterWithLag; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag_INIT.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag_INIT.mo index 8e6a201f822..b62c3fb65d5 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag_INIT.mo +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/LimiterWithLag_INIT.mo @@ -12,39 +12,13 @@ within Dynawo.NonElectrical.Blocks.NonLinear; * This file is part of Dynawo, an hybrid C++/Modelica open source time domain simulation tool for power systems. */ -model LimiterWithLag_INIT "LimiterWithLag INIT Model. Here the input is y0LF. This value will initialize the limiter's input variable, but since it could be out the saturation bounds, the initial value kept for y is y0 which is min(max(y0LF, UMin), UMax)" - import Modelica.Constants; - - extends AdditionalIcons.Init; - - parameter Real UMin "Minimum allowed u"; - parameter Real UMax "Maximum allowed u"; - - Real y0LF "Initial y from loadflow"; - Real u0 "Initial input"; - Real y0 "Initial output, =y0LF if compliant with saturations"; - discrete Types.Time tUMinReached0(start = Constants.inf) "Initial time when u went below UMin"; - discrete Types.Time tUMaxReached0(start = Constants.inf) "Initial time when u went above UMax"; +model LimiterWithLag_INIT "Initialization model of LimiterWithLag" + extends Dynawo.NonElectrical.Blocks.NonLinear.BaseClasses.BaseLimiterWithLag_INIT; equation - u0 = y0LF; - y0 = if (u0 < UMin) then UMin - else if (u0 > UMax) then UMax - else u0; - - // Lower Excitation Limit - when u0 < UMin then - tUMinReached0 = -Constants.inf; - elsewhen u0 >= UMin then - tUMinReached0 = Constants.inf; - end when; - - // Upper Excitation Limit - when u0 > UMax then - tUMaxReached0 = -Constants.inf; // Init in steadystate, UMax has been reached for a long time - elsewhen u0 <= UMax then - tUMaxReached0 = Constants.inf; - end when; + y0 = if u0 < UMin then UMin elseif u0 > UMax then UMax else u0; - annotation(preferredView = "text"); + annotation( + preferredView = "text", + Documentation(info = "In this model, y0 complies with both UMax and UMin.")); end LimiterWithLag_INIT; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/package.order b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/package.order index c21c423fd18..af8bb5688c6 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/package.order +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/NonLinear/package.order @@ -10,6 +10,8 @@ IntegratorOrFirstOrder LimitedFirstOrder LimitedIntegrator LimitedLeadLag +LimiterAtCurrentValueWithLag +LimiterAtCurrentValueWithLag_INIT LimiterWithLag LimiterWithLag_INIT LimRateLimFirstOrder