基于节点网络的光热电站冷热电综合能源系统优化调度 1. 项目背景与需求拆解为什么要做这样一个调度系统做综合能源系统优化调度的朋友应该都遇到过类似困惑单母线模型跑通之后换到节点网络拓扑结果调度结果一塌糊涂甚至直接不可行。今天分享的这套方案就是围绕“含光热电站的冷、热、电综合能源系统”来展开的核心工具是Matlab建模思路基于节点网络用优化调度的方式把整个系统的运行成本压下来。先把这个题目拆开看综合能源系统不是单纯的电系统而是把电力、供热、供冷统一协调起来的多能互补系统光热电站区别于常见的光伏电站它自带储热环节可以平抑太阳能波动能像“热电池”一样灵活调度出力节点网络说的是每个能源站、负荷区块不是简单挂在一根母线上而是分布在网络的不同节点上要考虑线路、管道的传输约束。把这三者放在一起做一次以经济性为目标的优化调度就是这个项目的全部内容。这个项目适合谁参考一类是正在做毕业设计、需要论文复现的硕士生和博士生另一类是做园区级综合能源规划、微电网调度的工程师。前者能通过代码理解光热电站建模和优化算法如何落地后者能把这个调度框架改造成自己的规划工具。如果你只是刚接触Matlab建议先把基础的线性规划和Yalmip工具箱用法摸熟上手会更快。一句话概括这套方案解决的核心问题是在24小时时间尺度内面对波动性的太阳能、固定或可调的冷热电负荷如何给出每一台设备每小时该发多少电、产多少热、充多少热、放多少热的完整计划让系统在满足用能需求的前提下运行成本最低。2. 系统建模的核心环节从光热电站到冷热电负荷2.1 光热电站模型不只是“太阳能发电”这么简单光热电站Concentrating Solar PowerCSP之所以在综合能源系统里备受青睐因为它和光伏有本质区别。光伏只有发电一个环节发多少全看天气没有存储缓冲调度灵活性差。而光热电站通常由聚光集热系统、储热系统Thermal Energy StorageTES、蒸汽发生系统和汽轮发电机组四部分组成。太阳能先被反射镜聚集成高温热能存入储热罐需要发电时再从储热罐抽取热量驱动汽轮机。这个“先存热、再发电”的结构让光热电站具备了类似常规火电的调节能力。建模方面光热电站可以分解成三个核心模块。第一个是光场集热模块输出的是集热功率 (P_{sf}(t))。它等于直接法向辐射 (DNI(t))、镜场总面积 (A_{sf})、光场效率 (\eta_{sf}) 三者的乘积这是白天太阳能输入的唯一入口。实际工程中光场效率会随着太阳高度角变化但调度模型中通常取一个分时段常数减少非线性求解负担。第二个是储热模块用储热罐的容量变化来描述。储热罐在某一时段的结束储热量 (E_{tes}(t1))等于上一时段储热量加上光场输入热量减去送往发电模块的热量同时考虑储热罐自身的散热损耗。这个等式就是储热系统动态变化的核心约束决定了光热电站能不能把中午的富余太阳能转移到晚高峰去发电。第三个是发电模块核心是热电转换效率 (\eta_{pb})发电功率等于从储热罐提取的热功率乘以这个效率。汽轮机有最小技术出力约束和爬坡约束这些都要写进调度模型里。2.2 冷热电联供系统的设备矩阵一个完整的冷、热、电综合能源系统设备往往不止光热电站一种。按照我自己的项目经验可以配置以下设备并分别建模光伏电站出力取决于光照强度在调度模型中通常按不可调度的负负荷处理直接叠加到净负荷上。光热电站上面已经详细说了是可调度的电源但受限于储热容量和光场输入。燃气轮机/燃气锅炉天然气驱动的可控电源或热源是系统灵活性的重要补充。电制冷机消耗电力来制取冷冻水供给冷负荷。它的特点是可以快速启停但能效比COP受负载率影响。吸收式制冷机消耗热源来制冷在有余热可用的综合能源系统中非常常见能把废热转化为冷量提高能源综合利用效率。储电装置也就是电池储能系统设定了充放电功率上限和SOC上下限。储热罐在系统中作为热缓冲用来平衡供热与用热的时间差。冷热电联供系统的典型运行逻辑就是“温度对口、梯级利用”。燃气轮机发电后产生的高温烟气先通过余热锅炉回收产生蒸汽一部分蒸汽直接供热一部分蒸汽驱动吸收式制冷机供冷这就实现了能量从高品位到低品位的逐级利用。把光热电站放入这个体系相当于又多了一个太阳热能来源它和燃气轮机的余热、储热罐之间可以灵活互补。2.3 节点网络为什么不能只用单母线模型很多初学者在初期建模时直接用单母线模型也就是全系统共用一个电母线、一个热母线、一个冷母线不考虑网络拓扑。这样做确实简单对初期的可行性验证没问题但一旦面对真实的园区级系统问题就来了不同能源站之间的电力输送距离、供热管网的延迟和散热损耗、冷站的供水温度约束这些都没有体现。节点网络模型的核心是把整个系统按地理或功能划分为若干个节点每个节点之间用线路、管道等传输通道连接。每个节点内部可以包含电源、热源、冷源和对应的负荷节点之间通过潮流计算来传递能量。这样一来优化调度不仅要决定每一台设备的出力还要决定各节点之间的能量交换量模型的复杂度和信息量都提升了。拿一个简化的三节点示范园区来举例节点A是光热电站和燃气轮机所在地节点B是商业办公区冷负荷高节点C是居民区热负荷高。在单母线模型里A、B、C三处冷热电负荷直接加总而节点网络模型则会计算A到B的供电量、A到C的供热量和B到C的供冷量每一条传输通道都有功率上限约束。这种建模方式更符合实际物理过程调度结果也更能直接用于运行指导。3. 优化调度的数学模型目标函数、约束条件与求解工具3.1 目标函数什么才是“最优”优化调度的目标函数要回答一个核心问题系统运行的时候省下来的钱到底省在哪里。从项目实际操作来看目标函数需要覆盖以下四项成本。第一是购电成本。当系统内部发电不足以满足负荷时从上级电网购电购电价格可以按照分时电价设置这也是为什么调度结果经常出现“夜间低谷蓄电、白天高峰放电”现象的根本原因。第二是燃料成本来自燃气锅炉和燃气轮机的天然气消耗每兆瓦时发电或产热对应一个燃料单价。第三是设备运维成本每台设备按输出功率乘以一个运维系数计算这反映的是设备磨损和维护费用。第四是弃光惩罚太阳能资源没有被利用造成的机会成本加上这个惩罚项之后调度器会自动尽量避免弃光。目标函数写成数学式就是各项成本之和的最小化。这里要提醒一句如果研究的重点是碳排放可以在目标函数中加入碳排放权重形成碳排放成本项如果既要经济性又要低碳性建议用加权系数法把两个目标合成一个单目标比直接做多目标优化比如NSGA-II简单得多而且便于在Matlab中调试。3.2 约束条件的基本盘光热电站和综合能源系统优化调度模型中的约束条件很多但归结起来就三大类功率平衡约束、设备出力约束、储能动态约束。功率平衡约束是每一段都必须满足的物理底线。电平衡指的是所有电源出力加购电等于所有电负荷加电制冷机耗电再加上储能充电功率热平衡指的是所有热源供热量等于热负荷加吸收式制冷机耗热量冷平衡指的是制冷总出力等于冷负荷。每个平衡只需要考虑自己的能量载体类型不需要直接跨载体计算但跨载体的耦合关系要通过设备的转换效率来实现。设备出力约束是每一台设备的运行边界。比如燃气轮机的出力上下限、爬坡速率约束光热电站汽轮机的出力上下限电制冷机的最大制冷量等。这些约束决定了调度结果的可行性。储能动态约束是储电、储热、储冷装置各自的状态转移方程。最常见的写法是SOC更新公式即当前时段末的储能状态等于上一时段末状态加上充入量、减去放出量、再减去自损耗。储能容量和充放功率上限也必须在这里限死。3.3 求解方案为什么推荐Yalmip加求解器整套模型在Matlab里的求解路径非常成熟我强烈建议用Yalmip工具箱来建模再搭配一个商业或开源求解器来求解。Yalmip的核心价值在于它把建模和求解器解耦让你用统一的语法写约束和变量求解时只需切换一行代码就能换求解器。这个思路和写SQL很像Yalmip是标准接口求解器是底层引擎。冷热电综合能源系统的调度模型如果时间尺度是24小时、步长1小时那么决策变量一般是设备的每小时出力、储能状态、购电量、节点间交换功率等整体规模在数千个变量的量级。目标函数和大部分约束都是线性的所以本质上是一个混合整数线性规划问题用CPLEX或者Gurobi求解非常稳。如果加入了储能充放标志位这类0-1变量问题会变成MILP这时用Gurobi的整数规划分支定界法也很快。有些同学会在模型里加入设备启停状态变量把目标函数写成包含固定启动成本和可变运行成本的形式。这种模型的求解时间会比纯线性模型长很多建议在小规模测试时先去掉启停变量确定框架跑通后再加上。4. Matlab代码实现整体框架、核心代码与参数配置4.1 代码文件的整体组织一个标准的光热电站综合能源系统优化调度工程在Matlab里会分成五个部分main.m主程序入口负责初始化参数、读取数据、调用优化求解、输出结果。data_define.m定义系统结构、设备参数、负荷曲线、辐射数据和电价数据也负责生成各个节点的连接矩阵。build_model.m用Yalmip定义变量、约束和目标函数返回一个OptimizationProblem对象。solve_optimization.m调用CPLEX或Gurobi求解器处理求解返回结果。plot_results.m绘制各个设备的出力曲线、储能曲线、节点间交换功率用于结果分析。这种文件结构的好处很明显数据和模型分离换一套场景数据不用改代码模型和求解分离换求解器不用改约束定义求解和绘图分离方便批量跑灵敏度分析。4.2 核心代码Yalmip建模示例下面这段示例代码是光热电站储热环节和电平衡约束的Yalmip写法。实际项目中建议把系统结构也写清楚这里为了精简只保留最核心的逻辑% 定义调度周期和时间分辨率 N 24; % 24小时 dt 1; % 时间步长单位小时 % 决策变量定义 P_pv sdpvar(N, 1); % 光伏出力 P_csp sdpvar(N, 1); % 光热电站发电功率 E_tes sdpvar(N, 1); % 储热罐储热量时段末 H_sf sdpvar(N, 1); % 光场集热功率输入储热罐 H_pb sdpvar(N, 1); % 储热罐放热功率送汽轮机 P_gb sdpvar(N, 1); % 燃气锅炉热出力 P_ec sdpvar(N, 1); % 电制冷机耗电功率 P_buy sdpvar(N, 1); % 向电网购电功率 SOC_bat sdpvar(N1, 1); % 电池SOC多一个初始值 P_ch sdpvar(N, 1); % 电池充电功率 P_dis sdpvar(N, 1); % 电池放电功率 % 目标函数购电成本 天然气成本 运维成本 C_buy 0.8 * ones(N, 1); % 购电价元/kWh C_gas 0.35; % 天然气折算成本元/kWh C_om_csp 0.02; % 光热运维成本系数 obj sum(C_buy .* P_buy) C_gas * sum(P_gb) ... C_om_csp * sum(P_csp); % 约束 Constraints []; % 储热罐动态平衡 rho_tes 0.98; % 储热罐保温效率 eta_sf 0.45; % 光场集热效率 DNI_data ...; % 读取实测DNI数据 A_sf 5000; % 镜场面积m2 H_col eta_sf * A_sf * DNI_data / 1e6; % 转为MW for t 1:N if t 1 Constraints [Constraints, ... E_tes(t) E_tes0 * rho_tes H_col(t) - H_pb(t)]; else Constraints [Constraints, ... E_tes(t) E_tes(t-1) * rho_tes H_col(t) - H_pb(t)]; end end % 光热发电功率与放热功率的关系 eta_pb 0.42; % 光热发电效率 Constraints [Constraints, P_csp eta_pb * H_pb]; % 电功率平衡约束 P_load_e ...; % 电负荷数据 P_pv_forecast ...; % 光伏预测出力 Constraints [Constraints, ... P_pv P_csp P_buy P_dis P_load_e P_ec P_ch]; % 储热罐容量约束 E_tes_max 120; % 最大储热容量MWh Constraints [Constraints, ... 0 E_tes E_tes_max, ... 0 H_pb 80, ... 0 P_csp 50]; % 电池SOC递推与容量约束 Constraints [Constraints, ... SOC_bat(2:end) SOC_bat(1:end-1) P_ch*0.9 - P_dis/0.9, ... 0 SOC_bat 100, ... 0 P_ch 20, ... 0 P_dis 20];这段代码的核心在于储热罐的动态约束。仔细观察就会发现光热电站的调度自由度完全来自储热环节如果少了储能公式光热电站就直接退化成随风而动的光伏电站失去了调度价值。4.3 参数配置与数据准备跑这个系统的关键参数如下表我整理了一份可复用的基准参数集供参考类别参数名称数值单位光热电站光场效率 eta_sf0.45无量纲光热电站镜场面积 A_sf5000m²光热电站发电效率 eta_pb0.42无量纲光热电站储热罐容量 E_tes_max120MWh光热电站储热罐保温效率 rho_tes0.98无量纲光伏电站峰值装机容量30MW燃气锅炉最大热出力60MW燃气锅炉热效率0.9无量纲电制冷机制冷COP3.5无量纲吸收式制冷机制冷COP1.2无量纲电池储能容量50MWh电池储能最大充放功率20MW电网交互联络线功率上限40MW电价峰段1.2元/kWh电价谷段0.3元/kWh这里特别说明一下DNI数据、负荷曲线和分时电价都是外部输入在实际项目中建议收集当地典型日数据来替换。我的习惯是把这些数据统一放到Excel表中用readtable函数读入Matlab这样换场景的时候不用改代码本身只要改Excel就行。5. 结果分析与调试心得从调度曲线到常见问题排查5.1 怎么看调度结果求解完成后Matlab变量空间里会得到所有决策变量的最优值。我的习惯是先把以下四张图画出来第一张是电功率平衡堆叠图第二张是热功率平衡堆叠图第三张是储热罐和电池的SOC曲线第四张是各节点交换功率图。电功率平衡堆叠图最有信息量。理想情况下你应该看到光伏出力在午间达到峰值光热电站的出力曲线会呈现“午间储热、晚峰放热”的形态燃气锅炉则主要用于补充早晚供热高峰。如果光热电站出力曲线是平平的一条直线说明储热约束或者目标函数设置有问题光热的时间平移能力没有被调度器利用起来。储热罐SOC曲线也要重点检查。合理的结果应该是有明显的充放循环白天充热、傍晚和夜间放热。如果SOC曲线一直贴着容量上限或者下限不动说明储换热平衡的耦合系数有误或者目标函数导向不对。5.2 最常见的求解失败问题及排查方法根据我自己跑这类模型的经验把高频问题整理成了一个速查表错误现象可能原因解决思路模型不可行infeasible某个功率平衡约束两侧在某个时段无论如何都凑不齐检查负荷数据是否有突变放宽对应节点交换功率上限或给储能增设初始SOC求解器长时间不收敛0-1变量过多或约束中存在隐含非线性去掉设备启停标志位先把问题简化为LP检查是否有sdpvar误写成intvar储热罐SOC一直为0储热动态约束的递推关系写错了方向或者变量间单位不一致单独验证E_tes的递推公式去掉目标函数后单独测一测约束是否可满足光伏出力曲线与预测不一致常数定义错误或公式少了面积单位换算DNI数据通常单位是W/m²注意除以1e6换算成MWGurobi/CPLEX求解器报错许可证未配置或者求解器路径未加入Yalmip配置在Matlab中运行yalmiptest检查Yalmip与求解器是否正常绑定5.3 我的排查方法论跑这类调度模型我有一个很大的经验教训不要一上来就追求最优解先确保可行域不是空集。具体做法是先把目标函数设置为常数0只求解一个可行性问题看看约束之间是否矛盾。如果可行性问题都过不去那目标函数再精巧也白搭。这样做的好处是求解器报错时可以明确区分是“约束写错”还是“目标函数写错”。还有一个很实用的技巧是分模块验证。先固定光热电站出力为某个确定值运行一次调度看电平衡和热平衡是否满足然后把光伏、燃气锅炉逐个接入。每次只增加一个设备发现问题时就能快速定位到哪个模块出了问题。这种模块化调试法对于综合能源系统这种多设备耦合模型特别管用。在我实际跑这套代码的过程中最常踩的坑集中在单位换算上。DNI数据的单位、储热罐容量单位、功率与能量的关系经常在不知不觉中出现MW和MWh的混用。建议在代码开头统一规定功率一律用MW能量一律用MWh时间步长以小时为单位这样储能递推公式就不会出现系数错误。另外建议在main.m开头加一段参数断言检查。比如判断储热罐容量是否大于0、负荷向量长度是否等于24、DNI数据是否有负数等。这些断言在数据规模变大时能节省大量排查时间。这个项目后续还能扩展的方向也很多。在光热电站侧可以把DNI的随机性纳入考虑做成随机优化或者鲁棒优化在网络侧可以把三节点扩展成更多节点的实际园区拓扑加入管道散热系数在求解层面如果系统规模达到百节点级别可以尝试把模型做成分布式优化用交替方向乘子法ADMM求解。作为一套完整的调度框架这套节点网络建模加Matlab求解的方案既能用于学术研究也能作为实际园区能源管理系统的核心算法模块。