Message Boards Message Boards

0
|
2404 Views
|
5 Replies
|
1 Total Likes
View groups...
Share
Share this post:

SystemModelLinearize or TransferFunctionModel seems to produce unexpected result

Posted 1 year ago

I have a relatively simple Modelica model, and I would like to calculate its transfer functions. The problem is that the transfer function calculation with Mathematica yields zero, which is unexpected.

The problem emerged in a complex model, and here I only show a minimal example. The model comprises an angular spring attached to a massless rod, with a mass at the other end. The system is hanging and is actuated at the ground level. The actuation is an angular acceleration and serves as an input port. The spring constant and the rotational inertia of the mass are such that the resonant frequency is close to 1 Hz.

I have tested the model in time domain, and it seems to be doing something sensible. However, the calculation of the transfer function using Mathematica yields exactly zero. Somehow, this problem reminds me this post, but they don't seem to be related in an obvious way.

The Modelica model and the Mathematica notebook are shown below.

Given the simplicity of the model, I have the impression I'm missing something that may be obvious for the trained eye.

Any help would be highly appreciated.

Cheers,

Fabián

model AngularSpring
  inner Modelica.Mechanics.MultiBody.World world(label2 = "z", n = {0, 0, -1}) annotation(Placement(visible = true, transformation(origin = {-93.004, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.MultiBody.Joints.Revolute revolute1(useAxisFlange = true, phi.start = 0, phi.fixed = true, w.fixed = true, stateSelect = StateSelect.never) annotation(Placement(visible = true, transformation(origin = {25, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.Rotational.Components.Spring spring1(c = (2 * Modelica.Constants.pi) ^ 2) annotation(Placement(visible = true, transformation(origin = {25, 45}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.MultiBody.Parts.FixedTranslation fixedTranslation1(r = {0, 0, -0.25}) annotation(Placement(visible = true, transformation(origin = {62.15, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.MultiBody.Parts.FixedTranslation fixedTranslation2(r = {0, 0, -0.5}) annotation(Placement(visible = true, transformation(origin = {-25, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.MultiBody.Joints.Revolute revolute2(useAxisFlange = true, stateSelect = StateSelect.never) annotation(Placement(visible = true, transformation(origin = {-57.339, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.Rotational.Sources.Position position1(f_crit = 10000, exact = true) if false annotation(Placement(visible = true, transformation(origin = {-75, 67.223}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Blocks.Sources.Sine sine1(f = 10, amplitude = 17e-3) if false annotation(Placement(visible = true, transformation(origin = {-120, 67.339}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Blocks.Interfaces.RealInput u annotation(Placement(visible = true, transformation(origin = {-127.5, 12.5}, extent = {{-12.5, -12.5}, {12.5, 12.5}}, rotation = 0), iconTransformation(origin = {-78.502, 83.333}, extent = {{-20, -20}, {20, 20}}, rotation = 0)));
  Modelica.Mechanics.MultiBody.Sensors.AbsoluteAngles absoluteAngles1 annotation(Placement(visible = true, transformation(origin = {102.339, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Blocks.Interfaces.RealOutput y annotation(Placement(visible = true, transformation(origin = {132.721, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {88.481, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.MultiBody.Parts.Body body1(m = 1, I_33 = 1, I_11 = 1, I_22 = 1) annotation(Placement(visible = true, transformation(origin = {125, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Mechanics.Rotational.Sources.Accelerate accelerate1 annotation(Placement(visible = true, transformation(origin = {-85, 11.642}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
  connect(spring1.flange_a, revolute1.support) annotation(Line(visible = true, origin = {14.6, 34}, points = {{0.4, 11}, {-4.6, 11}, {-4.6, -4}, {4.4, -4}, {4.4, -14}}));
  connect(spring1.flange_b, revolute1.axis) annotation(Line(visible = true, origin = {35.835, -7.5}, points = {{-0.835, 52.5}, {4.39, 52.5}, {4.39, 27.5}, {-10.835, 27.5}}));
  connect(revolute1.frame_b, fixedTranslation1.frame_a) annotation(Line(visible = true, origin = {41.788, -10}, points = {{-6.788, 20}, {-1.788, 20}, {-1.788, -20}, {10.362, -20}}, color = {95, 95, 95}));
  connect(fixedTranslation2.frame_b, revolute1.frame_a) annotation(Line(visible = true, origin = {-5, -10}, points = {{-10, -20}, {-5, -20}, {-5, 20}, {20, 20}}, color = {95, 95, 95}));
  connect(revolute2.frame_b, fixedTranslation2.frame_a) annotation(Line(visible = true, origin = {-41.169, -30}, points = {{-6.169, 0}, {6.169, 0}}, color = {95, 95, 95}));
  connect(revolute2.frame_a, world.frame_b) annotation(Line(visible = true, origin = {-75.172, -30}, points = {{7.833, 0}, {-7.833, 0}}, color = {95, 95, 95}));
  connect(position1.flange, revolute2.axis) annotation(Line(visible = true, origin = {-59.893, 38.149}, points = {{-5.107, 29.074}, {2.554, 29.074}, {2.554, -58.149}}));
  connect(sine1.y, position1.phi_ref) annotation(Line(visible = true, origin = {-101, 67.281}, points = {{-8, 0.058}, {-3, 0.058}, {-3, -0.058}, {14, -0.058}}, color = {0, 0, 127}));
  connect(absoluteAngles1.angles[3], y) annotation(Line(visible = true, origin = {123.03, 0}, points = {{-9.691, 0}, {9.691, 0}}, color = {0, 0, 127}));
  connect(fixedTranslation1.frame_b, body1.frame_a) annotation(Line(visible = true, origin = {93.575, -30}, points = {{-21.425, 0}, {21.425, 0}}, color = {95, 95, 95}));
  connect(absoluteAngles1.frame_a, fixedTranslation1.frame_b) annotation(Line(visible = true, origin = {84.792, -15}, points = {{7.547, 15}, {2.547, 15}, {2.547, -15}, {-12.642, -15}}, color = {95, 95, 95}));
  connect(u, accelerate1.a_ref) annotation(Line(visible = true, origin = {-117.333, 11.928}, points = {{-10.167, 0.572}, {-10.167, -0.286}, {20.333, -0.286}}, color = {0, 0, 127}));
  connect(accelerate1.flange, revolute2.axis) annotation(Line(visible = true, origin = {-63.226, 1.095}, points = {{-11.774, 10.547}, {5.887, 10.547}, {5.887, -21.095}}));
  annotation(experiment(StopTime = 10.0), Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 114, 195}, fillColor = {255, 255, 255}, extent = {{-100, -100}, {100, 100}}, radius = 25), Text(visible = true, textColor = {64, 64, 64}, extent = {{-150, 110}, {150, 150}}, textString = "%name")}));
end AngularSpring;

POSTED BY: Fabián Peña
5 Replies
Posted 11 months ago

Dear Sergio,

Thank you very much for your reply again.

I tried making the example even simpler. Instead of using a revolute joint driven by an rotational spring, I adapted the revolute constraint to accept a torque. The modification worked using the numerical linearization method, but the symbolic one still fails.

I have the impression it's not possible to make the example simpler. It's just a single angular spring acting on a single body with rotational inertia. It's the angular equivalent of the classical spring with a mass attached. I'm not an expert, but I guess the difficulty lies in dealing with the three-dimensional space rotations matrices of the MultiBody library.

Sadly, for the project I have in mind, this limitation rules out the use of System Modeler (and maybe Modelica) with Mathematica. Is there a way to know if future development of SystemModelLinearize would include dealing with this kind of problem? This information would be useful for me to decide a way forward.

Thank you very much.

Regards,

Fabián

POSTED BY: Fabián Peña

We have discussed possible improvements that may help in symbolic linearization, like the reworking of the code that performs the fetching and processing of model equations, but this is not a simple task and unfortunately it is not possible for us to determine at the moment how large of an impact this may have in the end. As you indicate, the intrinsic (reduced) math of this model is not particularly complex, even when considering the rotational degrees of freedom. The challenge lays in the reduction and effective translation of component based modeling into WL equations. This can be seen when you work with models that are not component-based, by which I mean models that instead use raw equations. For those, the current symbolic linearization functionality struggles far less.

POSTED BY: Sergio Vargas
Posted 1 year ago

Dear Sergio,

Thank you very much for your reply.

Using "NumericDerivative" as an option does indeed produce the correct result.

I wonder if there is a workaround that would allow me to use "SymbolicDerivative" instead. In my model, I require to keep all the spring constants symbolic during linearization, in order to later replace them by complex values and analyze the transfer functions in frequency space.

I tried using "SymbolicDerivative" with "EquilibriumValues" instead of "InitialValues". However, after a long time, it failed with a message saying that I should use "NumericDerivative". In my model, the initial values equal the equilibrium values.

By any chance, is there a way to identify the feature in my model that produces this condition? In such a case, perhaps I would be able to modify my model accordingly.

Any suggestion would be highly appreciated.

Cheers,

Fabián

POSTED BY: Fabián Peña

Unfortunately, I think you have probably already reached the model size/complexity at which the current symbolic differentiation method won't be able to preserve symbolic parameters.

One long-shot of a workaround I could think of is to try to do a fit, using several numerically-linearized versions of your model that have different parameter values. Whether this is doable or not would depend on how complicated the dependence of the transfer function on the parameters is.

POSTED BY: Sergio Vargas

Using the option Method -> "NumericDerivative" in SystemModelLinearize may work better for this model when selecting "InitialValues" as operating point.

POSTED BY: Sergio Vargas
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract