64

MATLAB + Simulink で複数のシミュレーションを一気に実行!

 2 years ago
source link: https://blogs.mathworks.com/japan-community/2022/03/23/matlab-simulink-parsim/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

MATLAB + Simulink で複数のシミュレーションを一気に実行!

皆さんこんにちは。トレーニングエンジニアの遠藤です。
このブログでは、「Simulink と MATLAB をつなぐ」をコンセプトとして、主に技術的な内容について書いております。

さて、先日ついに R2022a がリリースされましたね!注目の新機能が盛り沢山で私も楽しくリリースノートを読んでいます。今回の記事で早速それらの機能の紹介!……と行きたいところなのですが、例のごとくリリース直後ということもあって自分でも色々と機能を調査中のため、新機能の紹介はまた別の機会にできればと思います。

ということで、今回は Simulink と MATLAB を繋ぐ大きな理由の一つである「複数シミュレーションの実行」について解説記事を書いていこうかと思います。いろんなパラメータをスイープさせてシミュレーションを行い結果を比較したい、異なる入力データでシミュレーションを行いモデルの検証をしたいなどなど、複数のシミュレーションを一度に実行したい場面は少なくありません。もちろん手動でモデルを編集して逐次的に実行することもできますが、プログラムで自動化すると非常に効率的にシミュレーションを実行できます。

しかし、複数シミュレーション用の関数は少々使い方に癖があり、MATLAB に慣れていない人にとっては少し手を出しづらい部分もあります。そこで、この記事では「パラメータのスイープ」と「異なる入力データの使用」の2つに焦点を当て、複数シミュレーション実行の方法について解説していきたいと思います。

こんな方にオススメ!

  • 最適なパラメータの調査のために、パラメータをスイープしながらシミュレーションを実行したい
  • 色々な入力データを使ってシミュレーションを実行したい
  • 複数コアを用いてシミュレーションを並列実行したい

※複数コアを使ってシミュレーションを並列実行する場合は Parallel Computing Toolbox が必要です。この記事で紹介している機能は Parallel Computing Toolbox なしでも使用できますが、その場合シミュレーションは逐次実行となります。

1. parsim 関数を用いた複数シミュレーション

プログラムで複数シミュレーションというと for ループ+ sim 関数を思い浮かべる方もいらっしゃるかもしれませんが、実は MATLAB R2017a から複数シミュレーション実行用の関数である parsim が導入されています。この関数を使用すると、より効率的に複数シミュレーションを実行できます。

まずは parsim 関数の使い方を確認するために、1回のシミュレーションを行ってみましょう。parsim 関数は sim 関数とは違い、単純にモデル名を指定してシミュレーションを行うということはできず、SimulationInput というオブジェクトを渡してあげる必要があります。SimulationInput オブジェクトは、Simulink.SimulationInput 関数にモデル名を指定することで作ることができます。

>> in = Simulink.SimulationInput("vdp");

作った SimulationInput オブジェクトを parsim 関数に渡せばシミュレーションを実行することができます。

>> out = parsim(in)
out =
Simulink.SimulationOutput:
SimulationMetadata: [1×1 Simulink.SimulationMetadata]
ErrorMessage: [0x0 char]

これだけだと面倒くさいだけの sim 関数に見えるかもしれませんが、parsim 関数の最大の特徴は、SimulinkInput オブジェクトの配列を渡してあげることで、その配列分のシミュレーションを行ってくれる点です。

for i = 10:-1:1
  in(i) = Simulink.SimulationInput("vdp");
end

for ループで SimulationInput 配列を作成しました(10 から 1 に減らす方向に for ループしているのは、最初に 10 個分のメモリを確保するためです。特にメモリを気にしない方は 1 から 10 のループでも問題なく動作します)このようにして作った配列を parsim に渡せば、

>> out = parsim(in)
out =
1×10 Simulink.SimulationOutput 配列

10 回シミュレーションが行われました。ただ、もちろん何も設定していないので 10 回とも同じシミュレーションが行われています。この配列の各要素の設定を変更することで、異なるパラメータや入力データを使ったシミュレーションを一気に行うことができますので、早速やり方を確認していきましょう。

