自由帳

人に見られる自由帳

Matlab から FDTDsolver をぶん殴る

この記事は eeic Advent Calendar 2018 の8日目の記事として書かれたものです。

概要

この記事は具体的には以下の要素から成り立っている。

  • MATLABで、商用 FDTD solver である "Lumerical" を叩く(シミュレーションを実行させる)方法の紹介
  • Lumericalが提供しているサンプルコードの雑さの紹介
  • その雑さで苦しんだことによる僕のキレ

はじめに

まず最初に言っておくとこの記事を読んでうれしい人はこの世界にほとんどいないと思う。

まず "Lumerical" というのはFDTD法によって電磁界解析を行うことができるシミュレーションソフトなのだけれどかなり良いお値段がする。
このソフトを使っている人は「恵まれているんだなあ」と、予算を取ってくれる指導教員の先生に感謝しよう。
そしてこのソフトはGUIがかなり充実しており、スクリプトを使わずとも様々なシミュレーションを簡単に*1行うことができる。
パラメータを変化させて最適化するといったこともデフォルトの機能として備わっている。
また細かい条件を変化させて何度もシミュレーションを行いたいという場合にはスクリプトからの実行が便利である。
Lumericalも専用のスクリプトエディターで編集したスクリプトを実行することでシミュレーションを行うことができる。

しかしながら、人によっては異なった条件で何度もシミュレーションを実行したかったり、より複雑な最適化を実行したかったりするかもしれない。
そんな人のためにLumericalには、MATLABPythonからLumericalを実行するためのAPIや .mat file を扱うためのコマンドなどが用意されている。

この記事はMATLABからLumericalを動かしたいという人に向けた記事である(日本語を読めるそんな人がどれだけいるんだろうか)。
ただ、Lumericalを知らない人にも読んでもらえるように、必要な情報は逐一補足する。

How to do?

サンプルファイルをダウンロード

なにはともあれまずはサンプルコードをダウンロードしよう。
Lumericalのオンラインマニュアル、Lumerical Knowledge BaseMATLAB API のページからダウンロードできる。
今回はとりあえず、.m file からLumericalのスクリプトファイルである .lsf file をLumericalに実行させることを目標とするので、 "Coupler_Optimization_Main_Script.m" だけでよい。
また、変数を送りあったりするのも今回は無しで。
必要最低限の箇所をサンプルから抽出すると以下のようになる。

clear;
%Add Lumerical Matlab API path
path(path,'C:\Program Files\Lumerical\FDTD\api\matlab');
sim_file_path=('Change\This\To\Your\Folder\Structure'); % update this path to user's folder
sim_file_name=('grating_coupler_2D_Matlab_Optimization.fsp');

%Open FDTD session
h=appopen('fdtd');

%Load the FDTD simulation file and get simulation parameters
code=strcat('cd(sim_file_path);',...
  'load(sim_file_name);');

%send the script in 'code' to Lumerical FDTD Solutions
appevalscript(h,code);

%Close session
appclose(h);

ここで

sim_file_name=('grating_coupler_2D_Matlab_Optimization.fsp');

となっている。
.fsp file はLumericalで実際にシミュレーションを行うために必要な情報が詰まったファイルで、これを run させればシミュレーションが実行される。
ただ、今回は .lsf file を用いてスクリプトから run するという状況を想定しているので、

sim_file_name=('hemi');

としておく( ".lsf" は不要である)(元のファイル名が長過ぎるので変更した)。
またLumericalはスクリプトファイル名を打ち込むとそのスクリプトを実行するようになっているので、"load" も不要である。
ディレクトリ名も一応それらしく変更しておこう。

sim_file_path=('C:\Users\Desktop\Mitchy-W\Lumerical');

整理すると、

clear;
%Add Lumerical Matlab API path
path(path,'C:\Program Files\Lumerical\FDTD\api\matlab');
sim_file_path=('C:\Users\Desktop\Mitchy-W\Lumerical');
sim_file_name=('hemi');

%Open FDTD session
h=appopen('fdtd');

%Load the FDTD simulation file and get simulation parameters
code=strcat('cd(sim_file_path);',...
  'sim_file_name;');

%send the script in 'code' to Lumerical FDTD Solutions
appevalscript(h,code);

%Close session
appclose(h);

となる。
まず、MATLABの検索パスにLumericalの持っているMATLAB向けのAPIがある場所を追加している。
次に "sim_file_path" に .lsf file のあるディレクトリを、 "sim_file_name" に実行する .lsf file の名前を、それぞれ文字列で定義している。
その後、 "appopen" でLumericalを立ち上げる。
"code" にはLumericalに読み込ませる命令文の全てを文字列として、繋げて代入する。
最後にその "code" をLumericalに送って実行させる。
という流れだろう。
というわけでMATLABからこのサンプルコードを実行すれば、Lumericalが立ち上がり自動的にシミュレーションが開始されるはず。

……はい。
開始されません(キレ)。

サンプルコードの修正作業

配布されてるサンプルコードをそのままコピーしても正しく実行されないことは稀によくあると一般に知られている。
いやキレるが。

おそらくここではLumericalは立ち上がるものの、そのLumericalがエラーを吐いて止まっていると思う。
Lumericalが出しているエラーメッセージは

