Цель этой демонстрации состоит в том, чтобы предоставить полезные советы для выполнения нескольких симуляций с помощью инструментов параллельной симуляции. Этот пример будет работать, даже если Parallel Computing Toolbox™ недоступен, но симуляции будут выполняться последовательно. Мы будем использовать sldemo_suspn_3dof модели для этого примера.
mdl = 'sldemo_suspn_3dof';
isModelOpen = bdIsLoaded(mdl);
open_system(mdl);
Обычно вы создадите массив из 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
.
Наконец, закройте параллельный пул и модель, если они не были открыты ранее.
if(~isModelOpen) close_system(mdl, 0); end delete(gcp('nocreate'));