Несколько советов рабочего процесса симуляций

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

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

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

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

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.SimulationInput object s с неправильным значением.

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 object, чтобы видеть любые сообщения об ошибке, которые прибывают из симуляции.

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)'

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

in(1).applyToModel;

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

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

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

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