Meepを使って周期的な構造を作製しシミュレーションする方法を紹介します。この記事ではPythonのfor文を利用し、一次元的なフォトニック結晶あるいはブラッググレーティング(Bragg grating)と呼ばれる構造を作ります。
今回は以下の図に示すような構造をMeepで作っていきます。
空気中(屈折率n0)の中央部分にx軸方向に伸びる光導波路(屈折率n1)を置きます。そして、導波路中の屈折率を部分的にn2に変更することで、異なる屈折率もを持つ誘電体が交互に並んだ構造を作ります。
このような構造に光を入射させると、屈折率の異なる境界面で反射する光の成分と透過する光の成分が発生するため、それらの光が干渉しブラッグ反射という現象が起こります。
上記に構造に対応するMeepのPythonコードを以下に示します。jupyter notebook にコードをコピペして実行してみてください。
#meep, numpyライブラリのインポート
import meep as mp
import numpy as np
#計算領域のサイズを定義
cell = mp.Vector3(16,8,0)
#誘電体の構造の定義(導波路部分のみ)
geometry = [mp.Block(mp.Vector3(mp.inf,1,mp.inf),
center=mp.Vector3(),
material=mp.Medium(index=1.5))]
#周期的に設置する誘電体の座標リスト
positions = np.arange(-4, 5, 1)
#geometryリストにBlockを繰り返し追加する
for i in positions:
geometry.append(mp.Block(mp.Vector3(0.5,1,mp.inf),
center=mp.Vector3(i,0,0),
material=mp.Medium(index=2)))
#光源の定義
sources = [mp.Source(mp.ContinuousSource(wavelength=3),
component=mp.Ez,
center=mp.Vector3(-7,0))]
#吸収境界条件の定義
pml_layers = [mp.PML(1.0)]
#計算解像度の定義
resolution = 10
#シミュレーションオブジェクトの定義
sim = mp.Simulation(cell_size=cell,
boundary_layers=pml_layers,
geometry=geometry,
sources=sources,
resolution=resolution)
#シミュレーション条件の設定と実行
sim.run(mp.at_beginning(mp.output_epsilon),
mp.to_appended("ez", mp.at_every(0.6, mp.output_efield_z)),
until=200)
Meepの使い方(アニメーション出力編)で使用したコードがベースになっていますが、何ヶ所か加筆・修正した部分があるのでそれらを見ていきます。
まず、周期構造を作るために追加した部分である
#周期的に設置する構造の座標リスト
positions = np.arange(-4, 5, 1)
#geometryリストにBlockを繰り返し追加する
for i in positions:
geometry.append(mp.Block(mp.Vector3(0.5,1,mp.inf),
center=mp.Vector3(i,0,0),
material=mp.Medium(index=2)))
にというコードを説明します。2行目で positions という変数を作り、周期構造を設置したい x座標の配列を代入しています。np.arange(start, end, spacing) は配列(ここでは数列)を生成するnumpyのメソッドです。start から end まで、spacing の間隔で等間隔に数値を生成します。上記の場合 position = [-4, -3, -2, -1, 0, 1, 2, 3, 4] という配列になります。end に書いた数値は含まない点に注意してください。numpy のライブラリを利用しているため、コード全体の最初に import numpy as np によってライブラリをインポートしています。
続いて4行目はPythonにおける for 文になっています。これは「ある要素に対して以下の処理を繰り返しせよ」というコードです。ここでのある要素とは、「positions 内の各要素 i 」です。つまり、positions 配列の各要素 -4, -3, ... を順番に i に代入した上で、次の行の処理を繰り返し実行します。positions の配列要素数が 9個なので 9 回繰り返します。
繰り返し行う処理は 5~7行目に記載されたもので、geometry 変数にBlockを追加する処理です。リストに要素を追加するappendメソッドを使用しています。geometry を最初に定義した際、横長のBlockを一つ作っており、この繰り返し処理でBlock の上に屈折率の異なる小さなBlockを並べていきます。サイズは (x, y, z) = (0.5, 1, infinity) なので最初の図に示した通り縦長の小さなブロックで、中心座標を (x, y, z) = (i, 0, 0) とすることで positions 配列で設定した通りの位置に置かれます。Meep では既に置いてある構造の上に別の構造を重ねた場合、重ねたものに上書きされる性質があります。
繰り返される処理はインデントされた範囲のみに及ぶため5~7行目だけです。
以上が今回のコードで最も重要な部分です。コード全体に注目すると、Meepの使い方(アニメーション出力編)で使用したコードと異なる点としては、material を定義するときに 誘電率 epsilon の代わりに屈折率 index を使用していたり、光源を定義するときに周波数 frequency の代わりに波長 wavelength を使用しています。そのような書き方もある、という程度に覚えておきましょう。
notebook でシミュレーションを実行したら、次は以下のコードを使って構造をプロットして確認してみましょう。
#numpy, pyplotライブラリのインポート
import numpy as np
import matplotlib.pyplot as plt
#誘電率分布を取得することで誘電体構造をプロットする
eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric)
plt.figure()
plt.imshow(eps_data.transpose(), interpolation='spline36', cmap='binary')
plt.axis('off')
plt.show()
これをnotebookの次のセルに貼り付けて実行すると以下ようなの画像が得られます。
ちゃんと導波路内に屈折率の周期的な変調ができていることが確認できます。灰色の部分が屈折率1.5, 黒い部分が 2, 周囲の白い部分が 1 です。何か現実にある物質を考慮した屈折率比率ではないので注意してください。
最後にシミュレーション結果をアニメーションとして表示してみます。今回は比較のために「周期構造がある場合」と「周期構造がない場合」で2回シミュレーションを行って、2つを並べてみました。
左(スマホの場合は上):周期構造あり 右(スマホの場合は下):周期構造なし
明らかな違いが見られます。周期構造のない右図の場合は光がそのまま導波路内を伝搬していきますが、周期構造のある左図の場合は導波路の先まで到達する光の量が減っています。また、左半分の範囲で定在波のような電場の振動が見られます(同じ地点で赤・青と色が切りかわっています)。これらは周期構造の部分で光が反射されているため起こる現象です。
ここから発展させて、光の波長を変えてみたり、ブロックの間隔やサイズを変えてみたり、屈折率の比率を変えてみた場合、同様の現象は見られるでしょうか。各自でコード内の数値を変えて試してみてください。
for文で周期構造を作製する内容の説明は以上になります。今回はx軸方向のみの座標を変数 i に割り当てましたが、y軸方向についても座標のリストを作れば、2次元平面上で好きなように構造を並べることができます。また、for文による繰り返し処理は光源の設置にも使うことができます。