Lumerical FDTD 脚本开发综合技术指南

Lumerical FDTD 脚本开发综合技术指南 (v3)

适用范围:本指南适用于使用 Lumerical LSF 脚本语言为 FDTD 求解器编写自动化仿真代码的全部场景,涵盖从基础物理原理、语言语法、工程代码规范到结构建模、参数扫描、结果提取与 Python 后处理的完整链路。核心目标是让 AI 生成的代码一次性通过编译并正确执行,避免因语法混淆、求解器命令越界、属性依赖顺序错误等导致的运行时故障。


1. FDTD 求解器核心物理原理

1.1 Maxwell 方程与 Yee 网格离散

FDTD 方法在非磁性材料中求解 Maxwell 旋度方程,控制方程为:

  • D /∂t = ∇ × H
  • D (ω) = ε₀εᵣ(ω)E(ω)
  • H /∂t = −(1/μ₀)∇ × E

其中 εᵣ(ω) = n² 为复相对介电常数。2D 情形下,Maxwell 方程分裂为两组独立模式:TE 模式 (Ex, Ey, Hz)和 TM 模式(Hx, Hy, Ez)。

FDTD 采用 Yee 元胞 离散,每个电磁场分量在网格单元内处于略有偏移的位置。Lumerical FDTD 自动将数据插值到网格原点,用户在分析中无需直接处理 Yee 偏移。

Courant 稳定性条件 自动由求解器处理,用户通过 dt stability factor(<1)间接控制时间步长。

1.2 网格系统

  • 默认使用 自动非均匀网格mesh type = "auto non-uniform"
  • mesh accuracy(1--8)控制每波长网格点数:1→6 ppw,每级增加 4 ppw
  • 高折射率材料自动获得更细网格
  • 网格覆盖区addmesh)在关键区域强制细化
  • 共形网格(conformal mesh)技术允许较粗网格仍保持高精度

1.3 边界条件

边界类型 字符串值 物理含义
PML "PML" 完美匹配层,吸收出射波,模拟开放边界
Metal (PEC) "Metal" 理想电导体,E_平行=0,全反射
PMC "PMC" 理想磁导体,H_平行=0
Periodic "Periodic" 周期性,无相位差
Bloch "Bloch" 周期性带相位差,用于倾斜入射
Symmetric "Symmetric" 电场镜像、磁场反对称,可缩减 4x 计算量
Anti-Symmetric "Anti-Symmetric" 电场反对称、磁场镜像

边界条件通过在 FDTD 仿真区域对象 上设置属性实现,不存在独立的 addpml/addperiodic 等命令(那些是 DGTD 等求解器的命令)。

1.4 材料模型

模型 说明 关键属性
Dielectric 恒定实折射率 index
(n,k) 单频指定 n,k refractive index, imaginary refractive index
Conductive 3D 欧姆导电 permittivity, conductivity
Plasma (Drude) 自由电子金属 permittivity, plasma resonance, collision
Debye 弛豫型色散 permittivity, Debye permittivity, collision
Lorentz 共振型色散 permittivity, Lorentz permittivity, resonance, linewidth
Sellmeier 玻璃常用 系数 A, B, C
Sampled 3D data 实验数据拟合 MCM tolerance, max coefficients
PEC 理想电导体 无参数
Multi-coefficient (MCM) 通用色散拟合 从 Sampled 3D data 自动生成

2. LSF 语言语法精要

2.1 与 MATLAB / Python 的关键差异

