dsh-plugin-pscad-expert-vyma 1.0.14 → 1.0.16
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/README.md +1 -1
- package/knowledge/emtdc_custom_element_norton.md +75 -0
- package/knowledge/templates_index.md +26 -1
- package/package.json +1 -1
- package/plugin.yaml +3 -1
- package/scripts/self_heal_pscad_plugin.ps1 +3 -3
- package/templates/tmmb_norton_element.pscx +576 -0
- package/tools/main.py +297 -26
package/README.md
CHANGED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# EMTDC 自定义电气元件开发 SOP(Norton 等效 · 零矩阵重构 · 实证版)
|
|
2
|
+
|
|
3
|
+
> 来源:TMMB 热磁忆阻分支 v6 全链开发与验证(2026-08,PSCAD 5.0.0 / EMTDC gf46 / mhi.pscad 2.2.1)。
|
|
4
|
+
> 全部结论均经生成代码、官方 pslx/示例与对照仿真实证;三路验证(PSCAD ↔ 独立数值参考 ↔ 解析稳态)误差 <0.5%,关键案例逐位吻合。
|
|
5
|
+
|
|
6
|
+
## 一、数值离散(差分推导 → 实现)
|
|
7
|
+
|
|
8
|
+
元件方程:`v = R(w)·i + L0·di/dt`,`R(w) = RMIN + K·w²`,`dw/dt = α·v·i − β·w`。
|
|
9
|
+
|
|
10
|
+
**Norton 隐式梯形伴生模型**(每拍一次网络求解,无受控源一拍延迟):
|
|
11
|
+
```
|
|
12
|
+
G_eq = 1/(R(w) + 2·L0/Δt) # 分支等效电导
|
|
13
|
+
Z1 = R(w) − 2·L0/Δt
|
|
14
|
+
I_hist = (1 − Z1·G_eq)·G_eq·v_prev − Z1·G_eq·I_hist_prev # seriesrl2 官方递推
|
|
15
|
+
```
|
|
16
|
+
- L0=0 时 Z1·G_eq=1 → I_hist≡0(纯电阻无记忆),递推自动退化。
|
|
17
|
+
- 状态方程半隐式(β 隐式保证无条件稳定,功率项显式用上一拍):
|
|
18
|
+
`W_new = (W·(1 − βΔt/2) + α·Δt·v·i) / (1 + βΔt/2)`
|
|
19
|
+
- 代数环闭合:DSDYN 内 Picard 迭代 2–3 次闭合 W↔R 环(稳态零差异,瞬态跟踪改善);DSOUT 校正器为可选补足。**同拍 v,i 完全闭合对注入型组件无公开接口**(EMTDC 的网络迭代 ITN/EBRD 仅分支型元件可用,mmc 的 `EBRD(...)` 写入为证);显式功率 O(Δt) 是 EMTDC 官方非线性元件同款标准精度。
|
|
20
|
+
|
|
21
|
+
## 二、零重构电气接口(最终方案:CCBR/GEQ 分支注入)
|
|
22
|
+
|
|
23
|
+
**核心原则:矩阵静态 + 右端项注入分离。** 每拍开关/变值若改分支拓扑或矩阵电导,EMTDC 将重新三角分解导纳矩阵——大电网灾难(实测 v4 开关阵列方案即如此)。
|
|
24
|
+
|
|
25
|
+
```fortran
|
|
26
|
+
! Branch 段(可切换分支声明,官方 seriesrl2 范式):
|
|
27
|
+
BRR = $NA $NB BREAKER 1.0E6
|
|
28
|
+
|
|
29
|
+
! TIMEZERO(一次,放入 #BEGIN/#ENDBEGIN):
|
|
30
|
+
GEQ($BRR, $SS) = G0 ! 固定电导 → 导纳矩阵逐拍恒不变(零重构)
|
|
31
|
+
DEFRDBR($BRR, $SS) = .TRUE. ! 分支电流源外部驱动
|
|
32
|
+
|
|
33
|
+
! 每拍(仅 RHS,永不触发重构):
|
|
34
|
+
CCBR($BRR, $SS) = I_hist + (G(w) − G0)·V ! 非线性 + 历史电流全部走右端项
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- **G0 选择**:`G0 = 1/(2·RMIN + 2·L0/Δt)`;补偿项 `(G−G0)·V` 随**分支电压**缩放(悬浮场景分支电压小,误差可控);显式补偿稳定条件 `|G−G0|·Z_th < 2`。
|
|
38
|
+
- **性能实证**:5s/50 万步,GGIN 每拍变化 vs 固定:4.44s vs 4.53s——无显著重构开销;CCIN/CCBR 为 RHS 注入,数学上永不触发重构。
|
|
39
|
+
- **状态功率读回**:`V = VBRANCH($SS, $BRR)`(子系统在前);**电流勿读 CBR**(DEFRDBR 外部驱动分支的 CBR 读回符号不可靠,实测导致悬浮案例状态发散)——用 Norton 自洽电流 `I = G·V + I_hist`。
|
|
40
|
+
|
|
41
|
+
## 三、备选接口与实测结论(含陷阱)
|
|
42
|
+
|
|
43
|
+
| 接口 | 结论 |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `E_BRANCH_CFG` 每拍 | 第 6 参=R(Ω)非 G(peswitch 5000Ω/source 0.001Ω 实证);对普通 R 分支每拍调用=no-op(分支停在 TIMEZERO 值);peswitch 生效靠库内部切换 |
|
|
46
|
+
| `E_VARRLC1_EXE` 动态 Z | 低阻区(Z≈1)每拍变 Z 触发网络塌缩(V/I→0);只适合固定 Z+变化 E(MMC 电容模式) |
|
|
47
|
+
| `GEQ`/`E_BRANCH_CFG` 每拍直写 | no-op(无重构标记) |
|
|
48
|
+
| `CCIN/GGIN` 节点注入(seriesrl1) | 单节点/接地场景精确(CCIN=理想电流源实证:0.1kA→节点电压精确偏移 10kV);**GGIN 仅对地**——悬浮双端口跨导耦合须上拍显式化 → 弱网大补偿误差放大(138 倍相消案例 4.8%) |
|
|
49
|
+
| `E1PBRKR1` 开关段(v4 方案) | 每拍切换可行但触发重构 + 开断为 1ms 线性斜坡(瞬态滞后);PESWITCH1 有二极管方向性不适配双向电阻 |
|
|
50
|
+
|
|
51
|
+
## 四、存储与编译规范(踩坑实证)
|
|
52
|
+
|
|
53
|
+
- `#STORAGE REAL:N` 分配到 STORF 池;代码必须写 `STORF(NSTORF+k)` 且段末 `NSTORF = NSTORF + N` 自增。**误写 STORI(整数池)会覆盖相邻组件状态**——曾致源组件损坏、节点电压塌缩到 48V(最小变体二分定位)。
|
|
54
|
+
- `#LOCAL REAL W, V, I, R, G, DTB` 合并行会被生成器丢弃(只剩第一个)→ 隐式类型陷阱(I 变 INTEGER)→ 状态死;**必须每行一条**。
|
|
55
|
+
- `#BEGIN/#ENDBEGIN` 内容进 MainDyn_Begin——该子程序**不含 emtstor.h**,不能访问 STORF/STORI;状态初始化放主段 `IF (TIMEZERO)` 块。
|
|
56
|
+
- 库调用(PESWITCH1_CFG / E1PBRKR1_CFG / E_VARRLC1_CFG / GEQ/DEFRDBR)放 #BEGIN。
|
|
57
|
+
- 电压/电流回读参数顺序:`VBRANCH(SS, NBR)`(子系统在前,RE.f 实证)、`CBR(NBR, SS)` / `GEQ(NBR,SS)` / `CCBR(NBR,SS)`(分支在前);`NODE(INODE+1)−NODE(INODE+2)` 依赖节点分配顺序不可靠。
|
|
58
|
+
|
|
59
|
+
## 五、验证方法(三路对照,防伪造)
|
|
60
|
+
|
|
61
|
+
1. 独立 Python 离散参考:镜像 Fortran 每拍序列(同离散方案、同执行顺序、含源斜坡),逐拍对照。
|
|
62
|
+
2. 解析稳态第三对照:`β·W* = α·Vrms²·R*/(R*²+(ωL0)²)`(L0=0 退化为 `W*·(RMIN+K·W*²)=α·Vrms²/β`)。
|
|
63
|
+
3. **强判别案例**:L0=0.1H 时电感把 W* 从 4.57 压到 ~0.1、电流相位 ~88°——伴生模型与历史电流注入的细微错误都会显形。
|
|
64
|
+
4. source_1 特性:Vm 为 RMS;**启动有 0.05s 线性软启动** `E(t)=Vm·√2·sin(ωt)·min(t/0.05,1)`(包络采样实证)——数值参考必须含斜坡否则早期轨迹偏差;f=0 时源输出为零(无现成直流源)。
|
|
65
|
+
|
|
66
|
+
## 六、TMMB v6 验证结果(PSCAD ↔ 数值参考)
|
|
67
|
+
|
|
68
|
+
| 案例 | I(PSCAD/数值)kA | W(PSCAD/数值) |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| 接地 L0=0(α=1,K=1,RMIN=1,10kV/50Hz) | 0.4575 / 0.4573 | 4.5682 / 4.5678 |
|
|
71
|
+
| 接地 L0=0.1 | 0.3182 / 0.3182 | 0.0939 / 0.0934 |
|
|
72
|
+
| 悬浮 L0=0(NB 经 100Ω 接地) | 0.099 / 0.0990 | 0.009 / 0.0089 |
|
|
73
|
+
| 悬浮 L0=0.1 | 0.0945 / 0.0945 | 0.0082 / 0.0082(逐位精确) |
|
|
74
|
+
|
|
75
|
+
参考实现:`D:\PSCAD_Lab\scripts\r4_tmmb_v6.py`(元件 XML+验证)、`r4_tmmb_num.py`(数值参考)、`r4_tmmb_v5f.py`(悬浮两节点数值参考)、`r4_tmmb_inj.py`/`r4_tmmb_rt.py`(注入行为与重构计时探针)。
|
|
@@ -90,11 +90,35 @@
|
|
|
90
90
|
|
|
91
91
|
---
|
|
92
92
|
|
|
93
|
+
## 4. [tmmb_norton_element.pscx]
|
|
94
|
+
|
|
95
|
+
- **文件位置**:`templates/tmmb_norton_element.pscx`(仓库内副本;源工程 `.gf46` 含 exe + `*_01.out`,运行数据完整)
|
|
96
|
+
- **功能摘要**:**TMMB 热磁忆阻分支(自定义 Norton 元件)验证基准**——source_1(10kV/50Hz,内阻 0.001Ω)→ ammeter → **工程内自定义组件 `TMMB`(CCBR/GEQ 零重构 Norton 范式)** → ground;电压表并行;Wx 状态通道。TMMB 定义内嵌于 .pscx(`UserCmpDefn`),打开即用。参数:RMIN/K/ALPHA/BETA/L0(v=R(w)·i+L0·di/dt,R(w)=RMIN+K·w²,dw/dt=α·v·i−β·w)。L0=0.1 案例验证基准:I_rms≈0.318kA、W≈0.094(电感限制功率,强判别);接地/悬浮、L0=0/0.1 四案例三路对照全通过(详见 knowledge/emtdc_custom_element_norton.md)。
|
|
97
|
+
- **已固化的核心拓扑**(Main 画布):
|
|
98
|
+
| 元件(Name) | 类型 | 位置(网格) |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| Src | source_1(Vm=10kV,f=50Hz,R=0.001Ω) | (60, 200) |
|
|
101
|
+
| Ix | ammeter(回路电流) | (140, 200) |
|
|
102
|
+
| NRT1 | `<工程名>:TMMB`(RMIN=1, K=1, A=1, B=1, L0=0.1) | (220, 200) |
|
|
103
|
+
| G1 | ground | (300, 200) |
|
|
104
|
+
| Vx | voltmetergnd | (180, 150) |
|
|
105
|
+
| Wx/Vx/Ix | pgb 输出通道(Wx=TMMB.OUT 状态信号) | (500~550, 140~200) |
|
|
106
|
+
- **二次开发与扩展指南**:
|
|
107
|
+
- **坐标安全区**:单链结构,新增支路(悬浮负载电阻等)建议 x∈[320, 480]。
|
|
108
|
+
- **修改切入点**:
|
|
109
|
+
- **调参(最常用)**:`find_first('NRT1').parameters(RMIN=..., K=..., ALPHA=..., BETA=..., L0=...)`——L0 设 0 即纯忆阻、设 0.1 即含电感伴生。
|
|
110
|
+
- **悬浮双端口演示**:将 G1 从 NRT1.NB 断开,改接 100Ω 电阻到地(CCBR/GEQ 跨导矩阵内精确,悬浮场景无需补偿)。
|
|
111
|
+
- **Picard 代数环闭合**:工具 `create_norton_element(..., picard=2)` 生成含 2 次 DSDYN 内迭代的定义。
|
|
112
|
+
- **元件定义再生成**:TMMB XML 由 `tools/main.py` 的 `_norton_definition_xml()` 生成;改 XML 后重新 `prj.create_definition(...)`(#LOCAL 每行一条、#BEGIN 禁 STORF、Fortran 注释禁中文——踩坑固化)。
|
|
113
|
+
- **验证基准(三路对照)**:接地 L0=0:I≈0.4575/4.5682(数值 0.4573/4.5678);接地 L0=0.1:0.3182/0.0939(0.3182/0.0934);悬浮 L0=0.1:0.0945/0.0082 逐位精确。source_1 有 0.05s 线性软启动,数值对照须含斜坡。
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
93
117
|
## 备选池(同样验证成功,未入选原因)
|
|
94
118
|
- `line_model_pi_100km.pscx`(source3 单线图 + newpi 空载充电/Ferranti)——结构简单(4 元件),作为"最小线路模板"备用。
|
|
95
119
|
- `gfm_island_droop_nose.pscx`(双 GFM 孤岛下垂+鼻点)——历史经典,但坐标体系为旧布局(y 间距小),易与新代码冲突。
|
|
96
120
|
- `three_phase_cable_fault.pscx`(三相电缆故障,Cable_Coax+cable_interface)——电缆专项模板,无 GFM/控制链。
|
|
97
|
-
- 本仓库 `templates/` 收录
|
|
121
|
+
- 本仓库 `templates/` 收录 7 个验证通过的模板;PSCAD 主库(master.pslx)为安装自带资产,不入库。
|
|
98
122
|
|
|
99
123
|
## 选型速查
|
|
100
124
|
| 需求 | 用哪个模板 |
|
|
@@ -102,3 +126,4 @@
|
|
|
102
126
|
| 并网电压/容量/位置扫描 | **grid_gfm_support**(改 Xg 三处 + RLA 负荷) |
|
|
103
127
|
| 故障/短路/序分量研究 | **fault_study**(改 tbreak TC/TO 选相,独立案例) |
|
|
104
128
|
| 孤岛频率/下垂/自定义控制器 | **island_droop_controller**(改 DROOPC 参数) |
|
|
129
|
+
| 自定义电气元件/Norton 支路(TMMB 类) | **tmmb_norton_element**(改 NRT1 参数或工具 create_norton_element 重建) |
|
package/package.json
CHANGED
package/plugin.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# 由知识资产固化项目自动生成(2026-08-25)· 部署至 Git 仓库
|
|
4
4
|
# ============================================================
|
|
5
5
|
name: pscad-automation-expert
|
|
6
|
-
version: 1.0.
|
|
6
|
+
version: 1.0.16
|
|
7
7
|
description: PSCAD 自动化建模与仿真控制专家插件
|
|
8
8
|
|
|
9
9
|
# ---- 系统提示词(加载到 Agent 上下文最前置位置)----
|
|
@@ -38,6 +38,7 @@ knowledge_base:
|
|
|
38
38
|
preload:
|
|
39
39
|
- knowledge/pscad_skill_core.md # 核心技能库:元件 API/布线 SOP/TOP3 排错
|
|
40
40
|
- knowledge/templates_index.md # 基准模板索引与二次开发指南
|
|
41
|
+
- knowledge/emtdc_custom_element_norton.md # EMTDC 自定义元件 Norton 等效开发 SOP
|
|
41
42
|
|
|
42
43
|
# ---- 模板资产 ----
|
|
43
44
|
templates:
|
|
@@ -49,6 +50,7 @@ templates:
|
|
|
49
50
|
- line_model_pi_100km.pscx # source3 单线图 + newpi 线路(Ferranti 对照)
|
|
50
51
|
- gfm_island_droop_nose.pscx # 双 GFM 孤岛下垂 + 鼻点(历史经典)
|
|
51
52
|
- three_phase_cable_fault.pscx # 三相电缆故障(Cable_Coax 专项)
|
|
53
|
+
- tmmb_norton_element.pscx # TMMB 热磁忆阻 Norton 等效自定义元件基准(v6 三路验证)
|
|
52
54
|
|
|
53
55
|
# ---- 运行环境(无硬编码:路径由 init_pscad_environment 动态配置于运行时)----
|
|
54
56
|
runtime:
|
|
@@ -53,9 +53,9 @@ if (-not (Test-Path -LiteralPath $pkgJson)) {
|
|
|
53
53
|
Copy-Item -LiteralPath $pkgJson -Destination "$pkgJson.bak-$(Get-Date -Format yyyyMMdd-HHmmss)" -Force
|
|
54
54
|
$text = [System.IO.File]::ReadAllText($pkgJson, [System.Text.Encoding]::UTF8)
|
|
55
55
|
|
|
56
|
-
# 4a)
|
|
57
|
-
$new = $text -replace '("dsh-plugin-pscad-expert-vyma"\s*:\s*")[^"]*(")', ('${1}' + $latest + '${2}')
|
|
58
|
-
if ($new -notmatch ('"' + $pkg + '"\s*:\s*"' + [regex]::Escape($latest) + '"')) {
|
|
56
|
+
# 4a) 依赖版本号:无论当前写的是什么,统一替换为 ^最新(^ 范围让后续 dsh plugin up 可解析新版本)
|
|
57
|
+
$new = $text -replace '("dsh-plugin-pscad-expert-vyma"\s*:\s*")[^"]*(")', ('${1}^' + $latest + '${2}')
|
|
58
|
+
if ($new -notmatch ('"' + $pkg + '"\s*:\s*"\^?' + [regex]::Escape($latest) + '"')) {
|
|
59
59
|
Write-Host " !! 未在 dependencies 找到插件条目,无法自动改版本,请先把上方输出发回。" -ForegroundColor Red
|
|
60
60
|
exit 1
|
|
61
61
|
}
|
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
<project name="TMMB_v6_g_l0_1_811387" version="5.0.0" schema="" Target="EMTDC">
|
|
2
|
+
<paramlist name="Settings">
|
|
3
|
+
<param name="creator" value="Administrator,1787881138" />
|
|
4
|
+
<param name="time_duration" value="3" />
|
|
5
|
+
<param name="time_step" value="10" />
|
|
6
|
+
<param name="sample_step" value="50" />
|
|
7
|
+
<param name="chatter_threshold" value=".001" />
|
|
8
|
+
<param name="branch_threshold" value=".0005" />
|
|
9
|
+
<param name="StartType" value="0" />
|
|
10
|
+
<param name="startup_filename" value="$(Namespace).snp" />
|
|
11
|
+
<param name="PlotType" value="1" />
|
|
12
|
+
<param name="output_filename" value="TMMB_v6_g_l0_1_811387.out" />
|
|
13
|
+
<param name="SnapType" value="0" />
|
|
14
|
+
<param name="SnapTime" value="0.3" />
|
|
15
|
+
<param name="snapshot_filename" value="$(Namespace).snp" />
|
|
16
|
+
<param name="MrunType" value="0" />
|
|
17
|
+
<param name="Mruns" value="1" />
|
|
18
|
+
<param name="Scenario" value="" />
|
|
19
|
+
<param name="Advanced" value="14335" />
|
|
20
|
+
<param name="sparsity_threshold" value="200" />
|
|
21
|
+
<param name="Options" value="16" />
|
|
22
|
+
<param name="Build" value="18" />
|
|
23
|
+
<param name="Warn" value="0" />
|
|
24
|
+
<param name="Check" value="0" />
|
|
25
|
+
<param name="description" value="" />
|
|
26
|
+
<param name="revisor" value="Administrator, 1787881143" />
|
|
27
|
+
</paramlist>
|
|
28
|
+
<Layers />
|
|
29
|
+
<List classid="Settings" />
|
|
30
|
+
<bookmarks />
|
|
31
|
+
<GlobalSubstitutions name="Default">
|
|
32
|
+
<List classid="Sub" />
|
|
33
|
+
<List classid="ValueSet" />
|
|
34
|
+
<paramlist>
|
|
35
|
+
<param name="Current" value="" />
|
|
36
|
+
</paramlist>
|
|
37
|
+
</GlobalSubstitutions>
|
|
38
|
+
<definitions>
|
|
39
|
+
<Definition classid="UserCmpDefn" name="TMMB" url="" view="false" instances="0" date="0" crc="63701272" id="362477968" group="R4">
|
|
40
|
+
<paramlist>
|
|
41
|
+
<param name="Description" value="Thermal-Magnetic Memristive Branch (v6: CCBR/GEQ Norton)" />
|
|
42
|
+
</paramlist>
|
|
43
|
+
<form name="TMMB" w="320" h="460" splitter="70" commentlines="4">
|
|
44
|
+
<category name="Configuration" visible="true">
|
|
45
|
+
<parameter name="Name" desc="Name for Identification" type="Text" group="" helpmode="Overwrite" allowemptystr="true">
|
|
46
|
+
<value><![CDATA[]]></value>
|
|
47
|
+
<cond type="Enable"><![CDATA[true]]></cond>
|
|
48
|
+
</parameter>
|
|
49
|
+
<parameter type="Text" name="COM" desc="Fortran Comment" group="" helpmode="Overwrite" allowemptystr="false">
|
|
50
|
+
<value><![CDATA[TMMB]]></value>
|
|
51
|
+
<cond type="Enable" />
|
|
52
|
+
</parameter>
|
|
53
|
+
<cond><![CDATA[true]]></cond>
|
|
54
|
+
</category>
|
|
55
|
+
<category name="TMMB Parameters" visible="true">
|
|
56
|
+
<parameter type="Real" name="RMIN" desc="Minimum resistance [ohm]" content_type="Variable" min="1E-9" max="1E+308" unit="ohm" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
57
|
+
<value><![CDATA[1.0]]></value>
|
|
58
|
+
<cond type="Enable" />
|
|
59
|
+
</parameter>
|
|
60
|
+
<parameter type="Real" name="K" desc="Memristance coefficient [ohm]" content_type="Variable" min="0" max="1E+308" unit="ohm" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
61
|
+
<value><![CDATA[1.0]]></value>
|
|
62
|
+
<cond type="Enable" />
|
|
63
|
+
</parameter>
|
|
64
|
+
<parameter type="Real" name="ALPHA" desc="Heating coupling [1/MW/s]" content_type="Variable" min="0" max="1E+308" unit="" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
65
|
+
<value><![CDATA[1.0]]></value>
|
|
66
|
+
<cond type="Enable" />
|
|
67
|
+
</parameter>
|
|
68
|
+
<parameter type="Real" name="BETA" desc="Cooling rate [1/s]" content_type="Variable" min="0" max="1E+308" unit="" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
69
|
+
<value><![CDATA[1.0]]></value>
|
|
70
|
+
<cond type="Enable" />
|
|
71
|
+
</parameter>
|
|
72
|
+
<parameter type="Real" name="L0" desc="Inductance [H]" content_type="Variable" min="0" max="1E+308" unit="H" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
73
|
+
<value><![CDATA[0.0]]></value>
|
|
74
|
+
<cond type="Enable" />
|
|
75
|
+
</parameter>
|
|
76
|
+
<cond><![CDATA[true]]></cond>
|
|
77
|
+
</category>
|
|
78
|
+
</form>
|
|
79
|
+
<svg viewBox="-200 -200 200 200">
|
|
80
|
+
<port model="Natural" name="NA" x="-72" y="0" dim="1" mode="Electrical" type="NonRemovable"><![CDATA[true]]></port>
|
|
81
|
+
<port model="Natural" name="NB" x="72" y="0" dim="1" mode="Electrical" type="NonRemovable"><![CDATA[true]]></port>
|
|
82
|
+
<port model="Transfer" name="OUT" x="0" y="-36" dim="1" mode="Output" type="Real"><![CDATA[true]]></port>
|
|
83
|
+
<rect x="-27" y="-15" width="54" height="30" stroke="Black" stroke-dasharray="none" stroke-width="0.2" fill-style="Hollow" fill-fg="Black" fill-bg="" />
|
|
84
|
+
<line x1="-72" y1="0" x2="-27" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
85
|
+
<line x1="27" y1="0" x2="72" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
86
|
+
<line x1="-12" y1="0" x2="-4" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
87
|
+
<line x1="-8" y1="-4" x2="-8" y2="4" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
88
|
+
<line x1="0" y1="0" x2="8" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
89
|
+
<line x1="4" y1="-4" x2="4" y2="4" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
90
|
+
<line x1="12" y1="0" x2="20" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
91
|
+
<line x1="16" y1="-4" x2="16" y2="4" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
92
|
+
<line x1="0" y1="15" x2="0" y2="36" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
93
|
+
<line x1="-5" y1="20" x2="0" y2="15" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
94
|
+
<line x1="5" y1="20" x2="0" y2="15" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
95
|
+
<text x="0" y="-1" stroke="Black" fill="Black" font-size="Small" text-anchor="Middle"><![CDATA[R(w)]]></text>
|
|
96
|
+
<text x="0" y="13" stroke="Black" fill="Black" font-size="Small" text-anchor="Middle"><![CDATA[TMMB]]></text>
|
|
97
|
+
</svg>
|
|
98
|
+
<script>
|
|
99
|
+
<segment name="Dsdyn" classid="CoreSegment" id="2093360559"><![CDATA[#STORAGE REAL:8
|
|
100
|
+
! $COM
|
|
101
|
+
! v = R(w)*i + L0*di/dt ; R(w)=RMIN+K*w^2 ; dw/dt=ALPHA*v*i-BETA*w
|
|
102
|
+
! CCBR/GEQ branch interface (seriesrl2 official pattern):
|
|
103
|
+
! GEQ fixed G0 at TIMEZERO (matrix static -> zero refactorization);
|
|
104
|
+
! per-step CCBR = I_hist + (G-G0)*V (RHS only).
|
|
105
|
+
! G=1/(R+2L0/DELT); Z1=R-2L0/DELT; I_hist=G*V-Z1*G*I.
|
|
106
|
+
! Storage: (1)w (2)v_prev (3)i_prev (4)i_hist (5)g (6)r (7)ccbr (8)spare
|
|
107
|
+
#LOCAL REAL W
|
|
108
|
+
#LOCAL REAL V
|
|
109
|
+
#LOCAL REAL I
|
|
110
|
+
#LOCAL REAL R
|
|
111
|
+
#LOCAL REAL G
|
|
112
|
+
#LOCAL REAL G0
|
|
113
|
+
#LOCAL REAL DTB
|
|
114
|
+
#LOCAL REAL Z1
|
|
115
|
+
#LOCAL REAL IH
|
|
116
|
+
#LOCAL INTEGER IVD1_1
|
|
117
|
+
#BEGIN
|
|
118
|
+
GEQ($BRR, $SS) = 1.0/(2.0*$RMIN + 2.0*$L0/DELT)
|
|
119
|
+
DEFRDBR($BRR, $SS) = .TRUE.
|
|
120
|
+
#ENDBEGIN
|
|
121
|
+
IF (TIMEZERO) THEN
|
|
122
|
+
STORF(NSTORF+1) = 0.0
|
|
123
|
+
STORF(NSTORF+2) = 0.0
|
|
124
|
+
STORF(NSTORF+3) = 0.0
|
|
125
|
+
STORF(NSTORF+4) = 0.0
|
|
126
|
+
STORF(NSTORF+5) = 1.0/$RMIN
|
|
127
|
+
STORF(NSTORF+6) = $RMIN
|
|
128
|
+
STORF(NSTORF+7) = 0.0
|
|
129
|
+
STORF(NSTORF+8) = 0.0
|
|
130
|
+
CCBR($BRR, $SS) = 0.0
|
|
131
|
+
$OUT = 0.0
|
|
132
|
+
ENDIF
|
|
133
|
+
W = STORF(NSTORF+1)
|
|
134
|
+
IH = STORF(NSTORF+4)
|
|
135
|
+
G = STORF(NSTORF+5)
|
|
136
|
+
V = VBRANCH($SS, $BRR)
|
|
137
|
+
I = G*V + IH
|
|
138
|
+
DTB = 0.5 * $BETA * DELT
|
|
139
|
+
W = (W*(1.0 - DTB) + $ALPHA*DELT*(V*I)) / (1.0 + DTB)
|
|
140
|
+
R = $RMIN + $K * W * W
|
|
141
|
+
G = 1.0/(R + 2.0*$L0/DELT)
|
|
142
|
+
Z1 = R - 2.0*$L0/DELT
|
|
143
|
+
! ---- seriesrl2 official recurrence (no CBR readback needed) ----
|
|
144
|
+
IH = (1.0 - Z1*G)*G*V - Z1*G*IH
|
|
145
|
+
G0 = 1.0/(2.0*$RMIN + 2.0*$L0/DELT)
|
|
146
|
+
CCBR($BRR, $SS) = IH + (G - G0)*V
|
|
147
|
+
STORF(NSTORF+1) = W
|
|
148
|
+
STORF(NSTORF+2) = V
|
|
149
|
+
STORF(NSTORF+3) = I
|
|
150
|
+
STORF(NSTORF+4) = IH
|
|
151
|
+
STORF(NSTORF+5) = G
|
|
152
|
+
STORF(NSTORF+6) = R
|
|
153
|
+
STORF(NSTORF+7) = CCBR($BRR, $SS)
|
|
154
|
+
STORF(NSTORF+8) = 0.0
|
|
155
|
+
NSTORF = NSTORF + 8
|
|
156
|
+
$OUT = W]]></segment>
|
|
157
|
+
<segment name="Branch" classid="CoreSegment" id="1366280103"><![CDATA[BRR = $NA $NB BREAKER 1.0E6]]></segment>
|
|
158
|
+
<segment name="FlyBy" classid="CoreSegment" id="1256125691"><![CDATA[TMMB memristive branch
|
|
159
|
+
:NA
|
|
160
|
+
Positive terminal
|
|
161
|
+
:NB
|
|
162
|
+
Negative terminal
|
|
163
|
+
:OUT
|
|
164
|
+
State variable w]]></segment>
|
|
165
|
+
</script>
|
|
166
|
+
<graphics>
|
|
167
|
+
<paramlist />
|
|
168
|
+
<Port id="137001279" classid="Port" x="-72" y="0">
|
|
169
|
+
<paramlist>
|
|
170
|
+
<param name="name" value="NA" />
|
|
171
|
+
<param name="internal" value="false" />
|
|
172
|
+
<param name="cond" value="true" />
|
|
173
|
+
<param name="mode" value="3" />
|
|
174
|
+
<param name="datatype" value="0" />
|
|
175
|
+
<param name="electype" value="0" />
|
|
176
|
+
<param name="dim" value="1" />
|
|
177
|
+
</paramlist>
|
|
178
|
+
</Port>
|
|
179
|
+
<Port id="1305594588" classid="Port" x="72" y="0">
|
|
180
|
+
<paramlist>
|
|
181
|
+
<param name="name" value="NB" />
|
|
182
|
+
<param name="internal" value="false" />
|
|
183
|
+
<param name="cond" value="true" />
|
|
184
|
+
<param name="mode" value="3" />
|
|
185
|
+
<param name="datatype" value="0" />
|
|
186
|
+
<param name="electype" value="0" />
|
|
187
|
+
<param name="dim" value="1" />
|
|
188
|
+
</paramlist>
|
|
189
|
+
</Port>
|
|
190
|
+
<Port id="1034241133" classid="Port" x="0" y="-36">
|
|
191
|
+
<paramlist>
|
|
192
|
+
<param name="name" value="OUT" />
|
|
193
|
+
<param name="internal" value="false" />
|
|
194
|
+
<param name="cond" value="true" />
|
|
195
|
+
<param name="mode" value="2" />
|
|
196
|
+
<param name="datatype" value="3" />
|
|
197
|
+
<param name="electype" value="0" />
|
|
198
|
+
<param name="dim" value="1" />
|
|
199
|
+
</paramlist>
|
|
200
|
+
</Port>
|
|
201
|
+
<Gfx classid="Graphics.Rectangle" id="2136562982" x="-27" y="-15" w="54" h="30">
|
|
202
|
+
<paramlist>
|
|
203
|
+
<param name="color" value="Black" />
|
|
204
|
+
<param name="dasharray" value="0" />
|
|
205
|
+
<param name="thickness" value="0" />
|
|
206
|
+
<param name="port" value="" />
|
|
207
|
+
<param name="fill_style" value="0" />
|
|
208
|
+
<param name="fill_fg" value="Black" />
|
|
209
|
+
<param name="fill_bg" value="White" />
|
|
210
|
+
<param name="cond" value="true" />
|
|
211
|
+
</paramlist>
|
|
212
|
+
</Gfx>
|
|
213
|
+
<Gfx classid="Graphics.Line" id="45103384" x="-72" y="0">
|
|
214
|
+
<vertex x="0" y="0" />
|
|
215
|
+
<vertex x="45" y="0" />
|
|
216
|
+
<paramlist>
|
|
217
|
+
<param name="color" value="Black" />
|
|
218
|
+
<param name="dasharray" value="0" />
|
|
219
|
+
<param name="thickness" value="0" />
|
|
220
|
+
<param name="port" value="" />
|
|
221
|
+
<param name="cond" value="true" />
|
|
222
|
+
</paramlist>
|
|
223
|
+
</Gfx>
|
|
224
|
+
<Gfx classid="Graphics.Line" id="47389884" x="27" y="0">
|
|
225
|
+
<vertex x="0" y="0" />
|
|
226
|
+
<vertex x="45" y="0" />
|
|
227
|
+
<paramlist>
|
|
228
|
+
<param name="color" value="Black" />
|
|
229
|
+
<param name="dasharray" value="0" />
|
|
230
|
+
<param name="thickness" value="0" />
|
|
231
|
+
<param name="port" value="" />
|
|
232
|
+
<param name="cond" value="true" />
|
|
233
|
+
</paramlist>
|
|
234
|
+
</Gfx>
|
|
235
|
+
<Gfx classid="Graphics.Line" id="708858009" x="-12" y="0">
|
|
236
|
+
<vertex x="0" y="0" />
|
|
237
|
+
<vertex x="8" y="0" />
|
|
238
|
+
<paramlist>
|
|
239
|
+
<param name="color" value="Black" />
|
|
240
|
+
<param name="dasharray" value="0" />
|
|
241
|
+
<param name="thickness" value="0" />
|
|
242
|
+
<param name="port" value="" />
|
|
243
|
+
<param name="cond" value="true" />
|
|
244
|
+
</paramlist>
|
|
245
|
+
</Gfx>
|
|
246
|
+
<Gfx classid="Graphics.Line" id="1382810431" x="-8" y="-4">
|
|
247
|
+
<vertex x="0" y="0" />
|
|
248
|
+
<vertex x="0" y="8" />
|
|
249
|
+
<paramlist>
|
|
250
|
+
<param name="color" value="Black" />
|
|
251
|
+
<param name="dasharray" value="0" />
|
|
252
|
+
<param name="thickness" value="0" />
|
|
253
|
+
<param name="port" value="" />
|
|
254
|
+
<param name="cond" value="true" />
|
|
255
|
+
</paramlist>
|
|
256
|
+
</Gfx>
|
|
257
|
+
<Gfx classid="Graphics.Line" id="316471579" x="0" y="0">
|
|
258
|
+
<vertex x="0" y="0" />
|
|
259
|
+
<vertex x="8" y="0" />
|
|
260
|
+
<paramlist>
|
|
261
|
+
<param name="color" value="Black" />
|
|
262
|
+
<param name="dasharray" value="0" />
|
|
263
|
+
<param name="thickness" value="0" />
|
|
264
|
+
<param name="port" value="" />
|
|
265
|
+
<param name="cond" value="true" />
|
|
266
|
+
</paramlist>
|
|
267
|
+
</Gfx>
|
|
268
|
+
<Gfx classid="Graphics.Line" id="251937415" x="4" y="-4">
|
|
269
|
+
<vertex x="0" y="0" />
|
|
270
|
+
<vertex x="0" y="8" />
|
|
271
|
+
<paramlist>
|
|
272
|
+
<param name="color" value="Black" />
|
|
273
|
+
<param name="dasharray" value="0" />
|
|
274
|
+
<param name="thickness" value="0" />
|
|
275
|
+
<param name="port" value="" />
|
|
276
|
+
<param name="cond" value="true" />
|
|
277
|
+
</paramlist>
|
|
278
|
+
</Gfx>
|
|
279
|
+
<Gfx classid="Graphics.Line" id="2139547155" x="12" y="0">
|
|
280
|
+
<vertex x="0" y="0" />
|
|
281
|
+
<vertex x="8" y="0" />
|
|
282
|
+
<paramlist>
|
|
283
|
+
<param name="color" value="Black" />
|
|
284
|
+
<param name="dasharray" value="0" />
|
|
285
|
+
<param name="thickness" value="0" />
|
|
286
|
+
<param name="port" value="" />
|
|
287
|
+
<param name="cond" value="true" />
|
|
288
|
+
</paramlist>
|
|
289
|
+
</Gfx>
|
|
290
|
+
<Gfx classid="Graphics.Line" id="1002252530" x="16" y="-4">
|
|
291
|
+
<vertex x="0" y="0" />
|
|
292
|
+
<vertex x="0" y="8" />
|
|
293
|
+
<paramlist>
|
|
294
|
+
<param name="color" value="Black" />
|
|
295
|
+
<param name="dasharray" value="0" />
|
|
296
|
+
<param name="thickness" value="0" />
|
|
297
|
+
<param name="port" value="" />
|
|
298
|
+
<param name="cond" value="true" />
|
|
299
|
+
</paramlist>
|
|
300
|
+
</Gfx>
|
|
301
|
+
<Gfx classid="Graphics.Line" id="1995477368" x="0" y="15">
|
|
302
|
+
<vertex x="0" y="0" />
|
|
303
|
+
<vertex x="0" y="21" />
|
|
304
|
+
<paramlist>
|
|
305
|
+
<param name="color" value="Black" />
|
|
306
|
+
<param name="dasharray" value="0" />
|
|
307
|
+
<param name="thickness" value="0" />
|
|
308
|
+
<param name="port" value="" />
|
|
309
|
+
<param name="cond" value="true" />
|
|
310
|
+
</paramlist>
|
|
311
|
+
</Gfx>
|
|
312
|
+
<Gfx classid="Graphics.Line" id="257938923" x="-5" y="20">
|
|
313
|
+
<vertex x="0" y="0" />
|
|
314
|
+
<vertex x="5" y="-5" />
|
|
315
|
+
<paramlist>
|
|
316
|
+
<param name="color" value="Black" />
|
|
317
|
+
<param name="dasharray" value="0" />
|
|
318
|
+
<param name="thickness" value="0" />
|
|
319
|
+
<param name="port" value="" />
|
|
320
|
+
<param name="cond" value="true" />
|
|
321
|
+
</paramlist>
|
|
322
|
+
</Gfx>
|
|
323
|
+
<Gfx classid="Graphics.Line" id="515372674" x="5" y="20">
|
|
324
|
+
<vertex x="0" y="0" />
|
|
325
|
+
<vertex x="-5" y="-5" />
|
|
326
|
+
<paramlist>
|
|
327
|
+
<param name="color" value="Black" />
|
|
328
|
+
<param name="dasharray" value="0" />
|
|
329
|
+
<param name="thickness" value="0" />
|
|
330
|
+
<param name="port" value="" />
|
|
331
|
+
<param name="cond" value="true" />
|
|
332
|
+
</paramlist>
|
|
333
|
+
</Gfx>
|
|
334
|
+
<Gfx classid="Graphics.Text" id="1082658360" x="0" y="-1">
|
|
335
|
+
<paramlist>
|
|
336
|
+
<param name="color" value="Black" />
|
|
337
|
+
<param name="font_size" value="0" />
|
|
338
|
+
<param name="full_font" value="Tahoma, 12world" />
|
|
339
|
+
<param name="anchor" value="1" />
|
|
340
|
+
<param name="cond" value="true" />
|
|
341
|
+
<param name="text" value="R(w)" />
|
|
342
|
+
<param name="angle" value="0" />
|
|
343
|
+
</paramlist>
|
|
344
|
+
</Gfx>
|
|
345
|
+
<Gfx classid="Graphics.Text" id="1380391487" x="0" y="13">
|
|
346
|
+
<paramlist>
|
|
347
|
+
<param name="color" value="Black" />
|
|
348
|
+
<param name="font_size" value="0" />
|
|
349
|
+
<param name="full_font" value="Tahoma, 12world" />
|
|
350
|
+
<param name="anchor" value="1" />
|
|
351
|
+
<param name="cond" value="true" />
|
|
352
|
+
<param name="text" value="TMMB" />
|
|
353
|
+
<param name="angle" value="0" />
|
|
354
|
+
</paramlist>
|
|
355
|
+
</Gfx>
|
|
356
|
+
</graphics>
|
|
357
|
+
</Definition>
|
|
358
|
+
<Definition classid="StationDefn" name="DS" id="528127591" group="" url="" version="" build="" crc="58860711" view="false">
|
|
359
|
+
<paramlist name="">
|
|
360
|
+
<param name="Description" value="" />
|
|
361
|
+
</paramlist>
|
|
362
|
+
<schematic classid="StationCanvas">
|
|
363
|
+
<paramlist>
|
|
364
|
+
<param name="show_grid" value="0" />
|
|
365
|
+
<param name="size" value="0" />
|
|
366
|
+
<param name="orient" value="1" />
|
|
367
|
+
<param name="show_border" value="0" />
|
|
368
|
+
<param name="monitor_bus_voltage" value="0" />
|
|
369
|
+
<param name="show_signal" value="0" />
|
|
370
|
+
<param name="show_virtual" value="0" />
|
|
371
|
+
<param name="show_sequence" value="0" />
|
|
372
|
+
<param name="auto_sequence" value="1" />
|
|
373
|
+
<param name="bus_expand_x" value="8" />
|
|
374
|
+
<param name="bus_expand_y" value="8" />
|
|
375
|
+
<param name="bus_length" value="4" />
|
|
376
|
+
</paramlist>
|
|
377
|
+
<grouping />
|
|
378
|
+
<Wire classid="Branch" id="1776616513" name="Main" x="180" y="180" w="66" h="82" orient="0" disable="false" defn="Main" recv="-1" send="-1" back="-1">
|
|
379
|
+
<vertex x="0" y="0" />
|
|
380
|
+
<vertex x="0" y="18" />
|
|
381
|
+
<vertex x="54" y="54" />
|
|
382
|
+
<vertex x="54" y="72" />
|
|
383
|
+
<User classid="UserCmp" id="262724584" name="TMMB_v6_g_l0_1_811387:Main" x="0" y="0" w="0" h="0" z="-1" orient="0" defn="TMMB_v6_g_l0_1_811387:Main" link="-1" q="4" disable="false">
|
|
384
|
+
<paramlist name="" link="-1" crc="4361682" />
|
|
385
|
+
</User>
|
|
386
|
+
</Wire>
|
|
387
|
+
</schematic>
|
|
388
|
+
</Definition>
|
|
389
|
+
<Definition classid="UserCmpDefn" name="Main" id="1173666291" group="" url="" version="" build="" crc="128000575" view="false" date="0">
|
|
390
|
+
<paramlist name="">
|
|
391
|
+
<param name="Description" value="" />
|
|
392
|
+
</paramlist>
|
|
393
|
+
<form name="" w="320" h="400" splitter="60" />
|
|
394
|
+
<graphics viewBox="-200 -200 200 200" size="2">
|
|
395
|
+
<Gfx classid="Graphics.Rectangle" id="496460006" x="-36" y="-36" w="72" h="72">
|
|
396
|
+
<paramlist>
|
|
397
|
+
<param name="color" value="Black" />
|
|
398
|
+
<param name="dasharray" value="0" />
|
|
399
|
+
<param name="thickness" value="0" />
|
|
400
|
+
<param name="port" value="" />
|
|
401
|
+
<param name="fill_style" value="0" />
|
|
402
|
+
<param name="fill_fg" value="Black" />
|
|
403
|
+
<param name="fill_bg" value="Black" />
|
|
404
|
+
<param name="cond" value="true" />
|
|
405
|
+
</paramlist>
|
|
406
|
+
</Gfx>
|
|
407
|
+
<Gfx classid="Graphics.Text" id="1656279956" x="0" y="0">
|
|
408
|
+
<paramlist>
|
|
409
|
+
<param name="text" value="%:Name" />
|
|
410
|
+
<param name="anchor" value="0" />
|
|
411
|
+
<param name="full_font" value="Tahoma, 10pt" />
|
|
412
|
+
<param name="angle" value="0" />
|
|
413
|
+
<param name="color" value="Black" />
|
|
414
|
+
<param name="cond" value="true" />
|
|
415
|
+
</paramlist>
|
|
416
|
+
</Gfx>
|
|
417
|
+
</graphics>
|
|
418
|
+
<schematic classid="UserCanvas">
|
|
419
|
+
<paramlist>
|
|
420
|
+
<param name="show_grid" value="0" />
|
|
421
|
+
<param name="size" value="0" />
|
|
422
|
+
<param name="orient" value="1" />
|
|
423
|
+
<param name="show_border" value="0" />
|
|
424
|
+
<param name="monitor_bus_voltage" value="0" />
|
|
425
|
+
<param name="show_signal" value="0" />
|
|
426
|
+
<param name="show_virtual" value="0" />
|
|
427
|
+
<param name="show_sequence" value="0" />
|
|
428
|
+
<param name="auto_sequence" value="1" />
|
|
429
|
+
<param name="bus_expand_x" value="8" />
|
|
430
|
+
<param name="bus_expand_y" value="8" />
|
|
431
|
+
<param name="bus_length" value="4" />
|
|
432
|
+
</paramlist>
|
|
433
|
+
<grouping />
|
|
434
|
+
<User classid="UserCmp" id="161649834" name="master:source_1" x="1080" y="3600" w="38" h="122" z="-1" orient="1" defn="master:source_1" link="-1" q="4" disable="false">
|
|
435
|
+
<paramlist name="" link="-1" crc="49505675">
|
|
436
|
+
<param name="Name" value="Src" />
|
|
437
|
+
<param name="Type" value="1" />
|
|
438
|
+
<param name="Grnd" value="1" />
|
|
439
|
+
<param name="Spec" value="0" />
|
|
440
|
+
<param name="Cntrl" value="0" />
|
|
441
|
+
<param name="AC" value="1" />
|
|
442
|
+
<param name="Vm" value="10 [kV]" />
|
|
443
|
+
<param name="Tc" value="0.05" />
|
|
444
|
+
<param name="Ph" value="0.0" />
|
|
445
|
+
<param name="f" value="50.0 [Hz]" />
|
|
446
|
+
<param name="P" value="0.0" />
|
|
447
|
+
<param name="Q" value="0.0" />
|
|
448
|
+
<param name="R" value="0.001 [ohm]" />
|
|
449
|
+
<param name="Rs" value="1.0" />
|
|
450
|
+
<param name="Rp" value="1.0" />
|
|
451
|
+
<param name="Lp" value="0.1" />
|
|
452
|
+
<param name="R_" value="1.0" />
|
|
453
|
+
<param name="L" value="0.1" />
|
|
454
|
+
<param name="C" value="1.0" />
|
|
455
|
+
<param name="L_" value="0.1" />
|
|
456
|
+
<param name="C_" value="1.0" />
|
|
457
|
+
<param name="CUR" value="" />
|
|
458
|
+
</paramlist>
|
|
459
|
+
</User>
|
|
460
|
+
<User classid="UserCmp" id="614898660" name="master:ammeter" x="2520" y="3600" w="44" h="28" z="-1" orient="0" defn="master:ammeter" link="-1" q="4" disable="false">
|
|
461
|
+
<paramlist name="" link="-1" crc="119030036">
|
|
462
|
+
<param name="Name" value="Ix" />
|
|
463
|
+
</paramlist>
|
|
464
|
+
</User>
|
|
465
|
+
<User classid="UserCmp" id="508652399" name="master:voltmetergnd" x="3240" y="2700" w="21" h="36" z="-1" orient="0" defn="master:voltmetergnd" link="-1" q="4" disable="false">
|
|
466
|
+
<paramlist name="" link="-1" crc="116145885">
|
|
467
|
+
<param name="Name" value="Vx" />
|
|
468
|
+
</paramlist>
|
|
469
|
+
</User>
|
|
470
|
+
<User classid="UserCmp" id="546041519" name="master:ground" x="5400" y="3600" w="34" h="26" z="-1" orient="0" defn="master:ground" link="-1" q="4" disable="false">
|
|
471
|
+
<paramlist name="" link="-1" crc="28206164" />
|
|
472
|
+
</User>
|
|
473
|
+
<User classid="UserCmp" id="628458748" name="TMMB_v6_g_l0_1_811387:TMMB" x="3960" y="3600" w="152" h="80" z="-1" orient="0" defn="TMMB_v6_g_l0_1_811387:TMMB" link="-1" q="4" disable="false">
|
|
474
|
+
<paramlist name="" link="-1" crc="90527443">
|
|
475
|
+
<param name="Name" value="TMMB1" />
|
|
476
|
+
<param name="COM" value="TMMB" />
|
|
477
|
+
<param name="RMIN" value="1.0" />
|
|
478
|
+
<param name="K" value="1.0" />
|
|
479
|
+
<param name="ALPHA" value="1.0" />
|
|
480
|
+
<param name="BETA" value="1.0" />
|
|
481
|
+
<param name="L0" value="0.1" />
|
|
482
|
+
</paramlist>
|
|
483
|
+
</User>
|
|
484
|
+
<Wire classid="WireOrthogonal" id="495705146" name="" x="1080" y="3564" w="1450" h="46" orient="0" disable="false">
|
|
485
|
+
<vertex x="0" y="0" />
|
|
486
|
+
<vertex x="0" y="36" />
|
|
487
|
+
<vertex x="1440" y="36" />
|
|
488
|
+
</Wire>
|
|
489
|
+
<Wire classid="WireOrthogonal" id="931971453" name="" x="2556" y="3600" w="1342" h="10" orient="0" disable="false">
|
|
490
|
+
<vertex x="0" y="0" />
|
|
491
|
+
<vertex x="1332" y="0" />
|
|
492
|
+
</Wire>
|
|
493
|
+
<Wire classid="WireOrthogonal" id="1303658187" name="" x="4032" y="3600" w="1378" h="10" orient="0" disable="false">
|
|
494
|
+
<vertex x="0" y="0" />
|
|
495
|
+
<vertex x="1368" y="0" />
|
|
496
|
+
</Wire>
|
|
497
|
+
<Wire classid="WireOrthogonal" id="783384810" name="" x="2556" y="3600" w="694" h="910" orient="0" disable="false">
|
|
498
|
+
<vertex x="0" y="0" />
|
|
499
|
+
<vertex x="0" y="-900" />
|
|
500
|
+
<vertex x="684" y="-900" />
|
|
501
|
+
</Wire>
|
|
502
|
+
<User classid="UserCmp" id="1436320645" name="master:datalabel" x="3960" y="3564" w="24" h="23" z="-1" orient="0" defn="master:datalabel" link="-1" q="4" disable="false">
|
|
503
|
+
<paramlist name="" link="-1" crc="127230955">
|
|
504
|
+
<param name="Name" value="Wx" />
|
|
505
|
+
</paramlist>
|
|
506
|
+
</User>
|
|
507
|
+
<User classid="UserCmp" id="1634070217" name="master:pgb" x="9900" y="3600" w="41" h="40" z="-1" orient="0" defn="master:pgb" link="-1" q="4" disable="false">
|
|
508
|
+
<paramlist name="" link="-1" crc="65740200">
|
|
509
|
+
<param name="Name" value="Wx" />
|
|
510
|
+
<param name="Group" value="" />
|
|
511
|
+
<param name="UseSignalName" value="1" />
|
|
512
|
+
<param name="enab" value="1" />
|
|
513
|
+
<param name="Display" value="1" />
|
|
514
|
+
<param name="Scale" value="1.0" />
|
|
515
|
+
<param name="Units" value="" />
|
|
516
|
+
<param name="mrun" value="0" />
|
|
517
|
+
<param name="Pol" value="0" />
|
|
518
|
+
<param name="Max" value="2.0" />
|
|
519
|
+
<param name="Min" value="-2.0" />
|
|
520
|
+
</paramlist>
|
|
521
|
+
</User>
|
|
522
|
+
<User classid="UserCmp" id="1455815762" name="master:datalabel" x="9900" y="3600" w="24" h="23" z="-1" orient="0" defn="master:datalabel" link="-1" q="4" disable="false">
|
|
523
|
+
<paramlist name="" link="-1" crc="127230955">
|
|
524
|
+
<param name="Name" value="Wx" />
|
|
525
|
+
</paramlist>
|
|
526
|
+
</User>
|
|
527
|
+
<User classid="UserCmp" id="1917243387" name="master:pgb" x="9000" y="3060" w="41" h="40" z="-1" orient="0" defn="master:pgb" link="-1" q="4" disable="false">
|
|
528
|
+
<paramlist name="" link="-1" crc="65740200">
|
|
529
|
+
<param name="Name" value="Vx" />
|
|
530
|
+
<param name="Group" value="" />
|
|
531
|
+
<param name="UseSignalName" value="1" />
|
|
532
|
+
<param name="enab" value="1" />
|
|
533
|
+
<param name="Display" value="1" />
|
|
534
|
+
<param name="Scale" value="1.0" />
|
|
535
|
+
<param name="Units" value="" />
|
|
536
|
+
<param name="mrun" value="0" />
|
|
537
|
+
<param name="Pol" value="0" />
|
|
538
|
+
<param name="Max" value="2.0" />
|
|
539
|
+
<param name="Min" value="-2.0" />
|
|
540
|
+
</paramlist>
|
|
541
|
+
</User>
|
|
542
|
+
<User classid="UserCmp" id="1163648990" name="master:datalabel" x="9000" y="3060" w="20" h="23" z="-1" orient="0" defn="master:datalabel" link="-1" q="4" disable="false">
|
|
543
|
+
<paramlist name="" link="-1" crc="127230955">
|
|
544
|
+
<param name="Name" value="Vx" />
|
|
545
|
+
</paramlist>
|
|
546
|
+
</User>
|
|
547
|
+
<User classid="UserCmp" id="1204200072" name="master:pgb" x="9000" y="2520" w="41" h="40" z="-1" orient="0" defn="master:pgb" link="-1" q="4" disable="false">
|
|
548
|
+
<paramlist name="" link="-1" crc="65740200">
|
|
549
|
+
<param name="Name" value="Ix" />
|
|
550
|
+
<param name="Group" value="" />
|
|
551
|
+
<param name="UseSignalName" value="1" />
|
|
552
|
+
<param name="enab" value="1" />
|
|
553
|
+
<param name="Display" value="1" />
|
|
554
|
+
<param name="Scale" value="1.0" />
|
|
555
|
+
<param name="Units" value="" />
|
|
556
|
+
<param name="mrun" value="0" />
|
|
557
|
+
<param name="Pol" value="0" />
|
|
558
|
+
<param name="Max" value="2.0" />
|
|
559
|
+
<param name="Min" value="-2.0" />
|
|
560
|
+
</paramlist>
|
|
561
|
+
</User>
|
|
562
|
+
<User classid="UserCmp" id="274305448" name="master:datalabel" x="9000" y="2520" w="16" h="23" z="-1" orient="0" defn="master:datalabel" link="-1" q="4" disable="false">
|
|
563
|
+
<paramlist name="" link="-1" crc="127230955">
|
|
564
|
+
<param name="Name" value="Ix" />
|
|
565
|
+
</paramlist>
|
|
566
|
+
</User>
|
|
567
|
+
</schematic>
|
|
568
|
+
</Definition>
|
|
569
|
+
</definitions>
|
|
570
|
+
<List classid="Resource" />
|
|
571
|
+
<hierarchy>
|
|
572
|
+
<call link="157125084" name="TMMB_v6_g_l0_1_811387:DS" z="-1" view="false" instance="0">
|
|
573
|
+
<call link="262724584" name="TMMB_v6_g_l0_1_811387:Main" z="-1" view="true" instance="0" />
|
|
574
|
+
</call>
|
|
575
|
+
</hierarchy>
|
|
576
|
+
</project>
|
package/tools/main.py
CHANGED
|
@@ -55,6 +55,7 @@ from __future__ import annotations
|
|
|
55
55
|
import json
|
|
56
56
|
import os
|
|
57
57
|
import re
|
|
58
|
+
import socket
|
|
58
59
|
import sys
|
|
59
60
|
import time
|
|
60
61
|
import math
|
|
@@ -522,13 +523,15 @@ def _gen_name(comp_type: str) -> str:
|
|
|
522
523
|
# ---------------------------------------------------------------------------
|
|
523
524
|
# 工具集 1:连接与工程加载(懒加载 mhi)
|
|
524
525
|
# ---------------------------------------------------------------------------
|
|
525
|
-
def _persist_case(prj: Any, project_name: str,
|
|
526
|
-
|
|
526
|
+
def _persist_case(prj: Any, project_name: str,
|
|
527
|
+
folder: str) -> Tuple[Optional[str], List[str]]:
|
|
528
|
+
"""尽力把会话内新建工程落盘,返回 (实际 .pscx 路径或 None, 尝试记录)。
|
|
527
529
|
|
|
528
530
|
mhi-pscad 2.9.7 的 create_case(project_name, folder=...) 与 save() 都可能
|
|
529
531
|
不按 folder 写 .pscx(工程仅在 PSCAD 会话内存)。依次尝试:
|
|
530
532
|
① save/save_as/save_case 变体;② prj 路径属性;③ 候选目录全盘搜同名文件。
|
|
531
533
|
"""
|
|
534
|
+
attempts: List[str] = []
|
|
532
535
|
expected = os.path.join(folder, project_name + '.pscx')
|
|
533
536
|
try:
|
|
534
537
|
# ① 常见保存 API
|
|
@@ -537,10 +540,13 @@ def _persist_case(prj: Any, project_name: str, folder: str) -> Optional[str]:
|
|
|
537
540
|
try:
|
|
538
541
|
fn = getattr(prj, meth)
|
|
539
542
|
fn(*args)
|
|
540
|
-
|
|
543
|
+
attempts.append('%s() -> 已调用' % meth)
|
|
544
|
+
except Exception as exc:
|
|
545
|
+
attempts.append('%s() -> 失败: %s' % (meth, exc))
|
|
541
546
|
continue
|
|
542
547
|
if os.path.isfile(expected):
|
|
543
|
-
|
|
548
|
+
attempts.append('目标文件已确认: %s' % expected)
|
|
549
|
+
return expected, attempts
|
|
544
550
|
# ② prj 自带路径属性
|
|
545
551
|
for attr in ('path', 'filename', 'file_name', 'case_path',
|
|
546
552
|
'project_path'):
|
|
@@ -550,13 +556,15 @@ def _persist_case(prj: Any, project_name: str, folder: str) -> Optional[str]:
|
|
|
550
556
|
p = p()
|
|
551
557
|
if isinstance(p, str) and p.lower().endswith('.pscx') \
|
|
552
558
|
and os.path.isfile(p):
|
|
553
|
-
|
|
559
|
+
attempts.append('prj.%s -> %s' % (attr, p))
|
|
560
|
+
return p, attempts
|
|
554
561
|
except Exception:
|
|
555
562
|
continue
|
|
556
|
-
# ③
|
|
563
|
+
# ③ 候选目录搜最近生成的同名文件(含 PSCAD 常见案例目录)
|
|
557
564
|
import glob as _glob
|
|
558
565
|
bases = [folder, os.getcwd(), os.path.expanduser('~/Documents'),
|
|
559
|
-
os.path.expanduser('~/PSCAD')
|
|
566
|
+
os.path.expanduser('~/PSCAD'),
|
|
567
|
+
os.path.expanduser('~/pscad_cases')]
|
|
560
568
|
best = None
|
|
561
569
|
for base in bases:
|
|
562
570
|
try:
|
|
@@ -568,9 +576,14 @@ def _persist_case(prj: Any, project_name: str, folder: str) -> Optional[str]:
|
|
|
568
576
|
for h in hits:
|
|
569
577
|
if best is None or os.path.getmtime(h) > os.path.getmtime(best):
|
|
570
578
|
best = h
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
579
|
+
if best:
|
|
580
|
+
attempts.append('目录搜索命中: %s' % best)
|
|
581
|
+
else:
|
|
582
|
+
attempts.append('目录搜索无命中(bases: %s)' % '; '.join(bases))
|
|
583
|
+
return best, attempts
|
|
584
|
+
except Exception as exc:
|
|
585
|
+
attempts.append('整体异常: %s' % exc)
|
|
586
|
+
return None, attempts
|
|
574
587
|
|
|
575
588
|
|
|
576
589
|
def connect_and_load_project(project_name: str,
|
|
@@ -608,10 +621,15 @@ def connect_and_load_project(project_name: str,
|
|
|
608
621
|
return _err(msg)
|
|
609
622
|
|
|
610
623
|
# folder 回退链:显式传入 → PSCAD_WORK_DIR 环境变量 → 用户目录 ~/pscad_cases
|
|
611
|
-
#
|
|
624
|
+
# (无盘符依赖,任何机器开箱即用;立即创建,保证缺省路径同样可写可落盘)
|
|
612
625
|
folder = folder or DEFAULT_FOLDER or os.path.expanduser('~/pscad_cases')
|
|
626
|
+
try:
|
|
627
|
+
os.makedirs(folder, exist_ok=True)
|
|
628
|
+
except Exception:
|
|
629
|
+
pass
|
|
613
630
|
_prj_folder = folder
|
|
614
|
-
pscx_path: Optional[str] = None
|
|
631
|
+
pscx_path: Optional[str] = None # 实际落盘的 .pscx 路径(探测后回报)
|
|
632
|
+
save_attempts: List[str] = [] # 落盘尝试记录(诊断用)
|
|
615
633
|
|
|
616
634
|
prj = None
|
|
617
635
|
try:
|
|
@@ -631,14 +649,9 @@ def connect_and_load_project(project_name: str,
|
|
|
631
649
|
|
|
632
650
|
if prj is None and create_if_missing:
|
|
633
651
|
try:
|
|
634
|
-
# 目录不存在可能导致 create_case 静默不落盘:先确保目标目录存在
|
|
635
|
-
try:
|
|
636
|
-
os.makedirs(folder, exist_ok=True)
|
|
637
|
-
except Exception:
|
|
638
|
-
pass
|
|
639
652
|
_pscad.create_case(project_name, folder=folder)
|
|
640
653
|
prj = _pscad.project(project_name)
|
|
641
|
-
pscx_path = _persist_case(prj, project_name, folder)
|
|
654
|
+
pscx_path, save_attempts = _persist_case(prj, project_name, folder)
|
|
642
655
|
if pscx_path:
|
|
643
656
|
folder = os.path.dirname(pscx_path) # 会话状态跟随真实落盘目录
|
|
644
657
|
_prj_folder = folder
|
|
@@ -658,16 +671,34 @@ def connect_and_load_project(project_name: str,
|
|
|
658
671
|
_main = None
|
|
659
672
|
return _err('打开 Main 画布失败: %s' % exc)
|
|
660
673
|
result = {'project': project_name, 'canvas': 'Main',
|
|
661
|
-
'pscx_path': pscx_path}
|
|
674
|
+
'folder': folder, 'pscx_path': pscx_path}
|
|
675
|
+
if save_attempts:
|
|
676
|
+
result['save_attempts'] = save_attempts
|
|
662
677
|
if create_if_missing and not pscx_path:
|
|
663
678
|
result['warning'] = ('create_case 未能在磁盘找到 .pscx(mhi 2.9.7 可能仅'
|
|
664
679
|
'内存建工程):工程仅存在于当前 PSCAD 会话,退出即丢;'
|
|
665
|
-
'
|
|
680
|
+
'已尝试落盘目录 <%s>,建议改用已有模板 .pscx 加载,'
|
|
681
|
+
'或确认该目录可写。' % folder)
|
|
666
682
|
return _ok(result)
|
|
667
683
|
except Exception as exc:
|
|
668
684
|
return _err(exc)
|
|
669
685
|
|
|
670
686
|
|
|
687
|
+
def _port_ready(port: int, timeout_s: float = 1.0) -> bool:
|
|
688
|
+
"""毫秒~秒级 TCP 端口探测:PSCAD 自动化端口是否已监听。
|
|
689
|
+
|
|
690
|
+
背景(P5 实测):mhi-pscad 2.9.7 的 connect(timeout=5) 在 PSCAD 未运行时会
|
|
691
|
+
内部重试阻塞 ~16s,不尊重超时参数;轮询循环若直接调 connect,单次迭代
|
|
692
|
+
≈18s,180s 名义上限实际只能尝试约 10 次。改用 socket 探测后单次迭代 ≈2s,
|
|
693
|
+
且 connect 只在端口就绪后才调用。
|
|
694
|
+
"""
|
|
695
|
+
try:
|
|
696
|
+
with socket.create_connection(('127.0.0.1', port), timeout=timeout_s):
|
|
697
|
+
return True
|
|
698
|
+
except Exception:
|
|
699
|
+
return False
|
|
700
|
+
|
|
701
|
+
|
|
671
702
|
def _ensure_connected() -> Tuple[bool, str]:
|
|
672
703
|
"""确保存在活的 mhi 连接(幂等;懒加载 mhi)。"""
|
|
673
704
|
global _pscad
|
|
@@ -680,6 +711,9 @@ def _ensure_connected() -> Tuple[bool, str]:
|
|
|
680
711
|
return True, ''
|
|
681
712
|
except Exception:
|
|
682
713
|
_pscad = None
|
|
714
|
+
# 端口未监听时直接快速失败(避免 mhi connect 阻塞 ~16s)
|
|
715
|
+
if not _port_ready(PSCAD_PORT, 0.5):
|
|
716
|
+
return False, 'PSCAD 自动化端口 %d 未就绪(PSCAD 未运行?)' % PSCAD_PORT
|
|
683
717
|
try:
|
|
684
718
|
_pscad = mhi.pscad.connect(port=PSCAD_PORT, timeout=CONNECT_TIMEOUT_S)
|
|
685
719
|
return True, ''
|
|
@@ -760,7 +794,13 @@ def _ensure_project() -> Optional[Dict[str, Any]]:
|
|
|
760
794
|
|
|
761
795
|
|
|
762
796
|
def _launch_pscad() -> Tuple[bool, str]:
|
|
763
|
-
"""拉起 PSCAD 进程并等待自动化端口就绪(崩溃恢复标准路径;懒加载 exe 路径)。
|
|
797
|
+
"""拉起 PSCAD 进程并等待自动化端口就绪(崩溃恢复标准路径;懒加载 exe 路径)。
|
|
798
|
+
|
|
799
|
+
轮询用 socket 端口探测(毫秒级)而非直接 mhi.pscad.connect:P5 实测
|
|
800
|
+
mhi 2.9.7 的 connect(timeout=5) 在 PSCAD 未起时阻塞 ~16s(不尊重超时),
|
|
801
|
+
直接调用会让 180s 名义上限实际只能尝试约 10 次;socket 探测使单次迭代
|
|
802
|
+
≈2s,端口就绪后才调用 connect 建立自动化连接。
|
|
803
|
+
"""
|
|
764
804
|
global _pscad
|
|
765
805
|
exe = _cfg_exe()
|
|
766
806
|
if not exe:
|
|
@@ -770,12 +810,14 @@ def _launch_pscad() -> Tuple[bool, str]:
|
|
|
770
810
|
'/port:%d' % PSCAD_PORT, '/splash:false'])
|
|
771
811
|
deadline = time.time() + LAUNCH_WAIT_S
|
|
772
812
|
while time.time() < deadline:
|
|
813
|
+
if _port_ready(PSCAD_PORT, 1.0):
|
|
814
|
+
try:
|
|
815
|
+
_pscad = mhi.pscad.connect(port=PSCAD_PORT,
|
|
816
|
+
timeout=CONNECT_TIMEOUT_S)
|
|
817
|
+
return True, ''
|
|
818
|
+
except Exception:
|
|
819
|
+
continue
|
|
773
820
|
time.sleep(2)
|
|
774
|
-
try:
|
|
775
|
-
_pscad = mhi.pscad.connect(port=PSCAD_PORT, timeout=5)
|
|
776
|
-
return True, ''
|
|
777
|
-
except Exception:
|
|
778
|
-
continue
|
|
779
821
|
return False, 'PSCAD 启动后 %ds 内端口未就绪' % LAUNCH_WAIT_S
|
|
780
822
|
except Exception as exc:
|
|
781
823
|
return False, str(exc)
|
|
@@ -1522,3 +1564,232 @@ def self_check() -> Dict[str, Any]:
|
|
|
1522
1564
|
})
|
|
1523
1565
|
except Exception as exc:
|
|
1524
1566
|
return _err(exc)
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
# ---------------------------------------------------------------------------
|
|
1570
|
+
# TMMB 热磁忆阻分支 / 通用 Norton 自定义元件(v6:CCBR/GEQ 零重构范式)
|
|
1571
|
+
# 实证依据见 knowledge/emtdc_custom_element_norton.md;四案例三路验证全通过。
|
|
1572
|
+
# ---------------------------------------------------------------------------
|
|
1573
|
+
_NORTON_DEF_NAME: str = 'TMMB'
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
def _norton_definition_xml(rmin: float, k: float, alpha: float,
|
|
1577
|
+
beta: float, l0: float,
|
|
1578
|
+
picard: int = 0) -> str:
|
|
1579
|
+
"""生成 v6 型 Norton 自定义元件定义 XML(TMMB 方程参数化)。
|
|
1580
|
+
|
|
1581
|
+
实现要点(全部实证):
|
|
1582
|
+
- Branch 段 ``BRR = $NA $NB BREAKER 1.0E6``(可切换分支,seriesrl2 范式)。
|
|
1583
|
+
- TIMEZERO(#BEGIN):``GEQ($BRR,$SS)=G0`` 固定 + ``DEFRDBR=.TRUE.``
|
|
1584
|
+
→ 导纳矩阵逐拍恒不变(零重构);G0=1/(2·RMIN+2·L0/Δt)。
|
|
1585
|
+
- 每拍仅更新右端项 ``CCBR = I_hist + (G-G0)*V``(RHS 永不触发重构)。
|
|
1586
|
+
- 历史电流用 seriesrl2 官方递推(不读 CBR——DEFRDBR 分支的 CBR 读回
|
|
1587
|
+
符号不可靠,实测陷阱);状态功率用 Norton 自洽电流 I=G*V+I_hist。
|
|
1588
|
+
- 状态存储 STORF(NSTORF+1..8) + NSTORF+=8(误写 STORI 会覆盖相邻组件);
|
|
1589
|
+
#LOCAL 每行一条(合并行被生成器丢弃致隐式类型陷阱);
|
|
1590
|
+
#BEGIN 无 emtstor.h 不能访问 STORF,状态初始化放主段 IF(TIMEZERO)。
|
|
1591
|
+
Args:
|
|
1592
|
+
rmin/k/alpha/beta: TMMB 方程参数(R(w)=RMIN+K·w²,dw/dt=α·v·i−β·w)。
|
|
1593
|
+
l0: 串联电感 [H](≥0;完整伴生 G=1/(R+2L/Δt))。
|
|
1594
|
+
picard: DSDYN 内 Picard 迭代次数(0/2/3;闭合 W↔R 环,默认 0)。
|
|
1595
|
+
Returns:
|
|
1596
|
+
定义 XML 字符串。
|
|
1597
|
+
"""
|
|
1598
|
+
pic = ''
|
|
1599
|
+
if picard >= 2:
|
|
1600
|
+
pic = (
|
|
1601
|
+
' DO IVD1_1 = 1, %d\n'
|
|
1602
|
+
' R = $RMIN + $K * W * W\n'
|
|
1603
|
+
' G = 1.0/(R + 2.0*$L0/DELT)\n'
|
|
1604
|
+
' I = G*V + IH\n'
|
|
1605
|
+
' W = (W*(1.0 - DTB) + $ALPHA*DELT*(V*I)) / (1.0 + DTB)\n'
|
|
1606
|
+
' END DO\n' % int(picard))
|
|
1607
|
+
return '''<Definition classid="UserCmpDefn" name="TMMB" url="" view="false" instances="0" date="0" crc="0" id="%d" group="R4">
|
|
1608
|
+
<paramlist>
|
|
1609
|
+
<param name="Description" value="Norton Element (CCBR/GEQ, zero-refactor)" />
|
|
1610
|
+
</paramlist>
|
|
1611
|
+
<form name="TMMB" w="320" h="460" splitter="70" commentlines="4">
|
|
1612
|
+
<category name="Configuration" visible="true">
|
|
1613
|
+
<parameter name="Name" desc="Name for Identification" type="Text" group="" helpmode="Overwrite" allowemptystr="true">
|
|
1614
|
+
<value><![CDATA[]]></value>
|
|
1615
|
+
<cond type="Enable"><![CDATA[true]]></cond>
|
|
1616
|
+
</parameter>
|
|
1617
|
+
<parameter type="Text" name="COM" desc="Fortran Comment" group="" helpmode="Overwrite" allowemptystr="false">
|
|
1618
|
+
<value><![CDATA[NORTON]]></value>
|
|
1619
|
+
<cond type="Enable" />
|
|
1620
|
+
</parameter>
|
|
1621
|
+
<cond><![CDATA[true]]></cond>
|
|
1622
|
+
</category>
|
|
1623
|
+
<category name="Norton Parameters" visible="true">
|
|
1624
|
+
<parameter type="Real" name="RMIN" desc="Minimum resistance [ohm]" content_type="Variable" min="1E-9" max="1E+308" unit="ohm" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
1625
|
+
<value><![CDATA[1.0]]></value>
|
|
1626
|
+
<cond type="Enable" />
|
|
1627
|
+
</parameter>
|
|
1628
|
+
<parameter type="Real" name="K" desc="Memristance coefficient [ohm]" content_type="Variable" min="0" max="1E+308" unit="ohm" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
1629
|
+
<value><![CDATA[1.0]]></value>
|
|
1630
|
+
<cond type="Enable" />
|
|
1631
|
+
</parameter>
|
|
1632
|
+
<parameter type="Real" name="ALPHA" desc="Heating coupling [1/MW/s]" content_type="Variable" min="0" max="1E+308" unit="" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
1633
|
+
<value><![CDATA[1.0]]></value>
|
|
1634
|
+
<cond type="Enable" />
|
|
1635
|
+
</parameter>
|
|
1636
|
+
<parameter type="Real" name="BETA" desc="Cooling rate [1/s]" content_type="Variable" min="0" max="1E+308" unit="" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
1637
|
+
<value><![CDATA[1.0]]></value>
|
|
1638
|
+
<cond type="Enable" />
|
|
1639
|
+
</parameter>
|
|
1640
|
+
<parameter type="Real" name="L0" desc="Inductance [H]" content_type="Variable" min="0" max="1E+308" unit="H" group="" helpmode="Append" intent="Input" dim="1" animate="false">
|
|
1641
|
+
<value><![CDATA[0.0]]></value>
|
|
1642
|
+
<cond type="Enable" />
|
|
1643
|
+
</parameter>
|
|
1644
|
+
<cond><![CDATA[true]]></cond>
|
|
1645
|
+
</category>
|
|
1646
|
+
</form>
|
|
1647
|
+
<svg viewBox="-200 -200 200 200">
|
|
1648
|
+
<port model="Natural" name="NA" x="-72" y="0" dim="1" mode="Electrical" type="NonRemovable"><![CDATA[true]]></port>
|
|
1649
|
+
<port model="Natural" name="NB" x="72" y="0" dim="1" mode="Electrical" type="NonRemovable"><![CDATA[true]]></port>
|
|
1650
|
+
<port model="Transfer" name="OUT" x="0" y="-36" dim="1" mode="Output" type="Real"><![CDATA[true]]></port>
|
|
1651
|
+
<rect x="-27" y="-15" width="54" height="30" stroke="Black" stroke-dasharray="none" stroke-width="0.2" fill-style="Hollow" fill-fg="Black" fill-bg="" />
|
|
1652
|
+
<line x1="-72" y1="0" x2="-27" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1653
|
+
<line x1="27" y1="0" x2="72" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1654
|
+
<line x1="-12" y1="0" x2="-4" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1655
|
+
<line x1="-8" y1="-4" x2="-8" y2="4" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1656
|
+
<line x1="0" y1="0" x2="8" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1657
|
+
<line x1="4" y1="-4" x2="4" y2="4" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1658
|
+
<line x1="12" y1="0" x2="20" y2="0" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1659
|
+
<line x1="16" y1="-4" x2="16" y2="4" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1660
|
+
<line x1="0" y1="15" x2="0" y2="36" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1661
|
+
<line x1="-5" y1="20" x2="0" y2="15" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1662
|
+
<line x1="5" y1="20" x2="0" y2="15" stroke="Black" stroke-dasharray="none" stroke-width="0.2" />
|
|
1663
|
+
<text x="0" y="-1" stroke="Black" fill="Black" font-size="Small" text-anchor="Middle"><![CDATA[R(w)]]></text>
|
|
1664
|
+
<text x="0" y="13" stroke="Black" fill="Black" font-size="Small" text-anchor="Middle"><![CDATA[NRT]]></text>
|
|
1665
|
+
</svg>
|
|
1666
|
+
<script>
|
|
1667
|
+
<segment name="Dsdyn" classid="CoreSegment"><![CDATA[#STORAGE REAL:8
|
|
1668
|
+
! v = R(w)*i + L0*di/dt ; R(w)=RMIN+K*w^2 ; dw/dt=ALPHA*v*i-BETA*w
|
|
1669
|
+
! CCBR/GEQ branch interface (seriesrl2 official pattern):
|
|
1670
|
+
! GEQ fixed G0 at TIMEZERO (matrix static -> zero refactorization);
|
|
1671
|
+
! per-step CCBR = I_hist + (G-G0)*V (RHS only).
|
|
1672
|
+
! G=1/(R+2L0/DELT); Z1=R-2L0/DELT; I_hist seriesrl2 recurrence.
|
|
1673
|
+
! Storage: (1)w (2)v_prev (3)i_prev (4)i_hist (5)g (6)r (7)ccbr (8)spare
|
|
1674
|
+
#LOCAL REAL W
|
|
1675
|
+
#LOCAL REAL V
|
|
1676
|
+
#LOCAL REAL I
|
|
1677
|
+
#LOCAL REAL R
|
|
1678
|
+
#LOCAL REAL G
|
|
1679
|
+
#LOCAL REAL G0
|
|
1680
|
+
#LOCAL REAL DTB
|
|
1681
|
+
#LOCAL REAL Z1
|
|
1682
|
+
#LOCAL REAL IH
|
|
1683
|
+
#LOCAL INTEGER IVD1_1
|
|
1684
|
+
#BEGIN
|
|
1685
|
+
GEQ($BRR, $SS) = 1.0/(2.0*$RMIN + 2.0*$L0/DELT)
|
|
1686
|
+
DEFRDBR($BRR, $SS) = .TRUE.
|
|
1687
|
+
#ENDBEGIN
|
|
1688
|
+
IF (TIMEZERO) THEN
|
|
1689
|
+
STORF(NSTORF+1) = 0.0
|
|
1690
|
+
STORF(NSTORF+2) = 0.0
|
|
1691
|
+
STORF(NSTORF+3) = 0.0
|
|
1692
|
+
STORF(NSTORF+4) = 0.0
|
|
1693
|
+
STORF(NSTORF+5) = 1.0/$RMIN
|
|
1694
|
+
STORF(NSTORF+6) = $RMIN
|
|
1695
|
+
STORF(NSTORF+7) = 0.0
|
|
1696
|
+
STORF(NSTORF+8) = 0.0
|
|
1697
|
+
CCBR($BRR, $SS) = 0.0
|
|
1698
|
+
$OUT = 0.0
|
|
1699
|
+
ENDIF
|
|
1700
|
+
W = STORF(NSTORF+1)
|
|
1701
|
+
IH = STORF(NSTORF+4)
|
|
1702
|
+
G = STORF(NSTORF+5)
|
|
1703
|
+
V = VBRANCH($SS, $BRR)
|
|
1704
|
+
I = G*V + IH
|
|
1705
|
+
DTB = 0.5 * $BETA * DELT
|
|
1706
|
+
W = (W*(1.0 - DTB) + $ALPHA*DELT*(V*I)) / (1.0 + DTB)
|
|
1707
|
+
%s R = $RMIN + $K * W * W
|
|
1708
|
+
G = 1.0/(R + 2.0*$L0/DELT)
|
|
1709
|
+
Z1 = R - 2.0*$L0/DELT
|
|
1710
|
+
IH = (1.0 - Z1*G)*G*V - Z1*G*IH
|
|
1711
|
+
G0 = 1.0/(2.0*$RMIN + 2.0*$L0/DELT)
|
|
1712
|
+
CCBR($BRR, $SS) = IH + (G - G0)*V
|
|
1713
|
+
STORF(NSTORF+1) = W
|
|
1714
|
+
STORF(NSTORF+2) = V
|
|
1715
|
+
STORF(NSTORF+3) = I
|
|
1716
|
+
STORF(NSTORF+4) = IH
|
|
1717
|
+
STORF(NSTORF+5) = G
|
|
1718
|
+
STORF(NSTORF+6) = R
|
|
1719
|
+
STORF(NSTORF+7) = CCBR($BRR, $SS)
|
|
1720
|
+
STORF(NSTORF+8) = 0.0
|
|
1721
|
+
NSTORF = NSTORF + 8
|
|
1722
|
+
$OUT = W]]></segment>
|
|
1723
|
+
<segment name="Branch" classid="CoreSegment"><![CDATA[BRR = $NA $NB BREAKER 1.0E6]]></segment>
|
|
1724
|
+
<segment name="FlyBy" classid="CoreSegment"><![CDATA[Norton element (TMMB)
|
|
1725
|
+
:NA
|
|
1726
|
+
Positive terminal
|
|
1727
|
+
:NB
|
|
1728
|
+
Negative terminal
|
|
1729
|
+
:OUT
|
|
1730
|
+
State variable w]]></segment>
|
|
1731
|
+
</script>
|
|
1732
|
+
</Definition>''' % (int(time.time() * 1000) % 10 ** 9, pic)
|
|
1733
|
+
|
|
1734
|
+
|
|
1735
|
+
def create_norton_element(x: int, y: int,
|
|
1736
|
+
rmin: float = 1.0, k: float = 1.0,
|
|
1737
|
+
alpha: float = 1.0, beta: float = 1.0,
|
|
1738
|
+
l0: float = 0.0,
|
|
1739
|
+
picard: int = 0,
|
|
1740
|
+
name: Optional[str] = None) -> Dict[str, Any]:
|
|
1741
|
+
"""在当前画布创建"纯 Fortran Norton 自定义元件"(CCBR/GEQ 零重构范式)。
|
|
1742
|
+
|
|
1743
|
+
适用于任意"非线性电阻/阻抗支路"建模需求(TMMB 热磁忆阻分支参数化:
|
|
1744
|
+
v=R(w)·i+L0·di/dt,R(w)=RMIN+K·w²,dw/dt=α·v·i−β·w)。元件无矩阵分支
|
|
1745
|
+
(BREAKER 分支 + GEQ 固定 G0 + 每拍 CCBR 右端项注入)——导纳矩阵逐拍
|
|
1746
|
+
恒不变,零重构;支持 L0≥0 完整伴生模型(历史电流 I_hist 经 seriesrl2
|
|
1747
|
+
官方递推注入)。生成代码经验证:接地/悬浮、L0=0/0.1 四案例三路对照
|
|
1748
|
+
全部吻合(见 knowledge/emtdc_custom_element_norton.md)。
|
|
1749
|
+
|
|
1750
|
+
Args:
|
|
1751
|
+
x, y: 放置锚点坐标(网格坐标,mhi 画布)。
|
|
1752
|
+
rmin: 最小电阻 [ohm](R(w) 下限,默认 1.0)。
|
|
1753
|
+
k: 忆阻系数 [ohm](默认 1.0)。
|
|
1754
|
+
alpha: 热耦合系数 [1/MW/s](PSCAD 内部 kV·kA=MW 语义,默认 1.0)。
|
|
1755
|
+
beta: 冷却速率 [1/s](默认 1.0)。
|
|
1756
|
+
l0: 串联电感 [H](≥0;完整 Norton 伴生,默认 0)。
|
|
1757
|
+
picard: DSDYN 内 Picard 迭代次数(0/2/3,闭合 W↔R 代数环;默认 0)。
|
|
1758
|
+
name: 显式 Name 标签;None 时自动生成唯一名(后续寻址主键)。
|
|
1759
|
+
|
|
1760
|
+
Returns:
|
|
1761
|
+
success: data 含 ``name``(唯一 Name 标签)、``component``、
|
|
1762
|
+
``defn``('<工程名>:TMMB')、``ports``({端口名: (x,y)})、
|
|
1763
|
+
``position``、``orient``、``params``(实际写入参数)。
|
|
1764
|
+
error: 创建/注入定义失败(含 traceback 摘要)。
|
|
1765
|
+
"""
|
|
1766
|
+
try:
|
|
1767
|
+
bad = _require_canvas()
|
|
1768
|
+
if bad:
|
|
1769
|
+
return bad
|
|
1770
|
+
if _prj is None:
|
|
1771
|
+
return _err('工程对象不可用,请先调用 connect_and_load_project()')
|
|
1772
|
+
xml = _norton_definition_xml(rmin, k, alpha, beta, l0, picard)
|
|
1773
|
+
try:
|
|
1774
|
+
_prj.create_definition(xml)
|
|
1775
|
+
except Exception as exc:
|
|
1776
|
+
return _err('create_definition 失败(Norton 元件定义注入):%s'
|
|
1777
|
+
% exc)
|
|
1778
|
+
final_name = name if name else _gen_name(_NORTON_DEF_NAME)
|
|
1779
|
+
comp = _main.create_component('%s:%s' % (_prj_name, _NORTON_DEF_NAME),
|
|
1780
|
+
int(round(x)), int(round(y)), orient=0,
|
|
1781
|
+
Name=final_name, RMIN=rmin, K=k,
|
|
1782
|
+
ALPHA=alpha, BETA=beta, L0=l0)
|
|
1783
|
+
ports: Dict[str, Tuple[int, int]] = {}
|
|
1784
|
+
try:
|
|
1785
|
+
ports = {kk: tuple(vv[:2]) for kk, vv in comp.ports().items()}
|
|
1786
|
+
except Exception:
|
|
1787
|
+
pass
|
|
1788
|
+
params = {'RMIN': rmin, 'K': k, 'ALPHA': alpha, 'BETA': beta,
|
|
1789
|
+
'L0': l0, 'picard': picard}
|
|
1790
|
+
return _ok({'name': final_name, 'component': comp,
|
|
1791
|
+
'defn': '%s:%s' % (_prj_name, _NORTON_DEF_NAME),
|
|
1792
|
+
'ports': ports, 'position': (int(round(x)), int(round(y))),
|
|
1793
|
+
'orient': 0, 'params': params})
|
|
1794
|
+
except Exception as exc:
|
|
1795
|
+
return _err(exc)
|