diff --git a/Modelica/Blocks/Math.mo b/Modelica/Blocks/Math.mo index c2c5d3fa36..08fb2bf17c 100644 --- a/Modelica/Blocks/Math.mo +++ b/Modelica/Blocks/Math.mo @@ -2299,37 +2299,64 @@ explicitly set to 0.0, if the mean value results in a negative value. textString="f=%f")})); end Mean; - block RectifiedMean "Calculate rectified mean over period 1/f" + block TriggeredMean "Calculate mean over period determined by trigger" extends Modelica.Blocks.Interfaces.SISO; - parameter SI.Frequency f(start=50) "Base frequency"; + import Modelica.Constants.eps; parameter Real x0=0 "Start value of integrator state"; - parameter Real y0(final min=0)=0 "Start value of output"; - Mean mean(final f=f, final x0=x0, - final y0=y0) - annotation (Placement(transformation(extent={{0,-10},{20,10}}))); - Blocks.Math.Abs abs1 - annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + parameter Real y0=0 "Start value of output"; + parameter Boolean yGreaterOrEqualZero=false + "= true, if output y is guaranteed to be >= 0 for the exact solution" + annotation (Evaluate=true, Dialog(tab="Advanced")); + Modelica.Blocks.Interfaces.BooleanInput trigger "Trigger input signal" + annotation (Placement( + transformation( + extent={{-20,-20},{20,20}}, + rotation=90, + origin={0,-120}))); + protected + Modelica.Units.SI.Time t0 "Last trigger instance"; + Real x "Integrator state"; + discrete Real y_last "Last sampled mean value"; + initial equation + pre(trigger)=false; + t0 = time; + x = x0; + y_last = y0; equation - connect(u, abs1.u) annotation (Line( - points={{-120,0},{-62,0}}, color={0,0,127})); - connect(abs1.y, mean.u) annotation (Line( - points={{-39,0},{-2,0}}, color={0,0,127})); - connect(mean.y, y) annotation (Line( - points={{21,0},{110,0}}, color={0,0,127})); + der(x) = u; + when edge(trigger) then + y_last = if noEvent((time - pre(t0))>eps) then + if not yGreaterOrEqualZero then pre(x)/(time - pre(t0)) + else max(0.0, pre(x)/(time - pre(t0))) + else pre(y_last); + t0 = time; + reinit(x, 0); + end when; + y = y_last; annotation (Documentation(info="

-This block calculates the rectified mean of the input signal u over the given period 1/f, using the -mean block. +This block calculates the mean of the input signal u over the period dtermined by the edges of the trigger:

+
+ 1   T
+---- ∫ u(t) dt
+T-t0 t0
+

-Note: The output is updated after each period defined by 1/f. +Note: The output is updated at each trigger instance. +

+ +

+If parameter yGreaterOrEqualZero in the Advanced tab is true (default = false), +then the modeller provides the information that the mean of the input signal is guaranteed +to be ≥ 0 for the exact solution. However, due to inaccuracies in the numerical integration scheme, +the output might be slightly negative. If this parameter is set to true, then the output is +explicitly set to 0.0, if the mean value results in a negative value.

"), Icon(graphics={Text( extent={{-80,60},{80,20}}, - textString="RM"), Text( - extent={{-80,-20},{80,-60}}, - textString="f=%f")})); - end RectifiedMean; + textString="mean")})); + end TriggeredMean; block ContinuousMean "Calculates the empirical expectation (mean) value of its input signal" @@ -2416,6 +2443,78 @@ This block is demonstrated in the examples points={{-76,-24},{70,-24}})})); end ContinuousMean; + block RectifiedMean "Calculate rectified mean over period 1/f" + extends Modelica.Blocks.Interfaces.SISO; + parameter SI.Frequency f(start=50) "Base frequency"; + parameter Real x0=0 "Start value of integrator state"; + parameter Real y0(final min=0)=0 "Start value of output"; + Mean mean(final f=f, final x0=x0, + final y0=y0) + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Blocks.Math.Abs abs1 + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + equation + connect(u, abs1.u) annotation (Line( + points={{-120,0},{-62,0}}, color={0,0,127})); + connect(abs1.y, mean.u) annotation (Line( + points={{-39,0},{-2,0}}, color={0,0,127})); + connect(mean.y, y) annotation (Line( + points={{21,0},{110,0}}, color={0,0,127})); + annotation (Documentation(info=" +

+This block calculates the rectified mean of the input signal u over the given period 1/f, using the +mean block. +

+

+Note: The output is updated after each period defined by 1/f. +

+"), Icon(graphics={Text( + extent={{-80,60},{80,20}}, + textString="RM"), Text( + extent={{-80,-20},{80,-60}}, + textString="f=%f")})); + end RectifiedMean; + + block TriggeredRectifiedMean + "Calculate rectified mean over period determined by trigger" + extends Modelica.Blocks.Interfaces.SISO; + parameter Real x0=0 "Start value of integrator state"; + parameter Real y0=0 "Start value of output"; + Modelica.Blocks.Interfaces.BooleanInput trigger "Trigger input signal" + annotation (Placement( + transformation( + extent={{-20,-20},{20,20}}, + rotation=90, + origin={0,-120}))); + Modelica.Blocks.Math.TriggeredMean triggeredMean( + final yGreaterOrEqualZero=true, + final x0=x0, + final y0=y0) + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + Modelica.Blocks.Math.Abs abs1 + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + equation + connect(u, abs1.u) annotation (Line( + points={{-120,0},{-62,0}}, color={0,0,127})); + connect(abs1.y, triggeredMean.u) + annotation (Line(points={{-39,0},{-12,0}}, color={0,0,127})); + connect(triggeredMean.y, y) + annotation (Line(points={{11,0},{110,0}}, color={0,0,127})); + connect(trigger, triggeredMean.trigger) + annotation (Line(points={{0,-120},{0,-12}}, color={255,0,255})); + annotation (Documentation(info=" +

+This block calculates the rectified mean of the input signal u over the period the period dtermined by the edges of the trigger, using the +triggered mean block. +

+

+Note: The output is updated at each trigger instance. +

+"), Icon(graphics={Text( + extent={{-80,60},{80,20}}, + textString="RM")})); + end TriggeredRectifiedMean; + block RootMeanSquare "Calculate root mean square over period 1/f" extends Modelica.Blocks.Interfaces.SISO; parameter SI.Frequency f(start=50) "Base frequency"; @@ -2458,6 +2557,53 @@ Note: The output is updated after each period defined by 1/f. textString="f=%f")})); end RootMeanSquare; + block TriggeredRootMeanSquare + "Calculate root mean square over period determined by trigger" + extends Modelica.Blocks.Interfaces.SISO; + parameter Real x0=0 "Start value of integrator state"; + parameter Real y0=0 "Start value of output"; + Modelica.Blocks.Interfaces.BooleanInput trigger "Trigger input signal" + annotation (Placement( + transformation( + extent={{-20,-20},{20,20}}, + rotation=90, + origin={0,-120}))); + Modelica.Blocks.Math.MultiProduct product(nu=2) + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Modelica.Blocks.Math.TriggeredMean triggeredMean( + final yGreaterOrEqualZero=true, + final x0=x0, + final y0=y0*y0) + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + Modelica.Blocks.Math.Sqrt sqrt1 + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + equation + + connect(product.y, triggeredMean.u) + annotation (Line(points={{-38.3,0},{-12,0}}, color={0,0,127})); + connect(triggeredMean.y, sqrt1.u) + annotation (Line(points={{11,0},{38,0}}, color={0,0,127})); + connect(sqrt1.y, y) annotation (Line( + points={{61,0},{110,0}}, color={0,0,127})); + connect(u, product.u[1]) annotation (Line( + points={{-120,0},{-80,0},{-80,3.5},{-60,3.5}}, color={0,0,127})); + connect(u, product.u[2]) annotation (Line( + points={{-120,0},{-80,0},{-80,-3.5},{-60,-3.5}}, color={0,0,127})); + connect(trigger, triggeredMean.trigger) + annotation (Line(points={{0,-120},{0,-12}}, color={255,0,255})); + annotation (Documentation(info=" +

+This block calculates the root mean square of the input signal u over the period the period dtermined by the edges of the trigger:, using the +triggered mean block. +

+

+Note: The output is updated at each trigger instance. +

+"), Icon(graphics={Text( + extent={{-80,60},{80,20}}, + textString="RMS")})); + end TriggeredRootMeanSquare; + block SignalExtrema "Calculate min and max of a signal" extends Modelica.Blocks.Icons.Block; diff --git a/Modelica/Blocks/package.mo b/Modelica/Blocks/package.mo index 2190133239..94239cf90b 100644 --- a/Modelica/Blocks/package.mo +++ b/Modelica/Blocks/package.mo @@ -1677,6 +1677,89 @@ The output is constant from the beginning. ")); end DemoSignalCharacteristic; + model DemoSignalCharacteristicVaryingFrequency + "Demonstrate characteristic values of a signal" + extends Modelica.Icons.Example; + import Modelica.Constants.pi; + Modelica.Blocks.Sources.Ramp rampFrequency( + height=40, + duration=0.5, + offset=10, + startTime=0.25) + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + Modelica.Blocks.Continuous.Integrator integrator(k=2*pi) + annotation (Placement(transformation(extent={{-50,40},{-30,60}}))); + Modelica.Blocks.Math.WrapAngle wrapAngle(positiveRange=false) + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + Modelica.Blocks.Logical.LessEqualThreshold lessEqualThreshold(threshold=0) + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=270, + origin={10,22}))); + Modelica.Blocks.Math.Sin sin1 + annotation (Placement(transformation(extent={{20,40},{40,60}}))); + Modelica.Blocks.Sources.Ramp rampOffset( + height=1, + duration=0.5, + offset=0, + startTime=0.25) + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Modelica.Blocks.Math.Add add annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=270, + origin={60,30}))); + Modelica.Blocks.Math.TriggeredMean triggeredMean + annotation (Placement(transformation(extent={{70,0},{90,20}}))); + Modelica.Blocks.Math.TriggeredRectifiedMean triggeredRectifiedMean + annotation (Placement(transformation(extent={{70,-40},{90,-20}}))); + Modelica.Blocks.Math.TriggeredRootMeanSquare triggeredRootMeanSquare + annotation (Placement(transformation(extent={{70,-80},{90,-60}}))); + equation + connect(rampFrequency.y, integrator.u) + annotation (Line(points={{-59,50},{-52,50}}, color={0,0,127})); + connect(integrator.y, wrapAngle.u) + annotation (Line(points={{-29,50},{-22,50}}, color={0,0,127})); + connect(wrapAngle.y, sin1.u) + annotation (Line(points={{1,50},{18,50}}, color={0,0,127})); + connect(wrapAngle.y, lessEqualThreshold.u) + annotation (Line(points={{1,50},{10,50},{10,34}}, color={0,0,127})); + connect(lessEqualThreshold.y, triggeredRectifiedMean.trigger) annotation (Line( + points={{10,11},{10,-50},{80,-50},{80,-42}}, color={255,0,255})); + connect(lessEqualThreshold.y, triggeredRootMeanSquare.trigger) annotation ( + Line(points={{10,11},{10,-90},{80,-90},{80,-82}}, color={255,0,255})); + connect(lessEqualThreshold.y, triggeredMean.trigger) + annotation (Line(points={{10,11},{10,-10},{80,-10},{80,-2}}, + color={255,0,255})); + connect(sin1.y, add.u2) + annotation (Line(points={{41,50},{54,50},{54,42}}, color={0,0,127})); + connect(rampOffset.y, add.u1) + annotation (Line(points={{-59,80},{66,80},{66,42}}, color={0,0,127})); + connect(add.y, triggeredMean.u) + annotation (Line(points={{60,19},{60,10},{68,10}}, color={0,0,127})); + connect(add.y, triggeredRectifiedMean.u) + annotation (Line(points={{60,19},{60,-30},{68,-30}}, color={0,0,127})); + connect(add.y, triggeredRootMeanSquare.u) + annotation (Line(points={{60,19},{60,-70},{68,-70}}, color={0,0,127})); + annotation (experiment( + Interval=0.0001, + Tolerance=1e-06), + Documentation(info=" +

+A sine with continuously varying frequency is added to an offset. +The triggered blocks detect mean, rectifiedMean and rootMeanSquare of the signal. +The trigger condition (i.e. the edge of the trigger) is detected when the wrapped angle is below zero, i.e. when the sine crosses zero from positive to negative values. +

+

Note

+

+Mathematically it is not correct to talk about characteristc values like rootMeanSquare, +if the period of the input signal is not constant (as in this example). +So the values during the frequency ramp are more or less an estimaton, +but at the beginning and at the end - when frequency is constant - the result is mathematically correct: +Since the amplitude of the sine is 1, at the beginning (offset=0) rms=1/sqrt(2) and at the end (offset=0) rms=sqrt(3/2) are correct. +

+")); + end DemoSignalCharacteristicVaryingFrequency; + package Noise "Library of examples to demonstrate the usage of package Blocks.Noise" extends Modelica.Icons.ExamplesPackage; diff --git a/Modelica/Resources/Reference/Modelica/Blocks/Examples/DemonstrateSignalCharaceristicVaryingFrequency/comparisonSignals.txt b/Modelica/Resources/Reference/Modelica/Blocks/Examples/DemonstrateSignalCharaceristicVaryingFrequency/comparisonSignals.txt new file mode 100644 index 0000000000..6a57c7655d --- /dev/null +++ b/Modelica/Resources/Reference/Modelica/Blocks/Examples/DemonstrateSignalCharaceristicVaryingFrequency/comparisonSignals.txt @@ -0,0 +1,4 @@ +time +triggeredMean.y +triggeredRectifiedMean.y +triggeredRootMeanSquare.y