dsh-motor-ai-l0 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +61 -5
- package/docs/ENGINEERING.md +1 -1
- package/docs/QUALITY-GATE.md +4 -1
- package/examples/01-y2-15kw-1460rpm.md +70 -0
- package/examples/02-75kw-1480rpm-660v.md +74 -0
- package/examples/03-pmsm-200kw-22000rpm.md +66 -0
- package/examples/README.md +42 -0
- package/index.mjs +3 -1
- package/lib/design-rules.mjs +26 -0
- package/lib/formula-engine.mjs +14 -0
- package/lib/param-schema.mjs +3 -1
- package/lib/surrogate-engine.mjs +63 -5
- package/models/l0_surrogate_family.json +162678 -238
- package/package.json +15 -3
- package/scripts/_publish_0_2_3.py +67 -0
- package/scripts/verify.mjs +160 -2
- package/skills/motor-l0-estimate/SKILL.md +11 -3
- package/skills/motor-l0-estimate/references/formula-reference.md +14 -2
- package/tools/l0/design-validate.mjs +5 -2
- package/tools/l0/index.mjs +11 -2
- package/tools/l0/l0-estimate.mjs +59 -12
- package/tools/l0/param-matrix.mjs +73 -3
- package/tools/l0/pipeline.mjs +213 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,39 @@
|
|
|
5
5
|
|
|
6
6
|
版本三重一致性:`package.json.version` = `SKILL.md` 的 `metadata.version` = `CHANGELOG.md` 最新条目。
|
|
7
7
|
|
|
8
|
+
## [0.2.4] - 2026-10-07 — 代理模型 v2.3.0-fixseg 部署 + GBR 残差校正启用
|
|
9
|
+
|
|
10
|
+
### 🚀 代理模型升级:v2.2.0 → v2.3.0-fixseg
|
|
11
|
+
- **特征空间扩展**:5 特征(含 `poles`),OD 三分位切段(small/medium/large × induction/pmsm)。
|
|
12
|
+
- **模型锁定**:云端重训流水线锁定 `scikit-learn==1.9.1`(`numpy==2.5.0` / `scipy==1.18.1`),复现 G7 门禁(纯 numpy 回放 vs sklearn 重训 maxdiff < 1e-6)。
|
|
13
|
+
- **校验**:`verify.mjs` 70/70 通过;代理模型版本断言 `2.3.0-fixseg`。
|
|
14
|
+
|
|
15
|
+
### ✨ 新能力:GBR 残差校正(ridge_plus_gbr 第二阶段)
|
|
16
|
+
- `lib/surrogate-engine.mjs` 新增 `predictGBR()`,消费模型每段 `gbr` 字段(400 树 / `lr=0.05`),对 ridge 基线做残差修正:`final = primary + gbr_residual`。
|
|
17
|
+
- 单测新增 4 例(无 gbr 退化为 0、残差量级合理、预测携带 `used_gbr` / `gbr_residual_pp`),单测 18 → 22 全绿。
|
|
18
|
+
- 置信度门控维持 ridge 通道口径(不放大降级),仅提升预测精度。
|
|
19
|
+
|
|
20
|
+
### 🔧 工程
|
|
21
|
+
- `tools/l0/pipeline.mjs` 聚合工具随包发布(一步跑完 `buildParamMatrix → runDesignValidate → runL0Estimate`,规避 DSH 2000 行截断)。
|
|
22
|
+
- 版本三重一致性:package.json / SKILL.md metadata / CHANGELOG 同步至 0.2.4。
|
|
23
|
+
|
|
24
|
+
### ⚠️ 不在本次发布范围
|
|
25
|
+
- V16(极数-转速同步一致性校验)等规则层改动仍在开发中,未并入本版本,避免裹挟未经验证的变更。
|
|
26
|
+
|
|
27
|
+
## [0.2.3] - 2026-09-27 — 默认通道回归修复 + 对外物料(推广就绪)
|
|
28
|
+
|
|
29
|
+
### 🔴 P0 回归修复:`auto` 不再进入代理通道
|
|
30
|
+
- **现象**:0.2.2 把 `l0Mode='auto'` 纳入代理分支后,异步机默认输出严重残缺 —— `temp_rise=0`、`tooth_flux_density`/`yoke_flux_density`/`power_factor` 全 `undefined`、`feasible_count=0`(120 个候选无一可行),且 `sort_by='temp_rise'/'total_loss'/'torque_density'` 全部退化为 0,排序失效。
|
|
31
|
+
- **根因**:`buildSurrogateResult()` 只输出 `efficiency` 一项,温升 / 损耗 / 磁密 / 可行判定均为 0 或缺失。代理通道本就只适合"效率排序",不适合做默认。
|
|
32
|
+
- **修复**:`tools/l0/l0-estimate.mjs:72` 代理分支条件回退为仅 `l0Mode === 'surrogate'`;`auto` 走字段完整的公式通道。代理模型 v2.2.0 与显式 `surrogate` 通道保持可用。
|
|
33
|
+
- **验证**:`verify.mjs` 61/61 通过;异步 15kW/1460rpm `auto` → `feasible_count=80`、Top1 效率 95.17% / 温升 14.6K / 轭磁密 1.39T(字段完整)。
|
|
34
|
+
|
|
35
|
+
### 📣 对外物料(推广就绪)
|
|
36
|
+
- **README**:删除 0.1.7 时代过时的「surrogate 实验特性 / cv_r2≈0 / 特征泄漏」警告,替换为 v0.2.2 真实指标表(异步三段 OD 覆盖 / 样本数 / CV R² / MAE,PMSM 自动降级);新增价值主张、示例输出(15kW 实跑 16 ms Top5)、通道分工表、明确不适用工况表;配置表补 `surrogatePath` / `surrogateConfidenceThreshold`。
|
|
37
|
+
- **examples/**(新增,随包发布):3 个真实算例 —— ① 15kW/1460rpm 异步(80 可行,16 ms)② 75kW/1480rpm/660V 异步(效率封顶并列时的二次排序)③ **200kW/22000rpm 高速 PMSM 反例**(`recommended=null`,公开能力边界)。
|
|
38
|
+
- **keywords**:9 → 20(补 `induction-motor` `motor-sizing` `ansys` `电机设计` `永磁同步电机` `异步电机` 等中英文关键词)。
|
|
39
|
+
- **assets/marketplace-listing.md**:0.1.0 → 0.2.2,重写 listing 文案、实测性能表、截图清单、npm 检查清单(含 npmjs 官方源踩坑提示)。
|
|
40
|
+
|
|
8
41
|
## [0.2.2] - 2026-09-26 — 代理通道修复(模型 v2.2.0)
|
|
9
42
|
|
|
10
43
|
### 🔴 P0 修复:代理模型 coef 空间错位(0.2.1 升级不可用根因)
|
package/README.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
`dsh-motor-ai-l0` · DSH 插件(bundle) · 纯 JS,零求解器依赖
|
|
4
4
|
|
|
5
|
+
> **不装 RMxprt / Motor-CAD / Python / license,把 120 个候选在十几毫秒内压成 Top5,
|
|
6
|
+
> 只把求解器时间花在最值得的那几个上。**
|
|
7
|
+
|
|
8
|
+
📁 **[算例集:3 个真实算例(含反例)→ examples/](examples/README.md)** · [能力边界](#已知精度边界)
|
|
9
|
+
|
|
5
10
|
覆盖电机设计全流程:需求解析 → 参数识别 → 候选矩阵 → L0/L1/L2 解算 → Top10 与校验 → 完整方案。
|
|
6
11
|
L0 用代理模型与经验公式毫秒级广筛候选;L1 RMxprt、L2 Motor-CAD 为**可选**精算工具。
|
|
7
12
|
装完即用 —— 无需预装 RMxprt / Motor-CAD / Python,无需 license。
|
|
@@ -22,10 +27,30 @@ node scripts/verify.mjs
|
|
|
22
27
|
2. `motor_design_validate` —— 批量物理校验,剔除 `failed`
|
|
23
28
|
3. `motor_l0_estimate` —— 对剩余候选排序,输出 TopN 与 L1 交接载荷
|
|
24
29
|
|
|
30
|
+
> ⚠️ **推荐用聚合工具 `motor_l0_pipeline` 一步跑完上述三步链**。DSH 对话上下文有 **2000 行读取上限**:
|
|
31
|
+
> 当 `count=120` 时,单 `motor_param_matrix` 就回显 4000+ 行,模型静默丢行后计数对不上 120 还**无报错**——
|
|
32
|
+
> 这是「让模型亲手编排三步链」的结构性风险(三案例实战全中)。聚合工具在插件进程内跑完三步链,
|
|
33
|
+
> 只回吐紧凑摘要(计数自检 + Top10 + 交接载荷 + 文件交接路径),上下文恒 < 2000 行,从根上绕开截断。
|
|
34
|
+
> 只有在单独调试某一步(查完整校验报告、手调 failed 阈值)时才拆开用三个独立工具。
|
|
35
|
+
|
|
25
36
|
> ⚠️ `motor_l0_estimate` 只接受 `params_list`(每项含 16 个 L1 顶层字段),**不接受** `power_kw` / `speed_rpm` 这类散装命名参数 —— 请先用第 1 步生成矩阵再传入。
|
|
26
37
|
> L0 结果只用于**排序与相对比较**,不用于绝对值交付;输出恒带 `solve_mode='l0'` 标记,最终结论须由 L1/L2 给出。
|
|
27
38
|
>
|
|
28
|
-
>
|
|
39
|
+
> **两条通道的分工(v0.2.2)**
|
|
40
|
+
>
|
|
41
|
+
> | 通道 | 触发 | 输出 | 适用 |
|
|
42
|
+
> |---|---|---|---|
|
|
43
|
+
> | **公式通道**(默认) | `l0Mode: 'auto'` / `'formula'` | 效率 + 温升 + 损耗拆分 + 齿/轭磁密 + 功率因数 + 可行判定 —— 字段完整 | 日常排序与相对比较 |
|
|
44
|
+
> | **代理通道**(可选增强) | `l0Mode: 'surrogate'` | **仅效率**(温升/损耗/磁密不输出) | 异步机效率排序的交叉参考 |
|
|
45
|
+
>
|
|
46
|
+
> 代理模型 v2.3.0-fixseg(在 v2.2.0 基础上用全量 6029 条真实 RMxprt 结果重训,特征扩为含 `poles` 的 5 维;`designs.db.l0_residuals`,`fault=0`,效率 ∈ [50,99]),按机座外径分三段:
|
|
47
|
+
>
|
|
48
|
+
> | 机种 | 样本 OD 覆盖 | 样本数 | 5 折 CV R² | MAE |
|
|
49
|
+
> |---|---|---|---|---|
|
|
50
|
+
> | 异步 small / medium / large | 150.6–756.5 / 151.3–1085.4 / 1196–2651 mm | 1291 / 2578 / 1276 | 0.652 / 0.438 / 0.670 | 1.44 / 3.29 / 4.53 pp |
|
|
51
|
+
> | PMSM small / medium / large | 612–1178 mm(均为大机座) | 367 / 745 / 355 | ≤ 0.31 → **自动降级公式通道** | — |
|
|
52
|
+
>
|
|
53
|
+
> 因此 **PMSM 与段外样本始终走公式通道**;`auto` 默认走字段完整的公式通道。启用代理时输出带 `surrogate_experimental: true`,且置信度低于阈值(`surrogateConfidenceThreshold`,默认 0.4)自动降级 —— 不会硬给一个数。
|
|
29
54
|
|
|
30
55
|
## 能力边界
|
|
31
56
|
|
|
@@ -41,13 +66,33 @@ node scripts/verify.mjs
|
|
|
41
66
|
|
|
42
67
|
| 工具 | 作用 | 关键入参 |
|
|
43
68
|
|---|---|---|
|
|
69
|
+
| `motor_l0_pipeline` | **推荐入口**:三步链聚合,只回紧凑摘要 + 文件交接,根治 2000 行截断 | `power_kw` `speed_rpm` `count` `top_n` `write_handoff` |
|
|
44
70
|
| `motor_param_matrix` | 生成候选参数矩阵(聚焦扫描,非笛卡尔积) | `power_kw` `speed_rpm` `voltage_v` `poles` `count` |
|
|
45
|
-
| `motor_l0_estimate` | 毫秒级估算 + 排序 + L1
|
|
46
|
-
| `motor_design_validate` |
|
|
71
|
+
| `motor_l0_estimate` | 毫秒级估算 + 排序 + L1 交接载荷(默认 Top10) | `params_list` `top_n` `sort_by` |
|
|
72
|
+
| `motor_design_validate` | 15 条物理一致性校验,返回 `passed`/`warning`/`failed` | `params_list` `escalate` |
|
|
47
73
|
|
|
48
74
|
入参别名:`power`→`power_kw`、`rpm`→`speed_rpm`、`volt`→`voltage_v`。
|
|
49
75
|
`sort_by` 白名单:`efficiency` `torque_density` `temp_rise` `total_loss` `power`(`temp_rise`、`total_loss` 升序,越小越好)。
|
|
50
76
|
|
|
77
|
+
## 示例(15kW / 1460rpm / 380V 异步,实跑 16 ms)
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
$ motor_param_matrix { power_kw: 15, speed_rpm: 1460, voltage_v: 380, motor_type: 'induction', count: 120 } → 120 候选
|
|
81
|
+
$ motor_design_validate 12 条物理校验 → 120 passed / 0 failed
|
|
82
|
+
$ motor_l0_estimate sort_by: 'efficiency' → Top5,80 个可行候选
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
| # | OD (mm) | L (mm) | 极数 | 槽数 | 效率 (%) | 温升 (K) | 轭磁密 (T) | 总损耗 (W) |
|
|
86
|
+
|---|---|---|---|---|---|---|---|---|
|
|
87
|
+
| 1 | 310 | 226.4 | 6 | 72 | 95.17 | 14.6 | 1.39 | 604 |
|
|
88
|
+
| 2 | 327 | 216.6 | 6 | 72 | 95.02 | 14.6 | 1.38 | 628 |
|
|
89
|
+
| 3 | 278 | 187.1 | 6 | 72 | 94.94 | 20.5 | 1.38 | 642 |
|
|
90
|
+
| 4 | 343 | 206.7 | 6 | 72 | 94.89 | 14.7 | 1.38 | 650 |
|
|
91
|
+
| 5 | 294 | 177.2 | 6 | 72 | 94.81 | 20.5 | 1.38 | 663 |
|
|
92
|
+
|
|
93
|
+
→ 这 5 个方案直接作为 L1(RMxprt)的入参,而不是把 120 个全丢给求解器。
|
|
94
|
+
完整算例、复现命令与另外两个工况(75kW 异步、200kW 高速 PMSM **反例**)见 **[`examples/`](examples/README.md)**。
|
|
95
|
+
|
|
51
96
|
## 配置
|
|
52
97
|
|
|
53
98
|
配置位于 `cordis.patch.yml`(查看:`npx -y @deepseek-ai/dsh --profile web --dump-config`)。最常用四项:
|
|
@@ -55,8 +100,10 @@ node scripts/verify.mjs
|
|
|
55
100
|
| 配置项 | 默认 | 说明 |
|
|
56
101
|
|---|---|---|
|
|
57
102
|
| `level` | `'l0'` | 层级总闸。设为 `l1`/`l2` 立即抛错(快速失败,杜绝静默降级) |
|
|
58
|
-
| `l0Mode` | `'auto'` | `formula`
|
|
59
|
-
| `
|
|
103
|
+
| `l0Mode` | `'auto'` | `formula` 纯公式(字段完整)/ `surrogate` 代理模型(**仅输出效率**)/ `auto` = 公式通道,段外与低置信度自动降级 |
|
|
104
|
+
| `surrogatePath` | `'models/l0_surrogate_family.json'` | 代理模型路径(v2.3.0-fixseg) |
|
|
105
|
+
| `surrogateConfidenceThreshold` | `0.4` | 代理置信度门限,低于此值降级公式 |
|
|
106
|
+
| `efficiencyCap` | `96` | 效率封顶(与 L1 同口径,避免两层排序跳变)。v0.2.4 起仅钳**展示值** `efficiency`,排序按 `efficiency_raw`(未封顶真值) |
|
|
60
107
|
| `insulationClass` | `'F'` | 绝缘等级,决定温升限值(B=80K / F=105K / H=125K) |
|
|
61
108
|
|
|
62
109
|
其余配置项(本地统计 `usageLog`;L0 运行 `surrogatePath` / `surrogateConfidenceThreshold` / `maxMatrixSize` / `topNPreview` / `tempRiseRange` / `airGapFluxT` / `highSpeedRpm`;脱敏回传 `telemetryEnabled` / `telemetryEndpoint` / `telemetryBatchSize` / `telemetryIntervalSec` / `sessionTelemetry`)见 [`docs/ENGINEERING.md`](docs/ENGINEERING.md#八配置全表) 与本文「脱敏聚合指标回传」节。
|
|
@@ -108,6 +155,15 @@ telemetryIntervalSec: 300
|
|
|
108
155
|
L0 物理通道目前是 **v0.1 未标定版**(回归质量门判定 DEBT):6 个标定案例效率低于参考带 0.35~2.96pt,温升偏保守。根因是损耗模型尚未用 RMxprt 批量结果标定(铁损未分齿/轭、铜损缺电路约束、机械损未标定、散热筋未计)。
|
|
109
156
|
因此 L0 的正确用法是**排序与相对比较**,不是绝对值采信 —— **排序稳定性优于绝对精度**。完整实算数据与标定计划见 [`docs/QUALITY-GATE.md`](docs/QUALITY-GATE.md)。
|
|
110
157
|
|
|
158
|
+
**明确不适用的工况**(实测,见 [`examples/03`](examples/03-pmsm-200kw-22000rpm.md)):
|
|
159
|
+
|
|
160
|
+
| 工况 | 表现 | 建议 |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| 高速 PMSM(>10000rpm) | 轭部磁路模型外推失真(轭磁密算得 >5 T,物理不可能)、温升 300 K+;门控会拒绝输出任何可行方案(`recommended = null`) | 直接进 L1 / L2 |
|
|
163
|
+
| 效率绝对值交付 | 本版未标定,6 个标定案例偏差 0.35~2.96 pt | 仅排序,绝对值由 L1 复核 |
|
|
164
|
+
|
|
165
|
+
> 门控"宁可交白卷,也不给假答案"是刻意设计:`level` 设为 `l1`/`l2` 时插件立即抛错,绝不静默降级成 L0 结果。
|
|
166
|
+
|
|
111
167
|
## 文档与许可
|
|
112
168
|
|
|
113
169
|
- [`docs/ENGINEERING.md`](docs/ENGINEERING.md) —— 目录结构、字段契约 Param 锁、12 条校验规则、与 Python 体系差异、工程复盘、配置全表、路线图
|
package/docs/ENGINEERING.md
CHANGED
|
@@ -225,7 +225,7 @@ Python 走 `Knowledge/y_series_physics.json` 查表;L0 要求零外部依赖
|
|
|
225
225
|
| `surrogateConfidenceThreshold` | `0.7` | 置信度低于此值自动降级到公式模式 |
|
|
226
226
|
| `maxMatrixSize` | `2000` | 参数矩阵最大组合数 |
|
|
227
227
|
| `topNPreview` | `20` | L0 结果预览返回的 TopN 数量 |
|
|
228
|
-
| `efficiencyCap` | `96` | 效率封顶(对齐 `motor_tools.py:752`,避免 L0/L1
|
|
228
|
+
| `efficiencyCap` | `96` | 效率封顶(对齐 `motor_tools.py:752`,避免 L0/L1 排序跳变)。⚠ v0.2.4 起它只作用于**展示值** `efficiency`;排序与区分度看 `efficiency_raw` |
|
|
229
229
|
| `tempRiseRange` | `[45, 130]` | `max_temp` 钳位区间(**°C**)。⚠ 命名待议 —— 易被误读为 L0 温升(K),拟改 `maxTempClamp` |
|
|
230
230
|
| `airGapFluxT` | `0.8` | 气隙磁密基准 T(齿 / 轭磁密反算输入),PMSM 典型 0.75~0.90 |
|
|
231
231
|
| `insulationClass` | `'F'` | 绝缘等级,决定温升限值(B=80K / F=105K / H=125K) |
|
package/docs/QUALITY-GATE.md
CHANGED
|
@@ -41,7 +41,9 @@ node scripts/regression.mjs --json # 机器可读输出
|
|
|
41
41
|
2. **铜损**:槽面积由几何推算,缺少「匝数 × 电流」的电路约束;槽满率 0.45 与电密 5.5 A/mm² 均为经验值
|
|
42
42
|
3. **机械损**:`MECH_LOSS_K = 5` 未标定,仅保证量级正确
|
|
43
43
|
4. **温升**:散热面积按**光滑**机座外表面积计,未计散热筋;`COOLING_COEFFICIENT` 为单点标定
|
|
44
|
-
5. **效率封顶**:`efficiencyCap=96` 是为与 `_run_simulated`
|
|
44
|
+
5. **效率封顶**:`efficiencyCap=96` 是为与 `_run_simulated` 同口径的权宜值,对高效高速机会低估。
|
|
45
|
+
v0.2.4 起封顶只影响展示值 `efficiency`;**排序与 TopN 区分度改用未封顶真值 `efficiency_raw`**,
|
|
46
|
+
整批触顶时结果行会带 `efficiency_capped=true`、顶层带 `efficiency_note` 说明
|
|
45
47
|
|
|
46
48
|
---
|
|
47
49
|
|
|
@@ -78,6 +80,7 @@ node scripts/regression.mjs --json # 机器可读输出
|
|
|
78
80
|
|
|
79
81
|
- [ ] 用 RMxprt 批量结果做 native vs L1 回归,拟合 `kh/ke`、`MECH_LOSS_K`、`COOLING_COEFFICIENT`
|
|
80
82
|
- [ ] 回归目标:标定域内 `|Δη| ≤ 2pt`、`|Δ温升| ≤ 10K`
|
|
83
|
+
- [x] 校准前先解耦"封顶"与"排序"(v0.2.4 已完成):cap 保持 96 维持 L1 同口径,排序改用 `efficiency_raw`
|
|
81
84
|
- [ ] 校准完成后重新评估 `efficiencyCap` 是否需要放宽(当前 96 对高速高效机偏保守)
|
|
82
85
|
|
|
83
86
|
### 翻转判据
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 算例 1 · Y2 系列 15kW / 1460rpm / 380V 三相异步机
|
|
2
|
+
|
|
3
|
+
> 本文件所有数值均由插件 **v0.2.2 实跑产出**(`l0Mode: auto`,Node.js 直调),未做人工修饰。
|
|
4
|
+
> 复现方式见本文件末尾「复现命令」。
|
|
5
|
+
|
|
6
|
+
## 1. 输入(Spec)
|
|
7
|
+
|
|
8
|
+
| 项目 | 值 |
|
|
9
|
+
|---|---|
|
|
10
|
+
| 功率 | 15 kW |
|
|
11
|
+
| 转速 | 1460 rpm |
|
|
12
|
+
| 电压 | 380 V |
|
|
13
|
+
| 机种 | induction(三相异步) |
|
|
14
|
+
| 候选规模 | 120 |
|
|
15
|
+
|
|
16
|
+
## 2. 流水线耗时
|
|
17
|
+
|
|
18
|
+
| 步骤 | 工具 | 耗时 |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| 生成参数矩阵 | `motor_param_matrix` | 4 ms |
|
|
21
|
+
| 物理一致性校验 | `motor_design_validate` | 6 ms |
|
|
22
|
+
| L0 估算 + 排序 | `motor_l0_estimate` | 6 ms |
|
|
23
|
+
| **合计** | | **16 ms**(120 个候选,单候选均摊 0.04 ms) |
|
|
24
|
+
|
|
25
|
+
## 3. 校验与估算汇总
|
|
26
|
+
|
|
27
|
+
| 指标 | 值 |
|
|
28
|
+
|---|---|
|
|
29
|
+
| 生成候选数 | 120 |
|
|
30
|
+
| 通过 12 条物理校验 | 120(0 条 `failed`) |
|
|
31
|
+
| 可行(feasible)候选 | **80** |
|
|
32
|
+
| 估算成功 / 失败 | 120 / 0 |
|
|
33
|
+
| 推荐方案(`recommended`) | OD 310 mm / 6 极 / 效率 95.17% / `verdict: feasible` |
|
|
34
|
+
|
|
35
|
+
## 4. Top5(按效率降序,已按「几何 + 极数 + 槽数」去重)
|
|
36
|
+
|
|
37
|
+
| # | OD (mm) | ID (mm) | L (mm) | 极数 | 槽数 | 效率 (%) | 温升 (K) | 齿磁密 (T) | 轭磁密 (T) | 功率因数 | 总损耗 (W) |
|
|
38
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
39
|
+
| 1 | 310 | 207.9 | 226.4 | 6 | 72 | 95.17 | 14.6 | 1.04 | 1.39 | 0.92 | 604 |
|
|
40
|
+
| 2 | 327 | 218.8 | 216.6 | 6 | 72 | 95.02 | 14.6 | 1.04 | 1.38 | 0.92 | 628 |
|
|
41
|
+
| 3 | 278 | 186.0 | 187.1 | 6 | 72 | 94.94 | 20.5 | 1.04 | 1.38 | 0.92 | 642 |
|
|
42
|
+
| 4 | 343 | 229.7 | 206.7 | 6 | 72 | 94.89 | 14.7 | 1.04 | 1.38 | 0.92 | 650 |
|
|
43
|
+
| 5 | 294 | 196.9 | 177.2 | 6 | 72 | 94.81 | 20.5 | 1.04 | 1.38 | 0.92 | 663 |
|
|
44
|
+
|
|
45
|
+
**读法**:齿磁密恒定 1.04 T 是本版 L0 按经验磁密取值的结果(非逐槽有限元解);轭磁密 1.38–1.39 T 落在常规 1.2–1.6 T 区间,未触发 V08 轭饱和门控(1.9 T)。
|
|
46
|
+
|
|
47
|
+
## 5. 怎么用这个结果
|
|
48
|
+
|
|
49
|
+
1. Top5 直接作为 L1(RMxprt)的入参矩阵 —— 求解器只跑 5 个方案,而不是 120 个。
|
|
50
|
+
2. 效率用于**相对排序**,绝对值需 L1 复核(本版 L0 物理通道为未标定版,见 README「已知精度边界」)。
|
|
51
|
+
3. 若客户对温升敏感,改用 `sort_by: 'temp_rise'`(升序)重排,无需重跑矩阵。
|
|
52
|
+
|
|
53
|
+
## 6. 复现命令
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 方式 A:在 DSH 内(插件已安装)
|
|
57
|
+
# 依次调用 motor_param_matrix → motor_design_validate → motor_l0_estimate
|
|
58
|
+
# 入参:{ power_kw: 15, speed_rpm: 1460, voltage_v: 380, motor_type: 'induction', count: 120 }
|
|
59
|
+
|
|
60
|
+
# 方式 B:裸 Node 直调(无需 DSH Runtime)
|
|
61
|
+
node -e "
|
|
62
|
+
import('./tools/l0/param-matrix.mjs').then(async (M) => {
|
|
63
|
+
const E = await import('./tools/l0/l0-estimate.mjs')
|
|
64
|
+
const cfg = { l0Mode: 'auto', level: 'l0' }
|
|
65
|
+
const rows = M.buildParamMatrix({ power_kw: 15, speed_rpm: 1460, voltage_v: 380, motor_type: 'induction', count: 120 }, cfg).matrix
|
|
66
|
+
const r = E.runL0Estimate({ params_list: rows, top_n: 5, sort_by: 'efficiency' }, cfg)
|
|
67
|
+
console.log(r.feasible_count, r.recommended, r.results.slice(0, 5).map(x => x.efficiency))
|
|
68
|
+
})
|
|
69
|
+
"
|
|
70
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# 算例 2 · 75kW / 1480rpm / 660V 三相异步机(矿用隔爆功率档)
|
|
2
|
+
|
|
3
|
+
> 本文件所有数值均由插件 **v0.2.2 实跑产出**(`l0Mode: auto`,Node.js 直调),未做人工修饰。
|
|
4
|
+
|
|
5
|
+
## 1. 输入(Spec)
|
|
6
|
+
|
|
7
|
+
| 项目 | 值 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| 功率 | 75 kW |
|
|
10
|
+
| 转速 | 1480 rpm |
|
|
11
|
+
| 电压 | 660 V |
|
|
12
|
+
| 机种 | induction(三相异步) |
|
|
13
|
+
| 候选规模 | 120 |
|
|
14
|
+
|
|
15
|
+
## 2. 流水线耗时
|
|
16
|
+
|
|
17
|
+
| 步骤 | 工具 | 耗时 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| 生成参数矩阵 | `motor_param_matrix` | 1 ms |
|
|
20
|
+
| 物理一致性校验 | `motor_design_validate` | 2 ms |
|
|
21
|
+
| L0 估算 + 排序 | `motor_l0_estimate` | 1 ms |
|
|
22
|
+
| **合计** | | **4 ms**(120 个候选,单候选均摊 0.01 ms) |
|
|
23
|
+
|
|
24
|
+
## 3. 校验与估算汇总
|
|
25
|
+
|
|
26
|
+
| 指标 | 值 |
|
|
27
|
+
|---|---|
|
|
28
|
+
| 生成候选数 | 120 |
|
|
29
|
+
| 通过 12 条物理校验 | 120(0 条 `failed`) |
|
|
30
|
+
| 可行(feasible)候选 | **80** |
|
|
31
|
+
| 估算成功 / 失败 | 120 / 0 |
|
|
32
|
+
| 推荐方案(`recommended`) | OD 435 mm / 6 极 / 效率 96% / `verdict: feasible` |
|
|
33
|
+
|
|
34
|
+
## 4. Top5(按效率降序,已按「几何 + 极数 + 槽数」去重)
|
|
35
|
+
|
|
36
|
+
| # | OD (mm) | ID (mm) | L (mm) | 极数 | 槽数 | 效率 (%) | 温升 (K) | 齿磁密 (T) | 轭磁密 (T) | 功率因数 | 总损耗 (W) |
|
|
37
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
38
|
+
| 1 | 435 | 291.7 | 262.5 | 6 | 72 | 96 | 27.1 | 1.04 | 1.38 | 0.92 | 1922 |
|
|
39
|
+
| 2 | 450 | 274.5 | 301.9 | 4 | 24 | 96 | 31.7 | 1.04 | 1.60 | 0.92 | 2603 |
|
|
40
|
+
| 3 | 450 | 274.5 | 288.8 | 4 | 24 | 96 | 32.2 | 1.04 | 1.60 | 0.92 | 2560 |
|
|
41
|
+
| 4 | 414 | 277.1 | 301.9 | 6 | 72 | 96 | 26.5 | 1.04 | 1.38 | 0.92 | 1953 |
|
|
42
|
+
| 5 | 414 | 277.1 | 275.6 | 6 | 72 | 96 | 27.0 | 1.04 | 1.38 | 0.92 | 1867 |
|
|
43
|
+
|
|
44
|
+
## 5. 这个算例能说明什么
|
|
45
|
+
|
|
46
|
+
**效率并列时的二次排序。** 前 5 名的**展示值**全部为 96 —— 这是配置项 `efficiencyCap`(默认 96)的封顶结果,不是巧合。封顶的意义是与 L1 同口径,避免 L0/L1 两层排序跳变。
|
|
47
|
+
|
|
48
|
+
⚠️ **v0.2.4 起这两个数要分开读**:`efficiency` 是钳位后的展示值(触顶时都等于 96),
|
|
49
|
+
`efficiency_raw` 才是未封顶真值,**排序按 `efficiency_raw` 进行**,所以 Top5 的先后顺序是有物理依据的,
|
|
50
|
+
不是并列。要看真实差距请读结果行里的 `efficiency_raw` 字段。若仍只见并列,可换维度看:
|
|
51
|
+
|
|
52
|
+
| 维度 | 结论 |
|
|
53
|
+
|---|---|
|
|
54
|
+
| 总损耗 | #5(1867 W)最优,比 #2(2603 W)低 28% |
|
|
55
|
+
| 温升 | #4(26.5 K)最优 —— 6 极方案整体优于 4 极 |
|
|
56
|
+
| 轭磁密 | 4 极方案 1.60 T 已越过 1.5 T 警告线,6 极 1.38 T 更从容 |
|
|
57
|
+
|
|
58
|
+
> 实践建议:`sort_by` 用 `efficiency` 拿到第一梯队后,再用 `total_loss` / `temp_rise` 复排一次(`sort_by` 白名单:`efficiency` `torque_density` `temp_rise` `total_loss` `power`,后两者升序)。
|
|
59
|
+
|
|
60
|
+
## 6. 复现命令
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node -e "
|
|
64
|
+
import('./tools/l0/param-matrix.mjs').then(async (M) => {
|
|
65
|
+
const E = await import('./tools/l0/l0-estimate.mjs')
|
|
66
|
+
const cfg = { l0Mode: 'auto', level: 'l0' }
|
|
67
|
+
const rows = M.buildParamMatrix({ power_kw: 75, speed_rpm: 1480, voltage_v: 660, motor_type: 'induction', count: 120 }, cfg).matrix
|
|
68
|
+
for (const by of ['efficiency', 'total_loss', 'temp_rise']) {
|
|
69
|
+
const r = E.runL0Estimate({ params_list: rows, top_n: 3, sort_by: by }, cfg)
|
|
70
|
+
console.log(by, '->', r.results.map(x => x.params.stator_od + '/' + x.params.poles + 'p'))
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
"
|
|
74
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# 算例 3 · 200kW / 22000rpm / 380V 高速 PMSM(**能力边界反例**)
|
|
2
|
+
|
|
3
|
+
> ⚠️ 这个算例**故意展示插件做不好的工况**。我们把它完整公开,是为了让使用者一眼看清 L0 的适用边界 ——
|
|
4
|
+
> 而不是装上一跑、拿到一堆看似漂亮的效率数字就去报价。
|
|
5
|
+
|
|
6
|
+
## 1. 输入(Spec)
|
|
7
|
+
|
|
8
|
+
| 项目 | 值 |
|
|
9
|
+
|---|---|
|
|
10
|
+
| 功率 | 200 kW |
|
|
11
|
+
| 转速 | 22000 rpm |
|
|
12
|
+
| 电压 | 380 V |
|
|
13
|
+
| 机种 | pmsm(永磁同步,高速) |
|
|
14
|
+
| 候选规模 | 120 |
|
|
15
|
+
|
|
16
|
+
## 2. 实跑结果
|
|
17
|
+
|
|
18
|
+
| 指标 | 值 |
|
|
19
|
+
|---|---|
|
|
20
|
+
| 生成候选数 | 120 |
|
|
21
|
+
| 通过 12 条物理校验 | **0**(全部被判 `failed`) |
|
|
22
|
+
| 可行(feasible)候选 | **0** |
|
|
23
|
+
| 推荐方案(`recommended`) | `null`(**不推荐任何方案**) |
|
|
24
|
+
|
|
25
|
+
Top5(按效率降序):
|
|
26
|
+
|
|
27
|
+
| # | OD (mm) | ID (mm) | L (mm) | 极数 | 槽数 | 效率 (%) | 温升 (K) | 齿磁密 (T) | 轭磁密 (T) | 判定 |
|
|
28
|
+
|---|---|---|---|---|---|---|---|---|---|---|
|
|
29
|
+
| 1 | 253 | 182.3 | 164.0 | 2 | 12 | 95.42 | 379.9 | 1.04 | 5.28 | `infeasible_thermal` |
|
|
30
|
+
| 2 | 253 | 182.3 | 172.3 | 2 | 12 | 95.39 | 368.4 | 1.04 | 5.28 | `infeasible_thermal` |
|
|
31
|
+
| 3 | 253 | 182.3 | 180.6 | 2 | 12 | 95.37 | 357.7 | 1.04 | 5.28 | `infeasible_thermal` |
|
|
32
|
+
| 4 | 253 | 182.3 | 188.9 | 2 | 12 | 95.35 | 347.7 | 1.04 | 5.28 | `infeasible_thermal` |
|
|
33
|
+
| 5 | 253 | 182.3 | 197.1 | 2 | 12 | 95.33 | 338.4 | 1.04 | 5.28 | `infeasible_thermal` |
|
|
34
|
+
|
|
35
|
+
## 3. 逐项解读
|
|
36
|
+
|
|
37
|
+
| 现象 | 说明 |
|
|
38
|
+
|---|---|
|
|
39
|
+
| **轭磁密 5.28 T** | 物理上不可能(硅钢 1.8–2.0 T 即深度饱和)。根因是本版 L0 的轭部磁路模型未覆盖 22000rpm / 2 极高速工况的极短轭部路径,属**模型外推失真**,不是设计结果 |
|
|
40
|
+
| **温升 338–380 K** | 远超 F 级限值 105 K。高速风摩耗与高频铁损的估算模型在本版未标定 |
|
|
41
|
+
| **`recommended = null`、`feasible_count = 0`** | ✅ **这是正确的行为**:V08 轭饱和门控识别到 `yoke_sat = true`,拒绝输出任何"看起来可行"的方案。宁可交白卷,也不给假答案 |
|
|
42
|
+
| 效率 95.33–95.42% | 在模型失真前提下**不可用**,请勿采信 |
|
|
43
|
+
|
|
44
|
+
## 4. 结论与建议用法
|
|
45
|
+
|
|
46
|
+
| 工况 | L0 是否适用 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| 中低速异步机(≤3000rpm,150–1085mm 机座) | ✅ 适用,见算例 1 / 2 |
|
|
49
|
+
| 常规 PMSM(≤6000rpm) | ⚠️ 排序可用,绝对值需 L1 复核 |
|
|
50
|
+
| **高速 PMSM(>10000rpm)** | ❌ **不适用**,请直接进入 L1(RMxprt)/ L2(Motor-CAD) |
|
|
51
|
+
|
|
52
|
+
插件的 `level` 配置会强制这一点:`l0Mode: 'auto'` 下无效方案不会进入 TopN;若你把 `level` 设为 `l1`/`l2`,插件会**立即抛错**而不是静默给出 L0 结果 —— 这是刻意设计的快速失败。
|
|
53
|
+
|
|
54
|
+
## 5. 复现命令
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
node -e "
|
|
58
|
+
import('./tools/l0/param-matrix.mjs').then(async (M) => {
|
|
59
|
+
const E = await import('./tools/l0/l0-estimate.mjs')
|
|
60
|
+
const cfg = { l0Mode: 'auto', level: 'l0' }
|
|
61
|
+
const rows = M.buildParamMatrix({ power_kw: 200, speed_rpm: 22000, voltage_v: 380, motor_type: 'pmsm', count: 120 }, cfg).matrix
|
|
62
|
+
const r = E.runL0Estimate({ params_list: rows, top_n: 5, sort_by: 'efficiency' }, cfg)
|
|
63
|
+
console.log('feasible =', r.feasible_count, '| recommended =', JSON.stringify(r.recommended))
|
|
64
|
+
})
|
|
65
|
+
"
|
|
66
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 算例集 · dsh-motor-ai-l0
|
|
2
|
+
|
|
3
|
+
本目录的每个算例都是 **v0.2.2 实跑产出**(`l0Mode: auto`,裸 Node 直调,无需 DSH Runtime / RMxprt / Motor-CAD),
|
|
4
|
+
数值未经人工修饰 —— 包括做不好的那一个。
|
|
5
|
+
|
|
6
|
+
| # | 算例 | 工况 | 结果概览 | 用途 |
|
|
7
|
+
|---|---|---|---|---|
|
|
8
|
+
| [01](01-y2-15kw-1460rpm.md) | Y2 系列 15kW 异步 | 15 kW / 1460 rpm / 380 V | 120 候选 → 80 可行,Top1 效率 95.17%、温升 14.6 K,**16 ms** | 入门:看完整输出长什么样 |
|
|
9
|
+
| [02](02-75kw-1480rpm-660v.md) | 75kW 异步(矿用档) | 75 kW / 1480 rpm / 660 V | 120 候选 → 80 可行,效率封顶并列,**4 ms** | 进阶:效率并列时如何用损耗/温升二次排序 |
|
|
10
|
+
| [03](03-pmsm-200kw-22000rpm.md) | 200kW 高速 PMSM | 200 kW / 22000 rpm / 380 V | **0 可行**,`recommended = null` | 边界:看清 L0 不适用什么(反例) |
|
|
11
|
+
|
|
12
|
+
## 三步流水线(顺序固定)
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
motor_param_matrix 功率/转速/电压 → 候选参数矩阵
|
|
16
|
+
↓
|
|
17
|
+
motor_design_validate 12 条物理校验,剔除 failed
|
|
18
|
+
↓
|
|
19
|
+
motor_l0_estimate 毫秒级估算 + 排序 + TopN + L1 交接载荷
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
> `motor_l0_estimate` 只接受 `params_list`(由第 1 步生成,每项含 16 个 L1 顶层字段),
|
|
23
|
+
> **不接受** `power_kw` / `speed_rpm` 这类散装参数。
|
|
24
|
+
|
|
25
|
+
## 复现
|
|
26
|
+
|
|
27
|
+
所有算例文件末尾都带有可直接粘贴的 `node -e` 命令,在插件根目录执行即可复现(Node.js ≥ 22):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd dsh-motor-ai-l0
|
|
31
|
+
node -e "<算例文件中的命令>"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 关于数值的可信度
|
|
35
|
+
|
|
36
|
+
| 用途 | 是否可信 |
|
|
37
|
+
|---|---|
|
|
38
|
+
| 方案之间的**相对排序** | ✅ L0 的设计目标,排序稳定性优先 |
|
|
39
|
+
| 效率 / 温升的**绝对值** | ⚠️ 本版物理通道未标定,须由 L1(RMxprt)复核 |
|
|
40
|
+
| 高速 PMSM(>10000rpm)任何结论 | ❌ 见算例 03 |
|
|
41
|
+
|
|
42
|
+
细节见根目录 [README.md](../README.md)「已知精度边界」与 [docs/QUALITY-GATE.md](../docs/QUALITY-GATE.md)。
|
package/index.mjs
CHANGED
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
* @property {number} surrogateConfidenceThreshold 置信度低于此值降级到公式
|
|
18
18
|
* @property {number} maxMatrixSize 参数矩阵最大组合数
|
|
19
19
|
* @property {number} topNPreview L0 结果预览 TopN
|
|
20
|
-
* @property {number} efficiencyCap 效率封顶(对齐 _run_simulated L752
|
|
20
|
+
* @property {number} efficiencyCap 效率封顶(对齐 _run_simulated L752)。
|
|
21
|
+
* v0.2.4 起仅钳展示值 efficiency;
|
|
22
|
+
* 排序与区分度看未封顶真值 efficiency_raw
|
|
21
23
|
* @property {[number, number]} tempRiseRange temp 钳位区间 (°C),对齐 L1 max_temp;命名待议(拟改 maxTempClamp)
|
|
22
24
|
* @property {boolean} [l1Enabled] 预留
|
|
23
25
|
* @property {boolean} [l2Enabled] 预留
|
package/lib/design-rules.mjs
CHANGED
|
@@ -43,6 +43,7 @@ export const RULE_CATALOG = [
|
|
|
43
43
|
{ id: 'V12', name: '温升限值', severity: 'warning', needs: 'power_kw 或 torque_nm(+ 冷却方式)' },
|
|
44
44
|
{ id: 'V14', name: '反电势闭环', severity: 'failed', needs: 'voltage/speed/poles/stator_id/core_length/slots_stator/parallel_circuits/turns_per_coil' },
|
|
45
45
|
{ id: 'V15', name: '槽满率可行性', severity: 'failed', needs: 'stator_od/stator_id/slots_stator/poles/peak_current/turns_per_coil/parallel_circuits' },
|
|
46
|
+
{ id: 'V16', name: '极数-转速同步一致性', severity: 'failed', needs: 'speed/poles' },
|
|
46
47
|
]
|
|
47
48
|
|
|
48
49
|
/** 可在 config 中把严重度提升为 failed 的规则(默认 warning) */
|
|
@@ -426,6 +427,31 @@ export function validateDesign(row, opts = {}) {
|
|
|
426
427
|
skipped.push('V15')
|
|
427
428
|
}
|
|
428
429
|
|
|
430
|
+
// ---- V16 极数-转速同步一致性(超同步拦截,P0 门禁)----
|
|
431
|
+
// 异步电动机额定转速必须低于同步转速 n_sync = 120·f_line/p(转差为正才能输出转矩);
|
|
432
|
+
// 若 n_sync ≤ 额定转速 ⇒ 转差 ≤ 0(超同步),异步机无法作为电动机运行(只能作发电机/制动)。
|
|
433
|
+
// 同步机(PMSM/BLDC/IPM)无转差概念,本规则不适用,显式跳过。
|
|
434
|
+
// ⚠ 工频 f_line 按 IEC/中国 50Hz 假设;60Hz 电网需后续在 config 暴露 line_freq_hz。
|
|
435
|
+
if (speed !== null && poles !== null) {
|
|
436
|
+
const isPm = isPmsmType(row?.motor_type)
|
|
437
|
+
if (isPm) {
|
|
438
|
+
skipped.push('V16')
|
|
439
|
+
} else {
|
|
440
|
+
const LINE_FREQ_HZ = 50
|
|
441
|
+
const nSync = (120 * LINE_FREQ_HZ) / poles
|
|
442
|
+
metrics.sync_speed_rpm = round1(nSync)
|
|
443
|
+
if (nSync <= speed) {
|
|
444
|
+
// 推荐极数:满足 n_sync > 转速 的最大极数(取 floor 留 1e-6 余量避免同步边界=speed 误判)
|
|
445
|
+
const recommendedPole = Math.max(2, Math.floor((120 * LINE_FREQ_HZ) / speed - 1e-6) || 2)
|
|
446
|
+
fail('V16', `极数 ${poles} 与转速 ${speed}rpm 不同步:同步转速 ${round1(nSync)}rpm ≤ 额定转速,` +
|
|
447
|
+
`异步机转差≤0(超同步),无法作为电动机运行;该转速档应选 ${recommendedPole} 极` +
|
|
448
|
+
`(n_sync=${(120 * LINE_FREQ_HZ) / recommendedPole}rpm)`)
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
} else {
|
|
452
|
+
skipped.push('V16')
|
|
453
|
+
}
|
|
454
|
+
|
|
429
455
|
// ---- V13 每线圈匝数下限(附在 V06 组,不单独占号)----
|
|
430
456
|
// v0.1.6:闭环反推可能给出 turns_per_coil=1(380V/高频低匝数场景,hairpin 扁线绕组可行),
|
|
431
457
|
// 故下限改为 <1(仅排除真正不可实现的 0/负匝数),不再误报 1 匝方案。
|
package/lib/formula-engine.mjs
CHANGED
|
@@ -302,6 +302,13 @@ export function estimateTempRise({ statorOd, coreLength, cooling }, totalLossW)
|
|
|
302
302
|
* L1 仿真效率去噪克隆 —— motor_tools.py:750-752
|
|
303
303
|
* base_eff = 85 + (od-180)·0.04 + (poles-8)·1.2,Python 侧另有 ±1.5 噪声
|
|
304
304
|
*/
|
|
305
|
+
/**
|
|
306
|
+
* 未封顶效率的物理硬上界(v0.2.4)
|
|
307
|
+
* 仅作数值保险:物理模型不可能算出 >100% 的效率,取 99.9 以防浮点/极端输入溢出。
|
|
308
|
+
* 注意与 efficiencyCap 的区别:cap 是「与 L1 同口径」的口径约定,此值是物理边界。
|
|
309
|
+
*/
|
|
310
|
+
const RAW_EFF_MAX = 99.9
|
|
311
|
+
|
|
305
312
|
export function l1EfficiencyProxy({ statorOd, poles }, clampMax = SIM_EFF.clampMax) {
|
|
306
313
|
const base =
|
|
307
314
|
SIM_EFF.base +
|
|
@@ -384,6 +391,11 @@ export function quickL0Estimate(params, opts = {}) {
|
|
|
384
391
|
const poleFactor = POLE_EFFICIENCY_FACTOR[poles] ?? 0.98
|
|
385
392
|
const rawEff = efficiencyFromLosses(powerKw, totalLossW) * poleFactor
|
|
386
393
|
const efficiency = round2(Math.min(efficiencyCap, Math.max(SIM_EFF.clampMin, rawEff)))
|
|
394
|
+
// v0.2.4:efficiencyCap 存在的意义是「与 L1 同口径」,不是物理真值。
|
|
395
|
+
// 大机座整批触顶时 efficiency 全被压成同一个数 ⇒ TopN 排序失去区分度(450kW 实测 10/10 触顶)。
|
|
396
|
+
// 故额外保留未封顶真值供排序使用,并打触顶标记,让调用方知道 efficiency 是"钳位显示值"。
|
|
397
|
+
const efficiencyRaw = round2(clamp(rawEff, SIM_EFF.clampMin, RAW_EFF_MAX))
|
|
398
|
+
const efficiencyCapped = rawEff > efficiencyCap + 1e-9
|
|
387
399
|
|
|
388
400
|
// ---- 温升(物理通道,含液冷标定修正)----
|
|
389
401
|
const tempRise = estimateTempRise({ statorOd, coreLength, cooling }, totalLossW)
|
|
@@ -409,6 +421,8 @@ export function quickL0Estimate(params, opts = {}) {
|
|
|
409
421
|
|
|
410
422
|
const native = {
|
|
411
423
|
efficiency,
|
|
424
|
+
efficiency_raw: efficiencyRaw,
|
|
425
|
+
efficiency_capped: efficiencyCapped,
|
|
412
426
|
torque: round2(torque),
|
|
413
427
|
temp_rise: tempRise,
|
|
414
428
|
total_loss: totalLossW,
|
package/lib/param-schema.mjs
CHANGED
|
@@ -136,7 +136,9 @@ export const PARAM_SCHEMA = {
|
|
|
136
136
|
|
|
137
137
|
/** L0 原生字段 —— 物理损耗通道的独立产出 + v0.1.6 可追溯诊断字段 */
|
|
138
138
|
export const L0_NATIVE_FIELDS = [
|
|
139
|
-
'efficiency', // %
|
|
139
|
+
'efficiency', // % 物理损耗模型推算(按 efficiencyCap 封顶,与 L1 同口径)
|
|
140
|
+
'efficiency_raw', // % 未封顶真实值(v0.2.4)—— 排序用,避免封顶压平区分度
|
|
141
|
+
'efficiency_capped',// bool 是否触顶被封(v0.2.4)—— 触顶时 efficiency 非真值
|
|
140
142
|
'torque', // Nm 9550·P/n
|
|
141
143
|
'temp_rise', // K 热负荷法温升(注意:与 max_temp 的 °C 口径不同)
|
|
142
144
|
'total_loss', // W 铜损+铁损+机械损
|
package/lib/surrogate-engine.mjs
CHANGED
|
@@ -151,6 +151,51 @@ export function predictLinear(features, coeffs) {
|
|
|
151
151
|
return result
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* 评估单棵 GBR 决策树(sklearn 数组导出格式)
|
|
156
|
+
* 约定:feature[i] === -2 表示叶子节点,values[i] 为叶子输出;
|
|
157
|
+
* 叶子节点 left/right 均为 -1。以 maxIter 兜底防异常树结构死循环。
|
|
158
|
+
* @param {number[]} features 标准化特征向量
|
|
159
|
+
* @param {object} tree 单棵树 { feature, threshold, left, right, values }
|
|
160
|
+
* @returns {number} 该树对残差的贡献
|
|
161
|
+
*/
|
|
162
|
+
function applyTree(features, tree) {
|
|
163
|
+
let node = 0
|
|
164
|
+
const maxIter = tree.feature.length + 1
|
|
165
|
+
for (let i = 0; i < maxIter; i++) {
|
|
166
|
+
const f = tree.feature[node]
|
|
167
|
+
if (f === -2) {
|
|
168
|
+
return tree.values[node]
|
|
169
|
+
}
|
|
170
|
+
if (features[f] <= tree.threshold[node]) {
|
|
171
|
+
node = tree.left[node]
|
|
172
|
+
} else {
|
|
173
|
+
node = tree.right[node]
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return tree.values[node] ?? 0
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* GBR 残差校正预测(ridge_plus_gbr 第二阶段)
|
|
181
|
+
* 公式(与训练端 M1 一致):residual = init + learning_rate * Σ applyTree(features, tree)
|
|
182
|
+
* 残差与 primary 线性预测同单位(效率百分点),最终效率 = primary + residual。
|
|
183
|
+
* 模型无 gbr 字段时返回 0(退化为纯 ridge 通道,行为不变)。
|
|
184
|
+
* @param {number[]} features 标准化特征向量
|
|
185
|
+
* @param {object|undefined} gbr GBR 模型对象(含 init/learning_rate/trees)
|
|
186
|
+
* @returns {number} 残差修正量(效率百分点)
|
|
187
|
+
*/
|
|
188
|
+
export function predictGBR(features, gbr) {
|
|
189
|
+
if (!gbr || !Array.isArray(gbr.trees) || gbr.trees.length === 0) {
|
|
190
|
+
return 0
|
|
191
|
+
}
|
|
192
|
+
let sum = 0
|
|
193
|
+
for (const tree of gbr.trees) {
|
|
194
|
+
sum += applyTree(features, tree)
|
|
195
|
+
}
|
|
196
|
+
return (gbr.init ?? 0) + (gbr.learning_rate ?? 1) * sum
|
|
197
|
+
}
|
|
198
|
+
|
|
154
199
|
/**
|
|
155
200
|
* 代理模型预测单个样本(分族模型)
|
|
156
201
|
* @param {object} params L0 参数字典
|
|
@@ -166,7 +211,7 @@ export function predictSurrogate(params, model, motorType = null) {
|
|
|
166
211
|
if (model.schema === 'l0_surrogate_family') {
|
|
167
212
|
const segment = selectFamilySegment(statorOd, type, model)
|
|
168
213
|
if (segment) {
|
|
169
|
-
return predictFromSegment(params, segment
|
|
214
|
+
return predictFromSegment(params, segment, model, type)
|
|
170
215
|
}
|
|
171
216
|
// 超出范围,返回 null 让调用方降级
|
|
172
217
|
return null
|
|
@@ -183,7 +228,8 @@ export function predictSurrogate(params, model, motorType = null) {
|
|
|
183
228
|
/**
|
|
184
229
|
* 从分族模型预测
|
|
185
230
|
*/
|
|
186
|
-
function predictFromSegment(params,
|
|
231
|
+
function predictFromSegment(params, segment, model, motorType) {
|
|
232
|
+
const primary = segment.primary
|
|
187
233
|
const norm = {
|
|
188
234
|
// primary.feature_names 是 v1.x 格式;v2.x 把特征顺序存在顶层 model.features
|
|
189
235
|
featureOrder: primary.feature_names ?? model.features,
|
|
@@ -192,11 +238,20 @@ function predictFromSegment(params, primary, model, motorType) {
|
|
|
192
238
|
}
|
|
193
239
|
const features = extractFeatures(params, norm)
|
|
194
240
|
|
|
195
|
-
//
|
|
241
|
+
// 基础预测(加权 Ridge)
|
|
196
242
|
const rawEff = predictLinear(features, primary)
|
|
197
|
-
const efficiency = Math.min(99, Math.max(50, rawEff))
|
|
198
243
|
|
|
199
|
-
//
|
|
244
|
+
// GBR 残差校正(ridge_plus_gbr 第二阶段):final = base + residual
|
|
245
|
+
// 残差与 primary 同单位(效率百分点),模型无 gbr 字段时退化为纯 ridge(行为不变)
|
|
246
|
+
const gbrResidual = predictGBR(features, segment.gbr)
|
|
247
|
+
const correctedEff = rawEff + gbrResidual
|
|
248
|
+
|
|
249
|
+
// 预测效率 (物理合理性钳位: 效率不可能 <50% 或 >99%)
|
|
250
|
+
const efficiency = Math.min(99, Math.max(50, correctedEff))
|
|
251
|
+
|
|
252
|
+
const usedGbr = !!segment.gbr && Array.isArray(segment.gbr.trees) && segment.gbr.trees.length > 0
|
|
253
|
+
|
|
254
|
+
// 置信度:基于 R² 和特征范围(维持与纯 ridge 通道一致,避免改变降级判定)
|
|
200
255
|
const confidence = estimateConfidence(features, norm, primary.cv_r2)
|
|
201
256
|
|
|
202
257
|
return {
|
|
@@ -207,6 +262,8 @@ function predictFromSegment(params, primary, model, motorType) {
|
|
|
207
262
|
prediction_source: 'surrogate',
|
|
208
263
|
family: { motor_type: motorType, size: primary.tag?.split('_')[0] },
|
|
209
264
|
cv_r2: primary.cv_r2,
|
|
265
|
+
used_gbr: usedGbr,
|
|
266
|
+
gbr_residual_pp: usedGbr ? Math.round(gbrResidual * 1000) / 1000 : 0,
|
|
210
267
|
}
|
|
211
268
|
}
|
|
212
269
|
|
|
@@ -387,5 +444,6 @@ export default {
|
|
|
387
444
|
buildSurrogateResult,
|
|
388
445
|
extractFeatures,
|
|
389
446
|
selectFamilySegment,
|
|
447
|
+
predictGBR,
|
|
390
448
|
DEFAULT_CONFIDENCE_THRESHOLD,
|
|
391
449
|
}
|