Using External Code
While it is easy to write Modelica functions, it is sometimes convenient to call a subroutine written in C. This tutorial shows how to use an external function written in C.
MODELS USED IN THIS TUTORIAL |
Chirp ChirpSignal SeriesCircuit |
Chirp Function
A chirp signal is a sinusoid with a frequency that changes continuously over:
The instantaneous frequency in this signal is obtained by differentiating the argument with respect to time t:
The instantaneous frequency increases from the lower bound of the frequency band to the higher. When applying the signal to a system, it gives good control over the excited frequency band and is therefore often used for system identification. In this example, the chirp function will be defined in C and then used as an external function in Modelica.
Note that a simple mathematical function such as chirp is generally better implemented as a normal user-defined Modelica function, as this allows the symbolic machinery inside System Modeler to access the defining expression. In this tutorial, the chirp function is just used as a simple illustration of how the external language interface works.
Modeling
Begin by creating a Modelica function called Chirp that will make an external call to a C function with the same name.
function Chirp
input Modelica.Units.SI.AngularVelocity w_start;
input Modelica.Units.SI.AngularVelocity w_end;
input Real A;
input Real M;
input Real t;
output Real y "output signal";
external "C" annotation(
Include = "#include \"Chirp.c\"",
IncludeDirectory = "modelica://IntroductoryExamples/Resources/ExternalFunctions/");
end Chirp;
The function has five input signals, one output signal, and a call to the external function Chirp.c. The declaration assumes that the function Chirp.c is declared with these five inputs and returns a double. If for some reason you wish to switch the order of the variables in calling the function, this is possible by changing the declaration to, for instance, the following.
external "C" y = Chirp(t, A, M, w_start, w_end) annotation(…);
However, in this case a function is defined that uses the same variables in the same order.
double Chirp(double w1, double w2, double A, double M, double time)
{
double y;
y = A * cos(w1 * time + (w2 - w1) * time * time / (2 * M));
return y;
}
The function can be written in any text editor and stored with the name Chirp.c. In this case, the C file should be placed in a new directory called Resources/ExternalFunctions inside the directory where the package is stored. It can be placed in other places too, and the IncludeDirectory annotation should then be changed accordingly.
As soon as the C function is saved, the Modelica function is ready to use. To do this, a new Modelica block is created and the Chirp function is called within it. After creating the ChirpSignal block and defining the necessary parameters, you can drag and drop the predefined Modelica connector Modelica.Blocks.Interfaces.RealOutput from the Class Browser onto the Diagram View. This will create an instance of the connector in the ChirpSignal block, and it can be directly used in the equation section of the block.
block ChirpSignal
Modelica.Blocks.Interfaces.RealOutput y »;
parameter Modelica.Units.SI.AngularVelocity w_start = 0;
parameter Modelica.Units.SI.AngularVelocity w_end = 10;
parameter Real A = 1;
parameter Real M = 10;
equation
y = Chirp(w_start, w_end, A, M, time);
end ChirpSignal;
Note that default parameters have been set so that the signal will increase from 0 to 10 rad/s in 10 seconds, as shown by this simulation result.
Plotting the chirp signal y of the IntroductoryExamples.ExternalFunctions.ChirpSignal model.
As a result of using the predefined Modelica connector Modelica.Blocks.Interfaces.RealOutput, ChirpSignal can be used in other models as an input source. For instance, it can be used to test the resonance frequency of the following electric circuit.
The Diagram View of the IntroductoryExamples.ExternalFunctions.SeriesCircuit model.
Note that the default parameters of the electrical components have been changed according to the preceding figure. The parameters of the chirp have also been changed to sweep from 0 to 1000 rad/s.
Next, simulate and study the current.
Plotting the current through the voltage source of the IntroductoryExamples.ExternalFunctions.SeriesCircuit model.
As seen, there is an amplitude peak at around 5 seconds, which corresponds to:
This can also be verified by calculating the resonance frequency for the circuit analytically as follows:
Of course, for more complicated systems it might be difficult to calculate the resonance frequency analytically, and in these cases a chirp signal can be very useful.
Exercise
The chirp signal can easily be implemented as one single Modelica block without using an external function. This is left to the interested reader as an exercise.