# OpticsFEM 完整使用说明与代码介绍

| 项目 | 说明 |
|------|------|
| 文档版本 | v3.0 |
| 编制日期 | 2026-06-09 |
| 适用代码 | **`3D opticsfem-master/`**（三维版，主算例 FemType=4 散射 + FemType=5 本征频率） |
| 适用平台 | Windows x64，**Visual Studio 2026（18）**，MSVC |
| 关联文档 | `compare/README.md`（COMSOL 对比）、上级目录 2D 版 `opticsfem-master/` |

---

## 目录

1. [程序概述](#1-程序概述)
2. [目录与文件总览](#2-目录与文件总览)
3. [各模块代码详解](#3-各模块代码详解)
4. [软件架构与执行流程](#4-软件架构与执行流程)
5. [完整使用说明](#5-完整使用说明)
6. [输入输出文件规范](#6-输入输出文件规范)
7. [对外 API 与集成方式](#7-对外-api-与集成方式)
8. [测试算例与数据集](#8-测试算例与数据集)
9. [代码阅读路径](#9-代码阅读路径)
10. [常见问题排查](#10-常见问题排查)

---

## 1. 程序概述

### 1.1 程序定位

**OpticsFEM3D** 是一套基于 C++ 实现的**三维矢量有限元（FEM）光学电磁仿真内核**。程序采用 **一阶 Nedelec 边元** 离散麦克斯韦方程，通过 JSON 配置物理模型、材料与边界条件，通过 `.dat` 文本文件读入四面体网格，计算结果以文本文件输出。

> **当前三维主算例**：
> - **FemType = 4**：三维 SBC 散射，`sbc3d.json`，网格 `SBCmesh.dat`，完整求解流程。
> - **FemType = 5**：三维本征频率，`eigen3d.json`，同一网格，当前完成 A/B 矩阵组装与导出。

### 1.2 支持的问题类型

| FemType | 问题类型 | 驱动类 | 网格 | 求解器 | 后处理 | 状态 |
|---------|----------|--------|------|--------|--------|------|
| 0 | 本征模式（2D 遗留） | `OpticsFEM_2D_EigenMode` | `Mesh_2D` | `Solver_EigenMode` | `Post_2D_EigenMode` | 遗留 |
| 1 | 本征频率（2D 遗留） | `OpticsFEM_2D_EigenFreq` | `Mesh_2D` | `Solver_EigenFreq` | `Post_2D_EigenFreq` | 遗留 |
| 2 | 2D 散射（按波长 λ） | `OpticsFEM_2D_Scatter` | `Mesh_2D` | `Solver_LdaDom` | `Post_2D_Scatter` | 遗留 |
| 3 | 2D 散射（按频率 f） | `OpticsFEM_2D_Scatter` | `Mesh_2D` | `Solver_LdaDom` | `Post_2D_Scatter` | 遗留 |
| **4** | **3D 一阶散射（SBC，按 λ）** | **`OpticsFEM_3D_Scatter`** | **`Mesh_3D`** | **`Solver_LdaDom`** | **`Post_3D_Scatter`** | **完整** |
| **5** | **3D 一阶本征频率** | **`OpticsFEM_3D_EigenFreq`** | **`Mesh_3D`** | **`Solver_EigenFreq`** | **`Post_3D_EigenFreq`** | **组装+矩阵导出** |

### 1.3 设计原则

- **单一 API 入口**：外部只需调用 `OpticsFEM_All()`，无需感知内部分支。
- **JSON 为配置语言**：物理、材料、边界、求解参数均通过 JSON 传递。
- **前后端解耦**：`Test_Main.cpp` 可替换为 GUI、脚本或 DLL 宿主，接口不变。
- **模块化分层**：网格 → 物理/材料 → 组装 → 求解 → 后处理，各层独立。

### 1.4 第三方依赖（源码内嵌）

| 依赖 | 路径 | 用途 |
|------|------|------|
| Eigen | `Eigen/` | 稠密/稀疏矩阵运算（337 个头文件，header-only） |
| nlohmann/json | `nlohmann/` | JSON 解析 |
| muparserX 派生库 | `parser/` | BELE、SBC、端口等边界表达式求值 |

### 1.5 运行时外部依赖

| FemType | 依赖 | 说明 |
|---------|------|------|
| **4（3D 散射）** | `complex/complexsolver.exe` | **CMake 自动编译**（Eigen SparseLU），求解 **A·x=b** |
| **5（3D 本征频率）** | 暂无（矩阵导出阶段） | 当前仅 `Assemble` + `Test_OutputMatrix`；完整求解需 `real_solver/`、`complex_solver/` |
| 0–3（2D 遗留） | `complex/complexsolver.exe` 等 | 本征问题另需 `real_solver/`、`complex_solver/` |

散射求解器通过**临时 `.dat` 文件**与主程序交换 CSR 格式矩阵，由 `system()` 启动。

---

## 2. 目录与文件总览

```
3D opticsfem-master/
├── CMakeLists.txt              # CMake：OpticsFEM + complexsolver
├── CMakeSettings.json          # VS CMake 设置（x64-Release）
├── sbc3d.json                  # ★ FemType=4 散射算例配置
├── eigen3d.json                # ★ FemType=5 本征频率算例配置
├── SBCmesh.dat                 # ★ 三维四面体网格（散射与本征共用）
├── Interface/                  # 对外 API（FemType 路由）
├── test/                       # Test_Main.cpp 入口、JSON 解析
├── complex/                    # complexsolver 源码（Eigen 稀疏求解）
├── compare/                    # MATLAB：COMSOL vs OpticsFEM 切面对比
├── phy/                        # 物理模型与边界条件
├── material/                   # 材料库
├── mesh/                       # Mesh_2D + Mesh_3D 读写
├── kernel/                     # 2D/3D 组装（散射 SBC + 本征 A/B）
├── solver/                     # 数值求解器接口
├── post/                       # Post_3D_Scatter / Post_3D_EigenFreq
├── function/                   # Nedelec 基函数与高斯积分
├── common/                     # 公共常量
├── parser/                     # 表达式解析器
├── nlohmann/                   # JSON 库
├── Eigen/                      # 线性代数库
├── scat3D/                     # 推荐：FemType=4 本地 CMake 构建（不上传）
└── eigen3D/                    # 推荐：FemType=5 本地 CMake 构建（不上传）
```

**源码统计（不含 scat3D/、eigen3D/、build/ 等构建目录）：**

| 类别 | 数量 | 说明 |
|------|------|------|
| 业务源文件 `.cpp` | 约 35 个 | 组装、求解、后处理等核心逻辑 |
| 业务头文件 `.h` | 约 20 个 | 类声明与接口 |
| parser 模块 | 约 89 个 | muparserX 表达式引擎 |
| Eigen 第三方 | 337 个 | 仅头文件，不参与业务修改 |
| **合计参与编译** | 约 70+ `.cpp` | 链接为单一 `OpticsFEM.exe` |

---

## 3. 各模块代码详解

### 3.1 Interface/ — 对外 API

| 文件 | 说明 |
|------|------|
| `FEM_Interface.h` | 定义 `OpticsFEMData` 结构体与 `OpticsFEM_API` 类；预留 `extern "C"` DLL 导出注释 |
| `FEM_Interface.cpp` | **核心调度器**：解析 JSON 中 `FemType`，创建对应 FEM 驱动/求解器/后处理对象，执行 Assemble → Run → Post 全流程 |

**关键函数：**

```cpp
struct OpticsFEMData {
    double test1;   // 保留字段
    double test2;   // 保留字段
    char*  data;    // UTF-8 JSON 字符串
};

class OpticsFEM_API {
public:
    static int OpticsFEM_All(OpticsFEMData data);  // 完整求解
    int OpticsFEM_Test(OpticsFEMData data);        // 连通性测试
};
```

**返回值：** 0 = FemType 无法识别；1 = 2D 本征模式；2 = 2D 本征频率；3 = 2D 散射；**4 = 3D 散射完成**；**5 = 3D 本征频率矩阵导出完成**。

---

### 3.2 test/ — 入口与数据解析

| 文件 | 说明 |
|------|------|
| `Test_Main.cpp` | 进程 `main()` 入口：从 JSON 文件（默认 `sbc3d.json`）读取整行 JSON，封装为 `OpticsFEMData`，调用 `OpticsFEM_All()`。本征算例改为 `eigen3d.json` 后须重新编译 |
| `Test_ReadData.cpp` | 实现 `Phy_WaveOpticsModel::Test_ReadData()` 与 `MaterialLib::Test_ReadData()`，将 JSON 字段映射到内存对象 |
| `Test_OutputData.cpp` | 调试用途：将组装后的稀疏矩阵 A/B/P 输出到文本文件 |
| `interfaceClass.h` | 遗留的 `FemInput` 结构体，记录预期配置字段（当前 JSON 路径未直接使用） |

**注意：** `Test_Main.cpp` 中声明的 `Phy_WaveOpticsModel`、`MaterialLib` 等对象在 `main()` 内未被直接使用；实际实例化在 `FEM_Interface.cpp` 中完成。注释块（第 39–58 行）保留了手动分步调用的旧版写法。

---

### 3.3 phy/ — 物理模型与边界条件

| 文件 | 说明 |
|------|------|
| `Phy_Base.h` | `Phy_WaveOpticsModel` 类声明：存储 PMC/PEC/PBC/PML/SBC/ELE/MAG/SCD/MPD/EPD/BELE/端口/高斯光束等边界数据及访问接口 |
| `Phy_Base.cpp` | 构造函数与各边界查询 getter 实现 |
| `Phy_Interface.cpp` | `GetPhy()` 占位桩 |

**BoundaryFlag 编码（`Test_ReadData.cpp`）：**

| 值 | 边界类型 |
|----|----------|
| 0 | PMC（理想磁导体） |
| 1 | PEC（理想电导体） |
| 2 | SBC（散射边界条件） |
| 3 | ELE（电场 Dirichlet 边界） |
| 4 | PBC（周期边界，成对计数） |
| 8 | MAG（磁场边界） |
| 9 | SCD（面电流密度） |

**支持的 JSON 边界扩展块：** `sbc`、`ef`、`mag`、`scd`、`pbc`、`mpd`、`epd`、`bele`、`pml`、`port`、`beam`（均为可选，按 `js.contains()` 判定是否解析）。

---

### 3.4 material/ — 材料库

| 文件 | 说明 |
|------|------|
| `Material_Base.h` | `Material`（单材料张量属性）与 `MaterialLib`（按物理域索引的材料库） |
| `Material_Base.cpp` | 材料属性 setter/getter |
| `Material_Interface.cpp` | `MaterialLib::SetMat()`、`SetNumberMat()`，材料类型分发（各向同性 ε/μ 或 n,k 折射率） |

**材料 JSON 字段：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `NbrDomain` | int | 物理域数量 |
| `matType` | int[] | 0 = ε/μ 张量；1 = n,k 折射率 |
| `epsilonrR/I` | double[] | 相对介电常数实部/虚部 |
| `murR/I` | double[] | 相对磁导率 |
| `sigma` | double[] | 电导率 |
| `chiheR/I`, `chiehR/I` | double[] | 磁电耦合张量 |
| `n`, `k` | double[] | 折射率（matType=1 时，ε = (n+ik)²） |

---

### 3.5 mesh/ — 网格

| 文件 | 说明 |
|------|------|
| `Mesh_Base.h` | `Mesh_2D`（三角形、边、边界域）与 `Mesh_3D`（四面体、棱柱，部分实现）数据结构及查询 API |
| `Mesh_Base.cpp` | 顶点、边、单元、域编号等基本访问器 |
| `Mesh_Interface.cpp` | `Mesh_2D::GetMesh()`：顺序解析 `.dat` 网格文件 |
| `Mesh_Find.cpp` | 域/PBC 索引查找：边/节点所属域、PBC 源/目标映射 |

**Mesh_3D** 已接入 `FemType=4`（散射）与 `FemType=5`（本征频率），读入 `SBCmesh.dat` 等三维四面体网格。

---

### 3.6 kernel/ — FEM 组装

| 文件 | 说明 |
|------|------|
| `Assemble_Base.h` | 声明全部 `OpticsFEM_*` 驱动类（2D 本征模式/频率/散射，3D 本征频率/散射） |
| `Assemble_Base.cpp` | 依赖注入（`GetMaterial`、`GetMesh` 等），各驱动的 `Run()`/`Post()` 实现 |
| `Assemble_kernel.cpp` | 各问题类型顶层 `Assemble()`：实/复矩阵选择、DOF 规模、边界分发 |
| `Assemble_EigenMode_Equation.cpp` | 2D 本征模式体积积分（curl-curl + 质量矩阵） |
| `Assemble_EigenMode_Boundary.cpp` | 本征模式 PEC/PBC 约束 |
| `Assemble_EigenFreq_Equation.cpp` | 2D/3D 本征频率体积积分 |
| `Assemble_EigenFreq_Boundary.cpp` | 本征频率 PEC/PBC |
| `Assemble_Scatter_Equation.cpp` | 散射问题驱动麦克斯韦弱形式体积积分 |
| `Assemble_Scatter_2D_Boundary.cpp` | 2D 边界项：SBC、BELE、PML、PEC/ELE、PBC、端口、MPD/EPD、MAG、SCD |
| `Assemble_Scatter_3D_Boundary.cpp` | 3D 边界组装（SBC、PEC/ELE，部分实现） |

**Assemble 阶段输出：** 稀疏矩阵 **A**、右端向量 **b**、预处理矩阵 **P**（实数或复数，由 PML/SBC/复材料等条件自动判定）。

---

### 3.7 solver/ — 数值求解

| 文件 | 说明 |
|------|------|
| `Solver_Base.h` | `Solver_EigenMode`、`Solver_EigenFreq`、`Solver_LdaDom` 类及稀疏矩阵参数结构 |
| `Solver_Base.cpp` | 简单 getter（`GetNbrMode`、`GetLda0`、`GetElectricType` 等） |
| `Solver_Interface.cpp` | JSON 求解参数解析，`SetParam`/`Run` 实现，调用特征值或线性求解器 |
| `eigen_solver.h` | 广义特征值求解 C API 声明（实/复 CSR 格式） |
| `eigen_solver.cpp` | 将矩阵写入 `./real_solver/` 或 `./complex_solver/` 临时文件，启动外部特征值求解器，读回结果 |
| `interface.h` | `solveRealLinearEqu`、`solveComplexLinearEqu` 声明 |
| `interface.cpp` | 通过临时 `.dat` 文件调用 `complex/complexsolver.exe` 等外部线性求解器 |
| `framework.h` | Windows DLL 风格求解器接口头 |

**求解器分层：**

| 层级 | 模块 | 适用问题 | 运行时依赖 |
|------|------|----------|------------|
| 特征值 | `eigen_solver.cpp` | FemType 0, 1 | `real_solver/real`, `complex_solver/complex` |
| 线性（实） | `interface.cpp` | 实散射 | `real/realsolver.exe` |
| 线性（复） | `interface.cpp` | 复散射 | `complex/complexsolver.exe` |

当前工程通过宏 `EIGENSOLVER_STATIC` 将 `eigen_solver.cpp` 静态编入可执行文件，**不再依赖** `lib/eigensolver.lib`。

---

### 3.8 post/ — 后处理

| 文件 | 说明 |
|------|------|
| `Post_Base.h` | `Post_2D_EigenMode`、`Post_2D_EigenFreq`、`Post_2D_Scatter` 及 3D 后处理类声明 |
| `Post_Base.cpp` | `GetMesh`/`GetSolver`/`GetResult`/`GetPhy` 接线 |
| `Post_CalEletric.cpp` | 利用 Nedelec 基函数将边/顶点 DOF 重构为顶点 Ex/Ey/Ez |
| `Post_GetEb.cpp` | 在网格顶点处用 muparser 求值 BELE 解析背景场 |
| `Post_Output.cpp` | 写入 `neff`/`freq`/`Ex`/`Ey`/`Ez`/`normE` 文本文件 |
| `Post_Power.cpp` | `GetPower()` 占位（本征模式返回 0） |

---

### 3.9 function/ — 基函数与高斯积分

| 文件 | 说明 |
|------|------|
| `BF.h` / `BF.cpp` | `BF` 分发类：按单元类型选择并求值基函数 |
| `BF_Line.cpp` | 一维 Lagrange 基函数及梯度/curl |
| `BF_Triangle.cpp` | 二维三角形 Lagrange 与 Nedelec（1 阶）基函数及 curl |
| `BF_Quadrangle.cpp` | 二维四边形 Lagrange/Nedelec 基函数 |
| `BF_Tetrahedron.cpp` | 三维四面体 Nedelec 基函数及 curl |
| `BF_Prism.cpp` | 三维棱柱 Nedelec 基函数及 curl |
| `Gauss.h` / `Gauss.cpp` | `Gauss` 类：按单元类型与阶次选择积分规则 |
| `Gauss_Line.h` | 线段高斯点/权重 |
| `Gauss_Triangle.h` | 三角形高斯点/权重 |
| `Gauss_Quadrangle.h` | 四边形高斯点/权重 |
| `Gauss_Tetrahedron.h` | 四面体高斯点/权重 |
| `Gauss_Prism.h` | 棱柱高斯点/权重 |

---

### 3.10 common/ — 公共定义

| 文件 | 说明 |
|------|------|
| `define.h` | 几何/网格/基函数/材料/物理常量（`c_const`、`Pi`、单元类型、边界标志等） |
| `util.h` / `util.cpp` | 数值 clamp、快速排序、唯一索引等网格/组装辅助工具 |

---

### 3.11 parser/ — 数学表达式解析器（muparserX）

共约 **89 个** `.cpp`/`.h` 文件，为 vendored **muparserX** 分支，用于求值 BELE、SBC、端口等边界上的字符串表达式（如 `"sin(2*pi*x)"`）。

| 分组 | 代表文件 | 作用 |
|------|----------|------|
| 核心引擎 | `mpParser.*`, `mpParserBase.*`, `mpRPN.*`, `mpTokenReader.*`, `mpScriptTokens.*` | 表达式 → RPN → 求值 |
| 值系统 | `mpValue.*`, `mpValueCache.*`, `mpVariable.*`, `mpValReader.*` | 类型化值存储、变量、缓存 |
| 函数库 | `mpFuncCommon/Cmplx/NonCmplx/Matrix/Str.*` | 内置数学/字符串/矩阵函数 |
| 运算符 | `mpOprtBinCommon/Assign/Shortcut/Cmplx/NonCmplx/Matrix/Index/PostfixCommon.*` | 二元/一元/后缀运算符 |
| 注册包 | `mpPackageCommon/Cmplx/NonCmplx/Matrix/Str/Unit.*` | 函数与运算符注册 |
| 插件接口 | `mpICallback.*`, `mpIOprt.*`, `mpIPackage.*`, `mpIValue.*`, `mpIToken.*`, `mpIValReader.*` | 扩展接口 |
| 辅助 | `mpError.*`, `mpIfThenElse.*`, `mpMatrix.*`, `mpTest.*`, `mpDefines.h`, `mpCompat.h`, `mpFwdDecl.h`, `mpTypes.h`, `mpStack.h`, `suSortPred.h`, `suStringTokens.h`, `utGeneric.h` | 错误处理、条件分支、矩阵类型、诊断 |

**一般用户无需修改此模块。**

---

### 3.12 nlohmann/ — JSON 库

| 文件 | 说明 |
|------|------|
| `json.hpp` | nlohmann JSON 单头文件完整实现 |
| `json_fwd.hpp` | 前向声明，加速编译 |

---

### 3.13 Eigen/ — 线性代数库

337 个头文件，header-only 第三方库。主要模块：`Core`、`Dense`、`Sparse`、`SparseCore`、`Eigenvalues`、`LU`、`QR`、`SVD`、`Geometry` 等。全项目矩阵运算与稀疏组装均依赖 Eigen。

**一般用户无需修改此模块。**

---

### 3.14 根目录构建文件

| 文件 | 说明 |
|------|------|
| `CMakeLists.txt` | 定义 `OpticsFEM` 可执行目标，列出全部源文件分组（PARSER/COMMON/GAUSS/BF/MESH/MATERIAL/PHY/SOLVER/POST/KERNEL/TEST/INTERFACE），设置 C++17 与 `EIGENSOLVER_STATIC` |
| `CMakeSettings.json` | Visual Studio 中 CMake 配置（生成器、架构等） |

---

## 4. 软件架构与执行流程

### 4.1 模块依赖关系

```
Test_Main.cpp
      │
      ▼
FEM_Interface.cpp  ──►  Phy / Material / Mesh（读入）
      │
      ├── FemType 0 ──► OpticsFEM_2D_EigenMode ──► Solver_EigenMode ──► Post_2D_EigenMode
      ├── FemType 1 ──► OpticsFEM_2D_EigenFreq  ──► Solver_EigenFreq  ──► Post_2D_EigenFreq
      ├── FemType 2/3 ► OpticsFEM_2D_Scatter   ──► Solver_LdaDom     ──► Post_2D_Scatter
      ├── FemType 4 ──► OpticsFEM_3D_Scatter   ──► Solver_LdaDom     ──► Post_3D_Scatter
      └── FemType 5 ──► OpticsFEM_3D_EigenFreq ──► Solver_EigenFreq  ──► Post_3D_EigenFreq
                              │
                              └── Mesh_3D ← SBCmesh.dat
                              │
                              ├── kernel（Assemble：体积 + 边界积分）
                              ├── function（BF + Gauss 数值积分）
                              └── parser（边界表达式求值）
```

### 4.2 完整调用序列（FemType=4，三维 SBC 散射）

```
Test_Main.cpp
  └─ 读取 sbc3d.json
       └─ OpticsFEM_All(data)
            └─ [FemType == 4]
                 ├─ Phy / Material ← JSON（含 sbc 块）
                 ├─ Mesh_3D::GetMesh("SBCmesh.dat")
                 ├─ OpticsFEM_3D_Scatter::Assemble()
                 │     ├─ Assemble_WaveEquation()
                 │     └─ Assemble_SBC()        SBCType 0 出射 + 1 入射
                 ├─ Run() → complex/complexsolver.exe
                 └─ Post("OutFile") → Ex, Ey, Ez, normE
```

### 4.2b 完整调用序列（FemType=5，三维本征频率）

```
Test_Main.cpp
  └─ 读取 eigen3d.json
       └─ OpticsFEM_All(data)
            └─ [FemType == 5]
                 ├─ Phy / Material ← JSON（PMC/PEC/PBC 边界）
                 ├─ Mesh_3D::GetMesh("SBCmesh.dat")
                 ├─ OpticsFEM_3D_EigenFreq::Assemble()
                 │     ├─ Assemble_WaveEquation()   A=curl-curl, B=ε·质量
                 │     └─ Assemble_PEC_PBC()        边界约束矩阵 P
                 └─ Test_OutputMatrix("OutFile") → Ai/Aj/Av, Bi/Bj/Bv
                 （Run/Post 待接入：eigs 求 λ，再重构 Ex/Ey/Ez/freq）
```

### 4.3 完整调用序列（FemType=2，二维散射，遗留）

```
main()
  └─ OpticsFEM_API::OpticsFEM_All(data)
       ├─ json::parse(data.data)
       ├─ Phy_WaveOpticsModel::Test_ReadData(str)
       ├─ MaterialLib::Test_ReadData(str)
       ├─ Mesh_2D::GetMesh(meshFile, str)
       └─ [FemType == 2]
            ├─ Solver_LdaDom::GetSolver(str)
            ├─ OpticsFEM_2D_Scatter::GetMaterial / GetMesh / GetPhy / GetSolver / GetPost
            ├─ OpticsFEM_2D_Scatter::Assemble()
            │     ├─ Assemble_WaveEquation()      体积积分
            │     ├─ Assemble_PEC_ELE()           理想导体/电边界
            │     ├─ Assemble_PBC()               周期边界
            │     ├─ Assemble_BELE()              边界等效源
            │     ├─ Assemble_PML()               完美匹配层
            │     └─ Assemble_Port() 等           端口激励
            ├─ OpticsFEM_2D_Scatter::Run()
            │     └─ Solver_LdaDom::Run() → solveComplexLinearEqu()
            └─ OpticsFEM_2D_Scatter::Post(outFile)
                  ├─ GetElectric()               DOF → 顶点 Ex/Ey/Ez
                  └─ OutputData()                写入 OutFile/
```

### 4.4 数据流

**FemType = 4（三维散射）：**

```
sbc3d.json ──► Phy（sbc 边界/入射场）
          ──► MaterialLib（epsilonrR 等）
SBCmesh.dat ──► Mesh_3D（四面体 + 三角边界）
          ──► Assemble ──► 稀疏矩阵 A, 向量 b
          ──► complexsolver ──► 解向量 x
          ──► Post ──► OutFile/Ex, Ey, Ez, normE
```

**FemType = 5（三维本征频率）：**

```
eigen3d.json ──► Phy（PMC/PEC/PBC）
            ──► MaterialLib
SBCmesh.dat ──► Mesh_3D
            ──► Assemble ──► 稀疏矩阵 A（刚度）, B（质量）
            ──► Test_OutputMatrix ──► OutFile/Ai,Aj,Av,Bi,Bj,Bv
            （后续 Run: eigs(A,B) → λ=k₀²；Post → freq, Ex/Ey/Ez）
```

**物理对应关系：** 散射体积分 `A_scatter ≈ A_eigen − k₀²·B_eigen`（同一网格与 Nedelec 基函数下）。

**FemType = 2（2D 遗留）：**

```
bele.json ──► Phy_WaveOpticsModel（边界/激励）
           ──► MaterialLib（材料参数）
           ──► MeshFile 路径
project_3.dat ──► Mesh_2D（网格拓扑）
           ──► Assemble ──► 稀疏矩阵 A, 向量 b
           ──► Solver ──► 解向量 x
           ──► Post ──► OutFile/Ex, Ey, Ez, normE
```

---

## 5. 完整使用说明

### 5.1 环境要求

| 组件 | 要求 |
|------|------|
| 操作系统 | Windows 10/11 x64 |
| 编译器 | Visual Studio 2026（18），工作负载「使用 C++ 的桌面开发」 |
| 构建工具 | CMake ≥ 3.8（VS 自带，见下方 PATH） |
| C++ 标准 | C++17 |

### 5.2 编译步骤

推荐使用**两个独立构建目录**，避免散射与本征互相覆盖 exe 和 OutFile：

```powershell
# 若 cmake 不在 PATH 中，追加 VS 2026 自带 CMake 路径
$env:Path += ";C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin"

cd "3D opticsfem-master"

# FemType=4 散射
cmake -B scat3D -G "Visual Studio 18 2026" -A x64


# FemType=5 本征频率
cmake -B eigen3D -G "Visual Studio 18 2026" -A x64
cmake --build eigen3D --config Release
```

**产物路径：**

- `scat3D/Release/OpticsFEM.exe` + `scat3D/Release/complex/complexsolver.exe`
- `eigen3D/Release/OpticsFEM.exe`

也可使用单一 `build/` 目录（见 `CMakeSettings.json`），但切换算例时需重新编译并注意 OutFile 覆盖。

### 5.3 运行前准备（FemType = 4，三维散射）

#### 步骤 1：指定 JSON 配置文件

`test/Test_Main.cpp` 默认读取 **`sbc3d.json`**：

```cpp
std::ifstream fd("sbc3d.json");
```

更换算例时修改文件名；修改后须**重新编译 scat3D**。

#### 步骤 2：部署输入文件

将 JSON 及 `MeshFile` 指定的网格文件复制到 **`scat3D/Release/`**（与 exe 同目录）：

```powershell
Copy-Item sbc3d.json, SBCmesh.dat -Destination scat3D\Release\
```

#### 步骤 3：确认求解器

```
scat3D/Release/
├── OpticsFEM.exe
├── sbc3d.json
├── SBCmesh.dat
└── complex/
    └── complexsolver.exe    ← cmake --build 后自动生成
```

#### 步骤 4：执行

```powershell
cd scat3D/Release
.\OpticsFEM.exe
```

控制台应打印 `OpticsFEM_All returned 4`。

#### 步骤 5：查看结果

检查 `OutFile/` 是否生成：`Ex`、`Ey`、`Ez`、`normE`。

---

### 5.3c 运行前准备（FemType = 5，三维本征频率）

#### 步骤 1：指定 JSON 配置文件

编辑 `test/Test_Main.cpp`：

```cpp
std::ifstream fd("eigen3d.json");
```

修改后须**重新编译 eigen3D**（可与 scat3D 并存，互不干扰）。

#### 步骤 2：部署输入文件

```powershell
Copy-Item eigen3d.json, SBCmesh.dat -Destination eigen3D\Release\
```

#### 步骤 3：执行

```powershell
cd eigen3D/Release
.\OpticsFEM.exe
```

控制台应打印 `OpticsFEM_All returned 5`。

#### 步骤 4：查看矩阵输出

`OutFile/` 下导出 A/B 稀疏矩阵 COO（0-based）：

| 文件 | 含义 |
|------|------|
| `Ai.txt`, `Aj.txt`, `Av.txt` | 刚度矩阵 A |
| `Bi.txt`, `Bj.txt`, `Bv.txt` | 质量矩阵 B（ε 加权） |

可与 MATLAB `3D一阶本征问题2` 中 `export_ab_matrix.m` 输出对比验证。

> **当前限制**：`Run()`（广义特征值求解）与 `Post()`（场重构、freq 输出）尚未接入 `FEM_Interface.cpp` 的 FemType=5 分支。

---

### 5.3b 运行前准备（FemType 0–3，2D 遗留）

#### 步骤 1：指定 JSON 配置文件

编辑 `test/Test_Main.cpp` 中 `fd.open(...)` 的文件名。

#### 步骤 2：部署输入文件

将 JSON 及 JSON 中 `MeshFile` 指定的 `.dat` 网格文件复制到 `build/Release/` 目录（与 `OpticsFEM.exe` 同目录）。

#### 步骤 3：部署外部求解器

**散射算例（FemType 2/3/4）最小目录：**

```
Release/
├── OpticsFEM.exe
├── *.json                    # sbc3d.json（FemType=4）或 bele.json（FemType=2）
├── *.dat                     # SBCmesh.dat 或 project_3.dat
└── complex/
    └── complexsolver.exe
```

**本征算例（FemType 0/1）另需：**

```
Release/
├── real_solver/real          # 实数特征值求解器
└── complex_solver/complex      # 复数特征值求解器
```

#### 步骤 4：执行

```powershell
cd build/Release
.\OpticsFEM.exe
```

#### 步骤 5：查看结果

检查 JSON 中 `OutFile` 指定目录（默认 `./OutFile`）是否生成：

- 散射：`Ex`、`Ey`、`Ez`、`normE`
- 本征模式：上述文件 + `neff`
- 本征频率：上述文件 + `freq`

### 5.4 切换算例

| 操作 | 方法 |
|------|------|
| 更换 JSON | 修改 `Test_Main.cpp` 中 `fd.open()` 文件名，或将目标 JSON 复制为当前文件名 |
| 更换网格 | 确保 JSON 中 `MeshFile` 与实际 `.dat` 文件名一致 |
| 更换问题类型 | 修改 JSON 中 `FemType`（0/1/2/3/4/5），程序自动路由 |

### 5.5 快速验证（sbc3d 三维 SBC 散射）

1. 编译 `scat3D` Release（见 5.2 节）
2. 确认 `Test_Main.cpp` 读取 `sbc3d.json`，复制 `sbc3d.json`、`SBCmesh.dat` 到 `scat3D/Release/`
3. 确认 `sbc3d.json` 中 `"FemType": 4`
4. 运行 `OpticsFEM.exe`
5. 检查 `OutFile/` 下四个场文件

与 COMSOL 对比见 `compare/README.md`。

### 5.5b 快速验证（eigen3d 三维本征频率）

1. 编译 `eigen3D` Release，`Test_Main.cpp` 改为读取 `eigen3d.json`
2. 复制 `eigen3d.json`、`SBCmesh.dat` 到 `eigen3D/Release/`
3. 确认 `"FemType": 5`
4. 运行 `OpticsFEM.exe`，应返回 5
5. 检查 `OutFile/` 下 `Ai/Aj/Av`、`Bi/Bj/Bv` 六个文件

### 5.6 快速验证（bele 二维算例，遗留）

1. 从 `../测试数据集/bele/` 复制 `bele.json` 和 `project_3.dat` 到 `build/Release/`
2. 修改 `Test_Main.cpp` 中 `fd.open("bele.json")`，重新编译
3. 部署 `complex/complexsolver.exe`
4. 运行 `OpticsFEM.exe`
5. 检查 `OutFile/` 下四个场文件

### 5.7 集成到其他程序

**方式 A — 独立可执行文件（当前模式）**

从文件读取 JSON，调用 API，适合本地验证。

**方式 B — 动态库（预留）**

取消 `FEM_Interface.h` 底部 `extern "C"` 注释，将 CMakeLists 中 `add_library(OpticsFEM SHARED ...)` 启用，编译为 DLL 供 C#/Python 等调用。

**方式 C — 直接调用 API**

```cpp
#include "Interface/FEM_Interface.h"

std::string jsonStr = "...";  // 紧凑 JSON 字符串
OpticsFEMData data;
data.test1 = 0;
data.test2 = 0;
data.data = (char*)jsonStr.data();

int ret = OpticsFEM_API::OpticsFEM_All(data);
// ret: 1=2D本征模式, 2=2D本征频率, 3=2D散射, 4=3D散射, 5=3D本征矩阵导出, 0=错误
```

---

## 6. 输入输出文件规范

### 6.1 JSON 配置文件

- **格式**：单行 UTF-8 紧凑 JSON（`getline()` 读整行）
- **必填公共字段**：`FemType`, `NbrBoundary`, `BoundaryFlag`, `NbrDomain`, `MeshFile`, `OutFile`

#### 公共字段说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `FemType` | int | 0=2D本征模式, 1=2D本征频率, 2=2D散射(λ), 3=2D散射(f), **4=3D散射(λ)**, **5=3D本征频率** |
| `NbrBoundary` | int | 边界数量（3D 为三角面边界条数；2D 为边界面条数） |
| `BoundaryFlag` | int[] | 每条边界的类型编码（见 3.3 节） |
| `NbrDomain` | int | 材料物理域数量 |
| `MeshFile` | string | 网格 `.dat` 文件路径 |
| `OutFile` | string | 结果输出目录 |
| `EletricType` | int | 0=Et, 1=Ez, 2=完整 E（散射/本征频率） |

#### 本征问题专用字段

| 字段 | 说明 |
|------|------|
| `NbrMode` | 求解模态数量（FemType 0/1/5） |
| `searchValue` | 特征值搜索目标（FemType 0/1/5） |
| `searchType`, `solverType`, `maxIterNum`, `tol`, `tolType` | 特征值求解器参数（FemType 5 JSON 已预留） |
| `lambda0` | 参考波长（FemType 0/5） |

#### 散射问题专用字段

| 字段 | 说明 |
|------|------|
| `lambda` | 真空波长（FemType=2 或 **4**） |
| `freq` | 频率 GHz（FemType=3，内部换算 λ = 0.299792458/freq） |

#### 边界扩展块（2D 遗留，FemType 0–3 可选）

| 块名 | 主要字段 | 用途 |
|------|----------|------|
| `bele` | `index`, `Ebx/y/z`, `curlEbx/y/z` | 背景等效场边界 |
| `ef` | `index`, `E0x/y/z` | 电场 Dirichlet 激励 |
| `pml` | `index`, `PMLType`, `PMLData` | 完美匹配层 |
| `sbc` | `SBCType`, `Index`, `E0x/y/z`, `kx/y/z` | 散射边界（**FemType=4 必填**） |
| `pbc` | `srcIndex`, `dstIndex`, `phiR`, `phiI` | 周期边界 |
| `port` | `PORTinc`, `PORTout`, `Einc`, `Eout` | 波导端口 |

#### sbc3d 算例 JSON 摘要（FemType = 4）

```json
{
  "FemType": 4,
  "EletricType": 2,
  "lambda": 0.8,
  "NbrBoundary": 14,
  "BoundaryFlag": [0, 2, 2, ...],
  "sbc": {
    "Index": [1, 2, 3, 4, 5, 14],
    "SBCType": [0, 0, 0, 1, 0, 0],
    "E0x": ["1", "1", "1", "1", "1", "1"],
    "E0y": ["0", "0", "0", "0", "0", "0"],
    "E0z": ["0", "0", "0", "0", "0", "0"],
    "kx": [0, 0, 0, 0, 0, 0],
    "ky": [0, 0, 0, 0, 0, 0],
    "kz": [0, 0, 0, 0, 0, 0]
  },
  "NbrDomain": 2,
  "domainType": [2, 2],
  "matType": [0, 0],
  "epsilonrR": [1.0, 1.5],
  "epsilonrI": [0.0, 0.0],
  "MeshFile": "SBCmesh.dat",
  "OutFile": "./OutFile"
}
```

**SBCType 含义（FemType=4）：**

| 值 | 含义 |
|----|------|
| 0 | 出射 SBC（吸收边界） |
| 1 | 入射 SBC（平面波激励，用 `E0x/y/z` 指定） |

**BoundaryFlag 编码（三角面边界）：** 0=PMC, 1=PEC, **2=SBC**, 3=ELE, 4=PBC, …

#### eigen3d 算例 JSON 摘要（FemType = 5）

```json
{
  "FemType": 5,
  "EletricType": 2,
  "NbrBoundary": 14,
  "BoundaryFlag": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  "NbrDomain": 2,
  "matType": [0, 0],
  "epsilonrR": [1.0, 1.5],
  "epsilonrI": [0.0, 0.0],
  "murR": [1.0, 1.0],
  "MeshFile": "SBCmesh.dat",
  "OutFile": "./OutFile",
  "NbrMode": 6,
  "searchType": 0,
  "searchValue": 374740572.5,
  "lambda0": 0.8
}
```

本算例为全 PMC 边界（`BoundaryFlag` 全 0），与 MATLAB `3D一阶本征问题2` 对齐。方程 **A·x = λ·B·x**，λ = k₀²。

#### SBCmesh.dat 网格格式（Mesh_3D）

文本格式，按块顺序读取（1-based 索引，读入后转 0-based）：

| 块名 | 内容 |
|------|------|
| `NbrVertex` / `Vertex` | 顶点坐标 (x,y,z) |
| `NbrTet` / `Tet` | 四面体顶点连接 |
| `DomainOfTet` | 体域编号 |
| `NbrEdge` / `Edge` | 边列表 |
| `EdgeOfTet` | 四面体六条边局部编号 |
| `NbrTri` / `Tri` | 三角边界元 |
| `DomainOfTri` | 边界面域编号 |
| `ConnOfTri` | 三角面与边的连接 |
| `NbrQuad` / `Quad` | 四边形面元（若有） |

#### bele 算例 JSON 摘要（FemType = 2，2D 遗留）

```json
{
  "FemType": 2,
  "EletricType": 2,
  "lambda": 1,
  "NbrBoundary": 13,
  "BoundaryFlag": [0, 0, 3, 0, ...],
  "bele": {
    "index": [4],
    "Eby": "sin(2*pi*x)",
    "Ebz": "cos(2*pi*x)"
  },
  "ef": { "index": [1], "E0y": ["0.5"], "E0z": ["0.3"] },
  "pml": { "index": [1,2,3,5], "PMLType": [1,1,1,1], ... },
  "NbrDomain": 5,
  "matType": [0,0,0,0,0],
  "epsilonrR": [1.0, 1.0, 1.0, 1.0, 1.0],
  "MeshFile": "project_3.dat",
  "OutFile": "./OutFile"
}
```

详细字段定义参见上级目录 `OpticsFEM_LASPCEM_接口规范.md`。

---

### 6.2 三维网格 SBCmesh.dat（Mesh_3D，FemType = 4 / 5）

见上文 [SBCmesh.dat 网格格式](#sbcmeshdat-网格格式mesh_3d)。

### 6.3 二维网格 `.dat` 文件（Mesh_2D，FemType 0–3）

由 `Mesh_2D::GetMesh()` 顺序解析，字段顺序固定：

```
NbrVertex
Vertex          （每行 x y，z 读入时置 0）
NbrEdge
Edge            （每行 顶点索引0 顶点索引1）
NbrTri
Tri             （每行 顶点索引0 1 2）
EdgeOfTri       （每三角形 3 条边索引）
DomainOfTri     （每三角形物理域编号，文件内 0-based，读入后 +1）
NbrEdges
CoonOfEdges     （边界边连接信息）
DomainOfEdges   （边界边所属域）
normal          （边界法向，块大小由 JSON 中 NbrBoundary 决定）
NbrCopyOfEdges
CopyOfEdges
NbrCopyOfVertexs
CopyOfVertexs
```

---

### 6.3 输出文件格式

#### 散射问题（`Post_2D_Scatter::OutputData`）

| 文件名 | 格式 | 内容 |
|--------|------|------|
| `Ex` | 首行 `//`，随后每行 `实部 虚部` | 各顶点 Ex |
| `Ey` | 同上 | 各顶点 Ey |
| `Ez` | 同上 | 各顶点 Ez |
| `normE` | 首行 `//`，随后每行一个浮点数 | 各顶点 \|E\| |

#### 本征模式

额外输出 `neff`：每行 `实部 虚部`（有效折射率）。多模态时 `Ex/Ey/Ez/normE` 以 `//` 分隔各模态块。

#### 本征频率

额外输出 `freq`：每行 `实部 虚部`（特征频率）。

---

## 7. 对外 API 与集成方式

### 7.1 数据结构

```cpp
struct OpticsFEMData {
    double test1;   // 保留
    double test2;   // 保留
    char*  data;    // 指向 UTF-8 JSON 字符串（需保证生命周期覆盖调用期间）
};
```

### 7.2 接口函数

| 函数 | 说明 | 返回值 |
|------|------|--------|
| `OpticsFEM_All(data)` | 读配置 → 组装 → 求解 → 后处理 | 0/1/2/3 |
| `OpticsFEM_Test(data)` | 向 `OutFile + "test"` 写入 `"test success"` | 1 |

### 7.3 DLL 导出（预留）

`FEM_Interface.h` 底部注释代码可在编译为 SHARED 库时启用：

```cpp
extern "C" {
    _declspec(dllexport) int OpticsFEM_ALL(OpticsFEMData data) {
        return OpticsFEM_API::OpticsFEM_All(data);
    }
}
```

---

## 8. 测试算例与数据集

测试数据位于上级目录 **`测试数据集/`**，源码树内**不包含**算例文件。

### 8.1 散射边界条件算例

| 文件夹 | JSON | 网格 | 测试内容 |
|--------|------|------|----------|
| `bele/` | `bele.json` | `project_3.dat` | 背景等效场边界 + PML |
| `pml_xy/` | `pml_xy.json` | `project_1.dat` | XY 方向 PML |
| `epd/` | `epd.json` | `project_4.dat` | 电偶极子源 |
| `mpd/` | `mpd.json` | `project_4.dat` | 磁偶极子源 |
| `mag/` | `mag.json` | `project_4.dat` | 磁场边界 |
| `scd/` | `scd.json` | `project_4.dat` | 面电流密度 |
| `port/` | `port.json` | `meshData_Port.txt` | 波导端口 |

### 8.2 波导/光纤本征模算例

| 文件夹 | 说明 |
|--------|------|
| `条形波导/case1` | 条形波导本征模 |
| `脊波导/case2` | 脊波导 |
| `槽波导/case3` | 槽波导 |
| `SPP波导/case4` | 表面等离激元波导 |
| `光子晶体波导/case5` | 光子晶体波导 |
| `阶跃折射率光纤/case6` | 阶跃折射率光纤 |
| `空芯光纤/case7` | 空芯光纤 |
| `多模光纤/case8` | 多模光纤 |
| `多芯光纤/case9` | 多芯光纤 |
| `光子晶体光纤/case10` | 光子晶体光纤 |
| `一维光子晶体/case11` | 一维光子晶体 |
| `方格光子晶体/case12` | 方格光子晶体 |
| `衍射光栅/case13` | 衍射光栅 |
| `表面等离激元线光栅/case14` | SPP 线光栅 |
| `scatter_modal/` | 散射模态 |

每个本征算例通常包含：`caseN.json`（或 `mesh.json`）、`project_*.dat` 网格，部分含 `.brep` 几何源文件。

---

## 9. 代码阅读路径

建议按以下顺序阅读，建立从入口到输出的完整认知：

| 序号 | 文件 | 阅读目标 |
|------|------|----------|
| 1 | `test/Test_Main.cpp` | 入口，默认读 `sbc3d.json`（本征改为 `eigen3d.json`） |
| 2 | `Interface/FEM_Interface.cpp` | FemType 路由（**4→3D散射**, **5→3D本征**） |
| 3 | `test/Test_ReadData.cpp` | JSON → Phy/Material（含 `sbc` 块） |
| 4 | `mesh/Mesh_Interface.cpp` | `Mesh_3D::GetMesh` 读 SBCmesh.dat |
| 5 | `kernel/Assemble_kernel.cpp` | `OpticsFEM_3D_Scatter` / `OpticsFEM_3D_EigenFreq` 总控 |
| 6 | `kernel/Assemble_Scatter_3D_Boundary.cpp` | 3D SBC 边界积分（FemType=4） |
| 7 | `kernel/Assemble_Scatter_Equation.cpp` | 散射四面体体积方程（FemType=4） |
| 8 | `kernel/Assemble_EigenFreq_Equation.cpp` | 本征 A/B 体积积分（FemType=5） |
| 9 | `kernel/Assemble_EigenFreq_Boundary.cpp` | 本征 PEC/PBC（FemType=5） |
| 10 | `complex/complexsolver.cpp` | Eigen 稀疏线性求解（FemType=4） |
| 11 | `post/Post_CalEletric.cpp` | `Post_3D_Scatter::GetElectric` |
| 12 | `post/Post_Output.cpp` | 写入 OutFile |

### 调试建议

- 在 `FEM_Interface.cpp` 各 `FemType` 分支入口设断点，确认路由正确。
- 散射分支已调用 `Test_OutputMatrix()`，可在 Assemble 后检查矩阵非零元。
- Post 完成后检查 `OutFile/` 目录内容。

---

## 10. 常见问题排查

| 现象 | 可能原因 | 处理措施 |
|------|----------|----------|
| `cmake` 无法识别 | CMake 未加入 PATH | 使用 VS 自带 CMake 完整路径 |
| `LNK1181: eigensolver.lib` | 旧版仍链接外部库 | 确认 `EIGENSOLVER_STATIC` 已启用 |
| 运行无输出、无 OutFile | 缺少 `complexsolver.exe` 或路径错误 | 检查 `complex/` 目录及工作目录 |
| 无法打开 `sbc3d.json` | 工作目录不含 JSON | 复制到 `Release/` 或在其中运行 |
| 无法打开 `SBCmesh.dat` | `MeshFile` 路径不匹配 | 确保 `.dat` 与 exe 同目录 |
| 无法打开 `eigen3d.json` | 本征算例 JSON 缺失 | 复制到 `eigen3D/Release/` 并确认 Test_Main 文件名 |
| 控制台打印 `err` | JSON 缺少或错误 `FemType` | 检查 JSON 完整性 |
| 编译警告 C4819 | Eigen 头文件编码 | 不影响功能，可忽略 |
| BELE 表达式报错 | 表达式语法错误或变量未定义 | 检查 muparser 支持的函数（如 `sin`, `pi`, `x`） |

---

## 附录 A：核心类关系图

```
OpticsFEM_API
    ├── Phy_WaveOpticsModel  ← JSON 边界/激励
    ├── MaterialLib          ← JSON 材料
    ├── Mesh_3D              ← SBCmesh.dat（FemType=4/5）
    ├── OpticsFEM_3D_Scatter ← FemType=4：A·x=b
    │       ├── Assemble（体积 + SBC）
    │       ├── Solver_LdaDom → complexsolver
    │       └── Post_3D_Scatter → Ex/Ey/Ez/normE
    └── OpticsFEM_3D_EigenFreq ← FemType=5：A·x=λB·x
            ├── Assemble（A 刚度 + B 质量 + PEC/PBC）
            ├── Test_OutputMatrix → Ai/Aj/Av, Bi/Bj/Bv
            └── （待接）Solver_EigenFreq → Post_3D_EigenFreq
```

---

## 附录 B：FemType 与 JSON 关键参数对照

| FemType | 关键 JSON 参数 | 输出特征量 |
|---------|----------------|------------|
| 0 | `lambda0`, `NbrMode`, `searchValue` | `neff`, Ex/Ey/Ez |
| 1 | `lambda0`, `NbrMode`, `searchValue`, `EletricType` | `freq`, Ex/Ey/Ez |
| 2 | `lambda`, 边界块 | Ex/Ey/Ez/normE |
| 3 | `freq`, 边界块 | Ex/Ey/Ez/normE |
| **4** | **`lambda`, `sbc` 块, `SBCmesh.dat`** | **Ex/Ey/Ez/normE** |
| **5** | **`NbrMode`, `searchValue`, `lambda0`, `SBCmesh.dat`** | **Ai/Aj/Av, Bi/Bj/Bv**（当前）；后续 **freq, Ex/Ey/Ez** |

---

## 附录 C：文档修订记录

| 版本 | 日期 | 修订内容 |
|------|------|----------|
| v3.0 | 2026-06-09 | 新增 FemType=5 三维本征频率；scat3D/eigen3D 双构建目录；eigen3d.json；A/B 矩阵导出 |
| v2.0 | 2026-06-08 | 适配 3D 版：FemType=4、sbc3d 算例、SBCmesh 格式、CMake complexsolver |
| v1.0 | 2026-06-03 | 初版（2D opticsfem-master） |

---

*本文档基于 `3D opticsfem-master` 当前代码状态编制。三维主算例：`sbc3d.json`（散射 FemType=4）+ `eigen3d.json`（本征 FemType=5），共用 `SBCmesh.dat`。*