2. パラメータのスイープ

SimulationInput オブジェクトの setVariable 関数を使用することで、シミュレーションに使用されるパラメータを変更することができます。

>> in = in.setVariable("K",10);

モデル内で使用されているパラメータ名と値をセットで指定します。注意点として、setVariable 関数はパラメータの値を変更した SimulationInput オブジェクトを出力引数として返すので、同じ名前の変数(今回は in)に入れ直す必要があります。

これを利用して、SimulationInput オブジェクトの配列を作成し、各オブジェクトにそれぞれ異なるパラメータを指定してあげることで、様々なパラメータを用いた並列シミュレーションを行うことができます。

例として、以下のような超簡単なモデルで挙動を確認してみます。

シミュレーション結果を確認しやすいように、データのエクスポート設定も変更しておきます。

このモデルの K を 1 から 10 までスイープさせて parsim 関数で実行してみましょう。まずはスイープさせる値を配列で作成します。
Ksweep = 1:10;
次に SimulationInput オブジェクトの配列を作成しながら、各要素に Ksweep の対応する値を setVariable で パラメータ K に設定します。

for i = 10:-1:1
  in(i) = Simulink.SimulationInput("myModel");
  in(i) = in(i).setVariable("K",Ksweep(i));
end
out = parsim(in)

for ループを 10 から 1 に減らす方向にしているのは、先に 10 個分のメモリーを確保するためです。シミュレーション結果を確認してみると……

>> out(1).yout(1)
ans =
1
>> out(2).yout(2)
ans =
2

ちゃんと各シミュレーションごとにゲインが変化していますね。注意点として、for ループ内に parsim 関数を入れてしまわないように気をつけましょう。勢いでやってしまいがちですが、それをしてしまうと10 x 10 = 100 回シミュレーションしてしまうことになります。

これでパラメータをスイープして複数シミュレーションを行うことができるようになりました。次は入力データを複数使用する方法を見ていきましょう。

3. 外部入力の変更

SimulationInput オブジェクトの setExternalInput 関数を使用することで、シミュレーションの外部入力を各シミュレーションごとに変更することもできます。また超簡単なモデルで試してみましょう。

まずは各シミュレーションの入力データを用意します。

t = (0:0.1:10)';
u1 = t;
u2 = sin(t);
u3 = -cos(t);
u = {u1,u2,u3};

入力データはベクトルになることが多いので、セル配列や行列でまとめておくとループで使いやすくなります。あとはパラメータスイープと同様に for ループで各要素に入力データを設定するだけです。

for i = 10:-1:1
  in(i) = Simulink.SimulationInput("myModel2");
  in(i) = in(i).setExternalInput([t,u{i}]);
end
out = parsim(in)

シミュレーション結果を確認してみると……

しっかり別々の入力データが使用されていますね!

4. 複数のシミュレーションの状況・結果を可視化する

複数の大規模シミュレーションを並列実行している場合、各シミュレーションの進捗状況をリアルタイムに確認できると便利ですよね。シミュレーションマネージャーを使うと、複数シミュレーションの状況を確認したり、シミュレーション結果を簡単に可視化することができます。

使い方は超簡単です。parsim 関数でシミュレーションを実行する際に ShowSimulationManager オプションを on にするだけです。

out = parsim(in, "ShowSimulationManager", "on")

これでシミュレーション実行時にシミュレーションマネージャーが起動し、各シミュレーションの状況を確認できます。

結果ペインの scatter や surf を使えば特定のパラメータとシミュレーション結果の関係を可視化することも可能です。他にも様々な機能が用意されていますので、詳しく知りたい方はシミュレーションマネージャーのドキュメントをご確認ください。

5. 終わりに

今回は parsim 関数を用いた複数シミュレーションについて解説しました。以前の Simulink API の記事 と同様、MATLAB 側で Simulink 用の関数を使うことで効率化できるタスクはたくさんあります。普段 Simulink だけを使って業務を行っている方は、MATLAB で楽できないか考えてみるのも意外と面白いですよ!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK