Skip to content

Commit e5947aa

Browse files
authored
Merge pull request #2561 from casella/LimiterHomotopy
Add more options for homotopy-based initialization of limiters
2 parents 060e292 + a4083f2 commit e5947aa

File tree

6 files changed

+570
-37
lines changed

6 files changed

+570
-37
lines changed

Modelica/Blocks/Continuous.mo

+25-12
Original file line numberDiff line numberDiff line change
@@ -918,10 +918,6 @@ to compute u by an algebraic equation.
918918
annotation(Dialog(enable=withFeedForward));
919919
parameter .Modelica.Blocks.Types.InitPID initType= .Modelica.Blocks.Types.InitPID.DoNotUse_InitialIntegratorState
920920
"Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
921-
annotation(Evaluate=true,
922-
Dialog(group="Initialization"));
923-
parameter Boolean limitsAtInit = true
924-
"= false, if limits are ignored during initialization"
925921
annotation(Evaluate=true, Dialog(group="Initialization"));
926922
parameter Real xi_start=0
927923
"Initial or guess value for integrator output (= integrator state)"
@@ -936,8 +932,14 @@ to compute u by an algebraic equation.
936932
parameter Real y_start=0 "Initial value of output"
937933
annotation(Dialog(enable=initType == .Modelica.Blocks.Types.InitPID.InitialOutput, group=
938934
"Initialization"));
935+
parameter Modelica.Blocks.Types.LimiterHomotopy homotopyType = Modelica.Blocks.Types.LimiterHomotopy.Linear
936+
"Simplified model for homotopy-based initialization"
937+
annotation (Evaluate=true, Dialog(group="Initialization"));
939938
parameter Boolean strict=false "= true, if strict limits with noEvent(..)"
940939
annotation (Evaluate=true, choices(checkBox=true), Dialog(tab="Advanced"));
940+
parameter Boolean limitsAtInit=true
941+
"Has no longer an effect and is only kept for backwards compatibility (the implementation uses now the homotopy operator)"
942+
annotation (Dialog(tab="Dummy"),Evaluate=true, choices(checkBox=true));
941943
constant Modelica.SIunits.Time unitTime=1 annotation (HideResult=true);
942944
Modelica.Blocks.Interfaces.RealInput u_ff if withFeedForward
943945
"Optional connector of feed-forward input signal"
@@ -984,7 +986,8 @@ to compute u by an algebraic equation.
984986
uMax=yMax,
985987
uMin=yMin,
986988
strict=strict,
987-
limitsAtInit=limitsAtInit)
989+
limitsAtInit=limitsAtInit,
990+
homotopyType=homotopyType)
988991
annotation (Placement(transformation(extent={{70,-10},{90,10}})));
989992
protected
990993
parameter Boolean with_I = controllerType==SimpleController.PI or
@@ -1242,13 +1245,23 @@ to compute u_m by an algebraic equation.
12421245
</p>
12431246
12441247
<p>
1245-
If parameter <strong>limitAtInit</strong> = <strong>false</strong>, the limits at the
1246-
output of this controller block are removed from the initialization problem which
1247-
leads to a much simpler equation system. After initialization has been
1248-
performed, it is checked via an assert whether the output is in the
1249-
defined limits. For backward compatibility reasons
1250-
<strong>limitAtInit</strong> = <strong>true</strong>. In most cases it is best
1251-
to use <strong>limitAtInit</strong> = <strong>false</strong>.
1248+
When initializing in steady-state, homotopy-based initialization can help the convergence of the solver,
1249+
by using a simplified model a the beginning of the solution process. Different options are available.
1250+
<ul>
1251+
<li><strong>homotopyType=Linear</strong> (default): the limitations are removed from the simplified model,
1252+
making it linear. Use this if you know that the controller will not be saturated at steady state.</li>
1253+
<li><strong>homotopyType=UpperLimit</strong>: if it is known a priori the controller will be stuck at the upper
1254+
limit yMax, this option assumes y = yMax as a simplified model.</li>
1255+
<li><strong>homotopyType=LowerLimit</strong>: if it is known a priori the controller will be stuck at the lower
1256+
limit yMin, this option assumes y = yMin as a simplified model.</li>
1257+
<li><strong>homotopyType=NoHomotopy</strong>: this option does not apply any simplification and keeps the
1258+
limiter active throughout the homotopy transformation. Use this if it is unknown whether the controller
1259+
is saturated or not at initialization and if the limitations on the output must be enforced throughout
1260+
the entire homotopy transformation.</li>
1261+
</ul>
1262+
</p>
1263+
<p>
1264+
The parameter <strong>limitAtInit</strong> is obsolete since MSL 3.2.2 and only kept for backwards compatibility.
12521265
</p>
12531266
</html>"));
12541267
end LimPID;

