ngspice timestep too small 报错:理想电压源并联导致奇异矩阵与工作点无解
更新时间:2026-11-11。长尾排查篇,属于 EDA 报错排查系列,汇总入口见 开源 EDA 报错排查导航。ngspice 跑一个只有几行网表的
.op直流工作点分析,却抛出Error: Transient op failed, timestep too small,退出码 1。网表里根本没有.tran,瞬态步长从何谈起?本文用一个双理想电压源并联的最小电路,把报错演进、求解器降级路径和两种修法全部跑透。
首屏答案:bad.cir 把 V1 1 0 DC 1 与 V2 1 0 DC 2 两个零内阻理想电压源直接并联在节点 1 上,1V 与 2V 同时强制同一节点电位,改进节点法列出的电路方程奇异、工作点没有唯一解。ngspice 依次尝试 dynamic gmin stepping、true gmin stepping、source stepping 三级延拓全部失败后,内部复用名为 "Transient op" 的兜底算法,最终留下 timestep too small 文案。修法有两条:删掉冲突电压源只留一个,或在回路中串入有限电阻 Rs 1 2 100,两种修法复跑均以退出码 0 收口。
这张流程卡对应本文的叙事顺序:先看清报错卡在哪一级求解,再理解为什么 .op 分析会冒出 Transient 文案,最后用两种修法的复跑输出收口。看到 timestep too small 就去翻瞬态步长参数,是这类问题最常见的误诊方向。
本文要回答的问题
- 两个理想电压源并联的最小网表,ngspice-47 的完整报错原文是什么,退出码是多少?
- 网表只写了
.op,为什么错误信息里出现Transient op与timestep too small? singular matrix与 gmin stepping、source stepping 三级延拓各自意味着什么?- 删掉一个电压源与串入有限电阻两种修法,分别怎样改变电路方程,复跑输出如何确认闭环?
一、完整报错原文
出问题的 bad.cir 只有五个有效行,两个理想电压源共用节点 1,分析请求只有一条 .op:
Two ideal voltage sources in parallel: singular matrix, timestep too small
V1 1 0 DC 1
V2 1 0 DC 2
R1 1 0 1k
.op
.end执行 ngspice -b bad.cir,求解器从奇异矩阵警告一路降级到兜底失败。下面是日志原样摘录,未作任何润色:
$ ngspice -b bad.cir
Warning: singular matrix: check node v1#branch
Note: Starting dynamic gmin stepping
Warning: singular matrix: check node v1#branch
Warning: singular matrix: check node v1#branch
Warning: Dynamic gmin stepping failed
Note: Starting true gmin stepping
Warning: True gmin stepping failed
Note: Starting source stepping
Warning: source stepping failed
Note: Transient op started
Error: Transient op failed, timestep too small
Error: The operating point could not be simulated successfully.
Any of the following steps may fail.!
doAnalyses: OP: Timestep too small; cause unrecorded.
run simulation(s) aborted
Circuit: two ideal voltage sources in parallel: singular matrix, timestep too small
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
Using SPARSE 1.3 as Direct Linear Solver
DC solution failed -读这段输出抓住三条线。第一,最先出现的是 Warning: singular matrix: check node v1#branch,点名问题出在 V1 的支路电流变量上,这是矩阵层面的直接症状;第二,ngspice 没有立刻放弃,而是按固定顺序启动三级延拓,每一级都以同一条 singular matrix 警告告终;第三,收尾的 doAnalyses: OP: Timestep too small 明确标着 OP,说明失败的分析类型自始至终是直流工作点,Transient op 只是内部兜底路径的名字。进程最终以退出码 1 结束,不产生任何工作点结果。
二、工具与版本
本次实验在 macOS 本机以 ngspice 批处理模式完成,版本与日志头部完全一致:
- ngspice-47,KLU 稀疏矩阵求解器,可执行文件位于
/usr/local/bin/ngspice - 批处理入口
ngspice -b <netlist>,不进入交互界面 - 运行日期 2026-11-11,默认温度 TEMP/TNOM 均为 27 摄氏度
版本要先固定,是因为降级路径的文案与启用顺序随 ngspice 版本演进过。本文的警告措辞、三级 stepping 的名称与退出码只对 ngspice-47 这个构建负责;换到其他大版本时,应保留当次完整输出再对照,不能凭本文文案反推。
三、根本原因:零内阻电源环让电路矩阵奇异
3.1 两个理想电压源在强制同一点取两个电位
SPICE 用改进节点法(MNA)把电路列成稀疏矩阵方程,每个理想电压源会引入一个支路电流未知量,并强行约束其正负端的电位差。理想电压源内阻为零,V1 1 0 DC 1 等价于方程 v(1) = 1,V2 1 0 DC 2 等价于 v(1) = 2,两条硬约束同时落在节点 1 上,互相矛盾且没有任何电阻缓冲。矩阵因此出现无法消去的奇异结构,线性求解器第一步就报 singular matrix。MNA 如何拼装节点方程、电压源为何要扩维引入支路变量,SPICE 仿真器数值内核 有完整推导。
下图画出求解器的降级链条,红色是根因与报错节点,蓝色是 ngspice 的求解动作:
图中蓝色三级延拓的原理,是给求解过程人为铺设一条「从易解点爬到目标点」的路径:gmin stepping 先在节点到地之间并一个大电导把矩阵变成良态,再逐步撤掉;source stepping 让电源从零缓升到额定值。它们能救的是初值不好、牛顿迭代落不进收敛域的电路,救不了方程本身矛盾的电路——本电路在每一级延拓的每一步都保持奇异,所以三级全败。延拓法的适用边界在 SPICE 仿真器数值内核 的收敛助手一节有系统讲解。
3.2 一个必须澄清的文案误导:.op 为什么报 Transient
三级延拓全部失败后,ngspice 启动最后一道内部兜底:把直流工作点问题改写成一个从零时刻缓慢爬坡的伪瞬态过程,指望时间离散化带来的数值项把矩阵正则化。这段代码路径在 ngspice 内部就叫 "Transient op",于是日志留下 Transient op started 与 timestep too small 字样。
这是本篇最容易把人带偏的地方。用户网表里没有任何 .tran 语句,失败分析类型在收尾行写得很清楚——doAnalyses: OP。对一个本质奇异的矩阵,伪瞬态爬坡同样迈不出任何有效步长,步长被反复折半到下限后即以 timestep too small 中止。所以看到这条报错,先查电路拓扑里的零电阻电源环、悬空节点和矛盾约束,而不是先去调 .tran 的步长参数;后者在纯 .op 网表里根本不存在。
四、排查清单:先查拓扑矛盾,再看求解助手
排查按四步走,顺序不要反:
- 数同一节点上的理想电压源:任何两个零内阻电压源直接并联,且额定电压不同,矩阵必奇异;电压相同虽不矛盾,也会留下冗余约束,应避免。
- 找零电阻回路:理想电压源与理想电感构成的纯电压源环、电流源与电容串联的割集,是同一类拓扑病,症状同样是 singular matrix。
- 读警告点名的支路变量:
check node v1#branch直接指向肇事电源的支路电流,顺着#branch名字回网表定位元件,比逐行猜快得多。 - 最后才动求解助手与容差:确认拓扑无矛盾后,再考虑
gmin、nodeset、itl1等旋钮;对奇异矩阵放宽容差只会让报错变形,不会让无解变成有解。
下图对比修复前后的回路结构,左红右绿:
左图里两个电源都直连节点 1,没有任何元件吸收电位差;右图插入 Rs 后,1V 的电位差落到电阻上变成确定的 10mA 回路电流,矛盾约束转化为 KCL 可解的正常方程,工作点恢复唯一解。
五、修复代码与复跑确认
5.1 修法 A:删掉冲突电压源
如果电路本意只需要一个 1V 激励,直接移除 V2,节点 1 的电位约束只剩一条,矩阵立刻良态:
Fixed: single voltage source, unique solution
V1 1 0 DC 1
R1 1 0 1k
.op
.end5.2 修法 B:串入有限电阻保留两个电源
若两个电源都是电路意图的一部分,就在它们之间串入电阻,给回路有限阻抗:
Fixed: a series resistor gives the two-source loop a unique solution
V1 1 0 DC 1
V2 2 0 DC 2
Rs 1 2 100
R1 1 0 1k
.op
.print op v(1)
.end一次 bash run.sh 顺序跑出坏网表失败与两种修法通过三段记录。失败段的终端实录如下:
两种修法的复跑实录如下,注意两段的退出码都是 0:
修法 B 的 .op 默认输出表给出两支路电流:v1#branch = 9.000000e-03(9mA)、v2#branch = -1.00000e-02(-10mA)。物理上完全对得上:Rs 上压降 1V,回路电流 10mA 由 V2 供出(故 V2 支路为负),其中 1mA 经 R1 入地,余下 9mA 灌入 V1 支路被其吸收。
这里还有一个 ngspice 语法上的真机坑:.print op 不接受支路电流向量,写成 .print op i(V1) 会收到 can't parse 'v1#branch' 一类警告。支路电流只能直接读 .op 默认输出表里的 vx#branch 列,.print op 只负责打印节点电压,所以修法 B 里写的是 .print op v(1)。
实验环境
- 机器/系统:macOS 本机,ngspice 批处理模式(
ngspice -b) - 工具版本:ngspice-47(KLU),可执行文件
/usr/local/bin/ngspice - 日期:2026-11-11
- 完整命令:在实验目录执行
bash run.sh;脚本依次运行ngspice -b bad.cir(坏网表,退出码 1)、ngspice -b fixed_remove.cir(删源修法,退出码 0)、ngspice -b fixed_resistor.cir(串电阻修法,退出码 0),并打印每步退出码。
代码获取
完整网表与复现脚本位于公开仓:https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/ts-ngspice-convergence-timestep-fail,含 bad.cir、fixed_remove.cir、fixed_resistor.cir 与 run.sh。本地安装 ngspice 后,在该目录执行以下命令即可原样复现三段运行:
bash run.sh这一篇在知识体系里的位置
本篇属于 开源 EDA 报错排查导航 的开源仿真器分支,回答「.op 分析为什么报 timestep、奇异矩阵怎样从拓扑上修」。矩阵装配、牛顿迭代与 gmin/source stepping 延拓法的原理见 SPICE 仿真器:在数值上解一张非线性动态电路,其中的不收敛系统排查顺序与本文的四步清单互为表里:那篇讲求解器视角的通用方法论,本篇讲一个拓扑硬矛盾的完整实例。
总结
ngspice timestep too small 在这篇最小复现里与瞬态步长毫无关系:两个零内阻理想电压源 V1 1 0 DC 1 与 V2 1 0 DC 2 直接并联,对同一节点给出 v(1)=1 与 v(1)=2 的矛盾硬约束,改进节点法矩阵奇异,dynamic gmin、true gmin、source stepping 三级延拓全部失败,ngspice 内部名为 "Transient op" 的伪瞬态兜底迈不出有效步长,留下 timestep too small 与 DC solution failed 并以退出码 1 中止。修复要么删掉冲突电源只留一条电位约束,要么串入 Rs 1 2 100 让电位差落到电阻上变成 10mA 的确定回路电流;两种修法复跑均退出码 0,支路电流读数与手工 KCL 完全吻合。