Activate で Modelica を使ってみる(その11) - シミュレーションの反復実行
Activate で Modelica を使ってみる(その11)
シミュレーションの反復実行
Modelica を含む 1D シミュレーションのためのモデルは、モデルの特性がパラメータ化されていることが多く、また、計算時間がそれほどかからないため、パラメータスタディを用いて特性値の変化がモデルの挙動に及ぼす影響を考察したり、最適化によって最適な特性値を自動的に求めたりする機会が多くあります。このパラメータスタディや最適化を実行するためにはシミュレーションを反復実行する必要があります。Activate でのシミュレーションの反復実行は OML スクリプトを用いて行うこともできますが、反復実行のためのブロックも用意されており、それを用いればスクリプトを組むことなく反復実行を実施できます。
今回は、最適化の前準備としてシミュレーションの反復実行用のブロックの使用方法とその適用例としてのパラメータスタディの事例を紹介します。
End ブロック
シミュレーションの反復はEnd ブロックを用いて行います。End ブロックはそれがアクティベートされると、指定されたオプションに従って実行中のシミュレーションを処理します。
例えば、以下は単に入力である正弦波をプロットしているだけの非常に簡単なモデル(添付:EndBlock_Sample_Stop.scm)ですが、実行時間が 15 秒を超えた瞬間に End ブロックが起動し、End ブロックに指定されたオプションが実行されます(Time ブロックから出力される現在の計算時間に Bias ブロックで指定された “-15” (秒)が足された値がゼロを超えた瞬間に EdgeTrigger ブロックがアクティベート信号を出力し、End ブロックを起動します)。
もし、そのオプションが上のように “Stop” ならシミュレーションは(つまり、プロットは)15 秒で終了し、以下のようなプロットが出力されます。
オプションが “Pause” の場合は、同じくシミュレーションは 15 秒で静止しますが、リボンの “シミュレーションの実行” ボタン をクリックすればシミュレーションが再開されます。
このオプションを “Restart” にすると、15秒後にもう一度最初からシミュレーションを実行します。つまり、単にこの 15 秒間のシミュレーションを果てしなく繰り返し実行することになります。当然ながらモデルは変更されていないので、描画されるプロットは毎回同じ結果になります。
この ”Restart” オプションの効果を見るために Bias ブロックのパラメータ値を “-15-__counter__” に変更してみます(添付:EndBlock_Sample_Restart.scm)。__counter__ という変数は内部的に定義されている整数変数で、繰り返しの回数を値として持っています。つまり、このモデルでは Bias の値が繰り返し毎に 1 秒ずつ減っていくことになり、繰り返し毎に実行時間が 1 秒ずつ増えていくことになります。このモデルで Scope を表示したままにすると 15 秒以降は徐々にプロットが進んでいくのを見ることができます。
ちなみに、シミュレーション時間が ”シミュレーションパラメータの定義” で指定された “最終時間” (このモデルでは30 秒)になれば、こちらの指定が有効になってシミュレーションが終了するため End ブロックは起動されず、繰り返しは終了します。
アクティベーション機能
上のモデルで End ブロックを起動しているアクティベーションというのは、要はイベントを発生させることです。アクティベーション信号を発生するブロックはブロックの下面にアクティベーション信号出力のためのポートを持っており、設定された条件に従ってアクティベーション信号を出力します。例えば、このモデル内の Sample Clock ブロックでは、指定された時間間隔(ここでは、0.1 秒毎)で定期的にアクティベーション信号を出力します。同じく EdgeTrigger ブロックでは入力が指定されたオプションに合致した時に(ここでは、入力の符号が負から正に変わった時に)アクティベーション信号を出力します。
このモデルでの End ブロックや Time ブロックのように、アクティベーション信号によって起動されるブロックは、ブロックの上面にアクティベーション信号入力のためのポートを持っています(ちなみに、アクティベーション信号関連のポートとそれを結ぶリンクは赤色で表示されます)。
Activate のシグナルベースモデルでは多くのブロックが “アクティベーション信号を受けた場合にのみ実行する” というオプション(ブロックによっては必須機能)を保持しています。これはたいていの場合 “外部アクティベーション” として表示されています。例えば、上記モデル中の Time ブロックのブロックダイアログは以下のようになっています。
なお、アクティベート機能についての詳細は Activate ヘルプに含まれている Extended Definitions の Chapter 1 を参照してください。アクティベーションを使った多彩な事例も紹介されています。
シミュレーションの反復実行によるパラメータスタディの例
いつものバネマスモデルを用いてシミュレーションの反復実行をパラメータスタディに適用した例を紹介します。以下のモデル(添付:SpringMass_Peak_Iter.scm)は、振動の教科書でよく見る、1自由度系のバネマスモデルの共振曲線(横軸が荷重の振動数で縦軸が応答値)をプロットすることを目的としています。
このモデルの VectorScope ブロックから出力される結果は以下のようなプロットになります。
このモデルでは、荷重である正弦波の振動数を徐々に変化させながらシミュレーションを繰り返しています(入力である荷重に関するパラメータを変化させているので、パラメータスタディと呼べるのかどうか微妙ですが)。モデルに含まれている減衰の影響により、各シミュレーションの結果は最終的には定常振動になるのですが、ここではその結果の振幅(=定常状態での応答の最大値)をシミュレーション毎に記録しそれをプロットしています。
まず、定常状態での応答の最大値を計算しているのは以下の ABS、MaxMin、DiscreteDelay、EventClock の各ブロックです。
PositionSensor から得られた変位の絶対値を計算し(Abs ブロック)、その前のステップの変位と比較して大きい方を出力します(MaxMin ブロックの Max オプション)。その結果は DiscreteDelay ブロックへフィードバックされ1ステップ分のデータが残されて MaxMin への入力となり次のステップの結果と比較されます。これを続けることにより最大値が残ることになります。
EventClock のダイアログは以下のように指定されており、MaxMin と DiscreteDelay を、シミュレーション開始 30 秒後に起動(アクティベート)し、その後は定期的(0.01 秒おき)に実行されるようにしています。この ”30 秒” にはあまり意味はなく、「30 秒ぐらいたてば定常状態になっているであろう」ぐらいの意味です。定常状態の判定を正しく行う方法もありますが、煩雑になるのでここではこのように簡単に処理しています。
次に、MaxMin で計算された最大値は Assignment に入力され、あらかじめ Y ポートから入力されているベクトル(もしくは、マトリクス)内のある要素をその値に置き換えます。置き換えられる要素のインデックスは I ポートから与えられます。このモデルでは __counter__ の値が I ポートから入力されているため、現在の繰り返し番号に対応する要素が MaxMin で計算された最大値に置き換えられることになります。
Assignment の Y ポートから入力されるベクトルの初期値は、ここでは以下のように FromBase ブロックで zeros(N,1) として定義されています。これは要素が全てゼロの N 行 1 列のベクトル(変数名:Peak)を作成することになります(N はコンテキストで N=100 と指定されています)。
ということで、__counter__ 行目の要素がそのシミュレーションの振幅に置き換えられたベクトル Peak は ToBase ブロックへ出力され、OML ワークスペースへ書き込まれます。この ToBase は上側にある EdgeTrigger ブロックによってアクティベーションがコントロールされています。これは前の事例と同じ仕組みであり、シミュレーション時間が 90 秒を超えると ToBase を起動するようになっています。
異なるシミュレーション間では直接データをやりとりすることはできないため、 このように、ToBase/FromBase を用いて OML ワークスペースを通してデータを伝達する必要があります(注:ToBase/FromBase 以外にも SignalOut/SignalIn 等の方法もあります)。
ただ、以下に示す仕組みによって、90 秒を超えると同時に IfThenElse ブロックが起動され、繰り返し回数が 99 回以下なら End ブロックの Restart オプションが実行され、ただちにシミュレーションがリスタートするため、90 秒以降のシミュレーションが行われることはありません。ちなみに、繰り返し回数が 100 回になると End ブロックの Stop オプションが実行されシミュレーションが終了します。
ToBase ブロックによって OML ワークスペースに書き込まれた変数値を Activate 内に読み込む方法はいくつかありますが、ToBase とのペアでよく用いられるのは FromBase ブロックです。既に紹介したように変数名を指定するだけで読み込んでくれます。もし指定された変数が OML ワークスペースに存在しない場合は、”変数のディフォルト値” フィールドで指定された値を使うことになります。
最後に、入力として使用されている SineWaveGenerator ブロックのブロックダイアグラムは以下のように指定されています。
このモデルではパラメータスタディのためにこの周波数 wf を徐々に変化させるのですが、それは “ダイアグラム” の “コンテキスト” で以下のように指定しています。
ここで、各定数は以下の通りです。
h:減衰定数(ここでは 20% として与えています)
wn:固有角振動数
wd:減衰時の固有角振動数
N:繰り返し回数の上限
ws:計算する角振動数の値の列(=ベクトル)(wd が中心になるようにしています。また、この ws は VectorScope の横軸としても使われます)
__counter__:そのシミュレーションの繰り返し回数(この行は OML コマンドウィンドウに繰り返し回数が表示されるように含めています)
wf:このシミュレーションで計算する角振動数(=入力正弦波の角振動数)
今回は、最適化の基礎となるシミュレーションを反復実行させるための方法を紹介しました。次回は、今回紹介した知識を用いて、最適化用ブロックである BobyqaOpt を用いた最適化の方法を紹介します。