Simulink

Parallel Simulations Using Parfor: Test-Case Sweep

This example shows how you can run multiple Simulink® simulations corresponding to different test cases in the Signal Builder block, in parallel by using the Parallel Computing Toolbox™. This involves five main steps:

  1. Start MATLAB® workers on your machine

  2. Set up data required for the multiple simulations

  3. Run multiple simulations in a parfor (parallel for) loop

  4. Plot results of multiple simulations

  5. Close MATLAB workers

Model Overview

The model sldemo_suspn_3dofsldemo_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);

Step 1: Start MATLAB Workers on Your Machine

First configure and start a pool of MATLAB workers. Use the parpool command to check if a parallel pool is open, and then open a local pool on your multicore desktop. This requires Parallel Computing Toolbox.

apool = gcp;
if isempty(apool)
    apool = parpool;
end
Starting parallel pool (parpool) using the 'local' profile ... connected to 12 workers.

Step 2: Set up Data Required for the Multiple Simulations

Determine the number of cases in the Signal Builder block using the signalbuildersignalbuilder function. The number of cases is used to determine the number of iterations to run in step 3. The number of cases is also used to preallocate an array of SimulationOutput objects in the Simulink package that will be used to collect the simulation results in step 3.

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

Step 3: Run Multiple Simulations in a parfor (Parallel for) Loop

Run multiple simulations corresponding to the different test cases in the Signal Builder block within a parfor loop. The signalbuilder function is used again here but this time to set the active signal in each iteration. The simsim command returns all the simulation data as a SimulationOutput object of the Simulink package. Note that the simulation results are collected in the simout variable, which was preallocated in step 2.

parfor idx = 1:numCases
    load_system(mdl);
    signalbuilder([mdl '/Road Profiles'],'activegroup',idx);
    simout(idx) = sim(mdl,'SimulationMode','normal');
end

Step 4: Plot Results of Multiple Simulations

Plot the vertical vehicle displacement from the different simulations to see how the vehicle performed to the different road profiles. Use the get method of the SimulationOutput object to obtain the timeseries contained in each element of simout. The time and and signal data are contained within the timeseries object.

legend_labels = cell(1,numCases);
for i = 1:numCases
        si = simout(i);
        ts = si.get('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');

Step 5: 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(apool);