Цель этой демонстрации - предоставить полезные советы по выполнению нескольких симуляций с помощью инструментов параллельного моделирования. Этот пример будет работать, даже если Toolbox™ параллельных вычислений недоступен, но моделирование будет выполняться последовательно. Для этого примера мы будем использовать sldemo_suspn_3dof модели.
mdl = 'sldemo_suspn_3dof';
isModelOpen = bdIsLoaded(mdl);
open_system(mdl);

Как правило, для выполнения нескольких моделирований создается массив объектов Simulink.ImentionInput. Существует несколько способов инициализации массива перед его заполнением данными.
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
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
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.Input с неверным значением.
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.CompingOutput, чтобы увидеть все сообщения об ошибках, поступающие из моделирования.
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.ColeOutput обнаруживается ошибка неокончательной производной.
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)'
applyToModel будет выполнена настройка модели с настройками на панели ввода, чтобы можно было выполнить локальную отладку проблемы.
in(1).applyToModel;
Обратите внимание, что значение переменной Mb в базовой рабочей области изменяется на 0, чтобы отразить значение, которое было использовано в моделировании, соответствующем первому объекту Input в in.
Наконец, закройте параллельный пул и модель, если они не были открыты ранее.
if(~isModelOpen) close_system(mdl, 0); end delete(gcp('nocreate'));