Modelica/Blocks/Nonlinear.mo

+71-9
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,38 @@ package Nonlinear
77
block Limiter "Limit the range of a signal"
88
parameter Real uMax(start=1) "Upper limits of input signals";
99
parameter Real uMin= -uMax "Lower limits of input signals";
10-
parameter Boolean strict=false
11-
"= true, if strict limits with noEvent(..)"
10+
parameter Boolean strict=false "= true, if strict limits with noEvent(..)"
1211
annotation (Evaluate=true, choices(checkBox=true), Dialog(tab="Advanced"));
12+
parameter Types.LimiterHomotopy homotopyType = Modelica.Blocks.Types.LimiterHomotopy.Linear "Simplified model for homotopy-based initialization"
13+
annotation (Evaluate=true, Dialog(group="Initialization"));
1314
parameter Boolean limitsAtInit=true
14-
"Has no longer an effect and is only kept for backwards compatibility (the implementation uses now the homotopy operator)"
15+
"Has no longer an effect and is only kept for backwards compatibility (the implementation uses now the homotopy operator)"
1516
annotation (Dialog(tab="Dummy"),Evaluate=true, choices(checkBox=true));
1617
extends Interfaces.SISO;
18+
protected
19+
Real simplifiedExpr "Simplified expression for homotopy-based initialization";
1720

