# Test_Main.cpp 代码理解 > 文件路径:`opticsfem-master/test/Test_Main.cpp` > 作用:OpticsFEM 程序的**主测试入口**,负责读取 JSON 配置文件并调用统一 API 完成有限元全流程。 --- ## 1. 整体结论 当前版本中,`main` 函数真正有效的逻辑只有两块: 1. **读取 JSON 配置文件**(`bele.json`) 2. **调用 `OpticsFEM_API::OpticsFEM_All`** 执行完整求解流程 第 17–22 行声明的 `phy`、`matLab`、`mesh`、`fem`、`solver`、`post` 对象在当前代码中**未被使用**,属于旧版手动分步调用留下的冗余代码。这些对象的创建与使用已在 `Interface/FEM_Interface.cpp` 的 `OpticsFEM_All` 函数内部完成。 精简后的核心逻辑等价于: ```cpp ifstream fd; std::string str; fd.open("bele.json"); getline(fd, str); OpticsFEMData data; data.data = (char*)str.data(); OpticsFEM_API::OpticsFEM_All(data); ``` --- ## 2. 文件结构概览 | 行号 | 内容 | 是否必要 | |------|------|----------| | 1–6 | 引入 phy / material / mesh / kernel / solver / post 头文件 | 当前不必需(旧代码遗留) | | 7 | 引入 `FEM_Interface.h` | **必要** | | 9–12 | 标准库:文件流、字符串等 | **必要** | | 17–22 | 声明物理、材料、网格、FEM、求解器、后处理对象 | **不必需** | | 24–29 | 读取 `bele.json` | **必要** | | 31–37 | 构造 `OpticsFEMData` 并调用 API | **必要** | | 39–57 | 注释掉的旧版手动流程 | 历史参考,不参与运行 | | 59 | `return 1` | 程序正常退出 | --- ## 3. 头文件说明 ### 3.1 当前实际需要的头文件 - `../Interface/FEM_Interface.h`:定义 `OpticsFEMData` 结构体和 `OpticsFEM_API` 类 - ``、``:读取 JSON 文件 ### 3.2 遗留头文件(1–6 行) | 头文件 | 对应模块 | |--------|----------| | `Phy_Base.h` | 波动光学物理模型(边界条件、激励等) | | `Material_Base.h` | 材料库 | | `Mesh_Base.h` | 二维网格 | | `Assemble_Base.h` | 有限元组装 | | `Solver_Base.h` | 求解器 | | `Post_Base.h` | 后处理与结果输出 | 这些头文件服务于注释掉的旧代码(第 39–57 行),在现行 API 调用方式下可以移除。 --- ## 4. 第 17–22 行:遗留对象声明 ```cpp Phy_WaveOpticsModel phy; // 物理模型(边界、PML、背景场等) MaterialLib matLab; // 材料库(ε、μ 等) Mesh_2D mesh; // 二维网格 OpticsFEM_2D_EigenFreq fem; // 本征频率 FEM 内核 Solver_EigenFreq solver; // 本征频率求解器 Post_2D_EigenFreq post; // 本征频率后处理 ``` ### 含义 - `Phy_WaveOpticsModel` 是**类名**(波动光学物理模型),`phy` 是该类的一个**对象实例** - 其余同理:`MaterialLib matLab` 表示创建一个名为 `matLab` 的材料库对象 ### 为何不需要 `OpticsFEM_All` 内部会根据 JSON 中的 `FemType` 自行创建对应类型的对象,例如: | FemType | FEM 内核 | 求解器 | 后处理 | |---------|----------|--------|--------| | 0 | `OpticsFEM_2D_EigenMode` | `Solver_EigenMode` | `Post_2D_EigenMode` | | 1 | `OpticsFEM_2D_EigenFreq` | `Solver_EigenFreq` | `Post_2D_EigenFreq` | | 2 / 3 | `OpticsFEM_2D_Scatter` | `Solver_LdaDom` | `Post_2D_Scatter` | 因此 `main` 里写死 `EigenFreq` 类型的声明既不会被用到,也无法适配其他题型。 --- ## 5. JSON 读取(第 24–29、35 行) ```cpp ifstream fd; std::string str; fd.open("bele.json"); getline(fd, str); data.data = (char*)str.data(); ``` ### 流程 1. 打开当前工作目录下的 `bele.json` 2. 用 `getline` 将文件内容读入字符串 `str`(项目中的 JSON 为单行格式) 3. 将 `str` 的指针写入 `OpticsFEMData.data`,传递给 API ### `bele.json` 是什么 总配置文件,包含一次有限元计算所需的全部参数,例如: | 字段 | 含义 | |------|------| | `FemType` | 计算类型(0 本征模 / 1 本征频率 / 2、3 散射) | | `MeshFile` | 网格文件路径(如 `project_3.dat`) | | `OutFile` | 结果输出目录 | | `BoundaryFlag`、`pml`、`bele` | 边界条件、吸收层、背景场 | | `epsilonrR`、`murR` 等 | 材料参数 | | `solverType`、`tol` 等 | 求解器设置 | ### 注意 - `main` 中**不解析** JSON 字段,解析工作在 `OpticsFEM_All` 内部完成 - `str` 必须在 API 调用期间保持有效(当前 `main` 满足此条件) - 运行前需确保 exe 工作目录下存在 `bele.json`,且 JSON 中引用的 `MeshFile` 等文件路径可访问 --- ## 6. femAPI 调用(第 31–37 行) ```cpp OpticsFEM_API femAPI; OpticsFEMData data; data.test1 = 1; data.test2 = 2; data.data = (char*)str.data(); femAPI.OpticsFEM_All(data); ``` ### OpticsFEMData:数据包裹 定义于 `Interface/FEM_Interface.h`: ```cpp struct OpticsFEMData { double test1; double test2; char* data; // 唯一实际使用的字段:JSON 字符串指针 }; ``` 设计目的是便于 DLL 对外暴露接口,外部程序(Python、MATLAB 等)只需传入 JSON 指针即可调用,无需直接依赖各模块头文件。`test1`、`test2` 为占位字段,当前实现未使用。 ### OpticsFEM_All:统一全流程入口 定义于 `Interface/FEM_Interface.cpp`,主要步骤: ``` 收到 JSON 字符串 ↓ nlohmann::json 解析,读取 FemType ↓ 创建 phy、matLab、mesh,从 JSON 填充 ↓ 按 FemType 选择 fem / solver / post ↓ GetMaterial / GetMesh / GetPhy / GetSolver / GetPost ↓ Assemble() → Run() → Post(OutFile) ↓ 返回状态码(0=错误,1/2/3=不同题型成功) ``` ### femAPI 对象是否必要 `OpticsFEM_All` 是静态成员函数,以下写法等价且更简洁: ```cpp OpticsFEM_API::OpticsFEM_All(data); ``` --- ## 7. 注释掉的旧版流程(第 39–57 行) 旧写法在 `main` 中手动完成 API 内部的各步骤: ``` phy/matLab/solver/mesh 从 JSON 读数据 ↓ fem 挂载各模块指针 ↓ Assemble → Test_OutputMatrix → Run → Post ``` 缺点: - 题型写死为本征频率(`OpticsFEM_2D_EigenFreq`) - 步骤分散在 `main` 中,不便复用和对外封装 现行 API 方式将上述逻辑收拢到 `OpticsFEM_All`,`main` 仅负责读文件和调接口。 --- ## 8. 执行流程图 ``` Test_Main.cpp (main) │ ├─ 打开 bele.json ├─ 读入 JSON 字符串 str ├─ 填入 OpticsFEMData.data │ └─ OpticsFEM_All(data) ← Interface/FEM_Interface.cpp │ ├─ 解析 JSON,读 FemType / MeshFile / OutFile ├─ phy.Test_ReadData(str) ├─ matLab.Test_ReadData(str) ├─ mesh.GetMesh(meshFile, str) │ ├─ [FemType 分支] 创建对应 fem / solver / post ├─ 挂载模块 → Assemble() → Run() → Post(outFile) │ └─ 输出结果到 OutFile 目录 ``` --- ## 9. 运行前提 1. 可执行文件工作目录下存在 `bele.json`(测试数据位于 `测试数据集/bele/bele.json`) 2. JSON 中 `MeshFile` 指向的网格文件存在且路径正确 3. 输出目录(`OutFile` 字段)可写 --- ## 10. 相关源文件 | 文件 | 关系 | |------|------| | `Interface/FEM_Interface.h` | API 与数据结构定义 | | `Interface/FEM_Interface.cpp` | `OpticsFEM_All` 全流程实现 | | `test/Test_ReadData.cpp` | phy / matLab 等模块的 JSON 解析实现 | | `phy/Phy_Base.h` | 物理模型类定义 | | `测试数据集/bele/bele.json` | 示例配置文件(FemType=2,散射问题) | --- ## 11. 一句话总结 `Test_Main.cpp` 是 OpticsFEM 的薄入口:**读 JSON → 调 `OpticsFEM_All`**。物理、材料、网格、组装、求解、后处理均由 API 内部按 `FemType` 自动完成;第 17–22 行及注释代码为历史遗留,理解架构时可忽略。