XIAN-FEM-2026June/OpticsFEM_开发与使用手册.md

22 KiB
Raw Permalink Blame History

OpticsFEM 二维光学有限元程序 — 开发与使用手册

项目 说明
文档版本 v1.0
编制日期 2026-06-03
适用代码 opticsfem-master/
适用平台 Windows x64Visual Studio 202618/ MSVC
关联文档 OpticsFEM_LASPCEM_接口规范.md

目录

  1. 概述
  2. 从源代码到可执行文件
  3. 软件架构与模块划分
  4. 程序执行流程
  5. 数据流与对象模型
  6. 对外 API 规范
  7. 输入与输出文件规范
  8. 构建与部署
  9. 算例运行指南
  10. 代码阅读路径
  11. 求解器依赖说明
  12. 常见问题与排查

1. 概述

1.1 程序定位

OpticsFEM 是一套基于 C++ 实现的二维矢量有限元FEM光学电磁仿真内核,采用 Nedelec 边元离散麦克斯韦方程,支持以下三类问题:

FemType 问题类型 核心类
0 本征模式EigenMode OpticsFEM_2D_EigenMode
1 本征频率EigenFreq OpticsFEM_2D_EigenFreq
2 散射Scatter按波长 OpticsFEM_2D_Scatter
3 散射Scatter按频率 OpticsFEM_2D_Scatter

程序通过 JSON 字符串 描述物理模型、材料参数、边界条件及求解配置;通过 .dat 文本文件 描述三角网格。计算结果以文本文件形式输出至指定目录。

1.2 入口程序与可执行文件的关系

test/Test_Main.cpp 并非完整程序,而是可执行文件的入口模块。其职责限于:

  1. 从本地文件系统读取 JSON 配置文件;
  2. 构造 OpticsFEMData 结构体;
  3. 调用统一 API OpticsFEM_API::OpticsFEM_All() 触发完整求解流程。

可执行文件 OpticsFEM.exe 由 CMake 将 Test_Main.cpp 与项目中全部业务源文件(约 70 余个 .cpp 单元)编译并链接为单一二进制产物。操作系统启动进程时,自 main() 函数开始执行;后续全部计算逻辑由 FEM_Interface.cpp 及其调用的各功能模块完成。

1.3 设计原则

原则 说明
单一 API 入口 外部调用方仅需调用 OpticsFEM_All(),无需感知内部分支
JSON 为配置语言 物理、材料、边界、求解参数均通过 JSON 字段传递
前后端解耦 Test_Main.cpp 可替换为 GUI、脚本或 DLL 宿主,接口不变
模块化组装 网格、物理、材料、组装、求解、后处理分层实现

2. 从源代码到可执行文件

2.1 构建系统

项目采用 CMake 管理构建,配置文件为 opticsfem-master/CMakeLists.txt。目标产物定义如下:

add_executable(OpticsFEM
    "test/Test_Main.cpp"
    ${PARSER} ${COMMON} ${GAUSS} ${BF}
    ${MESH} ${MATERIAL} ${PHY}
    ${SOLVER} ${POST} ${KERNEL}
    ${TEST} ${INTERFACE}
    "post/Post_GetEb.cpp"
)
target_compile_definitions(OpticsFEM PRIVATE EIGENSOLVER_STATIC)
set(CMAKE_CXX_STANDARD 17)

2.2 编译链接流程

┌──────────────────────────────────────────────────────────────────┐
│  源文件层                                                         │
│  Test_Main.cpp, FEM_Interface.cpp, Mesh_Interface.cpp, ...       │
└────────────────────────────┬─────────────────────────────────────┘
                             │  cmake .. -G "Visual Studio 18 2026" -A x64
                             ▼
┌──────────────────────────────────────────────────────────────────┐
│  工程生成层                                                       │
│  build/OpticsFEM.vcxproj, build/Project.slnx                     │
└────────────────────────────┬─────────────────────────────────────┘
                             │  cmake --build . --config Release
                             ▼
