1. 项目整体设计与优化思路梳理
1.1 热电联供型微网的组成结构
做微网优化运行项目,第一件事不是写代码,而是把物理系统的边界和内部结构彻底想清楚。我经手的这个模拟项目,目标是构建一个含冷、热、电多种负荷的园区级微网,通过多能互补实现各能源设备的协调调度。典型的热电联供型微网通常由以下几类设备构成:
- 供能侧:燃气轮机(或内燃机)作为热电联供核心,产生电能的同时回收余热;光伏发电作为可再生清洁电源接入;上级电网作为后备电源保障供电可靠性。
- 转换侧:余热锅炉将燃气轮机高温烟气转化为热负荷可用的蒸汽或热水;电锅炉实现电到热的转换,在电价低谷时段替代燃气供热;热交换器衔接不同供热网络。
- 储能侧:蓄电池平抑电功率波动、实现电能的时移;储热罐解耦热负荷与电负荷的刚性耦合,这是热电联供系统能否灵活运行的关键。
- 负荷侧:电负荷、热负荷(采暖/生活热水)、冷负荷(吸收式制冷机将热转换为冷)。
微网内部通过交流母线实现电功率的汇流分配,供热网络通过热水/蒸汽管道连接各热力设备。整个系统是一个典型的“双母线”结构:电母线和热母线。优化运行的核心就是在满足两类母线功率平衡的前提下,让每台设备的出力和启停状态都在合理区间运行。
1.2 多能互补与热电联供的结合逻辑
为什么要把“多能互补”和“热电联供”放在一起做优化?这是我做这个项目时反复琢磨的问题,也建议读者先想明白这个问题再动手,否则容易陷入纯数学模型堆砌的泥潭。
热电联供(CHP)的本质优势是能量梯级利用。常规火力发电的效率通常在35%~45%之间,大量热能随冷却系统散失;而热电联供机组发电后回收余热用于供热,综合能源利用率可以达到75%~85%。但热电联供有一个天然缺陷——电热耦合刚性:机组出力提升时,回收的热量也随之增加。如果园区热负荷小、电负荷大,机组为了满足电负荷必须多发电,产生的大量余热用不完,造成浪费;反过来,热负荷大、电负荷小时,机组为了供足热必须提高发电出力,发出的电可能面临无法就地消纳的困境。
多能互补是破解这个困境的出路。加入电锅炉和储热罐后,系统的灵活性大幅提升:热负荷需求高而电负荷消化能力弱时,可以用电锅炉把多余的电转为热存进储热罐;电负荷高峰而热负荷不足时,燃气轮机多发出来的热可以先存入储热罐,让机组不用降出力。再加上光伏、储能和电网交互,能量流从单一的电或热变成电、热、气多种能源协同的立体网络。优化运行要做的就是在这个复杂网络中找到成本最低、排放尽可能低、且满足所有物理约束的运行方案。
1.3 优化目标与决策变量的工程化定义
拿到一个优化问题,第一步是明确“优化什么”和“对什么优化”。这个项目里,我的优化目标设定为系统一个调度周期(24小时)内的综合运行成本最小化。成本项包括:
| 成本项 | 说明 | 建模要点 |
|---|---|---|
| 购电成本 | 微网从上级电网买电的费用 | 分时电价,不同时段单价不同 |
| 燃料成本 | 燃气轮机消耗天然气的费用 | 与发电功率/效率曲线相关 |
| 运维成本 | 各设备运行维护的折算成本 | 通常与出力成正比,系数各异 |
| 启停成本 | 机组启停产生额外损耗开支 | 简化时可仅计停机损耗 |
| 碳排放成本 | 将CO₂排放量折算为费用 | 可用碳税或碳配额价格折算 |
决策变量分为连续变量和整数变量两类。连续变量包括各时段的燃气轮机发电功率、热功率,电锅炉输入电功率,储热罐充放热功率,蓄电池充放电功率,与电网的交互功率,弃光功率等。整数变量(0-1变量)是机组在各时段的启停状态,以及储能设备在充/放两个方向之间的切换状态。
我在实际建模中发现,决策变量的选取直接影响模型规模和求解难度。如果只需要做功率分配优化,固定机组的启停状态,问题退化为线性规划;如果同时优化启停,就变成混合整数线性规划。做日前调度时建议把两套都跑一下,对比分析启停优化带来的成本下降幅度是否值得模型复杂度的增加。
2. 核心数学模型:从物理约束到可计算的优化方程
2.1 设备建模与能量流数学表达
数学建模是将物理设备行为“翻译”为代码的第一步,也是整个项目最需要耐心打磨的环节。以下是我在这个项目中采用的设备模型,均为工程常见的简化形式,兼顾精度和可解性。
燃气轮机模型:
$$P_{gt,t} = \eta_{gt} \cdot Q_{fuel,t}$$
$$H_{gt,t} = \frac{(1 - \eta_{gt}) \cdot \eta_{rec}}{\eta_{gt}} \cdot P_{gt,t}$$
其中$P_{gt,t}$为发电功率,$\eta_{gt}$为发电效率,$Q_{fuel,t}$为燃料输入能量,$H_{gt,t}$为回收热量,$\eta_{rec}$为余热回收效率。工程上还常用一条“热-电运行域”约束来限制机组在不同工况下的可行区间,即$P_{gt}$和$H_{gt}$必须落在某个由最大最小电出力和最大最小热出力围成的多边形区域内,这是比效率公式更准确的建模方式。
对于35kW~2MW等级的小型燃气轮机,我通常假设电效率在25%~40%之间,随负载率变化。简单的做法是取一个恒定效率,更精细的做法是分段线性化效率曲线。这个项目用的是恒定效率近似,重点放在多设备协同逻辑上,后续要扩展完全可以细化。
电锅炉是一个简单的转换环节:
$$Q_{eb,t} = \eta_{eb} \cdot P_{eb,t}$$
其中$\eta_{eb}$取0.95左右。蓄电池采用一阶动态模型,以荷电状态(SOC)为核心状态变量:
$$SOC_{t+1} = SOC_t + \left( P_{ch,t} \cdot \eta_{ch} - \frac{P_{dis,t}}{\eta_{dis}} \right) \cdot \Delta t / E_{bat}$$
储热罐类似,状态变量为当前蓄热量$S_{tes,t}$:
$$S_{tes,t+1} = S_{tes,t} + (Q_{st,t} - Q_{out,t}) \cdot \Delta t$$
拟建一个200kWh的储热罐,充放热速率上限设为50kW,自身热损耗系数取0.02/h,这样既起了灵活调节的作用,又不会因为模型过于理想化脱离实际。
2.2 功率平衡与设备运行约束体系
微网优化运行的可行域是靠约束条件画出来的。我按以下顺序逐一构建约束,既不会遗漏,也方便在代码里按块核对。
首先是电功率平衡约束,这是所有微网模型的“大梁”:
$$P_{gt,t} + P_{pv,t} + P_{dis,t} + P_{buy,t} = P_{load,t} + P_{eb,t} + P_{ch,t} + P_{sell,t}$$
左侧是供电来源,右侧是用电去向。注意这里把光伏实际消纳量$P_{pv,t}$和弃光量$P_{curt,t}$分开,实际光伏出力加上弃光量等于预测最大光伏出力,这部分约束决定光伏是全额消纳还是部分丢弃。在光伏渗透率高的时段,电价又低,配合蓄电池充电容量的上限,弃光现象几乎必然发生,模型里预留这个自由度非常重要。
其次是热功率平衡约束:
$$H_{gt,t} + Q_{eb,t} + Q_{out,t} + H_{gb,t} = H_{load,t} + Q_{st,t}$$
燃气轮机余热回收、电锅炉制热、储热罐放热、燃气锅炉备用供热(我在系统里放了台燃油/燃气锅炉做备用热源,应对极端工况)共同满足热负荷。
设备运行约束主要包括:各设备的出力上下限、启停状态与出力的耦合关系(机组停机时出力必须为0)、爬坡约束(机组出力变化速率不能超过设定值)、储能设备的荷电状态上下限和周期始末状态一致约束。最后这个“始末SOC一致”约束经常被初学者忽略——日前调度做完一个周期,储热罐和蓄电池不能比前一天亏了或盈了太多,否则第二天没法接着调度。我取SOC日在0.1~0.9之间,初始状态和末尾状态设为同一常数0.5,确保调度方案的可持续性。
联络线功率约束:与上级电网交换功率的上限。这个约束在容量有限的情况下会成为制约优化空间的关键瓶颈——买电多便宜也不能超过联络线容量,卖电再多也要留出受电裕度,否则实际运行时存在安全风险。
2.3 目标函数构造与碳排放折算处理
目标函数是优化的“指挥棒”,每一项的成本系数直接影响调度策略的走向。我用的目标函数形式如下:
$$\min \sum_{t=1}^{24} \left[ \begin{array}{l} price_{buy,t} \cdot P_{buy,t} \cdot \Delta t - price_{sell,t} \cdot P_{sell,t} \cdot \Delta t \ + k_{gas} \cdot Q_{fuel,t} + \sum_{i} k_{om,i} \cdot P_{i,t} \cdot \Delta t \ + c_{tax} \cdot E_{co2,t} \end{array} \right]$$
这里$price_{buy}$和$price_{sell}$分别是购售电价,采用峰谷分时电价制度;$k_{gas}$是天然气单位能量价格;$k_{om}$是各设备的单位运维成本系数;$c_{tax}$是碳税系数,$E_{co2,t}$是系统各时段的碳排放量,主要来自购电和天然气燃烧。
关于碳税,实际项目里往往不是每个地区都有明确碳价,我会在基础方案里把碳税系数设为0,单独做一组约束碳排放上限的方案进行对比,这样可以更清晰地展示“不同碳减排目标对运行策略的牵引作用”。例如碳税系数从0提高到经济性临界值,系统策略会逐步从“多用气少买电”向“少用气多买电”偏移,光伏利用率也会被动提升。
目标函数中所有包含0-1整数变量的项之间要保持线性关系。启停成本如果用固定费用乘以启停动作变量,需要额外引入一个描述“机组从停机到启动”的辅助变量,配合大M法线性化处理。我在初版代码里用了阶梯函数近似启停成本,省去了辅助变量的复杂性,效果也很理想,适合教学级项目,后续要发论文再做精细化处理。
3. 求解策略与Matlab代码实现要点
3.1 算法选型:混合整数线性规划的优势
做优化运行,业界主流做法是混合整数线性规划(MILP),而不是粒子群、遗传算法等智能启发式算法。原因非常现实:MILP有成熟的商业求解器(比如我用过的Gurobi、Cplex),能够在秒级到分钟级时间内在全局范围内找到最优解,而且有精确的最优性间隙(gap)指标。智能算法的参数需要反复调,运气不好还会陷入局部最优,每次跑出来的结果还不一样,这在工程调度中很难被接受。
我的建议是:模型能力允许的情况下优先用MILP,它的建模效率和可靠性都远高于启发式算法。如果你们实验室只有基础工具箱没有额外求解器,MATLAB自带的intlinprog也能处理中小规模的MILP问题。对于本项目的规模——24个时段、十几台设备、几十个0-1变量——intlinprog完全足够,求解时间通常在几十秒以内。
如果要用智能算法对比,我的经验是可以先用MILP求出一个理论最优解作为基准,再用粒子群算法去逼近,衡量启发式算法的逼近能力和稳定性,这种“双轨验证”思路在项目和论文中都很有说服力。
3.2 代码结构设计与模块划分
MATLAB代码的工程化结构决定了项目后期迭代的效率。我的代码目录结构如下:
thermal_power_microgrid/ ├── main.m # 入口脚本:载入数据、调用求解、输出结果 ├── data/ │ ├── load_data.m # 负荷与光伏预测数据 │ ├── price_data.m # 分时电价参数 │ └── device_param.m # 设备容量、效率参数 ├── model/ │ ├── build_problem.m # 构建优化问题(决策变量、目标、约束) │ ├── add_constraints.m # 分模块添加约束 │ └── objective.m # 目标函数定义 ├── solve/ │ └── run_solver.m # 调用求解器并处理返回结果 └── plot/ ├── plot_schedule.m # 绘制电功率平衡图 └── plot_soc.m # 绘制储能设备状态曲线一次完整的流程是:main.m先调用数据准备模块生成负荷、预测光伏和分时电价向量,然后构建优化问题,调用求解器获得最优解向量,最后把解拆分为各设备在各时段的出力,写结果并绘图。把数据和模型分开的好处是,后续换一组负荷数据或换一套设备参数,不需要改动模型代码,只需调整data文件。
3.3 核心代码片段与参数设置实录
以Yalmip工具箱为例,建模的核心代码非常直观。先声明决策变量:
%% 声明决策变量 P_gt = sdpvar(1, 24); % 燃气轮机发电功率 H_gt = sdpvar(1, 24); % 燃气轮机回收热功率 P_eb = sdpvar(1, 24); % 电锅炉输入电功率 Q_st = sdpvar(1, 24); % 储热罐充热功率(正为充) Q_out = sdpvar(1, 24); % 储热罐放热功率(正为放) P_buy = sdpvar(1, 24); % 购电功率 P_sell = sdpvar(1, 24); % 售电功率 SOC = sdpvar(1, 25); % 蓄电池荷电状态 S_tes = sdpvar(1, 25); % 储热罐蓄热量 u_gt = binvar(1, 24); % 燃气轮机启停状态(0/1)再添加约束,以电平衡约束为例:
%% 电功率平衡约束 % P_pv_forecast 是预测光伏出力向量 % P_load 是预测电负荷向量 % P_bat_dis 和 P_bat_ch 需要额外定义充放电变量 Constraints = []; Constraints = [Constraints, P_gt + P_pv_used + P_bat_dis + P_buy == ... P_load + P_eb + P_bat_ch + P_sell];目标函数片段:
%% 目标函数:购电成本 + 燃料成本 + 运维成本 + 碳排放折算 objective = ... sum(price_buy .* P_buy * dt) - sum(price_sell .* P_sell * dt) + ... sum(k_gas * Q_fuel * dt) + ... sum(k_om_gt * (P_gt + H_gt) * dt) + ... sum(k_om_eb * P_eb * dt) + ... sum(c_tax * co2_total * dt);求解:
%% 求解 ops = sdpsettings('solver', 'gurobi', 'verbose', 2, ... 'gurobi.MIPGap', 0.001, 'gurobi.TimeLimit', 300); optimize(Constraints, objective, ops);注意sdpvar和binvar的使用,Yalmip会自动把二元变量转化成MILP结构。设置求解器的MIPGap为0.001表示允许0.1%以内的最优性偏差,能显著加速求解;TimeLimit设为300秒防止极端情况陷入长时间搜索。
4. 算例设计与运行结果深度解读
4.1 典型日场景与基础数据设定
我设计了一个冬季典型日的算例:室外温度低,热负荷高,光伏出力相对较弱(冬季日照短)。电负荷曲线有两个明显高峰(早8~11点、晚18~21点),热负荷全天维持高位波动。基础设备参数如下:
| 参数 | 数值 | 说明 |
|---|---|---|
| 燃气轮机额定功率 | 100 kW | 最大发电能力 |
| 燃气轮机发电效率 | 0.35 | 恒定效率近似 |
| 余热回收效率 | 0.45 | 烟气余热转化为供热 |
| 电锅炉额定功率 | 80 kW | 最大输入电功率 |
| 电锅炉效率 | 0.95 | 电转热效率 |
| 蓄电池容量 | 200 kWh | 配置较大便于时移 |
| 储热罐容量 | 240 kWh | 可支撑较长热负荷 |
| 光伏装机容量 | 150 kW | 冬季出力受限 |
| 联络线交换上限 | 200 kW | 电网交互容量 |
| 碳税系数 | 50 元/吨CO₂ | 基准方案设定值 |
分时电价采用典型峰谷电价结构:峰时段(10:00-12:00,18:00-22:00)为1.2元/kWh,平时段(08:00-10:00,12:00-18:00)0.75元/kWh,谷时段(00:00-08:00)0.35元/kWh。天然气价格取2.5元/m³,折算为单位热值价格后约为0.25元/kWh。
4.2 三种运行模式的结果对比分析
我做了三组对比,用来量化多能互补的收益:模式A只有燃气轮机和电网,没有电锅炉、储能和储热;模式B在A基础上加入蓄电池;模式C为完整的多能互补系统。三组的结果如下表:
| 运行模式 | 总成本(元/日) | 购电量(kWh) | 天然气耗量(m³) | 光伏消纳率 |
|---|---|---|---|---|
| 模式A(纯热电联供) | 3862 | 528 | 428 | 92% |
| 模式B(+蓄电池) | 3427 | 396 | 402 | 94% |
| 模式C(+电锅炉+储热) | 2918 | 244 | 356 | 98% |
从模式A到模式B,降幅约11.3%,说明蓄电池的时移作用有效减少了峰时购电;再到模式C,相对模式A降幅达24.5%,多能互补带来的收益非常可观。模式C特别有意思:电锅炉在凌晨谷时段把便宜的电转为热水存在储热罐中,白天的热负荷高峰主要靠储热罐放热来支撑,燃气轮机则集中在电价高峰时段满发,发的电自用或售出,余热也直接供热或存入储热罐。这样不仅购电成本大幅下降,天然气的使用也更为节制,因为谷时段购电比烧气便宜得多。
光伏消纳率从92%提升到98%,背后是储电和储热共同拉动了局部消纳:光伏大发时段恰逢电价低谷,多余电力不是直接弃掉,而是充入蓄电池;热负荷不足时电锅炉还能把光伏电力转化为热水储存,又多了一条消纳路径。
4.3 调度策略的解构与规律提炼
看最优解对应的调度曲线,能明显看到优化算法的决策逻辑非常有“章法”:
- 凌晨(00:00-08:00):电价谷段,燃气轮机停机或最小出力运行,电锅炉全功率转热并储热,蓄电池在光伏未出时保持低功率充电,多余电力少量上网出售。
- 上午(08:00-10:00):电价平时段,电负荷爬升,燃气轮机启动并稳定在中等出力,热负荷高峰由余热和储热共同满足。
- 中午(10:00-13:00):光伏出力最大,燃气轮机降出力,蓄电池充电,多余热由储热罐吸纳,系统各设备协同平稳。
- 傍晚(18:00-22:00):电价峰段,燃气轮机接近满发,蓄电池放电支持电负荷,储热罐放热支持热负荷,需要时从电网少量购电补充缺口。
- 夜间(22:00-24:00):负荷回落,逐步恢复储热罐和蓄电池储量,为次日凌晨的运行做准备。
这套“谷段蓄能、峰段放能、光伏优先、气电互补”的逻辑,本质上就是优化算法面对价格信号和物理约束做出的理性选择。阅读调度曲线时,重点看两个指标是否符合工程直觉:一是燃气轮机在价格高峰时段的利用小时数是否明显提升;二是储能设备在谷充峰放的循环是否完整且SOC曲线在合理区间内平滑变化。
5. 调试经验与常见问题排查速查表
5.1 建模阶段最容易踩的坑
我在做这个项目时踩了几个比较深的坑,写出来供大家参考。
第一个坑是热功率平衡里漏了“热负荷”方向的偏差项。有时候电锅炉和燃气轮机的热出力预测值都对,但因为储热罐的状态变量边界设置不当,某些时段会出现“热不够用”却程序报无解的情况。排查方法:把所有约束逐条检查,重点看储热罐S_tes是不是掉出了[0,容量]区间,以及SOC是不是落在[δ, 1-δ]区间之间。
第二个坑是忽略了燃气轮机最小技术出力约束。燃气轮机不是从0功率就能启动的,通常有30%~50%的最小负载率限制。如果模型里允许P_gt从0连续启动,优化算法在低负荷时段会让机组在极低效率区间运行,计算得到的成本会远比实际偏小。必须加上P_gt >= u_gt * P_gt_min这样的约束。
第三个坑是蓄电池的充放电不能同时进行。如果不约束P_ch和P_dis互斥,优化算法会利用充放电同时发生的“零成本循环”来欺骗SOC约束。正确的做法是引入一个0-1变量指示充/放状态,并加上P_ch <= u_ch * P_ch_max和P_dis <= (1-u_ch) * P_dis_max两个约束。
第四个坑更具隐蔽性:储热罐充放热同时进行导致效率异常。储热罐虽然不像电池对同时充放那么敏感,但如果允许同时充放热,优化结果可能出现储热罐既充又放的“循环热”行为,成本账面上降低了实际却白白损失热量。我使用了储热罐的充放互斥约束,但效率惩罚设置较小时偶尔也会发生。检查结算结果里的Q_st和Q_out曲线,如果出现同一时段两者同时大于0的情况,就需要加强互斥约束。
5.2 求解阶段常见报错与处理方案
| 现象 | 直接原因 | 处理建议 |
|---|---|---|
| 模型无可行解(Infeasible) | 约束过强或存在矛盾 | 先用小规模数据诊断,逐步删减约束定位冲突源;检查SOC首末一致的数值是否超出容量范围 |
| 求解时间过长 | 整数变量过多或MIPGap过小 | 对MIPGap放宽到0.05;压缩时间粒度(从1小时改为2小时);先固定启停变量求解连续问题找到下界 |
| SOC曲线出现锯齿状波动 | 充放电切换过于频繁 | 添加最小持续运行时间约束,或增加充放电切换的惩罚系数 |
| 光伏消纳率为100%但成本异常高 | 很可能为了消纳光伏高价让燃气轮机停机 | 对比光伏成本(几乎为0)与天然气成本,判断是否值得为消纳光伏牺牲燃气轮机的中低负荷效率 |
5.3 让优化结果更贴近可落地运行的技巧
学术模型和工程落地的差距,往往体现在三个细节上。第一,调度结果对预测误差很敏感,实际运行中不可能完全按日前计划执行,建议在求解日前调度后,增加一个“实时调整”环节——每15分钟根据实际负荷和光伏出力,用模型预测控制或者简单滚动优化修正一次设备出力,这个做法在工程项目中属于标配,代码里留好接口非常关键。
第二,设备启停次数在模型里如果完全没有惩罚,优化结果可能频繁启停机组,实际运行哪受得了这种折腾。我给每台机组设置了最小运行时间和最小停机时间约束,比如燃气轮机至少连续运行2小时、停机后至少1小时才能再启动,这样调度曲线明显平滑很多,成本只牺牲了不到2%。
第三,最终结果的输出格式一定要贴近业务要求。我最后把调度表导出为Excel格式:行是各个设备,列是24小时,单元格里是每小时出力值;同时生成一张电平衡堆叠面积图和SOC曲线图,这样不管给导师看还是给运维人员沟通,都比“solver返回一个巨大的解向量”直观得多。
关于代码调试,再说一个亲测有效的技巧:先跑一个只含电负荷、不考虑热负荷和储热的简化模型,把代码全链路跑通,再把热网、储热、电锅炉逐模块加回去,每次只加一组约束、跑一次验证一次。这样做的好处是定位问题速度快得多——如果简化模型跑出好看的成本,加一个模块后突然无解,那问题十有八九出在这个模块的约束上,不会在全系统里大海捞针。
最后聊聊我的实际感受。这类热电联供微网优化运行的瓶颈,往往不在算法、也不在求解器,而在对物理系统的理解深度和建模的取舍拿捏。设备效率取恒定值还是分段线性化?储能模型要不要考虑温度影响?热网是否要建动态模型?这些选择决定了模型的复杂度,也决定了求解速度和结果可信度之间的平衡。初学者建议从最简单的MILP开始,把整个链路跑通、结果可视化、参数敏感性分析做完,再逐步细化模型。那样收获的不仅是一套代码,更是对能源系统运行逻辑的系统认知。