1821
equation
1922
assert(uMax >= uMin, "Limiter: Limits must be consistent. However, uMax (=" + String(uMax) +
2023
") < uMin (=" + String(uMin) + ")");
24+
simplifiedExpr = (if homotopyType == Types.LimiterHomotopy.Linear then u
25+
else if homotopyType == Types.LimiterHomotopy.UpperLimit then uMax
26+
else if homotopyType == Types.LimiterHomotopy.LowerLimit then uMin
27+
else 0);
2128
if strict then
22-
y = homotopy(actual = smooth(0, noEvent(if u > uMax then uMax else if u < uMin then uMin else u)), simplified=u);
29+
if homotopyType == Types.LimiterHomotopy.NoHomotopy then
30+
y = smooth(0, noEvent(if u > uMax then uMax else if u < uMin then uMin else u));
31+
else
32+
y = homotopy(actual = smooth(0, noEvent(if u > uMax then uMax else if u < uMin then uMin else u)),
33+
simplified=simplifiedExpr);
34+
end if;
2335
else
24-
y = homotopy(actual = smooth(0,if u > uMax then uMax else if u < uMin then uMin else u), simplified=u);
36+
if homotopyType == Types.LimiterHomotopy.NoHomotopy then
37+
y = smooth(0,if u > uMax then uMax else if u < uMin then uMin else u);
38+
else
39+
y = homotopy(actual = smooth(0,if u > uMax then uMax else if u < uMin then uMin else u),
40+
simplified=simplifiedExpr);
41+
end if;
2542
end if;
2643
annotation (
2744
Documentation(info="<html>
@@ -31,6 +48,20 @@ as long as the input is within the specified upper and lower
3148
limits. If this is not the case, the corresponding limits are passed
3249
as output.
3350
</p>
51+
<p>
52+
The parameter <code>homotopyType</code> in the Advanced tab specifies the
53+
simplified behaviour if homotopy-based initialization is used:
54+
<ul>
55+
<li><code>NoHomotopy</code>: the actual expression with limits is used</li>
56+
<li><code>Linear</code>: a linear behaviour y = u is assumed (default option)</li>
57+
<li><code>UpperLimit</code>: it is assumed that the output is stuck at the upper limit u = uMax</li>
58+
<li><code>LowerLimit</code>: it is assumed that the output is stuck at the lower limit u = uMin</li>
59+
</ul>
60+
</p>
61+
<p>
62+
If it is known a priori in which region the input signal will be located, this option can help
63+
a lot by removing one strong nonlinearity from the initialization problem.
64+
</p>
3465
</html>"), Icon(coordinateSystem(
3566
preserveAspectRatio=true,
3667
extent={{-100,-100},{100,100}}), graphics={
@@ -99,7 +130,11 @@ as output.
99130
block VariableLimiter "Limit the range of a signal with variable limits"
100131
extends Interfaces.SISO;
101132
parameter Boolean strict=false "= true, if strict limits with noEvent(..)"
102-
annotation (Evaluate=true, choices(checkBox=true));
133+
annotation (Evaluate=true, choices(checkBox=true), Dialog(tab="Advanced"));
134+
parameter Types.VariableLimiterHomotopy homotopyType = Modelica.Blocks.Types.VariableLimiterHomotopy.Linear "Simplified model for homotopy-based initialization"
135+
annotation (Evaluate=true, Dialog(group="Initialization"));
136+
parameter Real ySimplified = 0 "Fixed value of output in simplified model"
137+
annotation (Dialog(tab="Advanced", enable=homotopyType == Modelica.Blocks.Types.VariableLimiterHomotopy.Fixed));
103138
parameter Boolean limitsAtInit=true
104139
"Has no longer an effect and is only kept for backwards compatibility (the implementation uses now the homotopy operator)"
105140
annotation (Dialog(tab="Dummy"),Evaluate=true, choices(checkBox=true));
@@ -109,13 +144,27 @@ as output.
109144
Interfaces.RealInput limit2
110145
"Connector of Real input signal used as minimum of input u"
111146
annotation (Placement(transformation(extent={{-140,-100},{-100,-60}})));
147+
protected
148+
Real simplifiedExpr "Simplified expression for homotopy-based initialization";
112149
equation
113150
assert(limit1 >= limit2, "Input signals are not consistent: limit1 < limit2");
114-
151+
simplifiedExpr = (if homotopyType == Types.VariableLimiterHomotopy.Linear then u
152+
else if homotopyType == Types.VariableLimiterHomotopy.Fixed then ySimplified
153+
else 0);
115154
if strict then
116-
y = homotopy(actual = smooth(0, noEvent(if u > limit1 then limit1 else if u < limit2 then limit2 else u)), simplified=u);
155+
if homotopyType == Types.VariableLimiterHomotopy.NoHomotopy then
156+
y = smooth(0, noEvent(if u > limit1 then limit1 else if u < limit2 then limit2 else u));
157+
else
158+
y = homotopy(actual = smooth(0, noEvent(if u > limit1 then limit1 else if u < limit2 then limit2 else u)),
159+
simplified=simplifiedExpr);
160+
end if;
117161
else
118-
y = homotopy(actual = smooth(0,if u > limit1 then limit1 else if u < limit2 then limit2 else u), simplified=u);
162+
if homotopyType == Types.VariableLimiterHomotopy.NoHomotopy then
163+
y = smooth(0,if u > limit1 then limit1 else if u < limit2 then limit2 else u);
164+
else
165+
y = homotopy(actual = smooth(0,if u > limit1 then limit1 else if u < limit2 then limit2 else u),
166+
simplified=simplifiedExpr);
167+
end if;
119168
end if;
120169

121170
annotation (
@@ -127,6 +176,19 @@ limits specified by the two additional inputs limit1 and
127176
limit2. If this is not the case, the corresponding limit
128177
is passed as output.
129178
</p>
179+
<p>
180+
The parameter <code>homotopyType</code> in the Advanced tab specifies the
181+
simplified behaviour if homotopy-based initialization is used:
182+
<ul>
183+
<li><code>NoHomotopy</code>: the actual expression with limits is used</li>
184+
<li><code>Linear</code>: a linear behaviour y = u is assumed (default option)</li>
185+
<li><code>Fixed</code>: it is assumed that the output is fixed at the value <code>ySimplified</code></li>
186+
</ul>
187+
</p>
188+
<p>
189+
If it is known a priori in which region the input signal will be located, this option can help
190+
a lot by removing one strong nonlinearity from the initialization problem.
191+
</p>
130192
</html>"), Icon(coordinateSystem(preserveAspectRatio=true, extent={{-100,-100},{100,
131193
100}}), graphics={
132194
Line(points={{0,-90},{0,68}}, color={192,192,192}),

Modelica/Blocks/Types.mo

+18-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ package Types
1515
"Table points are interpolated (by Steffen splines) such that the monotonicity is preserved and the first derivative is continuous")
1616
"Enumeration defining the smoothness of table interpolation";
1717