┌──────────────────────────────────────────────────────────────────┐
│  编译层Translation                                            │
│  每个 .cpp → 对应 .obj 目标文件                                   │
└────────────────────────────┬─────────────────────────────────────┘
                             │  链接Linking
                             ▼
┌──────────────────────────────────────────────────────────────────┐
│  产物层                                                           │
│  build/Release/OpticsFEM.exe                                     │
└──────────────────────────────────────────────────────────────────┘

编译Compile:将各翻译单元(.cpp)独立转换为目标文件(.obj)。#include 头文件仅提供声明,不参与链接。

链接Link:合并全部 .obj,解析跨文件符号引用,以 Test_Main.cpp 中的 main() 作为进程入口,生成最终 .exe

2.3 第三方依赖

依赖 位置 用途
Eigen opticsfem-master/Eigen/ 稠密/稀疏矩阵运算
nlohmann/json opticsfem-master/nlohmann/ JSON 解析
muparser 派生库 opticsfem-master/parser/ BELE 等边界表达式求值

2.4 关于 Test_Main.cpp 中未使用的变量

Test_Main.cpp 中声明的 Phy_WaveOpticsModelMaterialLibMesh_2D 等对象在 main()未被直接使用。实际对象实例化与数据注入在 FEM_Interface.cpp::OpticsFEM_All() 中完成。上述声明为历史遗留或调试用途;注释块(第 3958 行)保留了手动分步调用流程的旧版写法,现行标准路径为 OpticsFEM_All() 一站式调用。


3. 软件架构与模块划分

3.1 目录结构与职责

opticsfem-master/
├── test/
│   ├── Test_Main.cpp           # 进程入口;读取 JSON 文件
│   ├── Test_ReadData.cpp       # JSON → Phy / Material 解析实现
│   └── Test_OutputData.cpp     # 调试输出
├── Interface/
│   ├── FEM_Interface.h         # 对外 API 声明
│   └── FEM_Interface.cpp       # FemType 路由与全流程调度
├── phy/                        # 物理模型:边界条件、激励
├── material/                   # 材料库ε、μ、σ、n、k
├── mesh/                       # 网格:.dat 读取与拓扑查询
├── kernel/                     # FEM 组装:方程与边界积分
├── solver/                     # 数值求解:线性方程组 / 特征值
├── post/                       # 后处理DOF → 顶点场 → 文件输出
├── function/                   # Nedelec 基函数、高斯积分
├── parser/                     # 数学表达式解析器
└── Eigen/                      # 线性代数库(第三方)

3.2 模块依赖关系

flowchart TB
    subgraph entry [入口层]
        TM[Test_Main.cpp]
        API[FEM_Interface.cpp]
    end

    subgraph io [数据读入层]
        PHY[phy]
        MAT[material]
        MSH[mesh]
    end

    subgraph core [计算核心层]
        KRN[kernel]
        SLV[solver]
    end

    subgraph output [输出层]
        PST[post]
    end

    TM --> API
    API --> PHY
    API --> MAT
    API --> MSH
    API --> KRN
    KRN --> SLV
    KRN --> PST
    SLV --> PST
    PHY --> KRN
    MAT --> KRN
    MSH --> KRN
    MSH --> PST
    PHY --> PST

3.3 核心类层次(二维)

类名 职责
Phy_WaveOpticsModel 存储边界类型、BELE/PML/EF/SBC 等边界数据
MaterialLib 存储各物理域材料参数
Mesh_2D 存储顶点、边、三角形及域编号
OpticsFEM_2D_Scatter 散射问题组装、求解、后处理调度
Solver_LdaDom 散射线性方程组求解接口
Post_2D_Scatter 散射结果电场插值与输出

4. 程序执行流程

4.1 顶层调用序列

FemType = 2散射bele 算例)为例,完整调用序列为:

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()
            ├─ OpticsFEM_2D_Scatter::Run()
            └─ OpticsFEM_2D_Scatter::Post(outFile)

4.2 Assemble 阶段内部流程

