Main Content

複数のシミュレーション ワークフローのヒント

この例の目的は、並列シミュレーション ツールを使った複数のシミュレーションの実行について、役立つヒントを紹介することです。この例は 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

モデルとブロック パラメーターの設定

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 オブジェクトの配列を不適切な値で誤って設定したと仮定します。

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);
[09-Dec-2021 11:45:05] Running simulations...
[09-Dec-2021 11:45:26] Completed 1 of 5 simulation runs. Run 1 has errors.
[09-Dec-2021 11:45:36] Completed 2 of 5 simulation runs
[09-Dec-2021 11:45:36] Completed 3 of 5 simulation runs
[09-Dec-2021 11:45:37] Completed 4 of 5 simulation runs
[09-Dec-2021 11:45:46] 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);
[09-Dec-2021 11:45:47] Checking for availability of parallel pool...
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).
[09-Dec-2021 11:47:08] Starting Simulink on parallel workers...
[09-Dec-2021 11:47:45] Configuring simulation cache folder on parallel workers...
[09-Dec-2021 11:47:45] Loading model on parallel workers...
[09-Dec-2021 11:48:06] Running simulations...
[09-Dec-2021 11:48:18] Completed 1 of 5 simulation runs. Run 1 has errors.
[09-Dec-2021 11:48:18] Completed 2 of 5 simulation runs
[09-Dec-2021 11:48:18] Completed 3 of 5 simulation runs
[09-Dec-2021 11:48:18] Completed 4 of 5 simulation runs
[09-Dec-2021 11:48:18] 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] 
[09-Dec-2021 11:48:18] Cleaning up parallel workers...

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

applyToModel メソッドは、ローカルで問題をデバッグできるように、SimulationInput 上の設定でモデルを構成します。

in(1).applyToModel;

ベース ワークスペースで変数 Mb の値が 0 に変化し、in の最初の SimulationInput オブジェクトに対応するシミュレーションで使われた値が反映されていることがわかります。

MATLAB ワーカーを閉じる

最後に、並列プールとモデルを閉じます (まだ閉じられていない場合)。

if(~isModelOpen)
    close_system(mdl, 0);
end
delete(gcp('nocreate'));
Parallel pool using the 'local' profile is shutting down.

参考

|

関連するトピック