特性 LSF MATLAB Python
数组索引 1-based 1-based 0-based
元素级乘法 A * B A .* B A * B (numpy)
矩阵乘法 mult(A,B) A * B A @ B
矩阵纵向拼接 [A; B] [A; B] np.vstack
矩阵横向拼接 [A, B] [A, B] np.hstack
逻辑与 &and &&& and
逻辑或 ` or` `
不等于 != ~= !=
注释 # % #
字符串拼接 + strcat+ + 或 f-string
字符串定界符 "' "' "'
虚数单位 i 1i1j 1j
块结束 } end 缩进
函数定义 function name(){...} function out = name() def name():
打印输出 ?expr;print(expr); disp(expr) print(expr)

2.2 变量与命名

lsf 复制代码
# 变量赋值 --- 无需声明类型
x = 5;                          # 标量
A = [1, 2; 3, 4];              # 2x2 矩阵(分号=新行,逗号=新列)
v = 1:10;                       # 行向量 [1, 2, ..., 10]
v2 = 1:0.5:10;                  # 步长 0.5
v3 = linspace(1, 10, 100);      # 100 个线性间隔点

# 变量名可包含空格(% 语法)
"my variable"% = 10;
?"my variable"%;                 # 输出 10

命名规则:

规则 说明 示例
允许字符 字母、数字、下划线 my_var, x_span_val
区分大小写 Xx 不同 ---
避开保留命令名 不可与命令冲突 不用 set 作变量名
变量名空格 用下划线或 % 语法 x_span%x span%
预定义常量 pi, c, eps0, mu0, h, hbar, true, false, e, i, endl 不可覆盖

⚠️ 致命混淆:变量名 vs 属性名

lsf 复制代码
# 变量(存储值)--- 用下划线,无引号
x_span_fdtd = 10e-6;            # ✅ 合法变量名

# 属性(set/get 参数)--- 用 GUI 原名(含空格),双引号包裹
set("x span", 10e-6);           # ✅ 合法属性名
set("x_span", 10e-6);           # ❌ 错误 --- 属性名是 "x span" 不是 "x_span"
set(x_span_fdtd, 10e-6);        # ❌ 错误 --- 把变量当属性名传了
set("x span", x_span_fdtd);     # ✅ 正确 --- 变量值赋给属性

2.3 预定义常量

常量 说明
pi 3.14159265... 圆周率
c 2.99792458e8 真空光速 (m/s)
eps0 8.854187817e-12 真空介电常数 (F/m)
mu0 1.2566370614e-6 真空磁导率 (H/m)
h 6.62606896e-34 普朗克常数 (J·s)
hbar 1.054571628e-34 约化普朗克常数 (J·s)
true 1 逻辑真
false 0 逻辑假
e 1.602176487e-19 元电荷 ©
i sqrt(-1) 虚数单位
endl --- 换行符,用于字符串拼接

2.4 数据类型

类型 创建 访问
实数/标量 x = 5; 直接
复数 z = 1 + 2i; real(z), imag(z), abs(z), angle(z)
矩阵 A = matrix(3,4);A = [1,2;3,4]; A(i,j) --- 1-based
元胞数组 C = cell(3); C{1} = "str"; C{i} --- 花括号
结构体 S = struct; S.field = value; S.field --- 点号
数据集 D = rectilineardataset; D.attribute, D.parameter --- 点号
字符串 str = "hello"; str + " world" 拼接

矩阵操作:

lsf 复制代码
# 元素访问(1-based)
val = A(2,3);           # 第2行第3列
row = A(2,:);           # 整行
col = A(:,3);           # 整列
sub = A(1:3, 2:4);      # 子矩阵
last = A(end);          # 最后一个元素(MATLAB-style)

# 创建辅助函数
I = eye(3);                     # 3x3 单位阵
Z = zeros(3,4);                 # 3x4 零矩阵
O = ones(2,2);                  # 2x2 全1阵
R = randmatrix(3,3);            # [0,1] 均匀随机
Rn = randnmatrix(3,3);          # 标准正态随机

# 维度与变形
s = size(A);            # [行数, 列数]
n = length(A);          # 总元素数
A = pinch(A);           # 去除单例维度
B = transpose(A);       # 转置
B = ctranspose(A);      # 共轭转置
C = inv(A);             # 矩阵求逆
D = mult(A,B);          # 矩阵乘法
E = A \ B;              # 解线性方程组
G = eig(A);             # 特征值

数据集操作:

lsf 复制代码
# 从监视器获取数据集
E = getresult("monitor", "E");      # 返回数据集
?E;                                  # 显示: "E vs x, y, z, lambda/f"

# 用点号提取数据
Ex = E.Ex;              # Ex 分量
x = E.x;                # x 位置向量
lambda = E.lambda;      # 波长向量

# 构造数据集
D = rectilineardataset;
D.addparameter("x", x_vec);
D.addparameter("y", y_vec);
D.addattribute("E", Ex_data, Ey_data, Ez_data);  # 矢量属性
D.addattribute("T", T_data);                      # 标量属性

⚠️ 数据集不可直接参与数学运算,必须先提取矩阵。

2.5 控制流

if-else:

lsf 复制代码
if (x < 5) {
    y = x^2;
} else if (x > 10) {
    y = 2*x;
} else {
    y = x;
}

# 逻辑组合
if ((a == 1) & (b == 2) | (c != 3)) { ... }

for 循环:

lsf 复制代码
# 单参数 --- 遍历向量
for (x = 1:100) { ?x; }

# 三参数 --- 初始化; 条件; 增量
for (i = 1; i <= 100; i = i + 1) { ... }

# while 等价写法(无 while 关键字)
x = 1;
for (0; x < 10; 0) {       # "0" 为占位符
    ?x;
    x = x + 1;
}

# 嵌套循环
for (i = 1:10) {
    for (j = 1:10) {
        A(i,j) = i*j;
    }
}

LSF 没有 breakcontinue。如需提前退出,需用条件控制循环条件。

try-catch 错误处理:

lsf 复制代码
try {
    run;
} catch (errMsg) {
    print(errMsg);
}

2.6 函数定义

lsf 复制代码
# 函数必须在全局作用域定义
function even_floor(a) {
    return floor(a) - mod(floor(a), 2);
}

# 多输入单输出
function add(a, b) {
    return a + b;
}

# 带参数校验的函数
function create_structure(params) {
    if (params.wg_width <= 0) {
        ?'Error: wg_width must be positive';
        return -1;
    }
    # 函数体...
    return result;
}

函数规则: 全局作用域定义;函数内不能嵌套定义函数;函数文件命名不能与函数名相同。

2.7 字符串操作

lsf 复制代码
# 创建与拼接
str = "hello world";
full = "hello" + " " + "world";     # 用 + 拼接

# 转换
num = str2num("3.14");              # 字符串转数字
s = num2str(3.14159);               # 数字转字符串
s = num2str(3.14159, 2);            # 保留2位小数

# 查找与提取
pos = findstring("hello world", "world");   # 返回 7
sub = substring("hello world", 7, 5);       # 返回 "world"
s = replace("hello world", 7, "WORLD");     # 返回 "hello WORLD"
s = replacestring("a,b,c", ",", ";");      # 返回 "a;b;c"
parts = splitstring("a,b,c", ",");          # 返回元胞数组
s = upper("hello");                 # "HELLO"
s = lower("HELLO");                 # "hello"

2.8 文件 I/O

lsf 复制代码
# 仿真文件
save("my_simulation.fsp");          # 保存 .fsp
load("my_simulation.fsp");          # 加载 .fsp
newproject;                          # 新建项目

# 数据文件
savedata("data.ldf", var1, var2);   # 保存 .ldf
loaddata("data.ldf");                # 加载 .ldf

# 文本文件
write("output.txt", "hello world"); # 写入文本
 data = readdata("input.txt");       # 读取文本

# JSON(自动加 .json 扩展名)
jsonsave("result", struct_var);     # 生成 result.json

# MATLAB(自动加 .mat 扩展名)
matlabsave("fields", fd);           # 生成 fields.mat
# ⚠️ 不要重复写扩展名:matlabsave("fields.mat", fd) → fields.mat.mat

# CSV
exportcsvresults("results.csv");

# 加载外部脚本
feval('materials.lsf');             # 执行 .lsf 文件
# ⚠️ feval 参数用 .lsf,不是 .txt

3. 工程代码规范与工作流

3.1 多文件组织

FDTD 仿真项目应按功能拆分为多个文件:

文件类型 命名示例 职责
材料库 materials.lsf 材料初始化函数
结构库 deep_etched_waveguide.lsf, grating.lsf 结构建模函数
FDTD 设置 fdtd_setup.lsf 仿真区域、端口、监视器配置
运行文件 run_sweep.lsf 参数定义、扫描循环、结果收集
Python 可视化 visualize_sweep.py 后处理与 HTML 报告生成

运行文件顶部加载库:

lsf 复制代码
# ============================================================
# 扫描运行文件
# ============================================================
feval('materials.lsf');
feval('deep_etched_waveguide.lsf');
feval('grating.lsf');
feval('fdtd_setup.lsf');

3.2 注释风格

lsf 复制代码
# ============================================================
# 文件头部 --- 用 = 分隔线
# 物理参数与坐标约定
# ============================================================

# ------------------------------------------------------------
# 子节分隔 --- 用 - 分隔线
# ------------------------------------------------------------

# 行内注释 --- 独立一行,中文描述物理含义
z_offset = bottom_clad_thickness + core_thickness / 2;

# 1. 步骤标记 --- 数字编号描述构建顺序
# 2. 创建下包层 (InP)
# 3. 创建稀释波导芯层

3.3 命名约定

类别 风格 示例
函数名 snake_case,动词开头 create_, init_, get_, generate_, setup_
对象名 snake_case,描述物理部件 input_core, top_cladding, grating_tooth_1
参数结构体 params 为主结构体 params.wg_length, params.core_thickness
物理尺寸 SI 单位(米),科学记数法 200e-9, 1e-6, 10e-6
材料名 数据库原名或描述标签 'Si (Silicon) - Palik', core_n3370
维度后缀 y→width, z→thickness, x→length wg_width, core_thickness

3.4 Z 坐标偏移约定

使用 z 偏移将波导芯层中心置于 z=0:

lsf 复制代码
z_offset = bottom_clad_thickness + core_thickness / 2;
# 所有 z_min/z_max 值都相对于此偏移量表达
# 实际设置时: 物理高度 - z_offset

3.5 材料初始化模式

始终先检查存在性再创建:

lsf 复制代码
# 动态命名材料(折射率编码到名称中)
core_mat_name = 'core_n' + num2str(round(n_core * 1000));
if (materialexists(core_mat_name) != 1) {
    core_mat = addmaterial('Sampled 3D data');
    setmaterial(core_mat, 'name', core_mat_name);
}
setmaterial(core_mat_name, 'max coefficients', 2);
setmaterial(core_mat_name, 'sampled data', core_data);
setmaterial(core_mat_name, 'color', [0.5, 1, 0.2, 1]);

Sampled 3D data 格式: [frequency(Hz), permittivity],其中 permittivity = (n + i*k)²,frequency = c / lambda。

lsf 复制代码
params.core_data = [c/1.5e-6, (3.380 + 0i)^2;
                    c/1.55e-6, (3.370 + 0i)^2;
                    c/1.6e-6, (3.360 + 0i)^2];

3.6 结构构建模式(多边形法)

标准 addpoly 流程:

lsf 复制代码
# 1. 定义顶点矩阵(相对于中心)
vertex = [
    -L/2,  width/2;
     L/2,  width/2;
     L/2, -width/2;
    -L/2, -width/2
];

# 2. 创建多边形并设置属性
addpoly;
set('name', 'object_name');
set('alpha', 0.9);                  # 透明度: core=0.9, clad=0.4, sub=0.3
set('vertices', vertex);
set('material', 'MaterialName');

# 3. 添加到组
addtogroup('group_name');

# 4. 选择并设置空间位置(必须在 addtogroup 之后)
select('group_name::object_name');
set('x', x_position);
set('y', y_position);
set('z min', z_bottom);
set('z max', z_top);
set('override mesh order from material database', 1);
set('mesh order', 2);               # core=2, clad/sub/fill=3

常用 alpha 值: core 层 0.9,cladding 0.4,substrate 0.3,fill 层 0.5-0.55

常用 mesh order: core 2,cladding/substrate/fill 3

3.7 参数扫描框架

lsf 复制代码
# ------------------------------------------------------------
# 扫描配置
# ------------------------------------------------------------
scan_param_name = 'grating_ridge_length';
scan_start = 200e-9;
scan_stop  = 800e-9;
scan_step  = 50e-9;
n_scan = round((scan_stop - scan_start) / scan_step) + 1;

# 输出目录保护
if (!exist('mat_output_dir')) {
    mat_output_dir = 'result_mats';
}

# ------------------------------------------------------------
# 扫描循环
# ------------------------------------------------------------
all_results = cell(n_scan);

for (i = 1:n_scan) {
    current_value = scan_start + (i - 1) * scan_step;
    
    # 复制并修改参数
    params = base_params;
    if (scan_param_name == 'grating_ridge_length') {
        params.grating_ridge_length = current_value;
        params.grating_period = params.grating_ridge_length + base_params.grating_slot_length;
        params.grating_duty_cycle = params.grating_ridge_length / params.grating_period;
    } else if (scan_param_name == 'n_periods') {
        params.n_periods = round(current_value);
    }
    # ... 其他参数分支 ...
    
    # 派生参数在运行时计算
    params.derived_param = params.some_field / 2 - params.other_field;
    
    # 文件名生成规则
    if (scan_param_name == 'n_periods' | scan_param_name == 'mesh_accuracy') {
        value_str = num2str(round(current_value));
    } else if (current_value >= 1) {
        value_str = num2str(round(current_value * 1000)) + 'um';
    } else {
        value_str = num2str(round(current_value * 1e9)) + 'nm';
    }
    
    # 重置环境
    switchtolayout;
    deleteall;
    
    # 构建与仿真
    create_structure(params);
    save('prefix_' + scan_param_name + '_' + value_str);    # ⚠️ 先 save
    run;                                                     # 后 run
    
    # 结果提取
    port_result = getresult('FDTD::ports::output_port', 'expansion for port monitor');
    T_net_value = port_result.T_net;        # 矢量:每频点一个值
    
    # 保存 .mat 场数据
    fd = struct;
    fd.Ex = getdata('monitor_xz', 'Ex');
    fd.x = getdata('monitor_xz', 'x');
    fd.z = getdata('monitor_xz', 'z');
    matlabsave('fields_' + scan_param_name + '_' + value_str, fd);
    
    # 保存 .json 结果
    result = struct;
    result.scan_index = i;
    result.transmission = T_net_value;
    jsonsave('result_' + scan_param_name + '_' + value_str, result);
    
    all_results{i} = result;
    switchtolayout;
}

# 保存汇总
summary = struct;
summary.scan_param_name = scan_param_name;
summary.results = all_results;
jsonsave('scan_summary_' + scan_param_name, summary);

4. FDTD 对象完整属性参考

4.1 属性发现与依赖机制

发现属性的方法: 创建对象后执行 ?get; 列出所有可用属性。

lsf 复制代码
addfdtd;    ?get;       # 列出 FDTD 区域所有属性
addrect;    ?get;       # 列出矩形所有属性
addport;    ?get;       # 列出端口所有属性

属性名必须与 GUI 完全一致 (含空格、大小写、特殊字符),用双引号包裹传给 set()/get()

Active vs Inactive 属性: 许多属性是条件激活的------当某个"主控"属性具有特定值时,依赖属性才可用。试图设置未激活属性会报错:"the requested property 'xxx' is inactive"

设置顺序原则:先设主控属性,再设依赖属性。

4.2 FDTD 仿真区域(addfdtd

General Tab:

属性 类型 说明
dimension Integer 1=2D, 2=3D
background index Float 背景介质折射率
background material String 背景材料名称(如 'SiO2 (Glass) - Palik'
simulation time Float 最大仿真时长(秒)
simulation temperature Float 温度(K)

Geometry Tab:

属性 类型 说明
x, y, z Float 中心位置
x min, x max Float X 边界
y min, y max Float Y 边界
z min, z max Float Z 边界
x span, y span, z span Float 各方向跨度

Mesh Settings Tab:

属性 类型 说明
mesh type String "auto non-uniform", "custom non-uniform", "uniform"
mesh accuracy Integer 1--8(仅 auto non-uniform 有效)
mesh cells x/y/z Integer 网格单元数(仅 custom/uniform 有效)
grading factor Float 网格渐变率 1--2(默认 sqrt(2))
mesh refinement String "conformal variant 0/1/2", "staircase"
dt stability factor Float Courant 限制分数(<1)
min mesh step Float 绝对最小网格步长

Boundary Conditions Tab:

属性 类型 说明
x min bc ~ z max bc String 边界条件字符串(见第1.3节)
allow symmetry on all boundaries Boolean 允许上下边界对称
set based on source angle Boolean 从光源角度自动设置 Bloch 矢量
kx, ky, kz Float Bloch 波矢分量
extend structure through pml Boolean 结构延伸穿过 PML(默认开)
pml profile Integer/Array 1=standard, 2=stabilized, 3=steep angle, 4=custom

Advanced Options(嵌套语法 ::):

属性 类型 说明
pml settings::type String "stretched coordinate""uniaxial anisotropic"
pml settings::kappa Float 归一化虚电导率
pml settings::sigma Float 最大归一化电导率
pml settings::layers Integer PML 层数
pml settings::polynomial Integer 电导率增长幂次
use early shutoff Boolean 自动关闭(能量衰减时)
auto shutoff min Float 自动关闭阈值
use divergence checking Boolean 发散检测
auto shutoff max Float 发散判定阈值
express mode Boolean GPU 仿真必须设为 1

4.3 矩形结构(addrect

属性 类型 说明
x, y, z Float 中心位置
x span, y span, z span Float 跨度
material String 材料名或 "<Object defined dielectric>"
index Float/String 折射率(仅 object-defined dielectric 时激活)。各向异性用分号:"1;1.5;1"
index units String "m", "um", "nm"(空间变化折射率)
override mesh order from material database Boolean 覆盖材料默认 mesh order
mesh order Integer mesh order(需先设 override=1)
alpha Float 渲染透明度 0--1
color opacity Float 颜色透明度
render type String "wireframe", "surface", "detailed"

属性依赖链:

lsf 复制代码
# 正确使用 object-defined dielectric
set('material', '<Object defined dielectric>');     # 主控属性
set('index', 1.5);                                   # 依赖属性 --- 现在可用
set('override mesh order from material database', 1); # 主控属性
set('mesh order', 2);                                # 依赖属性 --- 现在可用

4.4 模式光源(addmodesource

Modal Properties:

属性 类型 说明
injection axis String "x-axis", "y-axis", "z-axis"必须先设,决定可用几何参数
direction String "forward""backward"
amplitude Float 振幅
phase Float 相位(度)
mode selection String "fundamental mode", "fundamental TE mode", "fundamental TM mode", "user select"
selected mode numbers Vector 模式编号,如 (1:20)
number of field profile samples Integer 模式计算的频点数
bent waveguide Boolean 弯曲波导(默认 false)
bend radius Float 弯曲半径(需 bent waveguide=1)
bend orientation Integer 弯曲取向 1--3
multifrequency mode injection Boolean 多频模式注入

Advanced:

属性 类型 说明
eliminate discontinuity Boolean 平滑时间信号过渡
optimize for short pulse Boolean 最短脉冲(FDTD 默认开)

4.5 高斯光源(addgaussian

属性 类型 说明
injection axis String "x-axis", "y-axis", "z-axis"
direction String "forward""backward"
waist radius w0 Float 束腰半径(m)
distance from waist Float 束腰到注入面距离(m)
use scalar approximation Boolean 标量近似(默认开)
polarization angle Float 偏振角(度)

4.6 平面波光源(addplane

属性 类型 说明
injection axis String "x-axis", "y-axis", "z-axis"
direction String "forward""backward"
angle theta Float 入射角(度)
angle phi Float 方位角(度)
polarization angle Float 偏振角(度)

4.7 DFT 监视器(adddftmonitor / addpower

⚠️ 版本兼容性: 新版 Lumerical 使用 adddftmonitor,旧版使用 addpower/addprofile。若 adddftmonitor 报错不存在,回退到 addpower;

属性 类型 说明
monitor type String "2D X-normal", "2D Y-normal", "2D Z-normal", "3D", "Point", "Linear X/Y/Z"
override global monitor settings Boolean 主控:设为 true 才能设置以下频率属性
sample spacing String "uniform", "chebyshev", "custom"
use wavelength spacing Boolean 按波长间隔(需 override=1)
use source limits Boolean 使用光源频率范围(需 override=1)
frequency points Integer 频点数(需 override=1)
wavelength start Float 起始波长(需 use source limits=0)
wavelength stop Float 终止波长(需 use source limits=0)
x, y, z Float 中心位置
x span, y span, z span Float 跨度
down sample x/y/z Integer 空间降采样

正确设置顺序:

lsf 复制代码
adddftmonitor;  # 或 addpower(旧版)
set('name', 'transmission_monitor');
set('monitor type', '2D Y-normal');
set('x', 0); set('x span', 2e-6);
set('y', 5e-6); set('y span', 0);   # 2D Y-normal: y span = 0
set('z', 0); set('z span', 1e-6);

# 必须先开启 override
set('override global monitor settings', true);
set('use source limits', true);
set('use wavelength spacing', true);
set('frequency points', 101);

4.8 折射率监视器(addindex

属性与 DFT 监视器类似,主要属性:monitor type, override global monitor settings, use wavelength spacing, use source limits, frequency points, 以及几何属性。

4.9 模式扩展监视器(addmodeexpansion

属性 类型 说明
monitor type String "2D X-normal", "2D Y-normal", "2D Z-normal"
injection axis String "x-axis", "y-axis", "z-axis"
mode selection String "fundamental mode", "user select"
override global monitor settings Boolean 覆盖全局设置
auto update before analysis Boolean 分析前自动更新模式

必须与 DFT 监视器关联:

lsf 复制代码
adddftmonitor; set('name', 'dft');
# ... 设置 DFT 属性 ...

addmodeexpansion; set('name', 'mode_exp');
set('monitor type', '2D Y-normal');
setexpansion('mode_exp', 'dft');    # 关联 DFT 与模式扩展

4.10 端口(addport)--- FDTD 专属

Modal Properties:

属性 类型 说明
injection axis String "x-axis", "y-axis", "z-axis"先设
direction String "forward""backward"
amplitude Float 振幅
phase Float 相位(度)
mode selection String "fundamental mode", "user select"
selected mode numbers Vector (1:20)
number of field profile samples Integer 模式计算频点数
bent waveguide Boolean 弯曲波导
bend radius Float 弯曲半径(需 bent=1)
frequency dependent profile Boolean GPU 仿真必须设为 0
multifrequency mode injection Boolean 多频模式注入
number of trial modes Integer 搜索模式数

Impedance Tab:

属性 类型 说明
calculate characteristic impedance Boolean 计算特征阻抗 Z0
integration shape String "circular""rectangular"

端口结果访问:

lsf 复制代码
# 仿真后提取
S = getresult('port_1', 'S');           # S 参数
T = getresult('port_1', 'T');           # 透射率
neff = getresult('port_1', 'neff');     # 有效折射率
port_E = getresult('port_1', 'E');      # 模式场分布

# 注意:名称必须与 set('name', 'port_1') 完全一致

4.11 网格覆盖(addmesh

属性 类型 说明
override x mesh Boolean 启用 X 网格覆盖(主控
override y mesh Boolean 启用 Y 网格覆盖(主控
override z mesh Boolean 启用 Z 网格覆盖(主控
dx Float X 方向最大步长(需 override x mesh=1)
dy Float Y 方向最大步长(需 override y mesh=1)
dz Float Z 方向最大步长(需 override z mesh=1)
equivalent x index Float 等效折射率(dx 的替代)
based on a structure Boolean 基于结构定位
structure String 关联结构名(需 based on=1)
buffer Integer 结构周围缓冲单元数
x, y, z Float 中心位置(非 based on 时)
x span, y span, z span Float 跨度

4.12 电影监视器(addmovie

属性 类型 说明
monitor type String "2D X-normal", "2D Y-normal", "2D Z-normal"
x, y, z Float 中心位置
x span, y span, z span Float 跨度
down sample time Integer 时间降采样

5. 执行顺序与稳定性保障

5.1 黄金执行顺序

FDTD 仿真脚本必须遵循以下执行顺序,任何偏差都可能导致数据丢失或仿真失败:

lsf 复制代码
# ============================================================
# 标准执行顺序 --- 不可更改
# ============================================================

# 步骤 1: 新建项目(或加载已有)
newproject;
# 或: load("existing_project.fsp");

# 步骤 2: 初始化材料
feval('materials.lsf');

# 步骤 3: 构建结构
feval('structure.lsf');

# 步骤 4: 设置 FDTD 仿真区域
addfdtd;
set('dimension', 2);
set('x span', 10e-6); set('y span', 5e-6); set('z span', 2e-6);
set('mesh accuracy', 3);
set('simulation time', 1000e-15);
set('x min bc', 'PML'); set('x max bc', 'PML');
set('y min bc', 'PML'); set('y max bc', 'PML');
set('z min bc', 'PML'); set('z max bc', 'PML');
# GPU 必备:
set('express mode', 1);

# 步骤 5: 添加光源
addmodesource;
set('name', 'source');
set('injection axis', 'x-axis');
set('direction', 'forward');
set('x', -4e-6); set('y', 0); set('y span', 3e-6);
set('z', 0); set('z span', 1e-6);

# 步骤 6: 添加监视器
adddftmonitor;
set('name', 'monitor');
set('monitor type', '2D Y-normal');
set('override global monitor settings', true);
set('use source limits', true);
set('frequency points', 101);

# 步骤 7: 添加端口(如需要 S 参数)
addport;
set('name', 'input_port');
set('injection axis', 'x-axis');
set('direction', 'forward');
set('x', -3e-6); set('y', 0); set('y span', 8e-6);
set('z', 0); set('z span', 5e-6);
set('mode selection', 'user select');
set('selected mode numbers', (1:20));
# GPU 必备:
set('frequency dependent profile', 0);

# 步骤 8: 设置全局光源波长
setglobalsource('wavelength start', 1500e-9);
setglobalsource('wavelength stop', 1600e-9);

# 步骤 9: 【必须】保存项目
save("project_name");           # ⚠️ 必须先 save

# 步骤 10: 运行仿真
run;                             # 后 run

# 步骤 11: 提取结果
T = transmission("monitor");
port_result = getresult('FDTD::ports::input_port', 'expansion for port monitor');
T_net = port_result.T_net;

# 步骤 12: 保存结果
savedata("results.ldf", T);
jsonsave("result", result_struct);

# 步骤 13: 【如需修改】切换回布局模式
switchtolayout;                   # 之后才能修改对象

5.2 GPU 仿真三要素

使用 GPU 加速时必须同时满足以下三个条件,缺一不可:

要素 设置位置 命令
Express Mode FDTD 区域 set('express mode', 1);
关闭频变模式 每个端口 set('frequency dependent profile', 0);
先 save 再 run 全局 save('project_name');run; 之前

GPU 错误码 10: "there was an unknown parallel error. The error code is 10" 几乎总是以上三者之一未满足。

5.3 参数扫描执行流程

lsf 复制代码
for (i = 1:n_scan) {
    # 1. 切换布局并清空
    switchtolayout;
    deleteall;
    
    # 2. 重新构建结构
    create_structure(params);
    
    # 3. 设置 FDTD、光源、监视器、端口
    setup_fdtd(params);
    setup_ports(params);
    setup_monitors(params);
    
    # 4. 设置全局波长
    setglobalsource('wavelength start', params.lambda_min);
    setglobalsource('wavelength stop', params.lambda_max);
    
    # 5. 【必须】保存
    save('project_' + num2str(i));
    
    # 6. 运行
    run;
    
    # 7. 提取并保存结果
    extract_and_save_results(i);
    
    # 8. 准备下一次迭代
    switchtolayout;
}

5.4 稳定性检查清单

每次生成脚本后,对照以下清单检查:

  • save("name");run; 之前
  • GPU 时 set('express mode', 1); 已设置
  • GPU 时每个端口 set('frequency dependent profile', 0); 已设置
  • addfdtd; 后边界条件已设置(PML/Periodic 等)
  • 光源 injection axis 在几何属性之前设置
  • 端口 injection axis 在几何属性之前设置
  • 监视器 override global monitor settings = true 在频率属性之前
  • 网格覆盖 override x/y/z mesh = true 在 dx/dy/dz 之前
  • 对象 material = "<Object defined dielectric>"index 之前
  • switchtolayout; 在修改对象前(如果已运行过仿真)
  • run; 后使用 getresult/getdata 而非直接访问对象属性

6. 常见错误根因分析与修复

6.1 "syntax error"

根因 错误示例 正确写法
使用 endfor/endif endfor; } 关闭块
使用 end 关块 end; }
使用 Python def def myfunc(): function myfunc() { ... }
使用 MATLAB 函数语法 function out = myfunc() function myfunc() { return out; }
使用 && / ` `
使用 ~= if (x ~= 5) if (x != 5)
使用 % 注释 % comment # comment
使用 .* 元素乘法 A .* B A * B(同尺寸时元素级)
使用 % 变量 %var%(正确但易混淆) 推荐用下划线:my_var
使用 += 等复合赋值 x += 1; x = x + 1;
使用三元运算符 x = (a>b) ? c : d; 用 if-else
使用 clc clc; LSF 无此命令
缺少分号 x = 5 x = 5;
使用 j 作虚数 1+2j 1+2i

6.2 "xxx is not a valid function or variable name"

根因 错误示例 正确写法
变量名与命令冲突 set = 5; my_set = 5;
属性名当作变量 x span = 10e-6; x_span = 10e-6;%x span% = 10e-6;
版本不支持命令 adddftmonitor;(旧版) addpower;(旧版回退)
属性名用下划线 set("x_span", 10e-6); set("x span", 10e-6);

6.3 "argument list for set command is incorrect"

根因 错误示例 正确写法
属性名未加引号 set(x span, 10e-6); set("x span", 10e-6);
变量当属性名 set(x_span_fdtd, 10e-6); set("x span", x_span_fdtd);
参数数量不对 set("x span"); set("x span", 10e-6);
= 代替 , set("x span" = 10e-6); set("x span", 10e-6);

6.4 "the requested property 'xxx' is inactive"

这是最常见的运行时错误,根因是属性依赖链未按顺序设置。

监视器频率属性依赖链:

复制代码
override global monitor settings = true
    → use source limits [激活]
    → use wavelength spacing [激活]
    → frequency points [激活]
    → wavelength start/stop [激活,需 use source limits = false]

网格覆盖依赖链:

复制代码
override x mesh = true → dx [激活]
override y mesh = true → dy [激活]
override z mesh = true → dz [激活]

结构材料依赖链:

复制代码
material = "<Object defined dielectric>" → index [激活]
override mesh order from material database = 1 → mesh order [激活]

模式光源/端口依赖链:

复制代码
injection axis = "x-axis" → x, x span 可用(y, z 相关几何属性)
bent waveguide = 1 → bend radius [激活]

6.5 "index of A was out of range"

根因 错误示例 正确写法
0-based 索引 A(0) = 1; A(1) = 1;(LSF 是 1-based)
超界访问 A(5) = 1;(A 只有 4 个元素) 先预分配:A = zeros(1,10);
循环越界 for(i=1:100) A(i)=i;(A 只有 50) 预分配或动态增长
维度错误 A(i,j) 但 A 是 1D size(A); 检查维度

6.6 "d-card named xxx was not found"

根因 解决方案
对象名不匹配 检查 set('name', 'xxx')getresult('xxx', ...) 是否一致
仿真未运行 run; 必须在 getresult 之前
未先 save 再 run save('name'); 必须在 run; 之前
layout 模式访问数据 switchtolayout; 会清除数据,需先保存
结果名错误 ?getresult('monitor_name'); 查看可用结果
端口路径错误 端口结果路径:FDTD::ports::port_name

6.7 求解器命令混淆

❌ 错误命令(其他求解器) ✅ FDTD 正确做法
addperiodic; (DGTD) set('x min bc', 'Periodic'); 在 FDTD 区域上
addvoltagebc; (CHARGE) FDTD 不适用
addelectricalcontact; (CHARGE) FDTD 不适用
addemeport; (EME) addport;(FDTD 端口)
addmode; (MODE/FDE) addmodesource;addport;
addvarfdtd; (MODE) addfdtd;
addfde; (MODE) FDTD 不适用
adddgtdsolver; (DGTD) FDTD 不适用

6.8 GPU 相关错误

错误信息 根因 修复
Error GPU simulation cannot run without FDTD property 'express mode' 未开启 Express Mode set('express mode', 1);
Error GPU simulation does not support the frequency dependent profile option for ports 端口频变模式未关闭 set('frequency dependent profile', 0);
Error: there was an unknown parallel error. The error code is 10 以上任一 + 可能未 save 检查 express mode、frequency dependent profile、save

7. 结构构建模式速查

7.1 深刻蚀波导

层叠结构(自下而上):衬底 (InP) → 下包层 (InP) → 芯层 (动态材料) → 上包层 (InP),刻蚀区用 SiO2/Si3N4/BCB 填充。

lsf 复制代码
# Z 偏移计算
total_thickness = bottom_clad_thickness + core_thickness + top_clad_thickness;
z_offset = bottom_clad_thickness + core_thickness / 2;
z_etch_bottom = total_thickness - etch_thickness;

# 外侧分离逻辑(每层的刻蚀边界)
z_bottom_clad_outer_top = min([bottom_clad_thickness, max([z_etch_bottom, 0])]);
if (z_bottom_clad_outer_top > 0) {
    create_outer_block(group_name, 'bottom_clad_outer', ...);
}

7.2 光栅耦合器

光栅周期参数(互斥配置):

方案 1 --- ridge + slot 长度:

lsf 复制代码
params.grating_period = params.grating_ridge_length + base_params.grating_slot_length;
params.grating_duty_cycle = params.grating_ridge_length / params.grating_period;

方案 2 --- period + duty_cycle 直接:

lsf 复制代码
base_params.grating_period = 700e-9;
base_params.grating_duty_cycle = 0.99;

光栅实际长度:grating_actual_length = n_periods * grating_period + grating_period * grating_duty_cycle;

7.3 矩形多边形辅助函数

lsf 复制代码
function create_rect_poly(group_name, obj_name, x, y, z_min, z_max, width, x_length, material, mesh_order, alpha){
    vertex = [-x_length/2,  width/2; x_length/2,  width/2;
               x_length/2, -width/2; -x_length/2, -width/2];
    addpoly;
    set('name', obj_name);
    set('alpha', alpha);
    set('vertices', vertex);
    set('material', material);
    addtogroup(group_name);
    select(group_name + '::' + obj_name);
    set('x', x); set('y', y);
    set('z min', z_min); set('z max', z_max);
    set('override mesh order from material database', 1);
    set('mesh order', mesh_order);
}

7.4 渐变顶点生成

lsf 复制代码
function sine_profile(t) {
    return 0.5 * (1 - cos(pi * t));
}

function generate_taper_vertices(L, W_start, W_end, n_points) {
    vertices = matrix(n_points * 2, 2);
    for (i = 1:n_points) {
        t = (i - 1) / (n_points - 1);
        x = t * L;
        w = W_start * (1 - sine_profile(t)) + W_end * sine_profile(t);
        vertices(i, 1) = x;
        vertices(i, 2) = w / 2;
    }
    for (i = 1:n_points) {
        t = (n_points - i) / (n_points - 1);
        x = t * L;
        w = W_start * (1 - sine_profile(t)) + W_end * sine_profile(t);
        vertices(n_points + i, 1) = x;
        vertices(n_points + i, 2) = -w / 2;
    }
    return vertices;
}

8. Python 后处理规范

8.1 依赖包

python 复制代码
import json, sys, os, glob, re
from pathlib import Path
from datetime import datetime
from collections import OrderedDict
import numpy as np
from scipy.io import loadmat   # .mat v7 格式
import h5py                     # .mat v7.3 HDF5 格式
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.colors as pc

8.2 Lumerical JSON 解包

Lumerical 的 jsonsave() 生成嵌套结构,需解包:

python 复制代码
def _unwrap_lumerical_value(val):
    if isinstance(val, dict) and "_data" in val:
        data_arr = val["_data"]
        size = val.get("_size", [len(data_arr)])
        arr = np.asarray(data_arr, dtype=float)
        if len(size) > 1 and size[1] > 1:
            arr = arr.reshape(size, order='F')
        elif len(size) == 2 and size[1] == 1:
            arr = arr.reshape(size, order='F').flatten()
        return arr
    return val

def _unwrap_lumerical_results(data):
    if "summary" in data and isinstance(data["summary"], dict):
        data = data["summary"]
    results = data.get("results")
    if isinstance(results, dict) and "_data" in results:
        data = dict(data)
        data["results"] = results["_data"]
    return data

8.3 T_net 透射率提取

T_net 可能是 [n_freq, n_modes] 矩阵,默认取第一列(基模):

python 复制代码
def _extract_transmission_vector(trans):
    arr = np.asarray(trans, dtype=float)
    if arr.ndim == 2 and arr.shape[1] > 1:
        return arr[:, 0]    # 基模
    elif arr.ndim == 2 and arr.shape[1] == 1:
        return arr.flatten()
    return arr

8.4 .mat 文件多格式加载

python 复制代码
def load_field_mat(mat_path):
    # 先尝试 scipy (v7 格式)
    try:
        mat = loadmat(mat_path)
        if 'fd' in mat:
            fd = mat['fd']
            while isinstance(fd, np.ndarray) and fd.shape == (1, 1):
                fd = fd[0, 0]
            # 从 struct 提取字段
            Ex = _to_array(fd['Ex']) if 'Ex' in fd.dtype.names else None
            return {"Ex": Ex, ...}
    except (NotImplementedError, ImportError):
        pass
    
    # 回退到 h5py (v7.3 HDF5)
    with h5py.File(mat_path, 'r') as f:
        if 'fd' in f:
            fd = f['fd']
            # 读取数据集...

9. 快速参考表

9.1 边界条件字符串

类型
PML "PML"
Metal (PEC) "Metal"
PMC "PMC"
Periodic "Periodic"
Bloch "Bloch"
Symmetric "Symmetric"
Anti-Symmetric "Anti-Symmetric"

9.2 注入轴字符串

X "x-axis"
Y "y-axis"
Z "z-axis"

9.3 方向字符串

方向
正向 "forward"
反向 "backward"

9.4 监视器类型字符串

类型
2D X-法向 "2D X-normal"
2D Y-法向 "2D Y-normal"
2D Z-法向 "2D Z-normal"
3D "3D"
"Point"
线性 X "Linear X"
线性 Y "Linear Y"
线性 Z "Linear Z"

9.5 模式选择字符串

选择
基模 "fundamental mode"
基模 TE "fundamental TE mode"
基模 TM "fundamental TM mode"
用户选择 "user select"

9.6 PML 配置文件

类型 整数值
Standard 1
Stabilized 2
Steep angle 3
Custom 4

9.7 常用材料名

lsf 复制代码
"Si (Silicon) - Palik"
"SiO2 (Glass) - Palik"
"Si3N4 (Silicon Nitride) - Luke"
"Au (Gold) - CRC"
"Ag (Silver) - CRC"
"Al (Aluminum) - CRC"
"InP (Indium Phosphide) - Palik"
"GaAs (Gallium Arsenide) - Palik"
"TiO2 (Titanium Dioxide) - Siefke"
"<Object defined dielectric>"   # 用户自定义折射率

9.8 求解器兼容性矩阵

命令 FDTD MODE DGTD CHARGE HEAT FEEM INTERCONNECT
addfdtd
addport
addmodesource
adddftmonitor
addindex
addmodeexpansion
addmesh
getfdtdindex
transmission
farfield2d
grating
addperiodic
addemeport
addvoltagebc

10. AI 代码生成铁律(25 条)

  1. 只用 LSF 语法 ,绝不混用 MATLAB 或 Python 语法。禁止 .*&&||endforenddefimport+=

  2. 每条语句以 ; 结尾 。用 ?expr; 仅在需要显式输出时。

  3. 数组索引 1-based 。第一个元素是 A(1),永远不是 A(0)

  4. 属性名用 GUI 原名(含空格),双引号包裹 。如 set("x span", 10e-6);。属性名 ≠ 变量名。

  5. 变量名用下划线,不用空格 。如 x_span_value = 10e-6;。不要把变量名和属性名搞混。

  6. 先设主控属性,再设依赖属性 。如 override global monitor settings = true 在 use source limits 之前。

  7. 创建对象后用 ?get; 查看全部属性,确认属性名拼写和依赖关系。

  8. save("name"); 必须在 run; 之前。否则仿真数据可能无法写入。

  9. GPU 三要素缺一不可express mode = 1、端口 frequency dependent profile = 0、saverun 前。

  10. 修改对象前调用 switchtolayout;(如果已经运行过仿真)。

  11. 复数用 i1+2i),不用 j

  12. 字符串用双引号 "str"(单引号也可,双引号优先)。

  13. LSF 无 breakcontinue。用条件控制循环条件代替。

  14. 错误处理用 try { ... } catch (err) { ... }

  15. 矩阵纵向拼接 [A; B],横向拼接 [A, B]

  16. 数据集不可直接数学运算,先用点号提取矩阵。

  17. adddftmonitor 不存在时回退到 addpower(旧版 Lumerical)。

  18. 端口结果访问用 FDTD::ports::port_name 路径 ,名称必须与 set('name', ...) 完全一致。

  19. 光源波长通常全局设置 setglobalsource('wavelength start', ...),非单光源设置。

  20. feval('file.lsf') 参数用 .lsf ,不用 .txt

  21. jsonsave('filename', data)matlabsave('filename', data) 自动加扩展名 ,不要在参数里写 .json.mat

  22. max([a, b])min([a, b]) 必须用方括号包裹多参数max(a, b) 是错的。

  23. T_net 是矢量/矩阵(每频点一个值),不是标量。提取时注意维度。

  24. exist('varname') 返回 0(不存在)或 1(存在) 。用于变量保护:if (!exist('var')) { var = default; }

  25. round(value, n) 语法 。保留 n 位小数用 round(value * 10^n) / 10^n

相关推荐
劈星斩月2 小时前
机器学习、深度学习,向“人类大脑”抄作业
人工智能·深度学习·机器学习
深圳市机智人激光雷达2 小时前
空间几何解算与数字孪生:激光雷达在电力输电通道巡检中的核心机理
人工智能·机器学习·机器人·自动驾驶·无人机
宝贝儿好3 小时前
【LLM】第四章:项目实操案例:文本情感分析
人工智能·深度学习·神经网络·机器学习·自然语言处理·lstm
数智工坊4 小时前
周志华《Machine Learning》学习笔记--第九章--聚类
笔记·学习·机器学习
专注搞钱4 小时前
半导体MES智能化升级方案:基于机器学习与Transformer大模型落地实战手册
人工智能·机器学习·transformer
Eloudy4 小时前
光子的单缝衍射模型
线性代数·机器学习·概率论
dd0124 小时前
从标签平滑到不确定性建模:SoftLabel如何重塑机器认知边界
机器学习·医疗影像诊断·不确定性建模·softlabel
weixin_4296302613 小时前
3.49 HVLF:一种跨场景的整体视觉定位框架
深度学习·机器学习·计算机视觉
深圳市机智人激光雷达14 小时前
技术筑牢安全冗余:激光雷达在自动驾驶高阶感知中的底层价值与范式演进
人工智能·安全·机器学习·3d·机器人·自动驾驶·无人机