Dymola/ModelModel如何仅计算信号稳态段平均值及相关问题求解
自定义块报错原因
- 核心问题1:初始值不匹配。你当前的自定义块初始方程设置
mu = u,也就是仿真启动时刻(time=0)mu等于信号初始值,在t0=40s之前mu的导数始终为0,mu会一直保持u(0)的数值。到40s刚开启计算时,mu与当前u(40)的差值通常很大,除以极小的分母t_eps=1e-7会产生超大的导数,直接导致数值求解器发散报错。 - 核心问题2:触发逻辑缺少状态重置。你没有在均值计算启动时刻(t=t0)重置mu的数值,导致初始偏差一直存在,均值计算的初始值完全错误。
自定义块修复方案
修改ContinuosMeanStartTime块的方程部分,添加t0时刻的状态重置逻辑即可:
block ContinuosMeanStartTime "Similar block as Continuos Mean in MSL but with unprotected Start time (t_0)" extends Modelica.Blocks.Icons.Block; parameter Modelica.SIunits.Time t_eps(min=0.0) = 1e-7 "Mean value calculation starts at startTime + t_eps"; parameter Modelica.SIunits.Time t_0(min=0.0) = 0 "Start time"; Modelica.Blocks.Interfaces.RealInput u "Noisy input signal"; Modelica.Blocks.Interfaces.RealOutput y "Expectation (mean) value of the input signal"; protected Real mu "Internal integrator variable"; Boolean startCalc = time >= t_0 + t_eps; initial equation mu = u; equation // 增加t0时刻的重置逻辑 when time >= t_0 then mu = u; end when; der(mu) = noEvent(if startCalc then (u - mu)/(time - t_0) else 0); y = noEvent(if startCalc then mu else u); end ContinuosMeanStartTime;
修复后启动计算时mu会被重置为当前u的数值,不会出现导数爆炸的问题,求解可以正常进行。
无需自定义块的替代实现方案
Modelica语言规范明确规定受保护(protected)的类成员不允许外部访问修改,因此没有办法直接修改MSL中ContinuousMean的受保护参数t_0,你可以通过MSL现有模块组合实现相同功能,不需要自行开发自定义块:
- 使用时间判断逻辑生成t>=40s的使能信号
- 搭配带重置功能的
Modelica.Blocks.Continuous.LimIntegrator,在t=40s时触发重置,仅在使能阶段对输入信号积分 - 积分结果除以
max(time - 40, 1e-7)即可得到40s之后的连续均值,逻辑和ContinuousMean完全一致。
固定区间均值(40s到60s)的更简单实现
如果你只需要计算固定区间[40s,60s]的最终均值,不需要过程值,可以直接在仿真结束后通过结果后处理提取区间数据计算;也可以在模型中添加如下方程直接输出最终均值:
Real intervalMean; Real integral_u(start=0); equation der(integral_u) = noEvent(if time >=40 and time <=60 then signal else 0); intervalMean = noEvent(if time > 60 then integral_u / 20 else 0);
内容的提问来源于stack exchange,提问作者EngineerInProgress
相关产品推荐
相关产品推荐