OpticsFEM_2D_Scatter::Assemble()kernel/Assemble_kernel.cpp)执行以下步骤:

  1. 确定矩阵类型:根据 PML、SBC、复材料等条件判定采用实数或复数稀疏矩阵
  2. 体积积分Assemble_WaveEquation() — 在各三角形单元上积分麦克斯韦弱形式;
  3. 边界积分(按 JSON 配置条件触发):
    • Assemble_PEC_ELE() — 理想导体 / 电边界
    • Assemble_PBC() — 周期边界
    • Assemble_BELE() — 边界等效源bele 算例)
    • Assemble_PML() — 完美匹配层
    • Assemble_Port() — 端口激励
  4. 约束处理:对 Dirichlet 型边界自由度施加罚函数或消元。

输出:稀疏矩阵 A、右端向量 b、预处理矩阵 P

4.3 Run 阶段

void OpticsFEM_2D_Scatter::Run()
{
    _mSolver->SetParam(&_mA_complex, &_mB_complex, &_mP_complex);
    _mSolver->Run(&_mX);
}

Solver_LdaDom::Run() 调用 solveComplexLinearEqu()solver/interface.cpp),将 CSR 格式矩阵写入临时文件,并启动外部求解器 complex/complexsolver.exe 完成迭代求解。解向量经预处理矩阵变换后存入 _mX

4.4 Post 阶段

void OpticsFEM_2D_Scatter::Post(string file)
{
    _mPost->GetMesh(_mMesh);
    _mPost->GetSolver(_mSolver);
    _mPost->GetPhy(_mPhy);
    _mPost->GetResult(&_mX);
    _mPost->GetElectric();      // 边 DOF → 顶点 Ex/Ey/Ez
    _mPost->OutputData(file);   // 写入 OutFile/
}

5. 数据流与对象模型

5.1 端到端数据流

flowchart LR
    subgraph inputs [外部输入]
        J["bele.json\n(JSON 字符串)"]
        D["project_3.dat\n(网格文件)"]
    end

    subgraph parsed [内存对象]
        P["Phy_WaveOpticsModel\n边界/激励"]
        M["MaterialLib\n材料参数"]
        G["Mesh_2D\n网格拓扑"]
    end

    subgraph linear [离散方程]
        A["稀疏矩阵 A"]
        B["右端向量 b"]
        X["解向量 x"]
    end

    subgraph files [文件输出]
        O["OutFile/Ex, Ey, Ez, normE"]
    end

    J -->|Test_ReadData| P
    J -->|Test_ReadData| M
    J -->|MeshFile 字段| D
    D -->|GetMesh| G
    P --> A
    M --> A
    G --> A
    P --> B
    A --> X
    B --> X
    X --> O
    G --> O

5.2 JSON 字段到内存对象的映射

JSON 字段组 目标对象 解析函数
FemType, EletricType, BoundaryFlag, bele, ef, pml, sbc, … Phy_WaveOpticsModel Phy_WaveOpticsModel::Test_ReadData()
NbrDomain, epsilonrR/I, murR/I, n, k, sigma, … MaterialLib MaterialLib::Test_ReadData()
MeshFile 网格文件路径 Mesh_2D::GetMesh()
lambda / freq, NbrMode, searchValue, … 求解器参数 Solver_*::GetSolver()

5.3 bele 算例配置摘要

配置项 含义
FemType 2 散射问题
EletricType 2 求解完整电场 E
lambda 1 真空波长
bele.index [4] 边界域 4 施加 BELE
bele.Eby sin(2*pi*x) 边界切向电场解析表达式
ef 边界 1 电场激励 等效 Dirichlet 激励
pml 4 个吸收层 PML 参数
MeshFile project_3.dat 网格文件
OutFile ./OutFile 输出目录

6. 对外 API 规范

6.1 数据结构

struct OpticsFEMData {
    double test1;   // 保留字段
    double test2;   // 保留字段
    char*  data;    // UTF-8 JSON 字符串(单行或紧凑格式)
};

