Documentation

Parallel Simulations Using Parsim: Test-Case Sweep

This example shows how you can run multiple Simulink® simulations corresponding to different test cases in the Signal Builder block using SimulationInput objects and the parsim command. The parsim command uses Parallel Computing Toolbox™, if it is available, to run simulations in parallel, otherwise the simulations are run in serial.

Model Overview

The model sldemo_suspn_3dof shown below simulates the vehicle dynamics based on the road - suspension interaction for different road profiles. The vehicle dynamics are captured in three degrees of freedom: vertical displacement, roll, and pitch. The road profile data for the left and right tires is imported into the Signal Builder block as different test cases. The Road-Suspension Interaction subsystem calculates the suspension forces on the vehicle at the four tire locations based on the road data and the current vehicle state. In the Body Dynamics subsystem these forces and the resulting pitch and roll moments are used to determine the vehicle motion in three degrees of freedom: vertical displacement, roll, and pitch.

The suspension model is simulated using different road profiles to determine if the design meets desired performance goals. Parallel Computing Toolbox is used to speed up these multiple simulations, as illustrated below.

mdl               = 'sldemo_suspn_3dof';
isModelOpen       = bdIsLoaded(mdl);
open_system(mdl);

Set up Data Required for Multiple Simulations

Determine the number of cases in the Signal Builder block using the signalbuilder function. The number of cases is used to determine the number of iterations to run in step 3.

[~,~,~,cases]     = signalbuilder([mdl '/Road Profiles']);
numCases          = numel(cases);

Create an array of Simulink.SimulationInput objects to define the set of simulations to run. Each SimulationInput object corresponds to one simulation. The PreSimFcn on the SimulationInput object is used to run the signalbuilder function to set the active signal for each simulation. You can open the sldemo_parsim_testcase_suspn_presim function in the editor and inspect the code. The first argument to the PreSimFcn is always the SimulationInput object, and is passed into the function by Simulink®. In this case, we do not make use of this argument and use '~' as a placeholder instead. After defining the PreSimFcn, set the 'SimulationMode' model parameter to ensure that the simulation is always run in 'Normal' mode.

for idx = numCases:-1:1
    in(idx) = Simulink.SimulationInput(mdl);
    in(idx).PreSimFcn = @(~) sldemo_parsim_testcase_suspn_presim(mdl, idx);
    in(idx) = setModelParameter(in(idx), 'SimulationMode', 'Normal');
end

Note that specifying the model parameter on the SimulationInput object does not apply it to the model immediately. The specified value will be applied during the simulation and reverted back to its original value, if possible, after the simulation finishes.

Run Simulations in Parallel Using Parsim

Use the parsim function to execute the simulations in parallel. The array of SimulationInput objects, in, created in the last step is passed into the parsim function as the first argument. The output from the parsim command is an array of Simulink.SimulationOutput objects which is stored in the variable out. Set the 'ShowProgress' option to 'on' to print a progress of the simulations on the MATLAB command window.

out = parsim(in, 'ShowProgress', 'on');
[14-Aug-2017 18:47:01] Checking for availability of parallel pool...
Starting parallel pool (parpool) using the 'local' profile ...
connected to 12 workers.
[14-Aug-2017 18:47:43] Loading Simulink on parallel workers...
[14-Aug-2017 18:48:24] Loading model on parallel workers...
[14-Aug-2017 18:48:31] Configuring simulation cache folder on parallel workers...
[14-Aug-2017 18:48:38] Running simulations...
Analyzing and transferring files to the workers ...done.
[14-Aug-2017 18:48:53] Completed 1 of 20 simulation runs
[14-Aug-2017 18:48:53] Completed 2 of 20 simulation runs
[14-Aug-2017 18:48:53] Completed 3 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 4 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 5 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 6 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 7 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 8 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 9 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 10 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 11 of 20 simulation runs
[14-Aug-2017 18:48:54] Completed 12 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 13 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 14 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 15 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 16 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 17 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 18 of 20 simulation runs
[14-Aug-2017 18:48:59] Completed 19 of 20 simulation runs
[14-Aug-2017 18:49:00] Cleaning up parallel workers...
[14-Aug-2017 18:49:00] Completed 20 of 20 simulation runs

Each SimulationOutput object contains the logged signal along with the SimulationMetadata . When running multiple simulations using parsim, errors are captured so that subsequent simulations can continue to run. Any errors would show up in the ErrorMessage property of the SimulationOutput object.

Plot Results

Plot the vertical vehicle displacement from the different simulations to see how the vehicle performed to the different road profiles. The signal is logged in the SimulationOutput object in the Dataset format. Use the get method to obtain the timeseries object containing the time and signal data from each element of out.

legend_labels = cell(1,numCases);
for i = 1:numCases
        simOut = out(i);
        ts = simOut.logsout.get('vertical_disp').Values;
        ts.plot;
        legend_labels{i} = ['Run ' num2str(i)];
        hold all
end
title('Response of a 3-DoF Suspension Model')
xlabel('Time (s)');
ylabel('Vehicle vertical displacement (m)');
legend(legend_labels,'Location','NorthEastOutside');

Close MATLAB Workers

Last, close the parallel pool and the model if they were not previously opened.

if(~isModelOpen)
    close_system(mdl, 0);
end
delete(gcp('nocreate'));
Parallel pool using the 'local' profile is shutting down.
Was this topic helpful?