You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GAMS技术问询:逻辑条件变量使用及热储能罐运行策略建模

解决GAMS中热分层罐充放电模式的MINLP建模问题

作为经常在GAMS里折腾光热储能MINLP模型的人,我太懂你卡在热分层罐充放电逻辑判断上的痛苦了!结合SCIP求解器的特性,我给你梳理一套实用的建模思路:

1. 先用二进制变量标记运行模式

首先得用二进制变量明确每个时刻的运行状态——充电、放电还是待机。在GAMS里这么定义:

Binary Variables
    x_charge(t)  ! 1表示时刻t处于充电模式,0则不是
    x_discharge(t); ! 1表示时刻t处于放电模式,0则不是

然后加个互斥约束,确保同一时刻只能是一种模式(或者待机):

Equation eq_mode_mutual_exclusion(t);
eq_mode_mutual_exclusion(t).. x_charge(t) + x_discharge(t) =l= 1;

2. 用大M法绑定流量与运行模式

接下来要把流量变量和运行模式挂钩:充电时只有罐顶进高温HTF、罐底出低温HTF;放电则相反。这里用大M法来实现逻辑约束,M选你模型里的最大允许流量(比如Q_max),数值别太夸张,不然SCIP求解会变慢。

比如定义流量变量:

Variables
    Q_in_top(t)      ! 罐顶流入流量
    Q_out_bottom(t)  ! 罐底流出流量
    Q_in_bottom(t)   ! 罐底流入流量
    Q_out_top(t);    ! 罐顶流出流量

然后加约束:

! 充电模式下:仅顶进、底出有流量,其余为0
Equation eq_charge_flow_top(t), eq_charge_flow_bottom(t), eq_charge_flow_zero1(t), eq_charge_flow_zero2(t);
eq_charge_flow_top(t)..    Q_in_top(t) =l= Q_max * x_charge(t);
eq_charge_flow_bottom(t).. Q_out_bottom(t) =l= Q_max * x_charge(t);
eq_charge_flow_zero1(t)..  Q_in_bottom(t) =l= Q_max * (1 - x_charge(t));
eq_charge_flow_zero2(t)..  Q_out_top(t) =l= Q_max * (1 - x_charge(t));

! 放电模式下:仅底进、顶出有流量,其余为0
Equation eq_discharge_flow_bottom(t), eq_discharge_flow_top(t), eq_discharge_flow_zero1(t), eq_discharge_flow_zero2(t);
eq_discharge_flow_bottom(t).. Q_in_bottom(t) =l= Q_max * x_discharge(t);
eq_discharge_flow_top(t)..    Q_out_top(t) =l= Q_max * x_discharge(t);
eq_discharge_flow_zero1(t)..  Q_in_top(t) =l= Q_max * (1 - x_discharge(t));
eq_discharge_flow_zero2(t)..  Q_out_bottom(t) =l= Q_max * (1 - x_discharge(t));

如果要更严格的“等于0”约束,可以把上面的=l=改成=e=,但要确保M足够大,不会限制正常流量。

3. 温度变量的逻辑绑定

充放电模式下,流体温度是固定的(充电顶进是高温T_hot,底出是低温T_cold;放电则相反),同样用大M法约束:

Variables
    T_in_top(t)      ! 罐顶流入温度
    T_out_bottom(t)  ! 罐底流出温度
    T_in_bottom(t)   ! 罐底流入温度
    T_out_top(t);    ! 罐顶流出温度

! 充电模式下的温度约束
Equation eq_charge_temp_top(t), eq_charge_temp_bottom(t);
eq_charge_temp_top(t)..    T_in_top(t) =e= T_hot - M_temp*(1 - x_charge(t));
eq_charge_temp_bottom(t).. T_out_bottom(t) =e= T_cold - M_temp*(1 - x_charge(t));

! 放电模式下的温度约束
Equation eq_discharge_temp_bottom(t), eq_discharge_temp_top(t);
eq_discharge_temp_bottom(t).. T_in_bottom(t) =e= T_cold - M_temp*(1 - x_discharge(t));
eq_discharge_temp_top(t)..    T_out_top(t) =e= T_hot - M_temp*(1 - x_discharge(t));

这里M_temp选温度的最大可能差值(比如T_hot - T_cold的2倍),同样要选紧一点的数值。

4. 结合模式的罐内能量平衡

最后把运行模式和罐的能量变化绑定。如果是离散时间步长dt,能量平衡方程可以这么写:

Variables
    E_tank(t); ! 时刻t罐内存储的热能

Equation eq_energy_balance(t);
eq_energy_balance(t).. 
    E_tank(t) =e= E_tank(t-1) 
    ! 充电时的能量变化:输入高温能量 - 输出低温能量
    + (Q_in_top(t)*T_hot - Q_out_bottom(t)*T_cold)*cp*dt * x_charge(t)
    ! 放电时的能量变化:输入低温能量 - 输出高温能量(相当于释放存储的热能)
    + (Q_in_bottom(t)*T_cold - Q_out_top(t)*T_hot)*cp*dt * x_discharge(t);

cp是HTF的比热容,根据你的模型参数调整就行。

5. SCIP求解器的小提示

  • 调用SCIP时可以设置一些选项加速求解,比如限制时间、开启启发式算法:
    option solver=scip;
    scip_options = "limits/time 3600 heuristics/freq 10"; ! 3600秒时间限制,每10步跑启发式
    
  • 给二进制变量设置初始值:如果有已知的初始运行状态,比如初始时刻是待机,就给x_charge(t)和x_discharge(t)设0,帮助SCIP更快找到可行解。
  • 尽量缩小变量的上下界:比如给流量、能量变量设置合理的范围,减少求解器的搜索空间。

如果还有具体的代码冲突或者变量定义问题,把你的片段贴出来,我们再细化!

内容的提问来源于stack exchange,提问作者Help621

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:21:17