参考以上lumerical python代码,我想让你帮我写一个代码,仿真一个薄膜铌酸锂波导的截面。...
생성일: 2026년 2월 10일
답변에 사용된 모델 GPT-5.2 Thinking by Chat01
생성일: 2026년 2월 10일
답변에 사용된 모델 GPT-5.2 Thinking by Chat01
下面这份脚本会用 MODE(FDE) 求解器搭一个 蓝宝石衬底上的 TFLN(600 nm 厚、刻蚀 300 nm 的 ridge) 截面,并在 λ=4 µm 下求解模式。脚本里沿用了你示例代码那种 sys.path.append(lumerical_path) 的 lumapi 导入方式 (光子晶体5.py)。
材料色散我用 Sellmeier 公式在 4 µm 计算:LiNbO3 的 o/e 折射率 (refractiveindex.info),蓝宝石(o 光)折射率 (refractiveindex.info)。
FDE 建模/求模用到了 addfde / findmodes / getdata 的官方脚本接口说明 (optics.ansys.com);材料用 setmaterial(...,"sampled data",...) 的 4 列(频率+εx,εy,εz)方式做对角各向异性 (optics.ansys.com)。
晶向映射(X切 Y传 Z调制)在这个 2D Z-normal FDE 里这样对应:
- 仿真 y(竖直/厚度方向)← 晶体 X(X-cut,法向)
- 仿真 z(传播方向)← 晶体 Y(Y-prop)
- 仿真 x(横向/波导宽度方向)← 晶体 Z(Z-mod 方向)
因此对 LiNbO3(光轴在晶体 Z)来说,在仿真坐标里相当于 光轴沿 x,即 εx=εe, εy=εo, εz=εo。
pythonimport sys import numpy as np # ============================================================ # 1) 配置 Lumerical Python API 路径(按你电脑实际安装路径改) # 这里写法参考你给的示例脚本风格 # ============================================================ lumerical_path = r"C:\Program Files\ANSYS Inc\v241\Lumerical\api\python" if lumerical_path not in sys.path: sys.path.append(lumerical_path) try: import lumapi except ImportError as e: raise ImportError(f"无法导入 lumapi,请检查路径: {lumerical_path}") from e # ============================================================ # 2) Sellmeier(来自 refractiveindex.info:Zelmon 1997 / Malitson&Dodge 等) # 返回折射率 n(λ),λ 单位:um # ============================================================ def n_LN_o_zelmon(lam_um: float) -> float: lam2 = lam_um**2 n2 = 1 + 2.6734*lam2/(lam2-0.01764) + 1.2290*lam2/(lam2-0.05914) + 12.614*lam2/(lam2-474.60) return float(np.sqrt(n2)) def n_LN_e_zelmon(lam_um: float) -> float: lam2 = lam_um**2 n2 = 1 + 2.9804*lam2/(lam2-0.02047) + 0.5981*lam2/(lam2-0.0666) + 8.9543*lam2/(lam2-416.08) return float(np.sqrt(n2)) def n_sapphire_o_malitson(lam_um: float) -> float: lam2 = lam_um**2 c1 = 0.0726631**2 c2 = 0.1193242**2 c3 = 18.028251**2 n2 = 1 + 1.4313493*lam2/(lam2-c1) + 0.65054713*lam2/(lam2-c2) + 5.3414021*lam2/(lam2-c3) return float(np.sqrt(n2)) # ============================================================ # 3) 建立材料(各向异性 LN 用 sampled data: [f, epsx, epsy, epsz]) # ============================================================ def safe_deletematerial(mode, name: str): try: mode.deletematerial(name) except Exception: pass def build_materials(mode, lambda0_m: float): c0 = 299792458.0 lam_um = lambda0_m * 1e6 n_o = n_LN_o_zelmon(lam_um) n_e = n_LN_e_zelmon(lam_um) n_sap = n_sapphire_o_malitson(lam_um) # 频率点(给两三个点,避免只给 1 行数据导致拟合/插值异常) f0 = c0 / lambda0_m freqs = np.array([0.95*f0, f0, 1.05*f0]) # X切Y传Z调制:仿真坐标里 optic axis 沿 x # => epsx = n_e^2, epsy = n_o^2, epsz = n_o^2 epsx = n_e**2 epsy = n_o**2 epsz = n_o**2 ln_sampled = np.column_stack([freqs, epsx*np.ones_like(freqs), epsy*np.ones_like(freqs), epsz*np.ones_like(freqs)]) # 清理旧材料(如果存在) safe_deletematerial(mode, "TFLN_LN_Xcut_Yprop") safe_deletematerial(mode, "SAPPHIRE_iso") # --- 各向异性 LN:Sampled data(4 列:f, epsx, epsy, epsz)--- mode.addmaterial("Sampled data") mode.setmaterial("Sampled data", "name", "TFLN_LN_Xcut_Yprop") # 有些版本不需要/不支持显式设置 Anisotropy,失败就跳过 try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "Anisotropy", 1) # 1=Diagonal(若该属性存在) except Exception: pass mode.setmaterial("TFLN_LN_Xcut_Yprop", "sampled data", ln_sampled) try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "max coefficients", 2) except Exception: pass # --- 蓝宝石:简单当作各向同性 (n,k) 材料(k=0)--- mode.addmaterial("(n,k) Material") mode.setmaterial("(n,k) Material", "name", "SAPPHIRE_iso") mode.setmaterial("SAPPHIRE_iso", "Refractive Index", float(n_sap)) mode.setmaterial("SAPPHIRE_iso", "Imaginary Refractive Index", 0.0) return {"n_o": n_o, "n_e": n_e, "n_sap": n_sap} # ============================================================ # 4) 几何 & FDE 求模 # ============================================================ def simulate_tfln_ridge_fde( wg_width_um: float = 3.0, lambda_um: float = 4.0, tfln_thickness_nm: float = 600.0, etch_depth_nm: float = 300.0, ): # ---- 参数换算到 SI ---- lambda0 = lambda_um * 1e-6 w_wg = wg_width_um * 1e-6 t_ln = tfln_thickness_nm * 1e-9 etch = etch_depth_nm * 1e-9 slab_t = t_ln - etch # 刻蚀后剩余 slab 厚度 # 仿真窗口(可按需要调大/调小) x_span = max(12e-6, 4*w_wg) sub_thick = 4e-6 clad_thick = 4e-6 y_min = -sub_thick y_max = t_ln + clad_thick y_span = y_max - y_min y_center = 0.5*(y_min + y_max) # ---- 启动 MODE ---- mode = lumapi.MODE(hide=False) mode.deleteall() mats = build_materials(mode, lambda0) print(f"[Info] λ={lambda_um:.3f} um: LN no={mats['n_o']:.4f}, ne={mats['n_e']:.4f}; sapphire n={mats['n_sap']:.4f}") # ---- 基底:蓝宝石(y in [-sub_thick, 0])---- mode.addrect() mode.set("name", "substrate_sapphire") mode.set("material", "SAPPHIRE_iso") mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", -0.5*sub_thick) mode.set("y span", sub_thick) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN slab:厚 slab_t,铺满横向 ---- mode.addrect() mode.set("name", "ln_slab") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", 0.5*slab_t) mode.set("y span", slab_t) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN ridge:在 slab 上再加 etch 高度,宽度 w_wg ---- mode.addrect() mode.set("name", "ln_ridge") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", w_wg) mode.set("y", slab_t + 0.5*etch) mode.set("y span", etch) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- FDE region(XY 截面,传播沿 z)---- mode.addfde() mode.set("name", "FDE") mode.set("solver type", 3) # 2D Z normal(XY 平面) 见 addfde 示例 mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) # 开边界 mode.set("x min bc", "PML") mode.set("x max bc", "PML") mode.set("y min bc", "PML") mode.set("y max bc", "PML") # 网格(全局较粗 + LN 附近加密) mode.set("define x mesh by", "maximum mesh step") mode.set("dx", 120e-9) mode.set("define y mesh by", "maximum mesh step") mode.set("dy", 60e-9) mode.addmesh() mode.set("name", "mesh_ln") mode.set("x", 0.0) mode.set("x span", max(6e-6, 2*w_wg)) mode.set("y", 0.5*t_ln) mode.set("y span", t_ln + 0.8e-6) mode.set("dx", 30e-9) mode.set("dy", 20e-9) # ---- 求模设置 ---- mode.select("FDE") mode.setanalysis("wavelength", lambda0) mode.setanalysis("number of trial modes", 8) # 如果你更关心 TE-like/TM-like,可加: # mode.setanalysis("use max index", 1) # mode.setanalysis("n", mats["n_o"]) # 搜索初值(可选) # ---- 求解 ---- n_found = mode.findmodes() print(f"[Result] 找到模式数: {int(n_found)}") # 打印前几个模式的 neff / TE fraction n_report = min(int(n_found), 6) for i in range(1, n_report + 1): obj = f"FDE::data::mode{i}" neff = mode.getdata(obj, "neff") try: tefrac = mode.getdata(obj, "TE polarization fraction") tefrac_val = float(np.array(tefrac).squeeze()) except Exception: tefrac_val = float("nan") neff_val = float(np.array(neff).squeeze()) print(f" mode{i}: neff = {neff_val:.6f}, TE_frac = {tefrac_val:.4f}") # 可选:保存工程 # mode.save("tfln_ridge_on_sapphire_4um.lms") return mode if __name__ == "__main__": simulate_tfln_ridge_fde(wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0)
如果你希望我把 上包层改成 SiO2/空气封装、或者要按 “X切但传播方向换成 Z / Y切”等自动旋转晶轴(而不是我这里用“光轴沿 x”的等效映射),我也可以把脚本扩展成“晶向参数化 + 自动生成 ε 张量”。
(base) PS C:\Users\47004\Desktop\TFLN_Sim> & "C:/Program Files/ANSYS Inc/v251/Lumerical/python-3.9.9-embed-amd64/python.exe" c:/Users/47004/Desktop/TFLN_Sim/TFLN_Sapphire_600thi.py
Traceback (most recent call last):
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 225, in <module>
simulate_tfln_ridge_fde(wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0)
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 125, in simulate_tfln_ridge_fde
mats = build_materials(mode, lambda0)
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 75, in build_materials
mode.setmaterial("Sampled data", "name", "TFLN_LN_Xcut_Yprop")
File "C:\Program Files\ANSYS Inc\v251\Lumerical\api\python\lumapi.py", line 1257, in <lambda>
method = (lambda x: lambda self, *args: appCall(self, x, args))(name)
File "C:\Program Files\ANSYS Inc\v251\Lumerical\api\python\lumapi.py", line 899, in appCall
raise LumApiError(message)
lumapi.LumApiError: "The material 'Sampled data' cannot be found."
这个报错的原因很简单:addmaterial() 并不会创建一个名字叫 "Sampled data" 的材料;它会返回新建材料的实际名字(通常是 material1 之类)。你现在是:
pythonmode.addmaterial("Sampled data") mode.setmaterial("Sampled data","name","TFLN_LN_Xcut_Yprop") # ❌ 这里找不到 "Sampled data"
所以会报 cannot be found。官方脚本用法也是:temp = addmaterial("Sampled data"); setmaterial(temp,"name",...) (optics.ansys.com)
你参考的示例代码里也是先把 lumapi 路径加到 sys.path 再 import(你跑得通说明这部分没问题)(光子晶体5.py)
把你脚本里 build_materials() 里创建材料那段替换成下面这样(关键是 接住 addmaterial 的返回值):
pythondef build_materials(mode, lambda0_m: float): c0 = 299792458.0 lam_um = lambda0_m * 1e6 n_o = n_LN_o_zelmon(lam_um) n_e = n_LN_e_zelmon(lam_um) n_sap = n_sapphire_o_malitson(lam_um) f0 = c0 / lambda0_m freqs = np.array([0.95*f0, f0, 1.05*f0]) # X切Y传Z调制 => optic axis 沿仿真 x epsx = (n_e**2) + 0j epsy = (n_o**2) + 0j epsz = (n_o**2) + 0j ln_sampled = np.column_stack([ freqs, epsx*np.ones_like(freqs), epsy*np.ones_like(freqs), epsz*np.ones_like(freqs), ]) # 删除旧材料(如果存在) for name in ["TFLN_LN_Xcut_Yprop"]: try: mode.deletematerial(name) except Exception: pass # ✅ 正确:接住 addmaterial 的返回名 temp = mode.addmaterial("Sampled data") mode.setmaterial(temp, "name", "TFLN_LN_Xcut_Yprop") try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "Anisotropy", 1) # diagonal except Exception: pass mode.setmaterial("TFLN_LN_Xcut_Yprop", "sampled data", ln_sampled) try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "max coefficients", 2) except Exception: pass # —— 蓝宝石建议别折腾建材,直接用 object defined dielectric(更稳)—— # 你后面建 substrate 的地方,把 material 设成 "<Object defined dielectric>", # 再 set("index", n_sap) 即可,不需要 addmaterial return {"n_o": n_o, "n_e": n_e, "n_sap": n_sap}
然后把你建蓝宝石衬底那块改成下面这种(避免不同版本里 "(n,k) Material" 名字不一致导致新坑):
pythonmode.addrect() mode.set("name", "substrate_sapphire") mode.set("material", "<Object defined dielectric>") mode.set("index", mats["n_sap"]) # 其余 x/y 尺寸照旧
如果你还想确认 "Sampled data" 这个字符串在你 v251 里是否存在,可以临时加一句:
pythonprint(mode.eval("?addmaterial;"))
它会列出当前版本支持的 material model 名称(官方也这么建议查)(optics.ansys.com)
如果你把这两处改完后还有报错(比如 setanalysis("wavelength", ...) 或 findmodes() 的对象路径在你版本里不同),把新的报错贴出来,我再按 v251 的接口把**求模结果提取(neff / TE fraction / 模场图导出)**那部分也给你做成完全兼容版本。
请给我完整的可以直接运行的代码
import sys
import numpy as np
lumerical_path = r"C:\Program Files\ANSYS Inc\v241\Lumerical\api\python"
if lumerical_path not in sys.path:
sys.path.append(lumerical_path)
try:
import lumapi
except ImportError as e:
raise ImportError(f"无法导入 lumapi,请检查路径: {lumerical_path}") from e
def n_LN_o_zelmon(lam_um: float) -> float:
lam2 = lam_um**2
n2 = 1 + 2.6734lam2/(lam2-0.01764) + 1.2290lam2/(lam2-0.05914) + 12.614*lam2/(lam2-474.60)
return float(np.sqrt(n2))
def n_LN_e_zelmon(lam_um: float) -> float:
lam2 = lam_um**2
n2 = 1 + 2.9804lam2/(lam2-0.02047) + 0.5981lam2/(lam2-0.0666) + 8.9543*lam2/(lam2-416.08)
return float(np.sqrt(n2))
def n_sapphire_o_malitson(lam_um: float) -> float:
lam2 = lam_um2
c1 = 0.07266312
c2 = 0.11932422
c3 = 18.0282512
n2 = 1 + 1.4313493lam2/(lam2-c1) + 0.65054713lam2/(lam2-c2) + 5.3414021*lam2/(lam2-c3)
return float(np.sqrt(n2))
def build_materials(mode, lambda0_m: float):
c0 = 299792458.0
lam_um = lambda0_m * 1e6
textn_o = n_LN_o_zelmon(lam_um) n_e = n_LN_e_zelmon(lam_um) n_sap = n_sapphire_o_malitson(lam_um) f0 = c0 / lambda0_m freqs = np.array([0.95*f0, f0, 1.05*f0]) # X切Y传Z调制 => optic axis 沿仿真 x epsx = (n_e**2) + 0j epsy = (n_o**2) + 0j epsz = (n_o**2) + 0j ln_sampled = np.column_stack([ freqs, epsx*np.ones_like(freqs), epsy*np.ones_like(freqs), epsz*np.ones_like(freqs), ]) # 删除旧材料(如果存在) for name in ["TFLN_LN_Xcut_Yprop"]: try: mode.deletematerial(name) except Exception: pass # ✅ 正确:接住 addmaterial 的返回名 temp = mode.addmaterial("Sampled data") mode.setmaterial(temp, "name", "TFLN_LN_Xcut_Yprop") try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "Anisotropy", 1) # diagonal except Exception: pass mode.setmaterial("TFLN_LN_Xcut_Yprop", "sampled data", ln_sampled) try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "max coefficients", 2) except Exception: pass # —— 蓝宝石建议别折腾建材,直接用 object defined dielectric(更稳)—— # 你后面建 substrate 的地方,把 material 设成 "<Object defined dielectric>", # 再 set("index", n_sap) 即可,不需要 addmaterial return {"n_o": n_o, "n_e": n_e, "n_sap": n_sap}
def simulate_tfln_ridge_fde(
wg_width_um: float = 3.0,
lambda_um: float = 4.0,
tfln_thickness_nm: float = 600.0,
etch_depth_nm: float = 300.0,
):
# ---- 参数换算到 SI ----
lambda0 = lambda_um * 1e-6
w_wg = wg_width_um * 1e-6
t_ln = tfln_thickness_nm * 1e-9
etch = etch_depth_nm * 1e-9
slab_t = t_ln - etch # 刻蚀后剩余 slab 厚度
text# 仿真窗口(可按需要调大/调小) x_span = max(12e-6, 4*w_wg) sub_thick = 4e-6 clad_thick = 4e-6 y_min = -sub_thick y_max = t_ln + clad_thick y_span = y_max - y_min y_center = 0.5*(y_min + y_max) # ---- 启动 MODE ---- mode = lumapi.MODE(hide=False) mode.deleteall() mats = build_materials(mode, lambda0) print(f"[Info] λ={lambda_um:.3f} um: LN no={mats['n_o']:.4f}, ne={mats['n_e']:.4f}; sapphire n={mats['n_sap']:.4f}") # ---- 基底:蓝宝石(y in [-sub_thick, 0])---- mode.addrect() mode.set("name", "substrate_sapphire") mode.set("material", "<Object defined dielectric>") mode.set("index", mats["n_sap"])
textmode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", -0.5*sub_thick) mode.set("y span", sub_thick) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN slab:厚 slab_t,铺满横向 ---- mode.addrect() mode.set("name", "ln_slab") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", 0.5*slab_t) mode.set("y span", slab_t) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN ridge:在 slab 上再加 etch 高度,宽度 w_wg ---- mode.addrect() mode.set("name", "ln_ridge") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", w_wg) mode.set("y", slab_t + 0.5*etch) mode.set("y span", etch) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- FDE region(XY 截面,传播沿 z)---- mode.addfde() mode.set("name", "FDE") mode.set("solver type", 3) # 2D Z normal(XY 平面) 见 addfde 示例 mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) # 开边界 mode.set("x min bc", "PML") mode.set("x max bc", "PML") mode.set("y min bc", "PML") mode.set("y max bc", "PML") # 网格(全局较粗 + LN 附近加密) mode.set("define x mesh by", "maximum mesh step") mode.set("dx", 120e-9) mode.set("define y mesh by", "maximum mesh step") mode.set("dy", 60e-9) mode.addmesh() mode.set("name", "mesh_ln") mode.set("x", 0.0) mode.set("x span", max(6e-6, 2*w_wg)) mode.set("y", 0.5*t_ln) mode.set("y span", t_ln + 0.8e-6) mode.set("dx", 30e-9) mode.set("dy", 20e-9) # ---- 求模设置 ---- mode.select("FDE") mode.setanalysis("wavelength", lambda0) mode.setanalysis("number of trial modes", 8) # 如果你更关心 TE-like/TM-like,可加: # mode.setanalysis("use max index", 1) # mode.setanalysis("n", mats["n_o"]) # 搜索初值(可选) # ---- 求解 ---- n_found = mode.findmodes() print(f"[Result] 找到模式数: {int(n_found)}") # 打印前几个模式的 neff / TE fraction n_report = min(int(n_found), 6) for i in range(1, n_report + 1): obj = f"FDE::data::mode{i}" neff = mode.getdata(obj, "neff") try: tefrac = mode.getdata(obj, "TE polarization fraction") tefrac_val = float(np.array(tefrac).squeeze()) except Exception: tefrac_val = float("nan") neff_val = float(np.array(neff).squeeze()) print(f" mode{i}: neff = {neff_val:.6f}, TE_frac = {tefrac_val:.4f}") # 可选:保存工程 # mode.save("tfln_ridge_on_sapphire_4um.lms") return mode
if name == "main":
simulate_tfln_ridge_fde(wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0)
运行上面的代码报了以下的错误。请你给我完整的修改后可直接运行的代码
(base) PS C:\Users\47004\Desktop\TFLN_Sim> & "C:/Program Files/ANSYS Inc/v251/Lumerical/python-3.9.9-embed-amd64/python.exe" c:/Users/47004/Desktop/TFLN_Sim/TFLN_Sapphire_600thi.py
[Info] λ=4.000 um: LN no=2.1142, ne=2.0559; sapphire n=1.6752
Traceback (most recent call last):
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 218, in <module>
simulate_tfln_ridge_fde(wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0)
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 156, in simulate_tfln_ridge_fde
mode.set("name", "FDE")
File "C:\Program Files\ANSYS Inc\v251\Lumerical\api\python\lumapi.py", line 1257, in <lambda>
method = (lambda x: lambda self, *args: appCall(self, x, args))(name)
File "C:\Program Files\ANSYS Inc\v251\Lumerical\api\python\lumapi.py", line 899, in appCall
raise LumApiError(message)
lumapi.LumApiError: "in set, the requested property 'name' is inactive"
import sys
import numpy as np
lumerical_path = r"C:\Program Files\ANSYS Inc\v251\Lumerical\api\python"
if lumerical_path not in sys.path:
sys.path.append(lumerical_path)
try:
import lumapi
except ImportError as e:
raise ImportError(f"无法导入 lumapi,请检查路径: {lumerical_path}") from e
def n_LN_o_zelmon(lam_um: float) -> float:
lam2 = lam_um**2
n2 = 1 + 2.6734lam2/(lam2-0.01764) + 1.2290lam2/(lam2-0.05914) + 12.614*lam2/(lam2-474.60)
return float(np.sqrt(n2))
def n_LN_e_zelmon(lam_um: float) -> float:
lam2 = lam_um**2
n2 = 1 + 2.9804lam2/(lam2-0.02047) + 0.5981lam2/(lam2-0.0666) + 8.9543*lam2/(lam2-416.08)
return float(np.sqrt(n2))
def n_sapphire_o_malitson(lam_um: float) -> float:
lam2 = lam_um2
c1 = 0.07266312
c2 = 0.11932422
c3 = 18.0282512
n2 = 1 + 1.4313493lam2/(lam2-c1) + 0.65054713lam2/(lam2-c2) + 5.3414021*lam2/(lam2-c3)
return float(np.sqrt(n2))
def build_materials(mode, lambda0_m: float):
c0 = 299792458.0
lam_um = lambda0_m * 1e6
textn_o = n_LN_o_zelmon(lam_um) n_e = n_LN_e_zelmon(lam_um) n_sap = n_sapphire_o_malitson(lam_um) f0 = c0 / lambda0_m freqs = np.array([0.95*f0, f0, 1.05*f0]) # X切Y传Z调制 => optic axis 沿仿真 x epsx = (n_e**2) + 0j epsy = (n_o**2) + 0j epsz = (n_o**2) + 0j ln_sampled = np.column_stack([ freqs, epsx*np.ones_like(freqs), epsy*np.ones_like(freqs), epsz*np.ones_like(freqs), ]) # 删除旧材料(如果存在) for name in ["TFLN_LN_Xcut_Yprop"]: try: mode.deletematerial(name) except Exception: pass # ✅ 正确:接住 addmaterial 的返回名 temp = mode.addmaterial("Sampled data") mode.setmaterial(temp, "name", "TFLN_LN_Xcut_Yprop") try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "Anisotropy", 1) # diagonal except Exception: pass mode.setmaterial("TFLN_LN_Xcut_Yprop", "sampled data", ln_sampled) try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "max coefficients", 2) except Exception: pass return {"n_o": n_o, "n_e": n_e, "n_sap": n_sap}
def simulate_tfln_ridge_fde(
wg_width_um: float = 3.0,
lambda_um: float = 4.0,
tfln_thickness_nm: float = 600.0,
etch_depth_nm: float = 300.0,
):
# ---- 参数换算到 SI ----
lambda0 = lambda_um * 1e-6
w_wg = wg_width_um * 1e-6
t_ln = tfln_thickness_nm * 1e-9
etch = etch_depth_nm * 1e-9
slab_t = t_ln - etch # 刻蚀后剩余 slab 厚度
text# 仿真窗口(可按需要调大/调小) x_span = max(12e-6, 4*w_wg) sub_thick = 4e-6 clad_thick = 4e-6 y_min = -sub_thick y_max = t_ln + clad_thick y_span = y_max - y_min y_center = 0.5*(y_min + y_max) # ---- 启动 MODE ---- mode = lumapi.MODE(hide=False) mode.deleteall() mats = build_materials(mode, lambda0) print(f"[Info] λ={lambda_um:.3f} um: LN no={mats['n_o']:.4f}, ne={mats['n_e']:.4f}; sapphire n={mats['n_sap']:.4f}") # ---- 基底:蓝宝石(y in [-sub_thick, 0])---- mode.addrect() mode.set("name", "substrate_sapphire") mode.set("material", "<Object defined dielectric>") mode.set("index", mats["n_sap"]) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", -0.5*sub_thick) mode.set("y span", sub_thick) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN slab:厚 slab_t,铺满横向 ---- mode.addrect() mode.set("name", "ln_slab") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", 0.5*slab_t) mode.set("y span", slab_t) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN ridge:在 slab 上再加 etch 高度,宽度 w_wg ---- mode.addrect() mode.set("name", "ln_ridge") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", w_wg) mode.set("y", slab_t + 0.5*etch) mode.set("y span", etch) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- FDE region(XY 截面,传播沿 z)---- mode.addfde() mode.set("solver type", 3) # 2D Z normal(XY 平面) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) # 开边界 mode.set("x min bc", "PML") mode.set("x max bc", "PML") mode.set("y min bc", "PML") mode.set("y max bc", "PML") # 网格(全局较粗 + LN 附近加密) mode.set("define x mesh by", "maximum mesh step") mode.set("dx", 120e-9) mode.set("define y mesh by", "maximum mesh step") mode.set("dy", 60e-9) mode.addmesh() mode.set("name", "mesh_ln") mode.set("x", 0.0) mode.set("x span", max(6e-6, 2*w_wg)) mode.set("y", 0.5*t_ln) mode.set("y span", t_ln + 0.8e-6) mode.set("dx", 30e-9) mode.set("dy", 20e-9) # ---- 求模设置 ---- mode.select("FDE") mode.setanalysis("wavelength", lambda0) mode.setanalysis("number of trial modes", 8) # ---- 求解 ---- n_found = mode.findmodes() print(f"[Result] 找到模式数: {int(n_found)}") # 打印前几个模式的 neff / TE fraction n_report = min(int(n_found), 6) for i in range(1, n_report + 1): obj = f"FDE::data::mode{i}" neff = mode.getdata(obj, "neff") try: tefrac = mode.getdata(obj, "TE polarization fraction") tefrac_val = float(np.array(tefrac).squeeze()) except Exception: tefrac_val = float("nan") neff_val = float(np.array(neff).squeeze()) print(f" mode{i}: neff = {neff_val:.6f}, TE_frac = {tefrac_val:.4f}") # 可选:保存工程 # mode.save("tfln_ridge_on_sapphire_4um.lms") return mode
if name == "main":
simulate_tfln_ridge_fde(wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0)
上面这个代码报错:base) PS C:\Users\47004\Desktop\TFLN_Sim> & "C:/Program Files/ANSYS Inc/v251/Lumerical/python-3.9.9-embed-amd64/python.exe" c:/Users/47004/Desktop/TFLN_Sim/TFLN_Sapphire_600thi.py
[Info] λ=4.000 um: LN no=2.1142, ne=2.0559; sapphire n=1.6752
[Result] 找到模式数: 5
Traceback (most recent call last):
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 212, in <module>
simulate_tfln_ridge_fde(wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0)
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi.py", line 202, in simulate_tfln_ridge_fde
neff_val = float(np.array(neff).squeeze())
TypeError: can't convert complex to float
下面给你一份完整可直接运行的脚本(按你 v251 的环境写的)。它已经修复了你遇到的两个问题:
neff 在 v251 里可能返回 complex(即使虚部≈0),所以打印时取 real/imag,不再强制转 float 报错。把下面整段保存为 TFLN_Sapphire_600thi.py 直接运行即可(只需要确认 lumerical_path 是你机器上的实际路径)。
pythonimport sys import numpy as np # ============================================================ # 1) 配置 Lumerical Python API 路径(按你电脑实际安装路径改) # ============================================================ lumerical_path = r"C:\Program Files\ANSYS Inc\v251\Lumerical\api\python" if lumerical_path not in sys.path: sys.path.append(lumerical_path) try: import lumapi except ImportError as e: raise ImportError(f"无法导入 lumapi,请检查路径: {lumerical_path}") from e # ============================================================ # 2) Sellmeier:返回折射率 n(λ),λ 单位:um # ============================================================ def n_LN_o_zelmon(lam_um: float) -> float: lam2 = lam_um**2 n2 = 1 + 2.6734*lam2/(lam2-0.01764) + 1.2290*lam2/(lam2-0.05914) + 12.614*lam2/(lam2-474.60) return float(np.sqrt(n2)) def n_LN_e_zelmon(lam_um: float) -> float: lam2 = lam_um**2 n2 = 1 + 2.9804*lam2/(lam2-0.02047) + 0.5981*lam2/(lam2-0.0666) + 8.9543*lam2/(lam2-416.08) return float(np.sqrt(n2)) def n_sapphire_o_malitson(lam_um: float) -> float: lam2 = lam_um**2 c1 = 0.0726631**2 c2 = 0.1193242**2 c3 = 18.028251**2 n2 = 1 + 1.4313493*lam2/(lam2-c1) + 0.65054713*lam2/(lam2-c2) + 5.3414021*lam2/(lam2-c3) return float(np.sqrt(n2)) # ============================================================ # 3) 建立材料:TFLN 各向异性 (sampled data);蓝宝石用 object-defined index # 晶向:X切 Y传 Z调制 # 在 2D Z-normal FDE(截面 x-y,传播沿 z)里等效为: # optic axis (晶体Z) -> 仿真 x # => eps_x = n_e^2, eps_y = n_o^2, eps_z = n_o^2 # ============================================================ def build_materials(mode, lambda0_m: float): c0 = 299792458.0 lam_um = lambda0_m * 1e6 n_o = n_LN_o_zelmon(lam_um) n_e = n_LN_e_zelmon(lam_um) n_sap = n_sapphire_o_malitson(lam_um) f0 = c0 / lambda0_m freqs = np.array([0.95*f0, f0, 1.05*f0]) epsx = (n_e**2) + 0j epsy = (n_o**2) + 0j epsz = (n_o**2) + 0j ln_sampled = np.column_stack([ freqs, epsx*np.ones_like(freqs), epsy*np.ones_like(freqs), epsz*np.ones_like(freqs), ]) # 删除旧材料(如果存在) try: mode.deletematerial("TFLN_LN_Xcut_Yprop") except Exception: pass # ✅ addmaterial 返回新材料的真实名字(如 material1),必须用它来 setmaterial temp = mode.addmaterial("Sampled data") mode.setmaterial(temp, "name", "TFLN_LN_Xcut_Yprop") # 有些版本可能没有该属性,try/except 保证不报错 try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "Anisotropy", 1) # diagonal except Exception: pass mode.setmaterial("TFLN_LN_Xcut_Yprop", "sampled data", ln_sampled) try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "max coefficients", 2) except Exception: pass return {"n_o": n_o, "n_e": n_e, "n_sap": n_sap} # ============================================================ # 4) 几何 & FDE 求模 # ============================================================ def simulate_tfln_ridge_fde( wg_width_um: float = 3.0, lambda_um: float = 4.0, tfln_thickness_nm: float = 600.0, etch_depth_nm: float = 300.0, keep_open: bool = True, save_file: str | None = None, ): # ---- 单位换算 ---- lambda0 = lambda_um * 1e-6 w_wg = wg_width_um * 1e-6 t_ln = tfln_thickness_nm * 1e-9 etch = etch_depth_nm * 1e-9 slab_t = t_ln - etch # 刻蚀后剩余 slab 厚度 # 仿真窗口(可按需要调) x_span = max(12e-6, 4*w_wg) sub_thick = 4e-6 clad_thick = 4e-6 y_min = -sub_thick y_max = t_ln + clad_thick y_span = y_max - y_min y_center = 0.5*(y_min + y_max) # ---- 启动 MODE ---- mode = lumapi.MODE(hide=False) mode.deleteall() mats = build_materials(mode, lambda0) print(f"[Info] λ={lambda_um:.3f} um: LN no={mats['n_o']:.4f}, ne={mats['n_e']:.4f}; sapphire n={mats['n_sap']:.4f}") # ---- 先放一个空气背景块(更稳,避免背景材质不确定)---- mode.addrect() mode.set("name", "clad_air") mode.set("material", "<Object defined dielectric>") mode.set("index", 1.0) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- 蓝宝石衬底(y in [-sub_thick, 0])---- mode.addrect() mode.set("name", "substrate_sapphire") mode.set("material", "<Object defined dielectric>") mode.set("index", mats["n_sap"]) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", -0.5*sub_thick) mode.set("y span", sub_thick) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN slab:厚 slab_t,铺满横向 ---- mode.addrect() mode.set("name", "ln_slab") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", 0.5*slab_t) mode.set("y span", slab_t) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN ridge:在 slab 上再加 etch 高度,宽 w_wg ---- mode.addrect() mode.set("name", "ln_ridge") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", w_wg) mode.set("y", slab_t + 0.5*etch) mode.set("y span", etch) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- FDE region(XY 截面,传播沿 z)---- # 注意:不要 set("name","FDE"),有些版本 name 属性是 inactive fde_name = mode.addfde() # 如果 API 没返回名字,则默认就是 "FDE" if (fde_name is None) or (str(fde_name).strip() == ""): fde_name = "FDE" mode.set("solver type", 3) # 2D Z normal mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) # 开边界 mode.set("x min bc", "PML") mode.set("x max bc", "PML") mode.set("y min bc", "PML") mode.set("y max bc", "PML") # 网格(全局 + LN 附近加密) mode.set("define x mesh by", "maximum mesh step") mode.set("dx", 120e-9) mode.set("define y mesh by", "maximum mesh step") mode.set("dy", 60e-9) mode.addmesh() mode.set("name", "mesh_ln") mode.set("x", 0.0) mode.set("x span", max(6e-6, 2*w_wg)) mode.set("y", 0.5*t_ln) mode.set("y span", t_ln + 0.8e-6) mode.set("dx", 30e-9) mode.set("dy", 20e-9) # ---- 求模设置 ---- try: mode.select(fde_name) except Exception: # 如果 select 失败,尝试默认名 mode.select("FDE") fde_name = "FDE" mode.setanalysis("wavelength", lambda0) mode.setanalysis("number of trial modes", 8) # ---- 求解 ---- n_found = int(np.array(mode.findmodes()).squeeze()) print(f"[Result] 找到模式数: {n_found}") # ---- 结果打印(neff 在某些版本会返回 complex,哪怕虚部为 0)---- n_report = min(n_found, 6) for i in range(1, n_report + 1): obj = f"{fde_name}::data::mode{i}" neff = mode.getdata(obj, "neff") neff_c = complex(np.array(neff).squeeze()) # ✅ 强制转成 Python complex neff_re = neff_c.real neff_im = neff_c.imag # TE fraction 也做一下保险处理 tefrac_val = np.nan try: tefrac = mode.getdata(obj, "TE polarization fraction") tefrac_val = float(np.real(np.array(tefrac).squeeze())) except Exception: pass if abs(neff_im) < 1e-12: print(f" mode{i}: neff = {neff_re:.6f}, TE_frac = {tefrac_val:.4f}") else: print(f" mode{i}: neff = {neff_re:.6f} + j{neff_im:.3e}, TE_frac = {tefrac_val:.4f}") # 可选:保存工程 if save_file: try: mode.save(save_file) print(f"[Info] 工程已保存: {save_file}") except Exception as e: print(f"[Warn] 保存失败: {e}") if keep_open: input("仿真完成。按 Enter 退出并关闭 MODE...") try: mode.close() except Exception: pass return mode if __name__ == "__main__": simulate_tfln_ridge_fde( wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0, keep_open=True, # save_file="tfln_ridge_on_sapphire_4um.lms" save_file=None, )
如果你接下来想把模式场(Ex/Ey/Ez 或 |E|²)导出来到 .mat/.npz 或者自动画图/保存图片,我也可以在这个脚本基础上直接加上对应的 getdata(...,"Ex") 等导出段。
还是报错!(base) PS C:\Users\47004\Desktop\TFLN_Sim> & "C:/Program Files/ANSYS Inc/v251/Lumerical/python-3.9.9-embed-amd64/python.exe" c:/Users/47004/Desktop/TFLN_Sim/TFLN_Sapphire_600thi_2.py
Traceback (most recent call last):
File "c:\Users\47004\Desktop\TFLN_Sim\TFLN_Sapphire_600thi_2.py", line 103, in <module>
save_file: str | None = None,
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'
你这个报错不是 Lumerical 的问题,而是 你在用的 Python 是 3.9.9(Lumerical 自带的 embed python),它不支持 str | None 这种写法(这是 Python 3.10 才支持的 PEP604)。把它改成 Optional[str](或直接去掉类型标注)就能跑。
下面是我给你的完整可直接运行版(已把 str | None 全部改掉,同时保留你前面已经跑通的:不改 FDE name、neff 可能为 complex 的处理)。
直接保存为
TFLN_Sapphire_600thi_2.py运行即可。
pythonimport sys import numpy as np from typing import Optional # ============================================================ # 1) 配置 Lumerical Python API 路径(按你电脑实际安装路径改) # ============================================================ lumerical_path = r"C:\Program Files\ANSYS Inc\v251\Lumerical\api\python" if lumerical_path not in sys.path: sys.path.append(lumerical_path) try: import lumapi except ImportError as e: raise ImportError(f"无法导入 lumapi,请检查路径: {lumerical_path}") from e # ============================================================ # 2) Sellmeier:返回折射率 n(λ),λ 单位:um # ============================================================ def n_LN_o_zelmon(lam_um: float) -> float: lam2 = lam_um**2 n2 = 1 + 2.6734*lam2/(lam2-0.01764) + 1.2290*lam2/(lam2-0.05914) + 12.614*lam2/(lam2-474.60) return float(np.sqrt(n2)) def n_LN_e_zelmon(lam_um: float) -> float: lam2 = lam_um**2 n2 = 1 + 2.9804*lam2/(lam2-0.02047) + 0.5981*lam2/(lam2-0.0666) + 8.9543*lam2/(lam2-416.08) return float(np.sqrt(n2)) def n_sapphire_o_malitson(lam_um: float) -> float: lam2 = lam_um**2 c1 = 0.0726631**2 c2 = 0.1193242**2 c3 = 18.028251**2 n2 = 1 + 1.4313493*lam2/(lam2-c1) + 0.65054713*lam2/(lam2-c2) + 5.3414021*lam2/(lam2-c3) return float(np.sqrt(n2)) # ============================================================ # 3) 建立材料:TFLN 各向异性 (sampled data);蓝宝石用 object-defined index # 晶向:X切 Y传 Z调制 # 在 2D Z-normal FDE(截面 x-y,传播沿 z)里等效为: # optic axis (晶体Z) -> 仿真 x # => eps_x = n_e^2, eps_y = n_o^2, eps_z = n_o^2 # ============================================================ def build_materials(mode, lambda0_m: float): c0 = 299792458.0 lam_um = lambda0_m * 1e6 n_o = n_LN_o_zelmon(lam_um) n_e = n_LN_e_zelmon(lam_um) n_sap = n_sapphire_o_malitson(lam_um) f0 = c0 / lambda0_m freqs = np.array([0.95*f0, f0, 1.05*f0]) epsx = (n_e**2) + 0j epsy = (n_o**2) + 0j epsz = (n_o**2) + 0j ln_sampled = np.column_stack([ freqs, epsx*np.ones_like(freqs), epsy*np.ones_like(freqs), epsz*np.ones_like(freqs), ]) # 删除旧材料(如果存在) try: mode.deletematerial("TFLN_LN_Xcut_Yprop") except Exception: pass # addmaterial 返回新材料实际名字(如 material1),必须用它来 setmaterial temp = mode.addmaterial("Sampled data") mode.setmaterial(temp, "name", "TFLN_LN_Xcut_Yprop") try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "Anisotropy", 1) # diagonal(若该属性存在) except Exception: pass mode.setmaterial("TFLN_LN_Xcut_Yprop", "sampled data", ln_sampled) try: mode.setmaterial("TFLN_LN_Xcut_Yprop", "max coefficients", 2) except Exception: pass return {"n_o": n_o, "n_e": n_e, "n_sap": n_sap} # ============================================================ # 4) 几何 & FDE 求模 # ============================================================ def simulate_tfln_ridge_fde( wg_width_um: float = 3.0, lambda_um: float = 4.0, tfln_thickness_nm: float = 600.0, etch_depth_nm: float = 300.0, keep_open: bool = True, save_file: Optional[str] = None, # ✅ Python3.9 兼容写法 ): # ---- 单位换算 ---- lambda0 = lambda_um * 1e-6 w_wg = wg_width_um * 1e-6 t_ln = tfln_thickness_nm * 1e-9 etch = etch_depth_nm * 1e-9 slab_t = t_ln - etch # 刻蚀后剩余 slab 厚度 # 仿真窗口 x_span = max(12e-6, 4*w_wg) sub_thick = 4e-6 clad_thick = 4e-6 y_min = -sub_thick y_max = t_ln + clad_thick y_span = y_max - y_min y_center = 0.5*(y_min + y_max) # ---- 启动 MODE ---- mode = lumapi.MODE(hide=False) mode.deleteall() mats = build_materials(mode, lambda0) print(f"[Info] λ={lambda_um:.3f} um: LN no={mats['n_o']:.4f}, ne={mats['n_e']:.4f}; sapphire n={mats['n_sap']:.4f}") # ---- 背景空气块(更稳)---- mode.addrect() mode.set("name", "clad_air") mode.set("material", "<Object defined dielectric>") mode.set("index", 1.0) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- 蓝宝石衬底 ---- mode.addrect() mode.set("name", "substrate_sapphire") mode.set("material", "<Object defined dielectric>") mode.set("index", mats["n_sap"]) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", -0.5*sub_thick) mode.set("y span", sub_thick) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN slab ---- mode.addrect() mode.set("name", "ln_slab") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", 0.5*slab_t) mode.set("y span", slab_t) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- LN ridge ---- mode.addrect() mode.set("name", "ln_ridge") mode.set("material", "TFLN_LN_Xcut_Yprop") mode.set("x", 0.0) mode.set("x span", w_wg) mode.set("y", slab_t + 0.5*etch) mode.set("y span", etch) mode.set("z", 0.0) mode.set("z span", 1e-6) # ---- FDE region(不要 set name,避免 name inactive)---- fde_name = mode.addfde() if (fde_name is None) or (str(fde_name).strip() == ""): fde_name = "FDE" mode.set("solver type", 3) # 2D Z normal(截面 x-y,传播 z) mode.set("x", 0.0) mode.set("x span", x_span) mode.set("y", y_center) mode.set("y span", y_span) mode.set("z", 0.0) # 边界 mode.set("x min bc", "PML") mode.set("x max bc", "PML") mode.set("y min bc", "PML") mode.set("y max bc", "PML") # 网格 mode.set("define x mesh by", "maximum mesh step") mode.set("dx", 120e-9) mode.set("define y mesh by", "maximum mesh step") mode.set("dy", 60e-9) mode.addmesh() mode.set("name", "mesh_ln") mode.set("x", 0.0) mode.set("x span", max(6e-6, 2*w_wg)) mode.set("y", 0.5*t_ln) mode.set("y span", t_ln + 0.8e-6) mode.set("dx", 30e-9) mode.set("dy", 20e-9) # ---- 求模设置 ---- try: mode.select(fde_name) except Exception: mode.select("FDE") fde_name = "FDE" mode.setanalysis("wavelength", lambda0) mode.setanalysis("number of trial modes", 8) # ---- 求解 ---- n_found = int(np.array(mode.findmodes()).squeeze()) print(f"[Result] 找到模式数: {n_found}") # ---- 打印结果(neff 可能是 complex,哪怕虚部为 0)---- n_report = min(n_found, 6) for i in range(1, n_report + 1): obj = f"{fde_name}::data::mode{i}" neff = mode.getdata(obj, "neff") neff_c = complex(np.array(neff).squeeze()) neff_re, neff_im = neff_c.real, neff_c.imag tefrac_val = np.nan try: tefrac = mode.getdata(obj, "TE polarization fraction") tefrac_val = float(np.real(np.array(tefrac).squeeze())) except Exception: pass if abs(neff_im) < 1e-12: print(f" mode{i}: neff = {neff_re:.6f}, TE_frac = {tefrac_val:.4f}") else: print(f" mode{i}: neff = {neff_re:.6f} + j{neff_im:.3e}, TE_frac = {tefrac_val:.4f}") # 可选:保存工程 if save_file: try: mode.save(save_file) print(f"[Info] 工程已保存: {save_file}") except Exception as e: print(f"[Warn] 保存失败: {e}") if keep_open: input("仿真完成。按 Enter 退出并关闭 MODE...") try: mode.close() except Exception: pass if __name__ == "__main__": simulate_tfln_ridge_fde( wg_width_um=3.0, lambda_um=4.0, tfln_thickness_nm=600.0, etch_depth_nm=300.0, keep_open=True, save_file=None, # 或者 "tfln_ridge_on_sapphire_4um.lms" )
如果你运行后还有新的报错(比如 getdata 的字段名在你安装里不同),把报错全文贴出来就行;我会按 v251 的实际字段名把 neff/损耗/模式场导出那部分也一起做成“零报错版”。
很好,你现在写的这个FDE仿真已经很棒了。接下来我想用charge仿真这样的铌酸锂波导的电光调制效率。请你把铌酸锂的参数设置为厚600nm刻蚀300nm,4um波段,波导倾角为90度,然后电极的间距,宽度,厚度等参数可以设置,你暂时选一个认为比较好的参数。然后给我仿真出来调制效率也就是VpaiL 。 请你帮我写好python脚本代码
很好,你现在写的这个FDE仿真已经很棒了。接下来我想用charge仿真这样的铌酸锂波导的电光调制效率。请你把铌酸锂的参数设置为厚600nm刻蚀300nm,4um波段,波导倾角为90度,然后电极的间距,宽度,厚度等参数可以设置,你暂时选一个认为比较好的参数。然后给我仿真出来调制效率也就是VpaiL 。 请你帮我写好python脚本代码
注意我是用的是2025R1版本的lumerical,请你自己搜索他的charge仿真如何调用