From 4e763643b3b31da3795ead14457c30a751f68cc3 Mon Sep 17 00:00:00 2001 From: Anton Haumer Date: Fri, 29 Jul 2022 12:45:04 +0200 Subject: [PATCH] Implement continuous version of SignalExtrema --- Modelica/Blocks/Math.mo | 97 +++++++++++++++++++++++++++++++++++++- Modelica/Blocks/package.mo | 52 ++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) diff --git a/Modelica/Blocks/Math.mo b/Modelica/Blocks/Math.mo index d06d368c4b..ca81796847 100644 --- a/Modelica/Blocks/Math.mo +++ b/Modelica/Blocks/Math.mo @@ -2530,6 +2530,101 @@ This means that:

")); end SignalExtrema; + block ContinuousSignalExtrema "Peak of input signal" + extends Modelica.Blocks.Icons.Block; + parameter Modelica.Units.SI.Time T(min=Modelica.Constants.small)=1e-6 "Derivative time constant"; + Modelica.Blocks.Interfaces.RealInput u + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}))); + Modelica.Blocks.Interfaces.RealOutput y_min + annotation (Placement(transformation(extent={{100,-70},{120,-50}}))); + Modelica.Blocks.Interfaces.RealOutput y_max + annotation (Placement(transformation(extent={{100,50},{120,70}}))); + output Modelica.Units.SI.Time t_min "Time instant of last found minimum"; + output Modelica.Units.SI.Time t_max "Time instant of last found maximum"; + protected + Real x "Aux.state"; + initial equation + x = u; + y_min = u; + y_max = u; + t_min = time; + t_max = time; + equation + //first order approximation of input + der(x) = (u - x)/T; + //first order approximation of derivative of input + when {u<=x, u>=x, terminal()} then + //detect local extrema at zero derivative, just before and after a step, and at the end of the simulation + y_min = min({pre(y_min), u, pre(u)}); + y_max = max({pre(y_max), u, pre(u)}); + if y_minpre(y_max) then + t_min=pre(t_min); + t_max=time; + else + t_min=pre(t_min); + t_max=pre(t_max); + end if; + end when; + annotation (defaultComponentName="signalExtrema", + Documentation(info=" +

+This block detects positive and negative peaks of differentiable and non-differentiable input signals without sampling. +

+

+For differentiable input singals, an extremum is detected if the derivative of the input signal is zero. +

+

+To handle non-differentiable input signals, the input signal u is conditioned by a first order wth time constant T. +Like in the derivative block, +the derivative of the input signal is approximated by (u - x)/T. +This way even steps with local extrema just before and after the step are taken into account. +

+

+Additionally, when the simulation terminates, y_maxy_min and y_max are updated. +

+"), + Icon(graphics={ + Polygon( + points={{-80,90},{-88,68},{-72,68},{-80,90}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line( + points={{-80,0},{-75.2,32.3},{-72,50.3},{-68.7,64.5},{-65.5,74.2},{ + -62.3,79.3},{-59.1,79.6},{-55.9,75.3},{-52.7,67.1},{-48.6,52.2}, + {-43,25.8},{-35,-13.9},{-30.2,-33.7},{-26.1,-45.9},{-22.1,-53.2}, + {-18,-56},{-14.1,-52.5},{-10.1,-45.3},{-5.23,-32.1},{8.44,13.7}, + {13.3,26.4},{18.1,34.8},{22.1,38},{26.9,37.2},{31.8,31.8},{38.2, + 19.4},{51.1,-10.5},{57.5,-21.2},{63.1,-25.9},{68.7,-25.9},{75.2, + -20.5},{80,-13.8}}, + smooth=Smooth.Bezier, + color={192,192,192}), + Line(points={{-90,0},{68,0}}, color={192,192,192}), + Line(points={{-80,68},{-80,-80}}, 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={{-60,80},{52,80}}, + color={0,0,0}, + pattern=LinePattern.Dash), + Line( + points={{-18,-56},{50,-56}}, + color={0,0,0}, + pattern=LinePattern.Dash), + Text(extent={{60,-50},{92,-70}}, + textColor={0,0,0}, + textString="min"), + Text(extent={{60,70},{92,50}}, + textColor={0,0,0}, + textString="max")})); + end ContinuousSignalExtrema; + block Variance "Calculates the empirical variance of its input signal" extends Modelica.Blocks.Icons.Block; parameter SI.Time t_eps(min=100*Modelica.Constants.eps)=1e-7 @@ -3230,4 +3325,4 @@ connected with continuous blocks or with sampled-data blocks. 57.5,-63.9},{63.9,-49.2},{72,-26.8},{80,-2}}, color={95,95,95}, smooth=Smooth.Bezier)})); -end Math; \ No newline at end of file +end Math; diff --git a/Modelica/Blocks/package.mo b/Modelica/Blocks/package.mo index da7b420f75..26c4bed522 100644 --- a/Modelica/Blocks/package.mo +++ b/Modelica/Blocks/package.mo @@ -1490,6 +1490,58 @@ whereas signalExtrema2 catches the extrema rather good due to the fact that samp ")); end DemonstrateSignalExtrema; + model DemonstrateContinuousSignalExtrema + "Test the ContinuousSignalExtrema block" + extends Modelica.Icons.Example; + Modelica.Blocks.Sources.Sine sine( + amplitude=1, + f=9, + offset=-2) + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + Modelica.Blocks.Sources.SawTooth sawTooth( + amplitude=2, + period=1/9, + offset=1) + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + Modelica.Blocks.Sources.Sine amplitude( + amplitude=1, + f=0.75, + offset=0) + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Modelica.Blocks.Math.Product product1 + annotation (Placement(transformation(extent={{-20,20},{0,40}}))); + Modelica.Blocks.Math.Product product2 + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + Modelica.Blocks.Math.ContinuousSignalExtrema signalExtrema1 + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + Modelica.Blocks.Math.ContinuousSignalExtrema signalExtrema2 + annotation (Placement(transformation(extent={{20,-40},{40,-20}}))); + equation + connect(amplitude.y, product1.u2) annotation (Line(points={{-39,0},{-30,0},{ + -30,24},{-22,24}}, color={0,0,127})); + connect(amplitude.y, product2.u1) annotation (Line(points={{-39,0},{-30,0},{ + -30,-24},{-22,-24}}, color={0,0,127})); + connect(sine.y, product1.u1) annotation (Line(points={{-59,30},{-40,30},{-40, + 36},{-22,36}}, color={0,0,127})); + connect(sawTooth.y, product2.u2) annotation (Line(points={{-59,-30},{-40,-30}, + {-40,-36},{-22,-36}}, color={0,0,127})); + connect(product1.y, signalExtrema1.u) + annotation (Line(points={{1,30},{18,30}}, color={0,0,127})); + connect(product2.y, signalExtrema2.u) + annotation (Line(points={{1,-30},{18,-30}}, color={0,0,127})); + annotation (experiment( + StopTime=1, + Interval=0.0001, + Tolerance=1e-06), Documentation(info=" +

+The amplitude of both a differentiable sinudoidal signal (frequency 9 Hz) and a non-differentiable sawtooth signal (period 1/9 s) is modulated sinusoidally /frequency 0.75 Hz). +

+

+Note that the ContinuousSignalExtremaBlock detects extrema of both signals without sampling. +

+")); + end DemonstrateContinuousSignalExtrema; + model DemoSignalCharacteristic "Demonstrate characteristic values of a signal" extends Modelica.Icons.Example;