6.2 接口函数

class OpticsFEM_API {
public:
    // 完整求解流程:读配置 → 组装 → 求解 → 后处理
    static int OpticsFEM_All(OpticsFEMData data);

    // 连通性测试:向 OutFile 写入 "test success"
    int OpticsFEM_Test(OpticsFEMData data);
};

6.3 返回值

返回值 含义
0 FemType 无法识别
1 本征模式完成
2 本征频率完成
3 散射完成

6.4 集成方式

方式 A — 独立可执行文件(当前 Test_Main.cpp 模式)

从文件读取 JSON调用 API适用于本地验证与回归测试。

方式 B — 动态库宿主(注释代码预留)

FEM_Interface.h 底部预留 extern "C" 导出声明,可将内核编译为 DLL 供前端或其他语言调用。


7. 输入与输出文件规范

7.1 JSON 配置文件

  • 格式:单行 UTF-8 JSON 或紧凑 JSON
  • 读取方式Test_Main.cpp 使用 getline() 读取整行;
  • 必填公共字段FemType, NbrBoundary, BoundaryFlag, NbrDomain, MeshFile, OutFile
  • 边界扩展字段(可选,按 js.contains 判定):bele, ef, pml, sbc, mag, scd, pbc, mpd, epd, port, beam

详细字段定义参见 OpticsFEM_LASPCEM_接口规范.md 第 2.3 节。

7.2 二维网格 .dat 文件

Mesh_2D::GetMesh()mesh/Mesh_Interface.cpp)顺序解析,字段顺序为:

NbrVertex → Vertex → NbrEdge → Edge → NbrTri → Tri
→ EdgeOfTri → DomainOfTri → NbrEdges → CoonOfEdges
→ DomainOfEdges → normal → CopyOfEdges → ...

顶点坐标为二维 (x, y),第三分量在读取时置零。

7.3 输出文件

散射问题(Post_2D_Scatter::OutputData)在 OutFile 目录下生成:

文件名 内容
Ex 各顶点 Ex 分量(实部 虚部,逐行)
Ey 各顶点 Ey 分量
Ez 各顶点 Ez 分量
normE 各顶点电场模

本征问题额外输出 nefffreq 文件。


8. 构建与部署

8.1 环境要求

组件 要求
操作系统 Windows 10/11 x64
编译器 Visual Studio 202618Community工作负载「使用 C++ 的桌面开发」
构建工具 CMake ≥ 3.8VS 自带或独立安装)
C++ 标准 C++17

8.2 构建命令

# 配置 CMake 路径(若未加入系统 PATH
$env:Path += ";C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin"

cd opticsfem-master
mkdir build -Force
cd build

cmake .. -G "Visual Studio 18 2026" -A x64
cmake --build . --config Release

产物路径:build/Release/OpticsFEM.exe

8.3 运行时目录结构

散射算例bele最小部署结构

Release/
├── OpticsFEM.exe
├── bele.json              # 输入配置(文件名与 Test_Main.cpp 中 fd.open 一致)
├── project_3.dat          # 网格(与 JSON 中 MeshFile 一致)
└── complex/
    └── complexsolver.exe  # 外部线性求解器(运行时必需)

本征算例另需:

real_solver/real          # 或 real_solver 目录下对应可执行文件
complex_solver/complex

8.4 关于 eigen_solver 静态链接

当前工程已将 solver/eigen_solver.cpp 编入可执行文件,并通过宏 EIGENSOLVER_STATIC 取消 DLL 导入/导出修饰,不再依赖 lib/eigensolver.lib。该模块服务于本征模式/本征频率问题(realEigenSolver / complexEigenSolver),运行时仍依赖 real_solver/complex_solver/ 目录下的外部可执行文件。


9. 算例运行指南

9.1 标准运行步骤

步骤 1 — 编译

执行第 8.2 节构建命令,确认生成 OpticsFEM.exe

步骤 2 — 配置入口 JSON 文件名

编辑 test/Test_Main.cpp 第 28 行:

