资讯动态

计及新能源不确定性的综合能源系统协同优化:场景法建模与Matlab实现

发布时间:2026/9/25 3:30:06 来源:尧图企业网站定制
做综合能源系统优化的人应该都有过这种体会刚把确定性模型调通、求解器跑出结果的那一刻心里还挺爽的结果一对比实际运行数据发现风电光伏的实际出力和预测值差了十万八千里优化出来的调度方案根本没法直接落地。这个课题的核心就是把这层新能源出力不确定性纳入优化模型让综合能源系统在风光随机波动的情况下依然保持经济性和可操作性。下面我把整个项目的建模思路、场景处理方法和Matlab代码实现从头到尾拆一遍覆盖从概率建模到求解调试的完整链路希望能给正在做相关课题的同学一点实际参考。1. 项目思路拆解从确定性优化到随机协同优化1.1 这个课题到底在研究什么综合能源系统Integrated Energy SystemIES把电力、天然气、热力等异质能源通过燃气轮机、电锅炉、储能、电转气P2G等设备耦合在一起打破传统各能源系统独立规划运行的壁垒。所谓“协同优化”就是在满足电、热、气负荷需求的前提下找到各设备最优的出力分配方案让整个系统运行成本最低或者碳排放最少。“计及新能源出力不确定性”这个前缀是课题真正的研究重点。风电和光伏出力受天气影响具有很强的随机性和波动性预测精度再高也难免有误差。如果优化模型把预测值当成真实值来处理一旦实际出力偏离预测值轻则经济性打折扣重则出现功率不平衡、弃风弃光甚至切负荷的情况。所以模型必须在决策阶段就把这种不确定性考虑进去而不是等偏差出现了再去补救。“电气设备”这四个字指的是系统里那些具体可调度的设备——燃气轮机的启停与爬坡、储能的充放电、电锅炉的供热功率、P2G的产气速率等等。协同优化的落脚点就是这些设备的运行策略。1.2 为什么必须把不确定性“计及”进模型初学者最容易犯的一个错误是用一套确定性的预测曲线直接跑优化。比如把风电预测曲线当成固定输入得到一组看似最优的调度方案然后拿去仿真验证结果发现风电实际出力曲线稍微偏离一点方案就不可行了。打个比方这就好像你按天气预报规划第二天的行程预报说全天无雨你就没带伞结果下午一场阵雨把你淋了个透。真正可靠的做法是知道“有20%的概率会下雨”然后准备一把伞。这个伞在优化模型里就是“备用容量”和“多场景权衡”的体现。工程上处理不确定性常用的框架有两种一是随机规划Stochastic Programming用离散场景集表示可能的新能源出力情况二是鲁棒优化Robust Optimization用不确定集合描述出力的波动范围做最坏情况下的决策。本课题采用的是场景法随机规划因为它的建模直观、求解难度相对可控而且能给出各场景下的具体调度方案便于工程人员理解和决策。场景法随机规划通常写成两阶段模型第一阶段做“现在必须确定”的决策比如机组启停计划、日前购电合同量这些决策在不确定量实现之前就要定下来Here-and-Now第二阶段是“等不确定量实现后”的调整决策比如各机组的实际出力、储能的实时充放电它们可以针对每个场景单独调整Wait-and-See。目标函数是第一阶段的成本加上所有场景概率加权的第二阶段成本。1.3 工具链选型为什么是Matlab Yalmip Cplex/Gurobi做这类优化课题工具链的选择直接决定开发效率。我用的是Matlab Yalmip Cplex/Gurobi这套组合也推荐刚接触这个方向的同学从这套组合入手原因主要有三点。第一Matlab的矩阵运算和数组操作非常高效生成场景数据、写约束条件、做结果可视化都很顺手。相比PythonMatlab在数据处理和绘图上有天然优势尤其是做多场景循环和批量仿真时代码写起来逻辑更清晰。第二Yalmip是一个Matlab下的建模层工具它最大的价值在于把数学模型和求解器解耦。你用Yalmip描述决策变量、目标函数、约束条件写出来的代码和论文里的数学公式几乎一一对应改模型非常方便。而且Yalmip支持Cplex、Gurobi、Mosek等主流求解器只需要改一行参数就能切换方便对比不同求解器的效果。第三Cplex和Gurobi是这个领域公认的高性能MILP求解器。综合能源系统的协同优化模型引入机组启停整数变量之后本质上是一个混合整数线性规划MILP问题规模一大用免费求解器比如Matlab内置的linprog配合穷举根本跑不动。Gurobi和Cplex在分支定界算法上做了深度优化求解速度能快出一个数量级以上。这里有个经验如果只是做课程作业级别的算例用linprog或者Yalmip默认的求解器也能出结果但如果是论文级算例建议直接上Gurobi它在处理大规模MILP时比Cplex的默认参数往往更“激进”求解速度更快。2. 新能源出力不确定性建模场景生成与削减2.1 风光出力的概率模型先搞清楚要生成不确定性场景第一步是定义新能源出力的概率分布。风电出力的大小主要由风速决定而风速在工程上常用两参数Weibull分布描述其概率密度函数为[ f(v) \frac{k}{c}\left(\frac{v}{c}\right)^{k-1}\exp\left[-\left(\frac{v}{c}\right)^k\right] ]其中k是形状参数c是尺度参数。不同地区的风资源特性不一样k通常在1.5到3之间c则和年平均风速相关。比如一个年平均风速6米/秒的风电场c可以取6.5左右k取2.2这两个参数可以直接用历史风速数据通过极大似然估计拟合出来。风速得到之后通过风机的风速-功率转换曲线计算出力[ P_{wt} \begin{cases} 0 v v_{in} \text{ 或 } v v_{out} \ P_r \cdot \frac{v - v_{in}}{v_r - v_{in}} v_{in} \leq v \leq v_r \ P_r v_r v \leq v_{out} \end{cases} ]其中(v_{in})、(v_r)、(v_{out})分别是切入风速、额定风速、切出风速(P_r)是额定功率。光伏出力则主要受光照强度影响工程上常用Beta分布描述光照强度再通过效率和面积折算成功率这里不再展开公式。2.2 场景生成蒙特卡洛抽样和拉丁超立方采样有了概率分布就可以生成新能源出力场景了。最直接的方法是蒙特卡洛抽样Monte Carlo Sampling从Weibull分布中随机抽取N组风速序列再转换成风电功率序列。但纯蒙特卡洛有一个问题——样本点完全是随机的可能在某些概率区间扎堆而在尾部概率区间几乎没有样本导致场景代表性不够。更推荐的做法是拉丁超立方采样Latin Hypercube Sampling, LHS。它先把每个概率分布的累积函数分成N个等概率区间再从每个区间内各抽取一个样本这样保证抽取的样本均匀覆盖整个概率空间。LHS有点像分层随机抽样把[0,1]区间切成N层每层强制取一个样本点避免随机性导致的样本聚集。Matlab里实现LHS非常方便代码量很少% 场景参数设置 Nscen 500; % 场景数量 Ntime 24; % 调度时段数 k 2.2; % Weibull形状参数 c 6.5; % Weibull尺度参数 % 拉丁超立方抽样得到[0,1]均匀分布样本 u lhsdesign(Nscen, Ntime); % 通过逆变换映射到Weibull分布得到风速场景 v_scen wblinv(u, c, k); % 风速转风电功率分段函数 v_in 3; v_r 12; v_out 25; P_r 100; % 单位MW P_wt_scen zeros(Nscen, Ntime); P_wt_scen(v_scen v_in | v_scen v_out) 0; idx v_scen v_in v_scen v_r; P_wt_scen(idx) P_r .* (v_scen(idx) - v_in) / (v_r - v_in); idx v_scen v_r v_scen v_out; P_wt_scen(idx) P_r;这里lhsdesign是Matlab内置函数默认生成维度为(Nscen \times Ntime)的拉丁超立方样本矩阵每一列的边际分布都均匀覆盖[0,1]区间。然后用wblinv做逆累积分布变换得到的就是符合Weibull分布的风速样本。这就是“先均匀分层、再映射到目标分布”的完整流程。2.3 场景削减同步回代消除法的实现思路500个场景直接丢进随机优化模型决策变量和约束的数量会膨胀求解时间大概率让人崩溃。所以通常需要先做场景削减用少量有代表性的场景近似原来的场景集。同步回代消除法Simultaneous Backward Reduction是工程上最常用的场景削减算法。它的核心思想是迭代地删除一个场景同时把被删除场景的概率加到离它最近的场景上从而让剩余场景集与原始场景集的概率分布差异最小。具体步骤可以这样理解所有场景初始概率均为(1/N_{scen})。计算任意两个场景之间的“概率加权欧氏距离”(d(i,j) \pi_i \cdot | scen_i - scen_j |_2)。每一轮找到距离最小的场景对((i,j))删除场景(j)然后把(\pi_j)累加到(\pi_i)上。重复步骤2和3直到剩余场景数量达到预设目标。用Matlab实现时这是一个两层循环迭代的过程。为了提高计算效率可以预先把所有场景的风电出力曲线存成一个矩阵每轮削减只更新概率向量和场景矩阵。500个场景削减到30个典型耗时在几十秒以内完全可接受。2.4 削减效果怎么看场景削减不是拍脑袋定数量通常要验证削减前后场景集的统计特性是否一致。工程上会对比削减前后的风电出力期望值曲线、标准差以及分位数。如果期望值曲线和95%置信区间带基本重合说明削减后的场景集保留了原始场景集的大部分不确定性信息。实操上还有一个小技巧削减后的场景数量不是越多越好。场景数翻倍求解时间往往增长接近指数级。我在多个算例中测试下来30到50个场景通常是一个比较好的平衡点——既保留了不确定性特征又不至于让MILP求解器卡死。具体多少个合适建议做一组敏感性分析场景数从10、20、30、50依次增加观察目标函数值的变化。如果30个场景和50个场景的目标函数值相差不到1%那30个就足够了。3. 综合能源系统协同优化模型构建3.1 目标函数怎么设计才有区分度协同优化模型的目标函数一般包含经济性目标和低碳性目标。最常见的是最小化系统总运行成本包含以下几个部分购电成本从上级电网购电的费用分时电价下每个时段电价不同。燃气成本燃气轮机消耗天然气的费用。设备运维成本按出力大小线性折算。弃风弃光惩罚成本新能源出力没有完全消纳时按单位缺额成本惩罚。碳排放成本以碳交易价格折算的碳排放费用。如果论文强调低碳性可以在目标函数中加入碳排放项或者设置碳排放总量约束。注意碳排放成本不是“推不推荐加”的问题而是“审稿人看不看”的问题——现在做综合能源系统优化纯经济性模型很难有创新点加了碳交易机制之后模型复杂度上去了创新点也就有了。目标函数展开成两阶段形式可以写成[ \min \quad F_{first} \sum_{s1}^{S} \pi_s \cdot F_{second,s} ]其中(F_{first})对应第一阶段决策成本比如机组启停成本、固定购电容量费用(\pi_s)是削减后场景(s)的概率(F_{second,s})是场景(s)下各设备的运行成本和惩罚成本。3.2 核心设备模型与控制变量综合能源系统里的设备模型是整个模型的地基每个设备都要用一组数学约束来描述它的运行特性。把这部分做好后面的约束组合和求解才不容易出问题。燃气轮机的关键约束是出力上下限、爬坡约束和最小启停时间约束。出力上下限很好理解机组功率不能超出铭牌范围。爬坡约束是相邻时段出力变化量不能超过机组爬坡速率这保证了调度方案的物理可行性。最小启停时间约束因为引入了整数变量是MILP模型复杂度的重要来源但工程上可以适当松弛或者忽略——很多算例中机组一天启停次数本来就不多影响有限。储能设备的核心是SOC荷电状态递推方程[ SOC_{t1} SOC_t \eta_{ch} P_{ch,t} - \frac{P_{dis,t}}{\eta_{dis}} ]同时要满足充放电功率上下限和SOC上下限约束。这里有几个常见坑一是在写递推方程时时段的错位导致SOC变量维度和时段数对不上二是没有限制同一时段不能同时充放电导致模型出现“边充边放”的无意义解。限制同时充放电的做法可以引入互补整数变量也可以用P_ch_t * P_dis_t 0这类非线性约束但在Yalmip里更推荐用二元变量做互斥约束因为非线性约束会破坏MILP结构。电锅炉、P2G设备的模型相对简单本质上是一个能量转换环节输入电功率输出热/气功率转换效率取固定值或分段线性效率即可。它们的核心作用是提供多能互补的灵活性——比如光伏大发时段多余的电功率通过P2G转成天然气存起来晚高峰再通过燃气轮机发电供热实现“削峰填谷”。下面把典型设备的模型整理成一个表格方便对照建模设备决策变量关键约束风电场/光伏电站实际消纳功率(0 \le P_{renew} \le P_{avail})燃气轮机出力、启停状态上下限、爬坡、启停逻辑电储能充/放电功率、SOCSOC递推、功率限幅、互斥电锅炉耗电功率(0 \le P_{eb} \le P_{eb,max})P2G耗电功率、产气量效率线性折算、功率上限上级电网购电功率(0 \le P_{buy} \le P_{buy,max})3.3 系统级约束电-热-气平衡怎么闭合设备模型描述的是“能干什么”系统级约束则描述“必须平衡什么”。三类平衡约束是协同优化的骨架电力平衡任意时段燃气轮机出力、新能源消纳、储能放电、购电之和等于电负荷加上储能充电、电锅炉耗电、P2G耗电。这个方程是耦合所有电相关设备的中枢。热力平衡燃气轮机余热、电锅炉供热满足热负荷需求。如果有储热罐还要加入储热罐的蓄放热递推约束。热力系统的时间常数较大在日前调度中可以适当简化只做热功率平衡不细算管网温度动态。天然气平衡为了保证P2G和气负荷的气量平衡需要建立气网节点平衡方程。注意天然气有日内调峰的特性不像电力系统要求逐秒平衡气网动态过程通常用一段时间窗口内的累计平衡来近似。协同优化的价值就在这些平衡约束的交汇点体现电力系统的灵活性不足可以通过热力系统和天然气系统来弥补。光伏中午大发导致电力供过于求时与其弃光不如让电锅炉和P2G把多余电能转成热和气存起来。这些跨能源形式的耦合正是“综合能源系统协同优化”区别于单一电力系统优化的核心所在。3.4 协同优化比独立运行强在哪很多文章会用“系统独立运行”作为对比基准来体现协同优化的价值。独立运行模式下电力子系统只用电储能解决功率不平衡热力子系统只用燃气锅炉供热量两个系统之间没有能量交互。协同模式下燃气轮机可以“以热定电”或者“以电定热”余热回收利用P2G实现跨时段能量转移。仿真结果通常能显示协同模式比独立模式节省若干个百分点的运行成本同时新能源消纳率明显提升。这类对比是论文的亮点也是验证模型正确性的手段——如果协同优化结果比独立运行还差那说明模型大概率有Bug。4. Matlab代码实现与求解配置4.1 代码架构这样组织最清晰一个完整的不确定性协同优化项目Matlab代码最好按模块分文件组织别把所有代码堆在一个脚本里否则后面调参和Debug会非常痛苦。我的习惯是分成下面几个文件main.m主程序入口设置参数、调用各模块、输出结果。data_define.m定义系统参数、负荷曲线、设备参数、电价等集中管理方便改参数。scenario_generate.m生成新能源出力场景并做场景削减输出削减后的场景集和场景概率。build_model.m用Yalmip构建决策变量、目标函数和约束条件。solve_model.m调用求解器求解检查求解状态返回优化结果。plot_results.m绘制各设备出力曲线、SOC曲线、各场景成本分布图。这种模块化设计的核心好处是可以“独立替换”比如改用鲁棒优化时只需要重写scenario_generate.m和build_model.m中的约束写法主程序和结果分析不用动。只有把这些模块分开面对多种不确定性建模方法对比的课题需求时才能快速切换。4.2 Yalmip建模核心代码片段的正确姿势用Yalmip建模最关键的是变量维度的定义。我的建议是明确用(T, Nscen)二维矩阵来表示每个场景下的连续决策变量第一阶段决策单独用维度(T,1)定义。%% 定义变量 % 第一阶段日前决策 u_gt binvar(Ntime, 1, full); % 燃气轮机启停状态 P_gt_day sdpvar(Ntime, 1, full); % 日前计划出力备用参考 % 第二阶段各场景下的调整决策 P_gt sdpvar(Ntime, Nscen, full); % 燃气轮机实际出力 P_dis sdpvar(Ntime, Nscen, full); % 储能放电功率 P_ch sdpvar(Ntime, Nscen, full); % 储能充电功率 SOC sdpvar(Ntime1, Nscen, full); % 荷电状态比时段多一个初始值 P_buy sdpvar(Ntime, Nscen, full); % 购电功率 P_ab sdpvar(Ntime, Nscen, full); % 新能源实际消纳功率 %% 约束 Constraints []; % 功率平衡每个时段、每个场景都要满足 for t 1:Ntime for s 1:Nscen Constraints [Constraints, P_gt(t,s) P_ab(t,s) P_dis(t,s) P_buy(t,s) ... P_load(t) P_ch(t,s) P_eb(t,s) P_p2g(t,s)]; end end % 储能SOC递推 for s 1:Nscen for t 1:Ntime Constraints [Constraints, SOC(t1,s) SOC(t,s) eta_ch*P_ch(t,s) - P_dis(t,s)/eta_dis]; end end % 新能源消纳约束 for s 1:Nscen Constraints [Constraints, P_ab(:,s) P_wt_scen(:,s)]; % 场景s的可再生出力上限 end %% 目标函数 Cost ...; Objective Cost; ops sdpsettings(solver, gurobi, verbose, 2, showprogress, 1); Optimize_result optimize(Constraints, Objective, ops);写Yalmip约束时最推荐用repmat和矩阵整体运算替代双重for循环——模型规模大的时候循环写起来方便但求解前Yalmip内部的变量展开开销很大。比如功率平衡约束可以直接写成矩阵形式P_gt P_ab P_dis P_buy repmat(P_load,1,Nscen) P_ch P_eb P_p2g一行代码搞定所有场景的约束性能提升非常明显。4.3 求解器接入与参数调优实战求解器这块最容易卡住新手的是Gurobi的安装和路径配置。Gurobi安装完成之后需要把gurobi目录和matlab目录都加到Matlab路径里然后在Matlab命令行运行gurobi_setup完成环境初始化。如果提示找不到求解器先检查路径是否添加成功再用yalmiptest命令逐个测试Yalmip支持的求解器是否被识别。求解委托之后参数设置直接决定求解效率。我常用的关键参数有mipgapMIP相对间隙阈值设为0.01表示找到的整数解与最优解的差距在1%以内就停止。论文算例设1%完全够用硬要求精确最优解会把求解时间拖长数倍。timelimit单次求解的时间上限防止调试时模型有问题导致求解器无限跑下去。outputflag控制求解器日志输出设为0可以静默运行。求解完成后必须检查solinfo.problem状态码。0表示最优解1表示达到时间或间隙限制返回可行解2表示模型不可行。很多新手不看状态码直接取变量值结果求解器根本没找到可行解后面的绘图全是NaN。4.4 结果可视化怎么画才有说服力结果分析的图画好了论文的档次能上一个台阶。我一般固定画四类图各设备出力堆叠图展示调度方案的构成和平衡关系、储能SOC曲线展示跨时段能量转移策略、新能源消纳情况对比图体现不确定性处理方法的效果、以及不同场景下的成本分布箱线图体现随机优化的经济性稳健性。特别推荐画“场景概率加权的成本分布图”把每个场景下的优化成本画成柱状图同时在图上标出加权均值。这比单纯给一个目标函数数值直观得多审稿人一眼就能看出系统在不同新能源出力场景下的成本波动范围。5. 调试实操中的典型问题与避坑经验5.1 求解时间爆炸怎么治我见过太多人栽在这一步场景数取200个整数变量数破千模型丢给求解器跑了一晚上还在gap里挣扎。求解时间长的根源通常就两个整数变量太多和约束规模太大。对症下药的做法有三招。第一先做场景削减50个场景是一个相对稳妥的起点第二把能合并的变量合并比如多个同类型燃气轮机可以用一个聚合机组表示减少整数变量个数——很多论文模型里的“机组”其实是聚合模型第三给求解器一个合理的MIPGap阈值工程上1%的次优解和最优解的成本差异几乎可以忽略但求解时间能缩短一个数量级。如果你需要反复调试多个算例强烈建议在main.m里加一个NumScen开关变量小规模测试时设成10正式出结果时设成50。没有这个开关每次改场景数都要动模型代码改来改去容易出错。5.2 模型无可行解怎么查模型不可行是MILP调试中最头疼的问题因为求解器只会告诉你“没有可行解”不会告诉你哪个约束出错了。我的排查套路固定成三步。第一步先跑确定性模型把场景数设为1新能源出力取预测值确认基础模型逻辑没有问题。如果确定性模型都无解优先检查功率平衡方程电、热、气负荷和电源/供热能力是否匹配储能初始SOC是否设置合理。第二步逐步加入场景相关约束每次加一类约束就跑一次找到第一个导致无解的约束组。最常用的工具是给可疑约束加一个松弛变量比如在功率平衡约束右边加上松弛量求解后看哪些时段的松弛量不为零这些时段就是供需矛盾最严重的地方。第三步检查数值问题导致的“伪不可行”。比如约束量纲不统一某一项数值达到(10^6)另一项在(10^{-3})量级求解器的数值容差可能直接把小量项忽略掉造成约束永远无法满足。统一量纲之后很多“不可行”会神奇地消失。5.3 量纲统一和数值稳定性是隐形杀手这是新手最容易忽略、却最影响求解可靠性的细节。典型错误包括功率用kW储能容量用MWh成本用万元碳排放用吨所有数字混在一个模型里求解器数值范围跨越七八个数量级结果就是求解精度差、约束莫名其妙不满足。处理思路非常简单粗暴统一量纲。功率基准值取1MW能量就取1MWh成本统一用千元或者万元碳排放统一用吨。变量范围尽量控制在(10^{-3})到(10^3)之间。做敏感性分析时你会发现仅仅是把装置容量从“kW”改成“MW”求解时间可能缩短一半以上因为这个简单的改动把模型条件数大幅改善了。5.4 Yalmip常见报错速查报错现象常见原因解决方法Index exceeds matrix dimensions约束/变量维度不匹配检查sdpvar定义的维度用size确认No suitable solver foundYalmip未识别求解器运行yalmiptest检查求解器路径和LicenseNaN in constraint参数未初始化或含无穷值检查数据生成代码断点定位NaN来源Warning: Solver not applicable模型类型超出求解器能力确认模型是LP/MILP不是非线性MINLP求解时间无限长整数变量太多或约束冗余场景削减、聚合机组、设置MIPGap最后再说一个个人体会比较深的地方这类“计及不确定性的协同优化”项目最大的坑往往不在数学建模而在“模型写出来能求解”和“求解结果正确可信”之间的距离。一个负责任的调试习惯是每做完一个中间步骤就用小规模算例验证一遍——比如先验证设备模型单时段出力是否合理再验证储能SOC递推是否守恒最后再验证整个系统平衡是否正确。小步快跑看起来慢实际上比一口气写完整个模型然后花三天找Bug要快得多。如果后续想在这个课题上继续扩展有两个方向值得关注一是用分布鲁棒优化Distributionally Robust Optimization替代单纯场景法结合历史数据的矩信息构造模糊集在不确定性的经济性和保守性之间取得更优平衡二是引入多阶段决策框架把日前、日内、实时三个时间尺度的决策嵌套起来更贴近实际调度场景。把基础模型跑通之后在这两个方向上去加创新点论文的完整性和深度都会更扎实。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