This example shows the use of Rapid Accelerator in applications that require running parallel simulations for a range of input and parameter values.
We use the engine idle speed model which simulates the idle speed of an engine. The input of this model is the voltage of the bypass air valve and the output is the idle speed.
We run parallel simulations using
parsim with two sets of valve voltages and by independently varying two of the three gain parameters of the transfer functions over a range of two values. The following table lists the eight simulations that will be run along with the parameter values. The external inputs,
inpSets, are created in Step 2 below, and
gain3 are the variables corresponding to the two gain parameters.
It is easy to customize this example for your own application by modifying the script file used to build this example. Click the link in the top left corner of this page to edit the script file. Click the link in the top right corner to run this example from MATLAB®.
First we open the model where the simulation mode has been set to Rapid Accelerator. The default input data, and the required parameters are preloaded in the base workspace.
mdl = 'sldemo_raccel_engine_idle_speed'; open_system(mdl);
Here we perturb the default input values vector to obtain a new input values vector.
inpSets(1) = timeseries(inpData, time); rndPertb = 0.5 + rand(length(time), 1); inpSets(2) = timeseries(inpData.*rndPertb, time); numInpSets = length(inpSets);
We want to see how the idle speed changes for different values of parameters
gain3. Create an array of
Simulink.SimulationInput objects to specify the different parameter values and external input for each simulation. The array of SimulationInput objects is preallocated for better performance. Also note that the external input can be directly specified on the SimulationInput object instead of using a model parameter.
gain2_vals = 25:10:35; gain3_vals = 20:10:30; num_gain2_vals = length(gain2_vals); num_gain3_vals = length(gain3_vals); numSims = num_gain2_vals*num_gain3_vals*numInpSets; in(1:numSims) = Simulink.SimulationInput(mdl); idx = 1; for iG2 = 1:num_gain2_vals for iG3 = 1:num_gain3_vals for inpSetsIdx = 1:numInpSets in(idx) = in(idx).setModelParameter('SimulationMode', 'rapid', ... 'RapidAcceleratorUpToDateCheck', 'off', ... 'SaveTime', 'on', ... 'SaveOutput', 'on'); % Use setVariable to specify a new value for a variable during % simulations in(idx) = in(idx).setVariable('gain2', gain2_vals(iG2)); in(idx) = in(idx).setVariable('gain3', gain3_vals(iG3)); in(idx).ExternalInput = inpSets(inpSetsIdx); idx = idx + 1; end end end
Note that we also use the
setModelParameter method of the
SimulationInput object to set model parameters to run the simulations in Rapid Accelerator mode and enable logging. The Rapid Accelerator target is built using the
SetupFcn. The Rapid Accelerator target is build once and used by all subsequent simulations saving the time required for model compilation. Here is the code for the SetupFcn
function sldemo_parallel_rapid_accel_sims_script_setup(mdl) % Temporarily change the current folder on the workers to an empty % folder so that any existing slprj folder on the client does not % interfere in the build process. currentFolder = pwd; tempDir = tempname; mkdir(tempDir); cd (tempDir); oc = onCleanup(@() cd (currentFolder)); Simulink.BlockDiagram.buildRapidAcceleratorTarget(mdl); end
parsim function to execute the simulations in parallel. The array of
in, created in the last step is passed into the
parsim function as the first argument. Store the simulation output data in a variable,
out, whose value is an array of
Simulink.SimulationOutput objects. 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
out = parsim(in, 'ShowProgress', 'on', ... 'SetupFcn', @() sldemo_parallel_rapid_accel_sims_script_setup(mdl));
[16-Oct-2018 15:54:39] Checking for availability of parallel pool... Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6). [16-Oct-2018 15:55:37] Starting Simulink on parallel workers... Analyzing and transferring files to the workers ...done. [16-Oct-2018 15:55:38] Configuring simulation cache folder on parallel workers... [16-Oct-2018 15:55:38] Running SetupFcn on parallel workers... [16-Oct-2018 15:56:28] Loading model on parallel workers... [16-Oct-2018 15:56:29] Running simulations... [16-Oct-2018 15:56:34] Completed 1 of 8 simulation runs [16-Oct-2018 15:56:34] Completed 2 of 8 simulation runs [16-Oct-2018 15:56:34] Completed 3 of 8 simulation runs [16-Oct-2018 15:56:34] Completed 4 of 8 simulation runs [16-Oct-2018 15:56:34] Completed 5 of 8 simulation runs [16-Oct-2018 15:56:34] Completed 6 of 8 simulation runs [16-Oct-2018 15:56:38] Completed 7 of 8 simulation runs [16-Oct-2018 15:56:38] Completed 8 of 8 simulation runs [16-Oct-2018 15:56:38] Cleaning up parallel workers...
Plot the engine idle speed with respect to time for different parameter values and inputs. The output is logged in the array format and can be accessed from the SimulationOutput object.
for i = 1:numSims simOut = out(i); t = simOut.tout; y = simOut.yout; plot(t, y) hold all end
Parallel pool using the 'local' profile is shutting down.