# OpticsFEM 完整使用说明与代码介绍 | 项目 | 说明 | |------|------| | 文档版本 | v1.0 | | 编制日期 | 2026-06-03 | | 适用代码 | `opticsfem-master/` | | 适用平台 | Windows x64,Visual Studio 2022/2026,MSVC | | 关联文档 | 上级目录 `OpticsFEM_开发与使用手册.md`、`OpticsFEM_LASPCEM_接口规范.md` | --- ## 目录 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 程序定位 **OpticsFEM** 是一套基于 C++ 实现的**二维矢量有限元(FEM)光学电磁仿真内核**。程序采用 **Nedelec 边元** 离散麦克斯韦方程,通过 JSON 配置物理模型、材料与边界条件,通过 `.dat` 文本文件读入三角网格,计算结果以文本文件输出。 ### 1.2 支持的问题类型 | FemType | 问题类型 | 驱动类 | 求解器 | 后处理 | |---------|----------|--------|--------|--------| | 0 | 本征模式(EigenMode) | `OpticsFEM_2D_EigenMode` | `Solver_EigenMode` | `Post_2D_EigenMode` | | 1 | 本征频率(EigenFreq) | `OpticsFEM_2D_EigenFreq` | `Solver_EigenFreq` | `Post_2D_EigenFreq` | | 2 | 散射(按波长 λ) | `OpticsFEM_2D_Scatter` | `Solver_LdaDom` | `Post_2D_Scatter` | | 3 | 散射(按频率 f) | `OpticsFEM_2D_Scatter` | `Solver_LdaDom` | `Post_2D_Scatter` | ### 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 运行时外部依赖(不在源码树中) | 路径 | 用途 | |------|------| | `complex/complexsolver.exe` | 复数线性方程组求解(散射问题) | | `real/realsolver.exe` | 实数线性方程组求解 | | `real_solver/real` | 实数广义特征值求解(本征问题) | | `complex_solver/complex` | 复数广义特征值求解 | 外部求解器通过**临时 `.dat` 文件**与主程序交换 CSR 格式矩阵,由 `system()` 启动。 --- ## 2. 目录与文件总览 ``` opticsfem-master/ ├── CMakeLists.txt # CMake 构建配置 ├── CMakeSettings.json # Visual Studio CMake 设置 ├── Interface/ # 对外 API 层(2 文件) ├── test/ # 入口与 JSON 解析(4 文件) ├── phy/ # 物理模型与边界条件(3 文件) ├── material/ # 材料库(3 文件) ├── mesh/ # 网格读写与拓扑查询(4 文件) ├── kernel/ # FEM 方程与边界组装(10 文件) ├── solver/ # 数值求解器接口(8 文件) ├── post/ # 后处理与结果输出(6 文件) ├── function/ # Nedelec 基函数与高斯积分(14 文件) ├── common/ # 公共常量与工具(3 文件) ├── parser/ # 数学表达式解析器(约 89 文件) ├── nlohmann/ # JSON 库(2 文件) ├── Eigen/ # 线性代数库(337 文件) └── build/ # CMake 构建产物(可忽略) ``` **源码统计(不含 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 = 本征模式完成;2 = 本征频率完成;3 = 散射完成。 --- ### 3.2 test/ — 入口与数据解析 | 文件 | 说明 | |------|------| | `Test_Main.cpp` | 进程 `main()` 入口:从 `bele.json` 读取整行 JSON,封装为 `OpticsFEMData`,调用 `OpticsFEM_All()` | | `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** 已在头文件中声明,但 `OpticsFEM_All()` 当前未接入 3D 求解分支。 --- ### 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 │ ├── kernel(Assemble:体积 + 边界积分) ├── function(BF + Gauss 数值积分) └── parser(边界表达式求值) ``` ### 4.2 完整调用序列(以 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.3 数据流 ``` 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 2022 或 2026,工作负载「使用 C++ 的桌面开发」 | | 构建工具 | CMake ≥ 3.8 | | C++ 标准 | C++17 | ### 5.2 编译步骤 ```powershell # 若 cmake 不在 PATH 中,追加 VS 自带 CMake 路径 $env:Path += ";C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin" cd opticsfem-master mkdir build -Force cd build # VS 2022 cmake .. -G "Visual Studio 17 2022" -A x64 # 或 VS 2026 cmake .. -G "Visual Studio 18 2026" -A x64 cmake --build . --config Release ``` **产物路径:** `build/Release/OpticsFEM.exe` ### 5.3 运行前准备 #### 步骤 1:指定 JSON 配置文件 编辑 `test/Test_Main.cpp` 第 28 行: ```cpp fd.open("bele.json"); // 改为目标算例 JSON 文件名 ``` 修改后须**重新编译**。 #### 步骤 2:部署输入文件 将 JSON 及 JSON 中 `MeshFile` 指定的 `.dat` 网格文件复制到 `build/Release/` 目录(与 `OpticsFEM.exe` 同目录)。 #### 步骤 3:部署外部求解器 **散射算例(FemType 2/3)最小目录:** ``` Release/ ├── OpticsFEM.exe ├── bele.json ├── 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),程序自动路由 | ### 5.5 快速验证(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.6 集成到其他程序 **方式 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=本征模式, 2=本征频率, 3=散射, 0=错误 ``` --- ## 6. 输入输出文件规范 ### 6.1 JSON 配置文件 - **格式**:单行 UTF-8 紧凑 JSON(`getline()` 读整行) - **必填公共字段**:`FemType`, `NbrBoundary`, `BoundaryFlag`, `NbrDomain`, `MeshFile`, `OutFile` #### 公共字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `FemType` | int | 0=本征模式, 1=本征频率, 2=散射(λ), 3=散射(f) | | `NbrBoundary` | int | 边界边数量 | | `BoundaryFlag` | int[] | 每条边界的类型编码(见 3.3 节) | | `NbrDomain` | int | 材料物理域数量 | | `MeshFile` | string | 网格 `.dat` 文件路径 | | `OutFile` | string | 结果输出目录 | | `EletricType` | int | 0=Et, 1=Ez, 2=完整 E(散射/本征频率) | #### 本征问题专用字段 | 字段 | 说明 | |------|------| | `NbrMode` | 求解模态数量 | | `searchValue` | 特征值搜索目标 | | `lambda0` | 真空波长(本征模式 FemType=0) | #### 散射问题专用字段 | 字段 | 说明 | |------|------| | `lambda` | 真空波长(FemType=2) | | `freq` | 频率 GHz(FemType=3,内部换算 λ = 0.299792458/freq) | #### 边界扩展块(可选) | 块名 | 主要字段 | 用途 | |------|----------|------| | `bele` | `index`, `Ebx/y/z`, `curlEbx/y/z`(字符串表达式) | 背景等效场边界 | | `ef` | `index`, `E0x/y/z` | 电场 Dirichlet 激励 | | `pml` | `index`, `lambda`, `PMLType`, `PMLData`, `PMLBoundaryIndex` | 完美匹配层 | | `sbc` | `SBCType`, `Index`, `E0x/y/z`, `kx/y/z` | 散射边界 | | `pbc` | `srcIndex`, `dstIndex`, `phiR`, `phiI` | 周期边界 | | `mag` | `index`, `H0x/y/z` | 磁场边界 | | `scd` | `index`, `J0x/y/z` | 面电流密度 | | `mpd` | `index`, `mx/y/z` | 磁偶极子源 | | `epd` | `index`, `px/y/z` | 电偶极子源 | | `port` | `PORTinc`, `PORTout`, `Einc`, `Eout`, `EincCurl`, `EoutCurl` | 波导端口 | | `beam` | `type`, `kx`, `ky` | 高斯光束 | #### bele 算例 JSON 摘要 ```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 二维网格 `.dat` 文件 由 `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` | 进程入口、JSON 文件读取 | | 2 | `Interface/FEM_Interface.cpp` | FemType 路由、三阶段调度 | | 3 | `test/Test_ReadData.cpp` | JSON 字段 → Phy/Material 映射 | | 4 | `mesh/Mesh_Interface.cpp` | `.dat` 网格格式与读入 | | 5 | `kernel/Assemble_kernel.cpp` | Assemble / Run / Post 总控 | | 6 | `kernel/Assemble_Scatter_2D_Boundary.cpp` | BELE / PML / EF 等边界组装 | | 7 | `kernel/Assemble_Scatter_Equation.cpp` | 体积方程组装 | | 8 | `solver/Solver_Interface.cpp` | 求解器参数与 Run | | 9 | `solver/interface.cpp` | 外部线性求解器调用 | | 10 | `post/Post_Output.cpp` | 结果文件格式 | ### 调试建议 - 在 `FEM_Interface.cpp` 各 `FemType` 分支入口设断点,确认路由正确。 - 散射分支已调用 `Test_OutputMatrix()`,可在 Assemble 后检查矩阵非零元。 - Post 完成后检查 `OutFile/` 目录内容。 --- ## 10. 常见问题排查 | 现象 | 可能原因 | 处理措施 | |------|----------|----------| | `cmake` 无法识别 | CMake 未加入 PATH | 使用 VS 自带 CMake 完整路径 | | `LNK1181: eigensolver.lib` | 旧版仍链接外部库 | 确认 `EIGENSOLVER_STATIC` 已启用 | | 运行无输出、无 OutFile | 缺少 `complexsolver.exe` 或路径错误 | 检查 `complex/` 目录及工作目录 | | 无法打开 `bele.json` | 工作目录不含 JSON | 在 `Release/` 下运行,或复制输入文件 | | 无法打开 `project_3.dat` | `MeshFile` 路径不匹配 | 确保 `.dat` 与 exe 同目录 | | 控制台打印 `err` | JSON 缺少或错误 `FemType` | 检查 JSON 完整性 | | 编译警告 C4819 | Eigen 头文件编码 | 不影响功能,可忽略 | | BELE 表达式报错 | 表达式语法错误或变量未定义 | 检查 muparser 支持的函数(如 `sin`, `pi`, `x`) | --- ## 附录 A:核心类关系图 ``` OpticsFEM_API ├── Phy_WaveOpticsModel ← JSON 边界/激励 ├── MaterialLib ← JSON 材料(含 Material[]) ├── Mesh_2D ← .dat 网格 └── OpticsFEM_2D_* ← 问题驱动 ├── Assemble(kernel + function + parser) ├── Solver_* ← 外部求解器 └── Post_2D_* ← 场重构与输出 ``` --- ## 附录 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 | --- ## 附录 C:文档修订记录 | 版本 | 日期 | 修订内容 | |------|------|----------| | v1.0 | 2026-06-03 | 初版:全文件目录、模块说明、使用指南、I/O 规范、算例索引 | --- *本文档基于 `opticsfem-master` 当前代码状态编制。若 CMakeLists、API 或求解器路径发生变更,请同步更新相应章节。*