Несколько симуляций Рабочего процесса подсказок

Цель этой демонстрации состоит в том, чтобы предоставить полезные советы для выполнения нескольких симуляций с помощью инструментов параллельной симуляции. Этот пример будет работать, даже если Parallel Computing Toolbox™ недоступен, но симуляции будут выполняться последовательно. Мы будем использовать sldemo_suspn_3dof модели для этого примера.

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

Инициализация массива Simulink объектов .SimulationInput

Обычно вы создадите массив из Simulink объектов .SimulationInput в порядок, чтобы запустить несколько симуляций. Существует несколько способов инициализировать массив перед заполнением его данными.

numSims = 5;
Cf_sweep = Cf*linspace(.05,.95, numSims);

Метод 1: Инициализируйте массив перед циклом

in(numSims) = Simulink.SimulationInput;
for idx = 1:numSims
    % Need to populate the model name since we get any empty array by default
    in(idx).ModelName = 'sldemo_suspn_3dof';
    in(idx) = in(idx).setVariable('Cf', Cf_sweep(idx));
end

Метод 2: Инициализируйте массив в цикле

Обратите внимание, что переменная цикла idx начинается с самого большого значения так, чтобы весь массив был предварительно выделен.

for idx = numSims:-1:1
    % Since we are indexing from 5 to 1, the first iteration will
    % initialize the array.
    in(idx) = Simulink.SimulationInput('sldemo_suspn_3dof');
    in(idx) = in(idx).setVariable('Cf', Cf_sweep(idx));
end

Настройка параметров модели и блоков

The setModelParameter и setBlockParameter методы используют тот же синтаксис пары значение параметров, что и set_param API использует. Это означает, что большинство значений, которые вы передаете этим методам, должны быть символьными массивами, а не их буквальными значениями.

for idx = numSims:-1:1
    in(idx) = Simulink.SimulationInput('sldemo_suspn_3dof');

    % Incorrect
    in(idx) = in(idx).setModelParameter('StartTime', 5);

    % Correct
    in(idx) = in(idx).setModelParameter('StartTime', '3');
end

Настройка переменных

The setVariable метод ожидает, что вы передадите буквальное значение, которое вы хотите назначить переменной. Идея в том, что это тесно отражает assignin синтаксис.

for idx = numSims:-1:1
    in(idx) = Simulink.SimulationInput('sldemo_suspn_3dof');

    % Incorrect, Cf is expected to be a double, not a character array
    in(idx) = in(idx).setVariable('Cf', '2500');

    % Correct, Cf is a scalar double
    in(idx) = in(idx).setVariable('Cf', 2500);
end

Диагностика ошибок во время выполнения

Предположим, что вы случайно создали массив Simulink объектов .SimulationInput с неправильным значением.

Mb_sweep = linspace(0, 1500, numSims);
for idx = numSims:-1:1
    in(idx) = Simulink.SimulationInput('sldemo_suspn_3dof');

    % Accidentally set the Mass to 0 on the first iteration
    in(idx) = in(idx).setVariable('Mb', Mb_sweep(idx));

    % Shorten the stop time
    in(idx) = in(idx).setModelParameter('StopTime','1');
end

Симуляция их приведет к ошибке во время выполнения

out = sim(in);
[05-May-2020 13:22:50] Running simulations...
[05-May-2020 13:22:51] Completed 1 of 5 simulation runs. Run 1 has errors.
[05-May-2020 13:22:52] Completed 2 of 5 simulation runs
[05-May-2020 13:22:53] Completed 3 of 5 simulation runs
[05-May-2020 13:22:54] Completed 4 of 5 simulation runs
[05-May-2020 13:22:55] Completed 5 of 5 simulation runs
Warning: Simulation(s) with indices listed below completed with errors. Please
inspect the corresponding SimulationOutput to get more details about the error:
[1] 

К счастью, вы можете просмотреть объект Simulink .SimulationOutput, чтобы увидеть любые сообщения об ошибке, которые происходят из симуляции.

out(1).ErrorMessage
ans =

    'Derivative of state '1' in block '<a href="matlab:open_and_hilite_hyperlink ('sldemo_suspn_3dof/Body Dynamics/Vertical (Z) dynamics/Zdot','error')">sldemo_suspn_3dof/Body Dynamics/Vertical (Z) dynamics/Zdot</a>' at time 0.0 is not finite. The simulation will be stopped. There may be a singularity in the solution.  If not, try reducing the step size (either by reducing the fixed step size or by tightening the error tolerances)'

Это работает, чтобы решить проблемы с параллельными рабочими.

for idx = numSims:-1:1
    in(idx) = Simulink.SimulationInput('sldemo_suspn_3dof');

    % Accidentally set the Mass to 0 on the first iteration
    in(idx) = in(idx).setVariable('Mb', Mb_sweep(idx));

    % Shorten the stop time
    in(idx) = in(idx).setModelParameter('StopTime','1');
end

out = parsim(in);
[05-May-2020 13:22:55] Checking for availability of parallel pool...
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).
[05-May-2020 13:23:24] Starting Simulink on parallel workers...
[05-May-2020 13:23:47] Configuring simulation cache folder on parallel workers...
[05-May-2020 13:23:48] Loading model on parallel workers...
[05-May-2020 13:24:04] Running simulations...
[05-May-2020 13:24:10] Completed 1 of 5 simulation runs. Run 1 has errors.
[05-May-2020 13:24:12] Completed 2 of 5 simulation runs
[05-May-2020 13:24:12] Completed 3 of 5 simulation runs
[05-May-2020 13:24:12] Completed 4 of 5 simulation runs
[05-May-2020 13:24:12] Completed 5 of 5 simulation runs
Warning: Simulation(s) with indices listed below completed with errors. Please
inspect the corresponding SimulationOutput to get more details about the error:
[1] 
[05-May-2020 13:24:12] Cleaning up parallel workers...

Осмотр Simulink .SimulationOutput обнаруживает не конечную производную ошибку.

out(1).ErrorMessage
ans =

    'Derivative of state '1' in block 'sldemo_suspn_3dof/Body Dynamics/Vertical (Z) dynamics/Zdot' at time 0.0 is not finite. The simulation will be stopped. There may be a singularity in the solution.  If not, try reducing the step size (either by reducing the fixed step size or by tightening the error tolerances)'

The applyToModel метод сконфигурирует вашу модель с настройками на SimulationInput, чтобы можно было локально отлаживать задачу.

in(1).applyToModel;

Заметьте, что значение переменной Mb в базовом рабочем пространстве изменяется на 0, чтобы отразить значение, которое использовалось в симуляции, соответствующей первому объекту SimulationInput в in.

Закройте работников MATLAB

Наконец, закройте параллельный пул и модель, если они не были открыты ранее.

if(~isModelOpen)
    close_system(mdl, 0);
end
delete(gcp('nocreate'));