From b455896efbec1f53ad4def019f9b09bd53407409 Mon Sep 17 00:00:00 2001 From: ErwanGuichard49 Date: Thu, 25 Apr 2024 13:49:44 +0200 Subject: [PATCH] #3195 New integrator with variable limits and with anti-windup Signed-off-by: ErwanGuichard49 --- .../Blocks/Continuous/CMakeLists.txt | 1 + .../IntegratorVariableLimitsAntiWindup.mo | 127 ++++++++++++++++++ .../Blocks/Continuous/package.order | 1 + 3 files changed, 129 insertions(+) create mode 100644 dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/IntegratorVariableLimitsAntiWindup.mo diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/CMakeLists.txt b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/CMakeLists.txt index e2edeaee3c6..a7e08315820 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/CMakeLists.txt +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/CMakeLists.txt @@ -26,6 +26,7 @@ set(MODEL_FILES IntegratorWithReset.mo IntegratorSetFreeze.mo IntegratorVariableLimits.mo + IntegratorVariableLimitsAntiWindup.mo LeadMOrderLag.mo LimitedPI.mo LimPIDFreeze.mo diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/IntegratorVariableLimitsAntiWindup.mo b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/IntegratorVariableLimitsAntiWindup.mo new file mode 100644 index 00000000000..90a29ac3c41 --- /dev/null +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/IntegratorVariableLimitsAntiWindup.mo @@ -0,0 +1,127 @@ +within Dynawo.NonElectrical.Blocks.Continuous; + +/* +* 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 IntegratorVariableLimitsAntiWindup "Integrator with limited value of output (variable limits) and anti-windup" + extends Modelica.Blocks.Interfaces.SISO(y(start = Y0)); + + parameter Boolean DefaultLimitMax = true "If limitMin > limitMax : if true, y = limitMax, if false, y = limitMin"; + parameter Types.PerUnit K = 1 "Integrator gain"; + parameter Types.PerUnit Kaw "Antiwindup gain"; + parameter Types.PerUnit Tol "Tolerance on limit crossing as a fraction of the difference between initial limits"; + + Modelica.Blocks.Interfaces.RealInput limitMax(start = LimitMax0) "Connector of Real input signal used as maximum of output y" annotation( + Placement(transformation(extent={{-140,60},{-100,100}}))); + Modelica.Blocks.Interfaces.RealInput limitMin(start = LimitMin0) "Connector of Real input signal used as minimum of output y" annotation( + Placement(transformation(extent={{-140,-100},{-100,-60}}))); + + parameter Types.PerUnit LimitMax0 "Initial value of upper limit"; + parameter Types.PerUnit LimitMin0 "Initial value of lower limit"; + parameter Types.PerUnit Y0 = 0 "Initial or guess value of output"; + + final parameter Boolean FrozenMax0 = Y0 > LimitMax0 - Tol * abs(LimitMax0 - LimitMin0) "If true, integration is initially frozen at upper limit"; + final parameter Boolean FrozenMin0 = Y0 < LimitMin0 + Tol * abs(LimitMax0 - LimitMin0) "If true, integration is initially frozen at lower limit"; + +protected + Boolean isFrozenMax(start = FrozenMax0) "If true, integration is frozen at upper limit"; + Boolean isFrozenMin(start = FrozenMin0) "If true, integration is frozen at lower limit"; + Boolean keepFreezingMax(start = FrozenMax0) "If true, integration stays frozen at upper limit"; + Boolean keepFreezingMin(start = FrozenMin0) "If true, integration stays frozen at lower limit"; + Boolean startFreezingMax(start = FrozenMax0) "If true, integration becomes frozen at upper limit"; + Boolean startFreezingMin(start = FrozenMin0) "If true, integration becomes frozen at lower limit"; + Types.PerUnit v(start = 0) "Non-frozen integrator input"; + Types.PerUnit w(start = Y0) "Non-limited integrator output"; + +equation + startFreezingMax = w > limitMax and v > 0; + keepFreezingMax = w > limitMax - Tol * abs(LimitMax0 - LimitMin0) and v > 0 and pre(isFrozenMax); + isFrozenMax = startFreezingMax or keepFreezingMax; + + startFreezingMin = w < limitMin and v < 0; + keepFreezingMin = w < limitMin + Tol * abs(LimitMax0 - LimitMin0) and v < 0 and pre(isFrozenMin); + isFrozenMin = startFreezingMin or keepFreezingMin; + + v = K * u + Kaw * (y - w); + + if isFrozenMax then + w = limitMax; + elseif isFrozenMin then + w = limitMin; + else + der(w) = v; + end if; + + if limitMin > limitMax and DefaultLimitMax then + y = limitMax; + elseif limitMin > limitMax then + y = limitMin; + elseif w < limitMin then + y = limitMin; + elseif w > limitMax then + y = limitMax; + else + y = w; + end if; + + annotation( + preferredView = "text", + Documentation(info= "

