带换热器的控温泵Modelica模型求解失败求助
控温泵Modelica模型报错排查与修复
核心问题
Dymola报错说“需要输入变量inletTemperature的导数”,根源是:
你手动实现PID的微分项时,用了x_diff = der(controllerU),而controllerU是基于inletTemperature计算的温差误差,所以求解器会要求inletTemperature的导数。但inletTemperature是外部输入变量,求解器拿不到它的导数信息,直接导致DAE系统解不出来。
修复步骤
1. 删掉输入变量的内部初始化
输入变量不能在模型内部的initial equation里赋值,把这行删了:
inletTemperature = 20.0;
要给初始值的话,去外部连接的输入源里设置,或者如果这个温度是模型内部控制的,就把它改成内部变量/参数。
2. 换PID的实现方式
手动求导碰输入变量肯定出问题,两种解决办法:
办法A:用Modelica标准库的PID块(推荐)
直接用Modelica.Blocks.Continuous.PID,它会自动处理微分的数值稳定性,不用操心输入导数的问题:
// 替换你原来手动写的PID变量和方程,加个PID块 Modelica.Blocks.Continuous.PID pid( k=K_p, Ti=T_i, Td=T_d, uMax=x_max, uMin=x_min, resetIntegrator=true) annotation(Placement(origin={-30,0})); equation // 计算温差误差 currentTempSpread = outletTemperatureHeatExchanger.T - inletTemperature; pid.u = desiredTempSpread - currentTempSpread; // 把误差传给PID controlSignal = pid.y; // 拿PID的输出当控制信号 // 把原来手动写的controllerU、x、x_diff相关的方程全删掉
办法B:手动改微分项(不推荐)
非要自己写的话,就只对模型可控的出口温度求导,忽略输入温度的变化(只适合输入温度变化极慢的场景):
// 替换x_diff的方程 x_diff = der(outletTemperatureHeatExchanger.T);
3. 修正压力和流量的计算
- 你设的
maxPressure=10Pa太小了,实际系统压力不可能这么低,改成1e5 Pa(100000帕)才合理:
parameter Real maxPressure = 1e5;
- 压力计算要加边界,别算出负数:
pressure = max(minPressure, maxPressure - controlSignal);
4. 调流体边界的设置
FixedBoundary的温度设成303.15K(30℃),但作为回水口,建议改成和初始温度一致(293.15K),避免热力学冲突;- 检查
MixingVolume的端口连接,确保流向符合你的设计预期。
修复后的完整代码示例
model PumpTemperatureControlled // Parameter parameter Real maxFlowRate = 0.1; // 最大体积流量 m3/h parameter Real maxPressure = 1e5; // 最大压力 Pa(修正为合理值) parameter Real minPressure = 1e4; // 最小压力 Pa(修正为合理值) parameter Real desiredTempSpread = 4; // 目标温差 K parameter Real densityRefrigerant = 1032; // 介质密度 kg/m3 parameter Real zeta = 1; // 管道阻力系数 parameter Real crossSectionAreaPipe = 0.01; // 管道截面积 m2 // PID参数 parameter Real K_p = 1.0; // 比例系数 parameter Real T_i = 0.5; // 积分时间 parameter Real T_d = 0.2; // 微分时间 parameter Real x_min = -10.0; // 积分项下限 parameter Real x_max = 10.0; // 积分项上限 parameter Real capacityRefrigerant = 4180; // 变量 Real controlSignal(start=0, nominal=0); // 泵控制信号 Real currentTempSpread(start=0, nominal=4); // 当前温差 Real pressure(start=1e5, nominal=1e5); // 泵出口压力(修正初始值) Real flowSpeed(start=0.3, nominal=0.3); // 流体流速 // 组件 Buildings.Fluid.Sources.MassFlowSource_T boundary( nPorts = 1, redeclare package Medium = Buildings.Media.Antifreeze.PropyleneGlycolWater(X_a = 0.40, property_T = 293.15), use_m_flow_in = true, use_T_in = true) annotation(Placement(transformation(origin = {4, -36}, extent = {{-10, -10}, {10, 10}}))); Buildings.Fluid.MixingVolumes.MixingVolume vol( nPorts=2, V = 0.01, redeclare package Medium = Buildings.Media.Antifreeze.PropyleneGlycolWater(X_a = 0.40, property_T = 293.15), m_flow_nominal = 1, T_start = 293.15, p_start = 1e5) annotation(Placement(transformation(origin={34,14}, extent = {{-10, -10}, {10, 10}}))); Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow prescribedHeatFlow annotation(Placement(transformation(origin={-14,36}, extent = {{-10, -10}, {10, 10}}))); Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor outletTemperatureHeatExchanger annotation(Placement(transformation(origin = {54, 74}, extent = {{-10, -10}, {10, 10}}))); Modelica.Blocks.Interfaces.RealInput heatFlow annotation(Placement(transformation(origin = {-70, 36}, extent = {{-20, -20}, {20, 20}}), iconTransformation(origin = {-110, 44}, extent = {{-20, -20}, {20, 20}}))); Modelica.Blocks.Interfaces.RealInput inletTemperature annotation(Placement(transformation(origin={-72,-64}, extent = {{-20, -20}, {20, 20}}), iconTransformation(origin = {-110, -58}, extent = {{-20, -20}, {20, 20}}))); Modelica.Blocks.Interfaces.RealOutput outletTempHeatExchanger annotation(Placement(transformation(origin = {82, 42}, extent = {{-10, -10}, {10, 10}}), iconTransformation(origin = {108, 56}, extent = {{-10, -10}, {10, 10}}))); Modelica.Fluid.Sources.FixedBoundary bou( redeclare package Medium = Buildings.Media.Antifreeze.PropyleneGlycolWater(X_a = 0.40, property_T = 293.15), T = 293.15, // 修正为与初始温度一致 nPorts = 1) annotation(Placement(transformation(origin={36,-66}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Blocks.Interfaces.RealOutput massfluxHeatExchanger annotation (Placement(transformation(extent={{66,-6},{86,14}}))); // 使用标准PID块 Modelica.Blocks.Continuous.PID pid( k=K_p, Ti=T_i, Td=T_d, uMax=x_max, uMin=x_min, resetIntegrator=true) annotation(Placement(transformation(origin={-30, 0}, extent={{-10,-10},{10,10}}))); initial equation pid.x = 0.0; // 初始化PID积分项 equation // 计算温差误差 currentTempSpread = outletTemperatureHeatExchanger.T - inletTemperature; pid.u = desiredTempSpread - currentTempSpread; // 误差输入到PID controlSignal = pid.y; // 获取PID输出 // 压力计算(添加边界限制) pressure = max(minPressure, maxPressure - controlSignal); // 计算流速与质量流量 flowSpeed = sqrt(2*pressure/(densityRefrigerant*zeta)); boundary.m_flow = flowSpeed*crossSectionAreaPipe*densityRefrigerant; // 输出连接 massfluxHeatExchanger = boundary.m_flow; outletTempHeatExchanger = outletTemperatureHeatExchanger.T; // 重置积分项逻辑 when heatFlow < 1e-3 or pid.x < x_min or pid.x > x_max then reinit(pid.x, 0); end when; // 组件连接 connect(boundary.ports[1], vol.ports[1]) annotation( Line(points={{14,-36},{36,-36},{36,4},{33,4}}, color = {0, 127, 255})); connect(prescribedHeatFlow.port, vol.heatPort) annotation( Line(points={{-4,36},{24,36},{24,14}}, color = {191, 0, 0})); connect(outletTemperatureHeatExchanger.port, vol.heatPort) annotation( Line(points={{44,74},{24,74},{24,14}}, color = {191, 0, 0})); connect(heatFlow, prescribedHeatFlow.Q_flow) annotation( Line(points={{-70,36},{-24,36}}, color = {0, 0, 127})); connect(inletTemperature, boundary.T_in) annotation( Line(points={{-72,-64},{-8,-64},{-8,-32}}, color = {0, 0, 127})); connect(vol.ports[2], bou.ports[1]) annotation( Line(points={{35,4},{35,-36},{20,-36},{20,-66},{26,-66}}, color = {0, 127, 255})); end PumpTemperatureControlled;
额外提醒
- 确保Buildings库和Modelica标准库版本兼容,别因为组件接口不一样出问题;
- 运行前要给
heatFlow、inletTemperature这两个输入变量连上外部信号,要么给常量,要么给时间序列; - 用Dymola的“Model Setup”工具检查一下DAE系统的自由度,确认没有欠约束或过约束的情况。
内容的提问来源于stack exchange,提问作者Stephan Hirth
相关产品推荐
相关产品推荐