18-
type Extrapolation = enumeration(
18+
type Extrapolation = enumeration(
1919
HoldLastPoint
2020
"Hold the first/last table point outside of the table scope",
2121
LastTwoPoints
@@ -24,13 +24,13 @@ package Types
2424
NoExtrapolation "Extrapolation triggers an error")
2525
"Enumeration defining the extrapolation of table interpolation";
2626

27-
type TimeEvents = enumeration(
27+
type TimeEvents = enumeration(
2828
Always "Always generate time events at interval boundaries",
2929
AtDiscontinuities "Generate time events at discontinuities (defined by duplicated sample points)",
3030
NoTimeEvents "No time events at interval boundaries")
3131
"Enumeration defining the time event handling of time table interpolation";
3232

33-
type Init = enumeration(
33+
type Init = enumeration(
3434
NoInit
3535
"No initialization (start values are used as guess values with fixed=false)",
3636
SteadyState
@@ -53,7 +53,7 @@ package Types
5353
</dl>
5454
</html>"));
5555

56-
type InitPID = enumeration(
56+
type InitPID = enumeration(
5757
NoInit
5858
"No initialization (start values are used as guess values with fixed=false)",
5959
SteadyState
@@ -91,7 +91,7 @@ initialization definition.
9191
</dl>
9292
</html>"));
9393

94-
type SimpleController = enumeration(
94+
type SimpleController = enumeration(
9595
P "P controller",
9696
PI "PI controller",
9797
PD "PD controller",
@@ -121,6 +121,19 @@ initialization definition.
121121
Cosine "Cosine regularization")
122122
"Enumeration defining the regularization around zero";
123123

124+
type LimiterHomotopy = enumeration(
125+
NoHomotopy "Homotopy is not used",
126+
Linear "Simplified model without limits",
127+
UpperLimit "Simplified model fixed at upper limit",
128+
LowerLimit "Simplified model fixed at lower limit")
129+
"Enumeration defining use of homotopy in limiter components" annotation (Evaluate=true);
130+
131+
type VariableLimiterHomotopy = enumeration(
132+
NoHomotopy "Simplified model = actual model",
133+
Linear "Simplified model: y = u",
134+
Fixed "Simplified model: y = ySimplified")
135+
"Enumeration defining use of homotopy in variable limiter components" annotation (Evaluate=true);
136+
124137
class ExternalCombiTimeTable
125138
"External object of 1-dim. table where first column is time"
126139
extends ExternalObject;

Modelica/Electrical/Analog/Examples/OpAmps.mo

+14-7
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@ package OpAmps "Examples with operational amplifiers"
566566
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp(
567567
Vps=Vps,
568568
Vns=Vns,
569-
out(i(start=0)))
569+
out(i(start=0)),
570+
homotopyType=Modelica.Blocks.Types.LimiterHomotopy.LowerLimit)
570571
annotation (Placement(transformation(extent={{0,-10},{20,10}})));
571572
Modelica.Electrical.Analog.Basic.Ground ground
572573
annotation (Placement(transformation(extent={{-20,-100},{0,-80}})));
@@ -639,7 +640,8 @@ package OpAmps "Examples with operational amplifiers"
639640
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp(
640641
Vps=Vps,
641642
Vns=Vns,
642-
out(i(start=0)))
643+
out(i(start=0)),
644+
homotopyType=Modelica.Blocks.Types.LimiterHomotopy.UpperLimit)
643645
annotation (Placement(transformation(extent={{0,10},{20,-10}})));
644646
Modelica.Electrical.Analog.Basic.Ground ground
645647
annotation (Placement(transformation(extent={{-20,-100},{0,-80}})));
@@ -707,8 +709,9 @@ package OpAmps "Examples with operational amplifiers"
707709
parameter SI.Resistance R2=1000 "Resistance 2 for adjusting the Schmitt trigger voltage level";
708710
parameter SI.Resistance R=1000 "Arbitrary resistance";
709711
parameter SI.Capacitance C=1/f/(2*R*log(1 + 2*R1/R2)) "Calculated capacitance to reach the desired frequency f";
710-
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp(Vps=Vps, Vns=
711-
Vns) annotation (Placement(transformation(extent={{0,-10},{20,10}})));
712+
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp(
713+
Vps=Vps,
714+
Vns=Vns) annotation (Placement(transformation(extent={{0,-10},{20,10}})));
712715
Modelica.Electrical.Analog.Basic.Ground ground
713716
annotation (Placement(transformation(extent={{-20,-80},{0,-60}})));
714717
Modelica.Electrical.Analog.Sensors.VoltageSensor vOut annotation (Placement(
@@ -776,8 +779,11 @@ package OpAmps "Examples with operational amplifiers"
776779
parameter SI.Frequency f=10 "Desired frequency";
777780
parameter SI.Resistance R=1000 "Arbitrary resistance of integrator part";
778781
parameter SI.Capacitance C=Vps/VAmp/(4*f*R) "Calculated capacitance of integrator part to reach f";
779-
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp1(Vps=Vps, Vns=
780-
Vns)
782+
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp1(
783+
Vps=Vps,
784+
Vns=Vns,
785+
strict=false,
786+
homotopyType=Modelica.Blocks.Types.LimiterHomotopy.UpperLimit)
781787
annotation (Placement(transformation(extent={{-60,10},{-40,-10}})));
782788
Modelica.Electrical.Analog.Basic.Resistor r2(R=R2, i(start=Vps/R2))
783789
annotation (Placement(transformation(
@@ -793,7 +799,8 @@ package OpAmps "Examples with operational amplifiers"
793799
Modelica.Electrical.Analog.Ideal.IdealizedOpAmpLimted opAmp2(
794800
Vps=Vps,
795801
Vns=Vns,
796-
v_in(start=0))
802+
v_in(start=0),
803+
strict=false)
797804
annotation (Placement(transformation(extent={{30,-10},{50,10}})));
798805
Modelica.Electrical.Analog.Basic.Capacitor c(C=C, v(fixed=true, start=0))
799806
annotation (Placement(transformation(extent={{50,10},{30,30}})));

Modelica/Electrical/Analog/Ideal.mo

+25-1
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,10 @@ If the input voltage is vin larger than 0, the output voltage is out.v = VMax.
675675
annotation (Dialog(enable=not useSupply));
676676
parameter SI.Voltage Vns=-15 "Negative supply voltage"
677677
annotation (Dialog(enable=not useSupply));
678+
parameter Boolean strict=true "= true, if strict limits with noEvent(..)"
679+
annotation (Evaluate=true, choices(checkBox=true), Dialog(tab="Advanced"));
680+
parameter Modelica.Blocks.Types.LimiterHomotopy homotopyType = Modelica.Blocks.Types.LimiterHomotopy.Linear "Simplified model for homotopy-based initialization"
681+
annotation (Evaluate=true, Dialog(group="Initialization"));
678682
SI.Voltage vps "Positive supply voltage";
679683
SI.Voltage vns "Negative supply voltage";
680684
SI.Voltage v_in=in_p.v - in_n.v "Input voltage difference";
@@ -700,14 +704,34 @@ If the input voltage is vin larger than 0, the output voltage is out.v = VMax.
700704
Modelica.Electrical.Analog.Interfaces.NegativePin s_n(final i=-i_s, final v=
701705
vns) if useSupply "Optional negative supply pin" annotation (Placement(
702706
transformation(extent={{-10,-110},{10,-90}})));
707+
protected
708+
SI.Voltage simplifiedExpr "Simplified expression for homotopy-based initialization";
703709
equation
704710
if not useSupply then
705711
vps = Vps;
706712
vns = Vns;
707713
end if;
708714
in_p.i = 0;
709715
in_n.i = 0;
710-
v_out = homotopy(actual = smooth(0, if V0*v_in<vns then vns else if V0*v_in>vps then vps else V0*v_in), simplified=V0*v_in);
716+
simplifiedExpr = (if homotopyType == Modelica.Blocks.Types.LimiterHomotopy.Linear then V0*v_in
717+
else if homotopyType == Modelica.Blocks.Types.LimiterHomotopy.UpperLimit then vps
718+
else if homotopyType == Modelica.Blocks.Types.LimiterHomotopy.LowerLimit then vns
719+
else 0);
720+
if strict then
721+
if homotopyType == Modelica.Blocks.Types.LimiterHomotopy.NoHomotopy then
722+
v_out = smooth(0, noEvent(if V0*v_in>vps then vps else if V0*v_in<vns then vns else V0*v_in));
723+
else
724+
v_out = homotopy(actual = smooth(0, noEvent(if V0*v_in>vps then vps else if V0*v_in<vns then vns else V0*v_in)),
725+
simplified=simplifiedExpr);
726+
end if;
727+
else
728+
if homotopyType == Modelica.Blocks.Types.LimiterHomotopy.NoHomotopy then
729+
v_out = smooth(0, if V0*v_in>vps then vps else if V0*v_in<vns then vns else V0*v_in);
730+
else
731+
v_out = homotopy(actual = smooth(0, if V0*v_in>vps then vps else if V0*v_in<vns then vns else V0*v_in),
732+
simplified=simplifiedExpr);
733+
end if;
734+
end if;
711735
annotation (defaultComponentName="opAmp",
712736
Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,
713737
100}}), graphics={

0 commit comments

Comments
 (0)