Improving model efficiency and lowering run times:
There are 4 common causes of slow-running models:
- Poor initialisation values
- Large number of events during simulation
- Large number of non-linear systems of equations in model
- Large numbers of numerical jacobians in model
Poor initialisation values can lead to slow model initialisation and large amounts of CPU time spent whilst the model settles into a more stable state. For example: If we had a fluids system where two adjacent pipes were initialised at substantially different initial pressures (say 12 bar and 0.3 bar respectively), we would get a large transient at time t=0 and shortly beyond as the pressures in the two pipes stabilise. The same concept is valid for other domains. For a multibody vehicle system we might initialise the vehicle body to be travelling at 50mph but we might have forgotten to initialise the wheel rotational speeds to reflect the vehicle body initialisation. If the initialisation of the wheels is 0 rpm, we will get large amounts of tyre slip causing the model to be unnecessarily computationally intensive.
We need to understand:
- What initial conditions have been set,
- What initial conditions have not been set (Dymola will assume some default values for these)
- Understand where in the model we should be setting these initial conditions such that we influence the model initialisation.
To do the above we need to select the tick boxes Log selected default initial conditions and List continuous time states selected found within the Experiment Setup -> Translation tab (see below).
We can now translate the model to view the output information from selecting these boxes:
The log tells us that Dymola has assumed initial start values for 3 state variables. These are:
- both springs’ start length (s_rel) and
- one springs’ relative start velocity (v_rel).
In absence of a value being input by the user, Dymola initialises these variables with a default value of 0. By setting the initial values of the continuous time states (listed towards the end of the log) we can control the initialisation of the model. The initial values can be defined as either a guess value or a fixed value. The parameter dialog below is from the spring damper and we can set the initial values for s_rel and v_rel. By default the value entered will be used as a guess value for initialisation but by using the checkbox we can fix the initial value.
Tracking events during the simulation
Events during a simulation will cause the continuous solver to stop and iterations to take place until consistent re-start conditions have been met. At this point the continuous solver is re-started and continues until end of the simulation or until the next state event occurs. Reduction of state events during the simulation is thus desirable.
We can see the number of events that occurred during the simulation in the Messages window, on the Simulation tab. We can also log them in more detail, to find out when events occur and what the triggering equations are. To enable this logging, select Events during simulation and Events during initialisation in the Experiment Setup -> Debug tab.
An example of the detailed log in the Messages window is shown below. Notice the events were triggered by a boolean expression which changed from true to false during initialisation and from false to true during the simulation. The simulation statistics summary at the end of the log will only list the number of events during the simulation and not ones during initialisation.
To remove events we can re-work the model code to minimise the number of Boolean checks we are requesting or/and use special operators such as noEvent and smooth to reduce the number of events being generated.
Large number of non-linear systems of equations
Non linear systems of equations can cause computation to be slow. The number of non-linear systems of equations in a model can be viewed from the Translation tab in the Messages window after a model has been translated. Dymola will list the number of non-linear systems of equations before and after the symbolic manipulation has taken place. It is the number of non-linear systems of equations after manipulation which will be of most use to us because this will be the set of equations the model will run with.
In order to understand what the non-linear systems of equations are and which variables in the model are involved we can look at the dsmodel.mof file. The dsmodel.mof file contains the translated Modelica code and lists any non-linear systems of equations within it. To output the dsmodel.mof file to our current working directory select the option Generate listing of translated Modelica code in dsmodel.mof in the Simulation Setup dialog box.
Translate the model and open the dsmodel.mof file in notepad or similar text editor (this file will not be generated if the model contains encrypted classes). Do a text search for nonlinear and search down through the file to identify all the non-linear systems of equations within the model. We can now try and rework the code to reduce the number of non-linear systems of equations. Sometimes it is not feasible to remove all of them so we have to just live with them as they might be inherent to the behaviour of a system.
Numerical Jacobians are normally appear when Dymola cannot compute the derivative of an expression. Numerical Jacobians are computationally expensive so we should try to eliminate these when they occur. A numerical jacobian is usually generated when Dymola is unable to automatically differentiate a function. We can do this by providing Dymola with the expression for the derivative of the function within the model. To discover which functions cannot be differentiated but need to be set the flag Hidden.PrintFailureToDifferentiate=true before translating the model.
To tell Dymola to use a function as the derivative to another function we need to follow the Modelica specification. The language specification explains how to create the inputs and outputs for the derivative function and we then need to add the following annotation to the function we are adding the derivative for: annotation (derivative=ModelicaPathOfYourDerivativeFunction).