fd.open("bele.json");   // 改为目标算例 JSON 文件名

修改后须重新编译。

步骤 3 — 部署输入文件

将 JSON 及 MeshFile 指定的 .dat 文件复制至 build/Release/ 目录。

步骤 4 — 部署外部求解器

complex/complexsolver.exe 置于 Release/complex/ 目录(路径相对于工作目录)。

步骤 5 — 执行

cd build/Release
.\OpticsFEM.exe

步骤 6 — 验证输出

检查 OutFile/ 目录是否生成 ExEyEznormE

9.2 切换算例

操作 说明
更换 JSON 修改 Test_Main.cppfd.open() 文件名,或使用同名复制
更换网格 确保 JSON 中 MeshFile 字段与实际 .dat 文件名一致
更换问题类型 修改 JSON 中 FemType;程序自动路由至对应求解分支

测试数据集位于 测试数据集/ subdirectory 名称即边界/物理类型(如 bele/scd/pml_xy/)。


10. 代码阅读路径

建议按以下顺序阅读,以建立自入口至输出的完整认知:

序号 文件 阅读目标
1 test/Test_Main.cpp 进程入口、JSON 文件读取
2 Interface/FEM_Interface.cpp FemType 路由、三阶段调度
3 test/Test_ReadData.cpp JSON 字段解析逻辑
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.cppFemType 分支入口设置断点,确认路由正确;
  • Assemble() 返回后检查矩阵非零元数量(Test_OutputMatrix() 已在散射分支调用);
  • Post() 返回后检查 OutFile/ 目录。

11. 求解器依赖说明

11.1 求解器分层

层级 模块 适用问题 运行时依赖
特征值求解 eigen_solver.cpp FemType 0, 1 real_solver/real, complex_solver/complex
线性方程组(实) interface.cpp::solveRealLinearEqu 实散射 real/realsolver.exe
线性方程组(复) interface.cpp::solveComplexLinearEqu 复散射bele complex/complexsolver.exe

11.2 外部求解器调用机制

interface.cpp 采用文件交换方式与外部求解器通信:

  1. 将 CSR 格式矩阵、右端项写入当前目录临时文件;
  2. 通过 system() 调用外部 .exe
  3. 读取解向量临时文件;
  4. 清理临时文件。

因此,外部求解器必须与 OpticsFEM.exe 工作目录相对路径正确对应,且具备可执行权限。


12. 常见问题与排查

现象 可能原因 处理措施
cmake 无法识别 CMake 未加入 PATH 使用 VS 自带 CMake 完整路径,或配置环境变量
LNK1181: eigensolver.lib 旧版 CMakeLists 仍链接外部库 确认已启用 EIGENSOLVER_STATIC 并编入 eigen_solver.cpp
运行无输出、无 OutFile 缺少 complexsolver.exe 或路径错误 检查 complex/ 目录及工作目录
无法打开 bele.json 工作目录不含 JSON Release/ 目录下运行,或复制输入文件
无法打开 project_3.dat MeshFile 路径不匹配 确保 .dat 与 exe 同目录,或修正 JSON
编译警告 C4819 Eigen 头文件编码 不影响功能,可忽略
FemType 返回 0 打印 err JSON 缺少或错误 FemType 字段 检查 JSON 完整性

附录 AFemType 路由对照表

FemType 求解器类 后处理类 关键 JSON 参数
0 Solver_EigenMode Post_2D_EigenMode lambda0, NbrMode, searchValue
1 Solver_EigenFreq Post_2D_EigenFreq lambda0, NbrMode, searchValue
2 Solver_LdaDom Post_2D_Scatter lambda, 边界字段
3 Solver_LdaDom Post_2D_Scatter freq, 边界字段

附录 B文档修订记录

版本 日期 修订内容
v1.0 2026-06-03 初版:构建流程、架构、数据流、部署与算例指南

本文档基于 opticsfem-master 当前代码状态编制,若 CMakeLists 或 API 发生变更,请同步更新相应章节。