XIAN-FEM-2026June/代码理解/Test_Main.cpp理解.md

264 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Test_Main.cpp 代码理解
> 文件路径:`opticsfem-master/test/Test_Main.cpp`
> 作用OpticsFEM 程序的**主测试入口**,负责读取 JSON 配置文件并调用统一 API 完成有限元全流程。
---
## 1. 整体结论
当前版本中,`main` 函数真正有效的逻辑只有两块:
1. **读取 JSON 配置文件**`bele.json`
2. **调用 `OpticsFEM_API::OpticsFEM_All`** 执行完整求解流程
第 1722 行声明的 `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. 文件结构概览
| 行号 | 内容 | 是否必要 |
|------|------|----------|
| 16 | 引入 phy / material / mesh / kernel / solver / post 头文件 | 当前不必需(旧代码遗留) |
| 7 | 引入 `FEM_Interface.h` | **必要** |
| 912 | 标准库:文件流、字符串等 | **必要** |
| 1722 | 声明物理、材料、网格、FEM、求解器、后处理对象 | **不必需** |
| 2429 | 读取 `bele.json` | **必要** |
| 3137 | 构造 `OpticsFEMData` 并调用 API | **必要** |
| 3957 | 注释掉的旧版手动流程 | 历史参考,不参与运行 |
| 59 | `return 1` | 程序正常退出 |
---
## 3. 头文件说明
### 3.1 当前实际需要的头文件
- `../Interface/FEM_Interface.h`:定义 `OpticsFEMData` 结构体和 `OpticsFEM_API`
- `<fstream>`、`<string>`:读取 JSON 文件
### 3.2 遗留头文件16 行)
| 头文件 | 对应模块 |
|--------|----------|
| `Phy_Base.h` | 波动光学物理模型(边界条件、激励等) |
| `Material_Base.h` | 材料库 |
| `Mesh_Base.h` | 二维网格 |
| `Assemble_Base.h` | 有限元组装 |
| `Solver_Base.h` | 求解器 |
| `Post_Base.h` | 后处理与结果输出 |
这些头文件服务于注释掉的旧代码(第 3957 行),在现行 API 调用方式下可以移除。
---
## 4. 第 1722 行:遗留对象声明
```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 读取(第 2429、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 调用(第 3137 行)
```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. 注释掉的旧版流程(第 3957 行)
旧写法在 `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` 自动完成;第 1722 行及注释代码为历史遗留,理解架构时可忽略。