はじめに
近年、軌道角運動量(Orbital Angular Momentum, OAM)を持つ光を用いた
空間光通信(Free-Space Optical Communication)における多重化技術が盛んに研究されています。
OAM光は、位相がらせん状にねじれたビームであり、
異なるOAM次数(ℓ)同士が直交する
同一波長・同一偏光でも多重化が可能
といった特徴を持ち、周波数・偏光とは独立な自由度として注目されています。
https://ieeexplore.ieee.org/document/10986389
https://www.mdpi.com/2076-3417/8/11/2179
一方で、Ansys Lumerical FDTD には
ラゲール=ガウス(Laguerre–Gaussian, LG)ビームを
そのまま指定できる標準光源は用意されていません。
そこで本記事では、
Python + LightPipes で LG ビームの複素電場を生成し
lumapi を用いて
Lumerical FDTD の Import source に入射光源として設定する
という、研究・設計でそのまま使える実践的な方法を紹介します。
LGビームと軌道角運動量(OAM)
LGモードの電場は、円筒座標で次の位相因子を含みます。
$$ E(r,\phi) = \exp(i\ell\phi) $$
ここで、
- ℓ:方位角モード指数(azimuthal mode index)
量子論的には、光子1個あたりの軌道角運動量(OAM)は
$$ \text{OAM per photon} = \ell \hbar $$
で与えられます。
ℓ ≠ 0 のとき、ビーム中心を一周すると位相が
$$ 2\pi\ell $$
だけ変化します。
このらせん状の位相構造を持つことが、ラゲール=ガウス(LG)ビームが 軌道角運動量(OAM)を持つ光である理由です。
LightPipesとは
LightPipes(https://opticspy.github.io/lightpipes/install.html) は、パラキシアル近似に基づく
光ビーム伝搬シミュレーション用の Python ライブラリです。
特徴:
ガウシアン、LG、HG、Bessel などの解析的ビーム生成
複素電場(振幅+位相)を直接扱える
NumPy配列として電場を取得可能
全体の流れ
こちらが今回のワークフローになります
①LightPipesをインストールしておく(インストール方法はサイトをご参照)
②Lumericalのプロジェクトファイルを立ち上げ、ImportSourceを設定しプロジェクトファイル名を付けて保存しておく。
*今回のsource名はSource,プロジェクトファイル名はtest_LG1.fsp
③今回作成したpythonスクリプト(LG_source.py)を実行
実装例
こちらが事前に用意したプロジェクトファイルの画面です。

この状態でプロジェクトファイルを名前を付けて保存しておきます(今回はtest_LG1.fspとして保存)。
Pythonスクリプト(LG_source.py)
import numpy as np
import lumapi
from LightPipes import Begin, GaussBeam, nm, mm, um
wavelength = 1550 * nm
size = 10 * um
N = 512
w0 = 2 * um
n = 1
m = 3
LG = True
F = Begin(size, wavelength, N)
F = GaussBeam(F, w0, LG=LG, n=n, m=m)
E2 = F.field # complex (N,N)
# --- yz plane coordinates (meters) ---
y = np.linspace(-size/2, size/2, N, dtype=float)
z = np.linspace(-size/2, size/2, N, dtype=float)
# x location of the injection plane (set to your desired position)
x0 = 0.0
x = np.array([x0], dtype=float) # NOTE: length 1
c0 = 299792458.0
f = np.array([c0 / float(wavelength)], dtype=float)
# Build vector E: (Nx=1, Ny, Nz, 3)
E = np.zeros((1, N, N, 3), dtype=np.complex128)
# LightPipes grid is typically (y, x) order; here we map it onto (y, z).
# Depending on your orientation, you may need .T; start with transpose.
E_yz = E2.T.astype(np.complex128)
# Put the field into Ey (transverse to +x propagation)
E[0, :, :, 1] = E_yz # Ey component
with lumapi.FDTD("test_LG1.fsp") as fdtd:
fdtd.putv("x", x)
fdtd.putv("y", y)
fdtd.putv("z", z)
fdtd.putv("f", f)
fdtd.putv("E", E)
fdtd.eval(r'''
src = "source";
# Force source to propagate along +x
select(src);
set("injection axis","x");
set("direction","Forward");
# Build dataset on yz plane (x is length-1)
ds = rectilineardataset("LG_source", x, y, z);
ds.addparameter("f", f);
ds.addattribute("E", E);
importdataset(ds);
''')
fdtd.save()
こちらがスクリプトになります。
ラゲールガウスビームの幅、ビームウエストや、次数、光源の向きなどの設定を行いスクリプトの実行を行います。
実行結果
Sourceの所を選択してResultsの電場分布を可視化するとラゲールガウスモードの電場分布が設定されていることが確認できます。
あとはFDTDシミュレーションのシミュレーション領域や、モニターなどの追加設定を行えばFDTDシミュレーションできるでしょう。
※本記事は筆者個人の見解であり、所属組織の公式見解を示すものではありません。
問い合わせ
光学シミュレーションソフトの導入や技術相談、
設計解析委託をお考えの方はサイバネットシステムにお問合せください。
光学ソリューションサイトについては以下の公式サイトを参照:
👉 光学ソリューションサイト(サイバネット)
光学分野のエンジニアリングサービスについては以下の公式サイトを参照:
👉 光学エンジニアリングサービス(サイバネット)
