OpenModelica自定义布尔振荡器仿真错误求助
可变频率布尔振荡器仿真错误排查与解决
问题场景
实现一个带可变周期输入u的布尔振荡器模型,模型语法检查通过,但仿真时触发大量内部翻译错误。
原模型代码
class VarBoolPulse extends Modelica.Blocks.Interfaces.partialBooleanSource; Modelica.Blocks.Interfaces.BooleanOutput y; Modelica.Blocks.Interfaces.RealInput u; protected Modelica.SIunits.Time start "Start time of current period"; initial algorithm start := time; equation when sample(start, u) then start = time; end when; y = not(time >= start and time < start + u * 0.5); end VarBoolPulse;
仿真错误信息
Translation Error [/var/lib/jenkins3/ws/LINUX_BUILDS/tmp.build/openmodelica-1.21.0~2-g0bc3d29/OMCompiler/Compiler/BackEnd/BackendDAETransform.mo: 332:7-332:48]: Internal error BackendDAETransform.analyseStrongComponentBlock failed (Purely discrete algebraic loops cannot be solved by iterative processes. Try to break them open using the delay() operator.) $whenCondition1 start when $whenCondition1 then start := time; end when; $whenCondition1 = sample(1, start, u) [9] 15:56:07 Translation Error [/var/lib/jenkins3/ws/LINUX_BUILDS/tmp.build/openmodelica-1.21.0~2-g0bc3d29/OMCompiler/Compiler/BackEnd/BackendDAETransform.mo: 342:7-342:48]: Internal error BackendDAETransform.analyseStrongComponentBlock failed variables: $whenCondition1 start equations: when $whenCondition1 then start := time; end when; $whenCondition1 = sample(1, start, u) [10] 15:56:07 Translation Error [/var/lib/jenkins3/ws/LINUX_BUILDS/tmp.build/openmodelica-1.21.0~2-g0bc3d29/OMCompiler/Compiler/BackEnd/BackendDAETransform.mo: 346:7-346:90]: Internal error function analyseStrongComponentBlock failed [11] 15:56:07 Translation Error [/var/lib/jenkins3/ws/LINUX_BUILDS/tmp.build/openmodelica-1.21.0~2-g0bc3d29/OMCompiler/Compiler/BackEnd/BackendDAETransform.mo: 196:5-196:89]: Internal error function analyseStrongComponentScalar failed [12] 15:56:07 Translation Error [/var/lib/jenkins3/ws/LINUX_BUILDS/tmp.build/openmodelica-1.21.0~2-g0bc3d29/OMCompiler/Compiler/BackEnd/BackendDAETransform.mo: 107:7-107:113]: Internal error function strongComponentsScalar failed (sorting strong components) [13] 15:56:07 Translation Error [/var/lib/jenkins3/ws/LINUX_BUILDS/tmp.build/openmodelica-1.21.0~2-g0bc3d29/OMCompiler/Compiler/BackEnd/BackendDAEUtil.mo: 7953:5-7953:89]: Internal error Transformation module sort components failed
问题原因
核心问题是纯离散代数环:sample(start, u)的触发时刻依赖start变量,而start又在when sample(...)的事件中被重新赋值,形成循环依赖。OpenModelica的翻译器无法处理这种无延迟的离散环,导致编译阶段失败。
修正方案
使用pre()运算符打破循环依赖,pre(start)会取start变量的前一个时间步值,避免当前时刻的循环引用。以下提供两种可行的修正版本:
版本1:严格对齐初始时刻
class VarBoolPulse extends Modelica.Blocks.Interfaces.partialBooleanSource; Modelica.Blocks.Interfaces.BooleanOutput y; Modelica.Blocks.Interfaces.RealInput u; protected Modelica.SIunits.Time start "Start time of current period"; Boolean firstTrigger = true; // 标记首次触发 initial algorithm start := time; equation // 首次触发用初始start值,后续用前一时刻的start值 when sample(if firstTrigger then start else pre(start), u) then start := time; firstTrigger := false; end when; y = not(time >= start and time < start + u * 0.5); end VarBoolPulse;
版本2:简洁通用写法
如果不需要严格对齐初始时刻,可直接使用pre(start),初始时刻pre(start)会自动取初始赋值的start值:
class VarBoolPulse extends Modelica.Blocks.Interfaces.partialBooleanSource; Modelica.Blocks.Interfaces.BooleanOutput y; Modelica.Blocks.Interfaces.RealInput u; protected Modelica.SIunits.Time start "Start time of current period"; initial algorithm start := time; equation when sample(pre(start), u) then start := time; end when; y = not(time >= start and time < start + u * 0.5); end VarBoolPulse;
关键修改说明
pre()运算符的作用:获取变量的历史值,切断当前时刻start与触发条件的循环依赖,让求解器能按时间步迭代计算。- 两种版本均能有效打破离散代数环,解决仿真翻译错误。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