Error: prompt line 1: sim_file_path is not a valid function or variable name
Error: prompt line 1: cd takes at most one string argument

となっている。
ここで分かるのは

  • MATLABの "appopen" は成功している
  • "sim_file_path" がおかしい
  • Lumericalの "cd( )" 関数は文字列を引数とする

ということである。
"sim_file_path" にはパスをシングルクォーテーションでくくった文字列として代入しているので問題ないはずだが、ひとまずLumericalの "cd" について調べてみる。
すると、Syntaxの欄に

cd("directly");

とある。
そう、Lumericalでは文字列はシングルクォーテーションではなくダブルクォーテーションでくくる必要があるのだ。
またここで同時に注意したいのは、"code" の中身を読むのはあくまでLumericalであるということだ。
すなわち、"code" の中身はLumericalの文法で書かれる必要がある。
以上を踏まえた上で先のサンプルコードが何をしているかを見直してみる。

sim_file_path=('C:\Users\Desktop\Mitchy-W\Lumerical');
code=strcat('cd(sim_file_path);',...
  'sim_file_name;');

よってLumerical側で最初に実行されるのはおそらく次の命令文になるだろう。

cd(sim_file_path);
%つまり
cd(C:\Users\Desktop\Mitchy-W\Lumerical);

先ほど述べたように、Lumericalでは文字列はダブルクォーテーションでくくる必要があるので、

code=strcat('cd("sim_file_path");',...
  'sim_file_name;');

と修正すれば良さそうである。これで実行してみる。


が、世界はそう甘くはない。


おそらく先と同様にLumericalが立ち上がった後にエラーメッセージが出て止まっていると思う。
エラーは、

Error: prompt line 1: Invalid directory name passed to cd

となっていると思う。
つまり cd("ディレクトリ") というところまでは確認できたが肝心のディレクトリがおかしいということになる。
ここで試しにMATLABで次のようにしてみる。

word = 'hemi';
text = strcat(word, '_ha_kami')
text = 
    'hemi_ha_kami'
text2 = strcat('word', '_ha_kami')
text2 =
    'word_ha_kami'

当然といえば当然である。変数 "sim_file_path" が外側のシングルクォーテーションに囲われているので先ほどのコードでは

code = 'cd("sim_file_path");sim_file_name;'

という文字列がLumericalに送られてしまう。
変数 "sim_file_path" などを使わずに直接パスを入力することでこれは解決できるが、パスが変わるたびにいちいちこの部分を変更するのは無理なのでやはり変数を使いたい。
そのためには変数部分だけシングルクォーテーションから出してやればよいので、次のようにする必要がある。

code=strcat(...
    'cd("',sim_file_path,'");',...
    sim_file_name,';');

キモい。
"code" の中身は、

code = 
    'cd("C:\Users\Mitchy-w\Desktop\Mitchy-W\Lumerical");hemi;'

となる。まあ何はともあれこれで全て解決しただろうということで実行してみる。


動いた!!(動かなかったらごめん)


結局、全ての修正を終えたコードがこれ。

clear;
%Add Lumerical Matlab API path
path(path,'C:\Program Files\Lumerical\FDTD\api\matlab');
sim_file_path=('C:\Users\Desktop\Mitchy-W\Lumerical');
sim_file_name=('hemi.lsf');

%Open FDTD session
h=appopen('fdtd');

%Load the FDTD simulation file and get simulation parameters
code=strcat('cd("',sim_file_path,'");',...
    sim_file_name,';');

%send the script in 'code' to Lumerical FDTD Solutions
appevalscript(h,code);

%Close session
appclose(h);


ちなみにLumericalのコマンド:getpath(今のディレクトリのパスを表示してくれる)を入力してみると、

?getpath;
./
C:/Program Files/Lumerical/FDTD/scripts

と表示される。
そもそもこんなディレクトリが存在しないことはさておき、ここで表示されるパスはスラッシュで区切られている。
Lumericalはバックスラッシュで区切られていてもスラッシュで区切られていてもパスとして認識してくれるらしい。よくわからない気の使い方だ。

その他あれこれ

Lumerical と MATLAB とでデータをやり取り

ある一つのディレクトリ内に MATLAB から .mat ファイルを保存してそれを Lumerical で読み込んだり、逆に Lumerical が吐いた .mat ファイルを MATLAB で読み込んで処理するというのが基本。
頑張れば Lumerical だけでデータ処理もできるかもしれないが、如何せん Lumerical は行列演算が貧弱なので全くオススメしない。餅は餅屋。

matlabsave("file_name", data_name);
matlabload("file_name.mat");

基本的にこの二つのコマンドで完結する。
例えば Lumerical で波長ごとの電界分布をシミュレーション結果として得られたらそのまま丸ごと matlabsave するのが丸い。
4次元の行列データを Lumerical で処理しようとしても無理なのでデータの整理も MATLAB でやろう。

終わりに

テストとかしないんだろうか。
ソフトウェア開発をしているエンジニィィアの皆さんにはちゃんと動作するかどうかを確かめてからサンプルコードを公開して欲しいわね*2

*1:当社比

*2:サンプルを上げてくれるだけありがたいです