Stream Data from a MAT-File as Input for a Parallel Simulation

This example shows how to use Simulink.SimulationData.DatasetRef objects and the parsim function to stream input data from a version 7.3 MAT-file for parallel simulations. Consider following the steps outlined in this example when the inputs for your simulation are too large to load into memory. For example, you can use data logged to persistent storage from one set of parallel simulations as input for another.

This example uses parsim to run multiple simulations of a model, with each simulation using unique input data. The model is based on the sldemo_suspn_3dof model, modified to use Inport blocks as the source for inputs instead of the Signal Editor block. The model simulates the response of a suspension system to different road conditions. The MAT-file used in this example contains multiple Simulink.SimulationData.Dataset objects representing various road conditions. The example uses DatasetRef objects to stream the contents of an entire referenced Dataset object as simulation input.

You can also stream data for individual signals into parallel simulations run with parsim using objects. For details on creating SimulationDatastore objects, see Stream Individual Signals Using SimulationDatastore Objects.

Load Model and Access Input Data

Load the ex_sldemo_suspn_3dof_parsim_stream model. The model receives input data through two Inport blocks, and each Dataset object used as simulation input contains two elements: one for each Inport.

mdl = 'ex_sldemo_suspn_3dof_parsim_stream';

You can use the Simulink.SimulationData.DatasetRef.getDatasetVariableNames function to evaluate the contents of the MAT-file containing the input data without loading the data into memory. The function returns a cell array that contains elements for the name of each Simulink.SimulationData.Dataset variable the file contains. Use the function to access the variable names and determine the number of test cases in the file.

varNames = Simulink.SimulationData.DatasetRef.getDatasetVariableNames('suspn_3dof_test_cases.mat');
numTestCases = numel(varNames);

You can stream the test case data into the model using Simulink.SimulationData.DatsetRef objects. The DatasetRef object references a variable in the file used to create it and loads the variable data incrementally. Create a DatasetRef object for each Simulink.SimulationData.Dataset object in the test cases file.

for idx1 = 1:numTestCases
    inputData(idx1) = Simulink.SimulationData.DatasetRef('suspn_3dof_test_cases.mat',...

Configure and Run Parallel Simulations

To use the set of test case inputs as input for a set of parallel simulations, create an array of Simulink.SimulationInput objects that you can pass to the parsim function. Use the setExternalInput function to specify a Simulink.SimulationData.DatasetRef object corresponding to a test case as data to stream as simulation input.

in(1:numTestCases) = Simulink.SimulationInput(mdl);

for idx2 = 1:numTestCases
    in(idx2) = setExternalInput(in(idx2),inputData(idx2));

Use the parsim function to run a simulation for each test case. When you have the Parallel Computing Toolbox™, the parsim function runs simulations in parallel. Without the Parallel Computing Toolbox, the parsim function runs the simulations in serial.

The parsim function creates a worker pool based on the Parallel Computing Toolbox configuration. By default, parsim uses a local pool. If you use remote workers, you can use the AttachedFiles name-value pair to send the MAT-file containing the test case input data to each worker. When you specify the AttachedFiles name-value pair, parsim sends a copy of the file to each worker, which can take some time for large files. For streaming input data from a large file, local workers may be faster because the workers have access to the file without creating and sending copies. When you use remote workers, consider storing the MAT-file in a location that all remote workers can access and creating DatasetRef objects that reference that copy of the file.

out = parsim(in);
[29-Feb-2020 02:25:17] Checking for availability of parallel pool...
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 4).
[29-Feb-2020 02:26:23] Starting Simulink on parallel workers...
[29-Feb-2020 02:26:58] Configuring simulation cache folder on parallel workers...
[29-Feb-2020 02:26:58] Loading model on parallel workers...
[29-Feb-2020 02:27:31] Running simulations...
[29-Feb-2020 02:27:41] Completed 1 of 20 simulation runs
[29-Feb-2020 02:27:42] Completed 2 of 20 simulation runs
[29-Feb-2020 02:27:42] Completed 3 of 20 simulation runs
[29-Feb-2020 02:27:43] Completed 4 of 20 simulation runs
[29-Feb-2020 02:27:44] Completed 5 of 20 simulation runs
[29-Feb-2020 02:27:45] Completed 6 of 20 simulation runs
[29-Feb-2020 02:27:45] Completed 7 of 20 simulation runs
[29-Feb-2020 02:27:47] Completed 8 of 20 simulation runs
[29-Feb-2020 02:27:48] Completed 9 of 20 simulation runs
[29-Feb-2020 02:27:48] Completed 10 of 20 simulation runs
[29-Feb-2020 02:27:50] Completed 11 of 20 simulation runs
[29-Feb-2020 02:27:51] Completed 12 of 20 simulation runs
[29-Feb-2020 02:27:52] Completed 13 of 20 simulation runs
[29-Feb-2020 02:27:52] Completed 14 of 20 simulation runs
[29-Feb-2020 02:27:54] Completed 15 of 20 simulation runs
[29-Feb-2020 02:27:54] Completed 16 of 20 simulation runs
[29-Feb-2020 02:27:54] Completed 17 of 20 simulation runs
[29-Feb-2020 02:27:57] Completed 18 of 20 simulation runs
[29-Feb-2020 02:27:58] Completed 19 of 20 simulation runs
[29-Feb-2020 02:27:58] Completed 20 of 20 simulation runs
[29-Feb-2020 02:27:58] Cleaning up parallel workers...

View Simulation Results

You can access the simulation results programmatically when the simulations finish. Create a plot showing the vertical displacement for the vehicle for all the road profile test cases.

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

You can also view parsim simulation results using the Simulation Manager. To view results in the Simulation Manager, use the ShowSimulationManager name-value pair for parsim. With the Simulation Manager, you can monitor the progress of the runs, view simulation data, and show the parsim results in the Simulation Data Inspector.

Close Parallel Workers

When you have finished running parallel simulations, you can close the worker pool.


Related Topics

Load Big Data for Simulations

Log Data to Persistent Storage

Run Parallel Simulations Using parsim