447 lines
10 KiB
Markdown
447 lines
10 KiB
Markdown
# Learnings
|
||
|
||
Corrections, insights, and knowledge gaps captured during development.
|
||
|
||
**Categories**: correction | insight | knowledge_gap | best_practice
|
||
**Areas**: frontend | backend | infra | tests | docs | config
|
||
**Statuses**: pending | in_progress | resolved | wont_fix | promoted | promoted_to_skill
|
||
|
||
## Status Definitions
|
||
|
||
| Status | Meaning |
|
||
|--------|---------|
|
||
| `pending` | Not yet addressed |
|
||
| `in_progress` | Actively being worked on |
|
||
| `resolved` | Issue fixed or knowledge integrated |
|
||
| `wont_fix` | Decided not to address (reason in Resolution) |
|
||
| `promoted` | Elevated to CLAUDE.md, AGENTS.md, or copilot-instructions.md |
|
||
| `promoted_to_skill` | Extracted as a reusable skill |
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F01] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
Fortran 1-indexed 转 Rust 0-indexed 的关键规则
|
||
|
||
### Details
|
||
- 数组访问: `arr(i)` → `arr[i-1]`
|
||
- 循环范围: `DO I=1,N` → `for i in 0..n`
|
||
- 边界条件: Fortran jl=0 表示"在第一个有效索引之前",Rust jl=0 就是第一个有效索引
|
||
|
||
### Suggested Action
|
||
重构时删除类似 `IF (J.EQ.0) J = J+1` 的调整逻辑
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: ylintp.f, locate.f
|
||
- Tags: indexing, fortran, rust
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F02] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
Fortran 表达式 `-LOG(X)` 是 `-(LOG(X))`,不是 `LOG(-X)`
|
||
|
||
### Details
|
||
`XL=-LOG(X)` 应翻译为 `let xl = -x.ln()`,不是 `let xl = (-x).ln()`
|
||
后者对 x>0 会返回 NaN
|
||
|
||
### Suggested Action
|
||
翻译数学表达式时注意运算符优先级
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: erfcin.f
|
||
- Tags: expression, fortran, rust
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F03] insight
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
`(z1 - z2).powi(2)` 编译错误 - 类型推断失败
|
||
|
||
### Details
|
||
编译器无法推断中间表达式的类型,使用显式乘法 `(z1 - z2) * (z1 - z2)` 代替
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Tags: rust, type_inference, powi
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F04] best_practice
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: tests
|
||
|
||
### Summary
|
||
多项式近似精度容差:简单函数 1e-10,多项式 1e-7
|
||
|
||
### Details
|
||
Abramowitz-Stegun 多项式近似本身精度有限
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: eint.f
|
||
- Tags: precision, polynomial, testing
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F05] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
递减循环变量用 isize 不用 usize,避免溢出
|
||
|
||
### Details
|
||
当循环变量递减到负数时,无符号整数会溢出
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: collhe.f
|
||
- Tags: overflow, rust, loop
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F06] best_practice
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
重构前必须检查所有 INCLUDE 语句,不仅是 IMPLIC.FOR
|
||
|
||
### Details
|
||
已确认有 COMMON 依赖的"纯函数"文件:
|
||
gamsp.f, sgmer1.f, sgmerd.f, cross.f, gfree0.f, gfreed.f, gfree1.f, wn.f, crossd.f, dopgam.f, verner.f, sbfhe1.f
|
||
|
||
### Suggested Action
|
||
添加新结构体前先 grep 检查是否已存在
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Tags: common, fortran, dependency
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F07] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: tests
|
||
|
||
### Summary
|
||
测试数组值不能全部相同,会导致除零
|
||
|
||
### Details
|
||
```rust
|
||
// 错误:全部相同 → ddm = 0 → dtm = 1/0 = inf
|
||
let dm = vec![0.01; MDEPTH];
|
||
|
||
// 正确:递增模拟物理分布
|
||
let dm: Vec<f64> = (0..MDEPTH).map(|i| 0.01 + i as f64 * 0.01).collect();
|
||
```
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: rybmat.rs
|
||
- Tags: testing, data_design
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F08] insight
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
Fortran 修改 COMMON 块数组 → Rust 需要 &mut 引用
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: tabint.f
|
||
- Tags: rust, mutability, reference
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F09] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: config
|
||
|
||
### Summary
|
||
analyze_fortran.py 只匹配 CALL 语句,漏掉 FUNCTION 调用
|
||
|
||
### Details
|
||
需要两遍扫描:1) 收集所有已定义函数名 2) 只匹配已知函数名
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: scripts/analyze_fortran.py
|
||
- Tags: dependency, analysis, python
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F10] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: tests
|
||
|
||
### Summary
|
||
测试参数设置时避免矩阵列重叠
|
||
|
||
### Details
|
||
主循环更新列和温度/密度列可能重叠,设置 inre=0, inpc=0 避免重叠
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: bpopf.rs
|
||
- Tags: testing, matrix, indexing
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F11] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
公式中 `1/x` 和 `x` 的顺序要仔细核对
|
||
|
||
### Details
|
||
`5.484e-14 / x2 * (...)` 其中 x2=1/x²,等于乘以 x²,不是除以
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: rayleig.f
|
||
- Tags: formula, rust, physics
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F12] best_practice
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
大型 COMMON 块函数使用生命周期结构体
|
||
|
||
### Details
|
||
```rust
|
||
pub struct Alifr3ModelState<'a> {
|
||
pub elec: &'a [f64], // 输入
|
||
pub heit: &'a mut [f64], // 输出
|
||
}
|
||
```
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: alifr3.rs, alifr6.rs
|
||
- Tags: rust, struct, lifetime
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F13] insight
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
Fortran GOTO 分支 → Rust if-else + early return
|
||
|
||
### Details
|
||
每个 GOTO 标签对应一个 if 块
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Tags: fortran, goto, control_flow
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F14] correction
|
||
|
||
**Logged**: 2026-03-21T19:55:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
循环中重新赋值的变量必须声明为 mut
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: alifr6.rs
|
||
- Tags: rust, mutability
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F15] correction
|
||
|
||
**Logged**: 2026-03-21T12:00:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
Fortran 3D 数组转 Rust 扁平数组时,必须知道所有维度才能正确计算索引
|
||
|
||
### Details
|
||
Fortran `absopac(jt,jr,jf)` 是 3D 数组 (numtemp × numrh × nfreq),转 Rust 扁平数组时:
|
||
- **错误**: 用 `jt_idx * numtemp * nfreq` (用了 numtemp 作为第二维度)
|
||
- **正确**: 用 `jt_idx * max_numrh * nfreq` (必须用实际维度 max_numrh)
|
||
|
||
类似地,2D 数组 `rhomat(jt,jr)` 转扁平时:
|
||
- **错误**: `rhomat[jt_idx * numtemp]`
|
||
- **正确**: `rhomat[jt_idx * max_numrh]`
|
||
|
||
### Suggested Action
|
||
重构多维数组时,结构体必须包含所有维度信息,特别是可能变化的维度(如每个温度有不同的密度数)
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: opctab.rs, opctab.f
|
||
- Tags: array, indexing, fortran, rust, multi-dimensional
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F16] correction
|
||
|
||
**Logged**: 2026-03-21T12:00:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
Fortran 条件 `if(a.eq.b)` 转 Rust 时不要误用其他变量
|
||
|
||
### Details
|
||
Fortran `if(numtemp.eq.nd)` 检查表温度数是否等于总深度数:
|
||
- **错误**: `if table.numtemp == params.id` (用了当前深度索引)
|
||
- **正确**: `if table.numtemp == table.nd` (用总深度数)
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: opctab.rs, opctab.f
|
||
- Tags: condition, variable, fortran, rust
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F17] correction
|
||
|
||
**Logged**: 2026-03-21T12:00:00Z
|
||
**Priority**: high
|
||
**Status**: resolved
|
||
**Area**: backend
|
||
|
||
### Summary
|
||
分支条件相同代码是 bug,必须对照 Fortran 完整实现
|
||
|
||
### Details
|
||
`if params.ibc == 0 { ... } else { ... }` 两个分支代码完全相同时是错误的。
|
||
|
||
Fortran 原代码 ELSE 分支有额外项:
|
||
```fortran
|
||
REIT(ID)=REIT(ID)+WW*(D0*(DSFT1-DBDT)+E0*DABT1(ID)+
|
||
* RAD1(ID)*DABT1(ID)-DEMT1(ID)+
|
||
* ALI1(ID)/ABST*DBDT)
|
||
```
|
||
|
||
变量 `DBDT` 和 `E0` 在边界条件块中计算,需要在更大作用域中声明才能在积分方程块中使用。
|
||
|
||
### Suggested Action
|
||
重构时如果看到 if-else 分支代码相同,立即检查 Fortran 原代码
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: alifr1.rs, alifr1.f
|
||
- Tags: branch, bug, fortran, rust
|
||
|
||
---
|
||
|
||
## [LRN-20260321-F18] best_practice
|
||
|
||
**Logged**: 2026-03-21T12:00:00Z
|
||
**Priority**: medium
|
||
**Status**: resolved
|
||
**Area**: docs
|
||
|
||
### Summary
|
||
模块文档应完整描述所有功能,不仅是主要功能
|
||
|
||
### Details
|
||
opctab.rs 原文档只提到"插值计算",漏掉了:
|
||
- Rayleigh 散射计算(简单公式或调用 rayleigh 函数)
|
||
- 电子散射计算
|
||
|
||
### Suggested Action
|
||
重构完成后对照 Fortran 原代码检查文档是否完整
|
||
|
||
### Metadata
|
||
- Source: fortran-to-rust refactoring
|
||
- Related Files: opctab.rs, opctab.f
|
||
- Tags: documentation, completeness
|
||
|
||
---
|
||
|
||
## Quick Reference - Refactoring Checklist
|
||
|
||
重构新函数前检查:
|
||
|
||
- [ ] 是否有 INCLUDE 语句 (除 IMPLIC.FOR 外)
|
||
- [ ] 是否使用 COMMON 块
|
||
- [ ] COMMON 块结构体是否已存在于其他模块
|
||
- [ ] 是否有文件 I/O (OPEN, READ, WRITE)
|
||
- [ ] 数组索引是否需要 -1 调整
|
||
- [ ] 循环变量是否可能变负 (用 isize/i32)
|
||
- [ ] 多项式近似精度是否需要放宽
|
||
- [ ] 是否有嵌套 IF 分支遗漏
|
||
- [ ] 矩阵列索引是否可能与温度/密度列重叠
|
||
- [ ] 公式中 `1/x` 和 `x` 的顺序是否正确
|
||
- [ ] 大型 COMMON 块函数是否需要创建综合输入结构体
|
||
- [ ] 多分支 GOTO 是否正确转换为 if-else
|
||
- [ ] 循环中重新赋值的变量是否声明为 mut
|
||
- [ ] 多维数组扁平化时是否使用了正确的维度(不是第一个维度)
|
||
- [ ] 条件语句中的变量是否与 Fortran 原代码一致
|
||
- [ ] 模块文档是否描述了所有功能(包括次要功能)
|
||
- [ ] if-else 分支代码是否完全相同(相同则是 bug)
|
||
- [ ] 边界条件块中计算的变量是否在积分方程块中可用(作用域问题)
|