+This blocks computes w as integral +of variable which is equal to input u multiplied by gain K added to an antiwindup term.

+ +

If the integral reaches a given upper or lower limit, the +integration is halted and only restarted if the input drives +the integral away from the bounds, with a sufficient margin defined by Tol.

This margin is aimed at avoiding chattering i.e. rapid swings between frozen and unfrozen sates.

+ +

If the integration is halted, the integrator output follows the variable limit it has reached.

+ +

The output y is the result of the limitation of w by both variable limits.

+ +

If the \"upper\" limit is smaller than the \"lower\" one, the output y is ruled by the parameter DefaultLimitMax: y is equal to either limitMax or limitMin.

+ +

The integrator output is initialized with the parameter Y0.

+"), + Icon(coordinateSystem( + preserveAspectRatio=true, + extent={{-100,-100},{100,100}}), graphics={ + Line(points={{-80,78},{-80,-90}}, color={192,192,192}), + Polygon(lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{-80, 90}, {-88, 68}, {-72, 68}, {-80, 90}}), + Line(points={{-90,-80},{82,-80}}, color={192,192,192}), + Polygon(lineColor = {192, 192, 192}, fillColor = {192, 192, 192}, fillPattern = FillPattern.Solid, points = {{90, -80}, {68, -72}, {68, -88}, {90, -80}}), + Line(points = {{-80, -80}, {20, 20}, {80, 20}}, color = {0, 0, 127}), + Text(lineColor = {192, 192, 192}, extent = {{0, -10}, {60, -70}}, textString = "I"), + Text( + extent={{-150,-150},{150,-110}}, + textString="K=%K"), + Line( + points={{60,-100},{60,-80}}, + color={255,0,255}, + pattern=LinePattern.Dot)}), + Diagram(coordinateSystem( + preserveAspectRatio=true, + extent={{-100,-100},{100,100}}), graphics={ + Rectangle(lineColor={0,0,255}, extent={{-60,60},{60,-60}}), + Text( + extent={{-54,46},{-4,-48}}, + textString="lim"), + Line(points={{-100,0},{-60,0}}, color={0,0,255}), + Line(points={{60,0},{100,0}}, color={0,0,255}), + Text( + extent={{-8,60},{60,2}}, + textString="k"), + Text( + extent={{-8,-2},{60,-60}}, + textString="s"), + Line(points={{4,0},{46,0}})})); +end IntegratorVariableLimitsAntiWindup; diff --git a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/package.order b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/package.order index fc753986fbe..981c8d7611a 100644 --- a/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/package.order +++ b/dynawo/sources/Models/Modelica/Dynawo/NonElectrical/Blocks/Continuous/package.order @@ -11,6 +11,7 @@ IncreaseDetection IntegratorWithReset IntegratorSetFreeze IntegratorVariableLimits +IntegratorVariableLimitsAntiWindup LeadMOrderLag LimitedPI LimPIDFreeze