1. 问题背景与模型核心思路1.1 为什么要研究电热综合能源系统的日前调度做电力系统优化调度的同行应该都有体会传统的经济调度模型基本是围绕纯电力系统展开的——机组组合、备用安排、潮流约束这些内容在各类教材和论文里已经很成熟。但最近几年随着可再生能源渗透率一路走高大家发现一个很现实的问题只调电、不调热很多矛盾根本解不开。原因在于热电联产机组CHP在供暖季往往是“以热定电”——热负荷是刚性的电出力就被热出力捆住了。风电、光伏大发的时候如果CHP为了满足热负荷必须保持高电出力那风电就得弃。而电热综合能源系统把热力管网、储热装置、电锅炉这些环节都纳入调度框架相当于给原本僵硬的“以热定电”模式松了绑让热力侧去配合电力侧的调节需求。这个标题里最关键的两个词一个是“日前经济调度”一个是“可再生能源消纳”。前者决定了模型的时间尺度——提前一天以小时或者更细为间隔给出未来24小时各机组的出力计划后者决定了模型的优化目标不是简单的最低运行成本而是在经济性基础上尽可能给可再生能源让路减少弃风弃光。1.2 这个模型解决了什么痛点我早期做调度模型的时候习惯性地把热负荷当成固定值直接塞进约束条件里然后只优化电功率分配。结果算出来的方案有两个问题第一CHP的电出力范围被热负荷卡死灵活性严重不足第二完全没考虑热力系统的惯性——供热管网的蓄热效应、建筑围护结构的储热能力这些在短时间尺度上都能充当“虚拟储能”白白浪费了。引入储热罐之后情况就不一样了。热负荷的高峰可以在白天也可以挪到夜间储热罐把CHP的热出力在时间轴上搬移电出力就跟着松动了。进而风电大发、电价低谷的时段CHP可以压电出力同时让储热罐放热维持热平衡风电出力小、电价高的时段CHP满发多余的热先存进储热罐留给后面用。这个逻辑就是“可再生能源消纳”在电热耦合系统里的落地方式。所以这个模型的本质是在“电-热耦合”的约束空间里找到一组未来24小时的运行方案使得总运行成本最低同时让可再生能源的消纳量尽可能大。写代码的时候能不能把这个耦合关系表达清楚直接决定模型靠不靠谱。2. 数学模型设计目标函数与约束条件2.1 目标函数怎么定才合理目标函数是经济调度的“指挥棒”定了什么目标优化结果就往什么方向走。这个模型里我建议把目标函数设置成系统总运行成本最小包含以下几项CHP机组燃料成本通常表示成电出力和热出力的二次函数常规纯凝机组的燃料成本如果系统里有弃风弃光的惩罚成本购电成本如果系统与上级电网有功率交换储热罐的运行维护成本一般按充放热量的比例计电锅炉的耗电成本如果配置了电锅炉作为消纳手段。以小时为单位计一个典型的日前调度周期是24个时段目标函数表达式可以写成[ \min \sum_{t1}^{24} \left[ \sum_{i \in G} C_i(P_{i,t}) \sum_{j \in H} C_j(H_{j,t}) c^{grid}P_t^{grid} c^{curt}(P_t^{wind,curt}P_t^{pv,curt}) c^{EB}P_t^{EB} \right] ]这里 (C_i) 是机组成本函数(C_j) 是热源成本函数(P_t^{grid}) 是联络线交换功率购电为正、售电为负(P_t^{wind,curt}) 和 (P_t^{pv,curt}) 是弃风弃光量。惩罚成本的单位价格设置很关键——设置得太低模型会优先弃风设置得太高会强迫消纳导致运行成本虚高。我一般把惩罚成本设为煤电成本的1.5到2倍这样既保证消纳优先级又不至于让经济性失真。2.2 电热耦合约束CHP机组的“可行域”建模电热综合能源系统建模的难点几乎全在CHP机组的热电耦合关系上。国内常见的CHP类型有两种抽汽式extraction condensing和背压式backpressure。抽汽式CHP的可行域在 (P-H) 平面上是一个四边形区域四个顶点对应不同的运行工况。用线性不等式描述的话大概是这样[ \begin{cases} P - c_v H \leq P^{max} - c_v H^{min} \ P - c_v H \geq P^{min} - c_v H^{max} \ 0 \leq H \leq H^{max} \end{cases} ]其中 (c_v) 是电功率随热功率变化的斜率系数表示多抽一份蒸汽供热时电出力相应减少多少。这个参数可以从机组的供热工况图上读出来实际做算例的时候取0.15到0.25之间都是常见范围。背压式CHP则简单一些电出力和热出力是严格的线性关系[ P c_m H ](c_m) 是背压工况下的电热比。这种机组没有调节的灵活性只要热负荷定了电出力就定了。所以背压机组在含高比例新能源的系统里往往需要搭配储热或者电锅炉才能玩得转。写约束的时候我有个习惯把所有运行工况的顶点坐标列成表格然后用凸组合的方式描述可行域。这样不仅代码清晰还可以很方便地拓展到任意多边形可行域。表格形式如下工况点电出力/MW热出力/MWA2000B150100C80150D60502.3 储热罐模型别小看这个“时间搬移器”储热罐的建模相对直观核心是能量平衡约束和容量约束。能量平衡方程[ Q_{t1}^{TES} Q_t^{TES} (H_t^{ch} \eta_{ch} - \frac{H_t^{dis}}{\eta_{dis}}) \Delta t ]充放热功率约束[ 0 \leq H_t^{ch} \leq H_{max}^{ch} u_t^{ch}, \quad 0 \leq H_t^{dis} \leq H_{max}^{dis} u_t^{dis} ][ u_t^{ch} u_t^{dis} \leq 1 ]容量约束[ Q_{min}^{TES} \leq Q_t^{TES} \leq Q_{max}^{TES} ]最后还要加一个周期一致性约束保证调度周期结束时储热罐的蓄热量和初始时刻相同不然模型会利用“期末免费甩热”的漏洞来降低目标函数值——这个细节是我在实际调试中踩坑踩出来的很多初版代码没加这个约束跑出来的结果第一眼很漂亮仔细一分析全是问题。储热罐的充放热效率 (\eta) 一般取0.9到0.95之间。效率越高热量的时间搬移成本越低系统越愿意用储热来解耦CHP的电热约束。2.4 电锅炉与弃风弃光约束电锅炉在这个模型里的角色是“电力过剩时的热负荷消费者”。风电大发、电网消纳不了的时候与其弃风不如用电锅炉把多余的电转化成热供到热网里。电锅炉的模型简单就是电功率到热功率的转换[ H_t^{EB} \eta_{EB} P_t^{EB} ]电锅炉的效率可以取0.95左右这是电转热路径中效率最高的环节之一。弃风弃光约束其实是一个不平衡等式[ 0 \leq P_t^{wind,curt} \leq P_t^{wind,forecast}, \quad 0 \leq P_t^{pv,curt} \leq P_t^{pv,forecast} ]预测的出力上限决定了可再生能源的最大可用功率模型在满足安全约束的前提下可以选择消纳或者弃掉一部分。目标函数里的惩罚成本项就是用来引导模型做这个选择的。3. 不确定性处理与消纳机制设计3.1 预测误差怎么处理日前调度的所有输入都是预测值——风电出力预测、光伏出力预测、负荷预测、热负荷预测。既然是预测就有误差。这个模型如果不考虑不确定性调度方案在实时运行中大概率会跑偏。处理方式有三种层次第一种确定性模型加旋转备用约束。这是最务实、最容易实现的方案。在约束里加大正负旋转备用容量预留向上和向下的调节空间应对预测误差。[ \sum_{i} P_{i,t}^{max} u_{i,t} - \sum_{i} P_{i,t} \geq R_t^{up} ][ \sum_{i} P_{i,t} - \sum_{i} P_{i,t}^{min} u_{i,t} \geq R_t^{down} ]备用需求一般取预测负荷的一定比例加上风电预测出力的一个比例比如5%负荷 20%风电预测出力。这个经验公式在工程上用了很多年简单有效。第二种场景法。对风电和光伏的预测误差构造多个场景每个场景带一个概率然后做随机规划。代码实现上用Yalmip的implies或者直接展开场景约束计算量会成倍增加但结果更稳健。第三种鲁棒优化。不确定集用区间表示模型在所有可能的不确定参数实现下都可行。这个模型计算复杂但对数据要求低适合没有历史误差分布统计数据的场景。3.2 消纳能力从哪来很多人问我“同样一个系统为什么有的模型能消纳90%的风电有的只能消纳70%”关键在于两点一是系统有没有足够的灵活性资源二是调度模型能不能把这些灵活性资源的潜力挖出来。灵活性资源在电热系统里主要有四个来源CHP机组的电出力调节范围联络线交换功率的调节空间储热罐的充放热能力电锅炉的灵活用电能力。其中后两个是电热系统特有的。热负荷本身是刚性的但储热罐和电锅炉相当于给热力系统引入了“柔性”让热负荷在时间轴上可以搬移。从电力系统的视角看这就等效于给电网增加了调节容量。以我做过的一个算例来说不加储热罐和电锅炉时弃风率是17.3%加了一台50MW/200MWh的储热罐、两台20MW电锅炉之后弃风率降到了6.8%系统总运行成本还降了4.5%——虽然增加了电锅炉的耗电和储热罐的运维费用但减少的燃料成本和弃风惩罚远远覆盖了这些支出。这种“看似多花钱实则总账更划算”的结果正是综合能源系统调度的魅力所在。3.3 价格机制与消纳的互动目标函数里面购电价格曲线的形状对消纳结果影响非常大。如果采用分时电价峰谷差越大系统越有动力在风电大发的时段往往是夜间低谷时段多用电、多储热因为这意味着成本更低。反之如果电价都是平段的系统缺少跨时段调节的经济激励灵活性资源就“睡”在那里。所以做案例设计的时候我通常给三个电价场景做对比平电价、普通分时电价、深度峰谷电价。结论基本一致峰谷价差拉大后储热罐的利用率显著提高消纳率同步上升。这说明电价机制本身就是一种调度手段——规则设计得当比强行添加约束更有效。4. Matlab实现从数学模型到可运行代码4.1 为什么选Matlab Yalmip这套组合电力系统优化调度领域Matlab几乎是事实上的标准平台。原因不外乎三点矩阵运算天然友好、生态系统完整、上手门槛低。而求解优化问题我强烈建议用Yalmip作为建模层。Yalmip是一个Matlab的建模工具箱把约束和目标函数用符号化的方式写出来内部自动转换成求解器需要的标准形式。它支持绝大多数主流求解器Gurobi、CPLEX、Mosek、SCS、OSQP等。这样一来模型层和求解层完全解耦——想换求解器改一行配置就行不用动模型代码。配套的求解器我首选Gurobi。它的线性规划和混合整数线性规划求解速度在同类产品里属于第一梯队而且对Yalmip的支持非常完善。如果手头没有Gurobi或者CPLEX的授权退而求其次可以用Matlab自带的linprog和intlinprog但大规模算例的计算速度会差不少。4.2 代码结构怎么搭我写这类代码的习惯是分模块每个模块一个脚本或者函数。结构如下project/ ├── main.m % 主程序组装一切 ├── data/ │ ├── load_data.m % 载入基础数据 │ ├── wind_forecast.m % 风电预测数据 │ └── heat_load.m % 热负荷数据 ├── model/ │ ├── define_variables.m % 定义决策变量 │ ├── objective.m % 目标函数 │ ├── constraints_elec.m % 电力系统约束 │ ├── constraints_heat.m % 热力系统约束 │ ├── constraints_coupling.m % 耦合约束 │ └── solve_model.m % 求解与结果输出 └── results/ ├── plot_results.m % 结果可视化 └── export_data.m % 数据导出这种模块化结构的最大好处是改热力管网的拓扑、加一个新的耦合设备只要在对应的约束文件里增删代码就行不至于推倒重来。4.3 核心代码片段先定义决策变量%% 定义决策变量 P_chp sdpvar(24, n_chp, full); % CHP电出力 H_chp sdpvar(24, n_chp, full); % CHP热出力 P_wind sdpvar(24, 1, full); % 风电并网功率 P_wind_curt sdpvar(24, 1, full); % 弃风功率 P_grid sdpvar(24, 1, full); % 联络线功率 H_tes_ch sdpvar(24, 1, full); % 储热罐充热功率 H_tes_dis sdpvar(24, 1, full); % 储热罐放热功率 Q_tes sdpvar(24, 1, full); % 储热罐蓄热量 u_chp binvar(24, n_chp, full); % CHP启停状态 u_tes_ch binvar(24, 1, full); % 充热状态标志 u_tes_dis binvar(24, 1, full); % 放热状态标志这里注意一个细节binvar在Yalmip中定义了二进制变量模型就从LP变成了MILP。求解时间会显著增加但换来的是对机组启停、储热罐充放热互斥这些逻辑的精确刻画。目标函数%% 目标函数总运行成本最小 Cost 0; for t 1:24 for i 1:n_chp % CHP燃料成本二次函数用分段线性近似 Cost Cost a_chp(i) * P_chp(t,i)^2 b_chp(i) * P_chp(t,i) c_chp(i); end % 购电成本 Cost Cost price_grid(t) * P_grid(t); % 弃风惩罚 Cost Cost penalty_curt * P_wind_curt(t); % 储热运行成本 Cost Cost c_tes * (H_tes_ch(t) H_tes_dis(t)); end optimize(Constraints, Cost, sdpsettings(solver,gurobi,verbose,2));约束条件%% 约束条件 Constraints []; % 电功率平衡 for t 1:24 Constraints [Constraints, P_chp(t,:)*ones(n_chp,1) P_wind(t) P_grid(t) P_load(t)]; end % 热功率平衡 for t 1:24 Constraints [Constraints, H_chp(t,:)*ones(n_chp,1) H_tes_dis(t) H_eb(t) H_load(t) H_tes_ch(t)]; end % CHP可行域约束以四边形为例 for t 1:24 for i 1:n_chp Constraints [Constraints, P_chp(t,i) - c_v(i) * H_chp(t,i) P_max(i) - c_v(i) * H_min(i)]; Constraints [Constraints, P_chp(t,i) - c_v(i) * H_chp(t,i) P_min(i) - c_v(i) * H_max(i)]; Constraints [Constraints, 0 H_chp(t,i) H_max(i)]; end end % 储热罐约束 for t 1:24 Constraints [Constraints, 0 H_tes_ch(t) H_tes_ch_max * u_tes_ch(t)]; Constraints [Constraints, 0 H_tes_dis(t) H_tes_dis_max * u_tes_dis(t)]; Constraints [Constraints, u_tes_ch(t) u_tes_dis(t) 1]; if t 24 Constraints [Constraints, Q_tes(t1) Q_tes(t) H_tes_ch(t)*eta_ch - H_tes_dis(t)/eta_dis]; else Constraints [Constraints, Q_tes(1) Q_tes(24)]; % 周期约束 end end % 风电出力约束 for t 1:24 Constraints [Constraints, P_wind(t) P_wind_curt(t) P_wind_forecast(t)]; Constraints [Constraints, 0 P_wind_curt(t) P_wind_forecast(t)]; end这些代码片段组合起来就是一个可以跑通的日前经济调度基础版。实际做项目的时候还需要根据自己的系统拓扑加入热网管道的传输约束、节点的温度约束等但基础的骨架就是这个样子。4.4 求解器配置与调试技巧Yalmip求解器配置我踩过一个很常见的坑sdpsettings里的solver参数如果写成小写或者拼错Yalmip会静默地用一个默认求解器结果就是模型复杂的时候求解时间莫名其妙翻了好几倍。所以正式跑算例之前我习惯先运行一段验证代码确认当前环境和求解器兼容% 检查求解器是否可用 yalmip(clear); solvesdp(sdpvar(1), [], sdpsettings(verbose,0)); disp(yalmiptest);yalmiptest会列出所有已安装且可用的求解器跑之前花三秒钟看一眼能省下后面排查问题的大把时间。调试MILP模型的时候另一个常用技巧是先放松整数约束——把所有binvar换成sdpvar并加上0 x 1的边界看看LP松弛版本是否可行。如果LP都解不出来那肯定是约束建模有问题如果LP能解但MILP无解那问题是整数约束导致的排查方向就清晰了。5. 算例设计与结果分析5.1 一个可复现的测试系统为了让读者有一个可以直接复现的算例我设计了一个简化但完整的测试系统参数如下2台抽汽式CHP机组额定电出力100MW热出力80MW1台风电场额定装机200MW1个储热罐容量200MWh最大充放热功率50MW2台电锅炉单台额定功率20MW热负荷峰值120MW电负荷峰值180MW与上级电网的联络线功率上限100MW。风电预测数据用一个典型冬季日的数据白天出力小傍晚开始增大深夜达到峰值。热负荷数据也是典型的北方供暖日曲线夜间高、白天低。5.2 三组对比实验我通常做三组对比场景A纯电力调度电热完全解耦热负荷刚性CHP以热定电 场景B电热联合调度有储热罐电锅炉 场景C联合调度 深度分时电价。结果汇总成表格场景系统总成本/万元弃风率/%CHP平均电出力/MW储热罐利用率/%A纯电调度182.617.384.20B联合调度174.26.870.562CB分时电价168.94.165.378三个结论第一联合调度显著降低弃风率降幅超过10个百分点。核心原因是CHP的“以热定电”约束被储热罐打破给风电让出了出力空间。第二总成本不升反降说明弃风惩罚和燃煤消耗的减少超过了储热罐和电锅炉的额外运维成本。这在经济上是典型的“帕累托改进”。第三价格机制能进一步激发灵活性资源的潜力。深度峰谷电价下储热罐的充放策略更激进消纳效果更好成本更低。5.3 结果可视化怎么做Matlab出图这块我建议至少画三张图第一张24小时的功率平衡图——电功率平衡按机组堆叠面积图能直观看出风电、CHP、联络线各自承担的角色。第二张储热罐的蓄热量和充放热功率曲线——这张图能验证储热罐是否真正发挥了时间搬移作用。第三张弃风率对比柱状图——三个场景放到一起一目了然。画图代码用area、bar这些基础函数就行不需要额外的绘图工具箱。如果我需要出论文级别的图会再把坐标轴字体、图例位置、线宽统一调一遍但作为调试和汇报用的初版图功能齐全比美观更重要。6. 常见问题与排查经验6.1 模型不可行怎么办这是我被问得最多的问题。模型一跑就报infeasible怎么排查第一步查数据。检查所有数据是否都在合理的物理范围内特别是负荷数据、风电预测数据有没有出现异常值。比如热负荷负荷大于CHP最大热出力与储热最大放热功率之和那热平衡约束无论如何都满足不了——这种问题不用上求解器肉眼就能看出来。第二步关掉一部分约束试试。先把CHP可行域约束去掉简化成纯线性直接给边界看模型是否可行。如果简化后可解那问题出在可行域约束的参数上——多半是P_min、P_max、H_min、H_max这四个边界值不协调导致可行域为空。第三步用Yalmip的check命令检查每条约束的残差diagnostics optimize(Constraints, Cost); if diagnostics.problem 1 residual check(Constraints); % residual接近1的约束是紧约束接近0或者负的是矛盾约束 find(residual 1e-3) endcheck返回的是每个约束对应的对偶值或者残差信息能快速定位是哪一条约束把模型搞垮了。6.2 结果里储能利用率太低怎么办好不容易模型可解了结果一看储热罐一天没用几次充放功率曲线几乎是平的。这个现象通常是两种原因第一种储热罐的容量或者充放功率上限设置得太大导致它只需要很短的时间就能完成充放任务其他时间都在待机。解决方法是检查储能参数是否偏离实际设备的规格。第二种电价峰谷差太小跨时段搬移热量的收益比不上储热损失和运维成本。这时候模型会觉得“不动比动更划算”。把分时电价的峰谷比拉大到2.5倍以上或者适当降低储热罐的运维成本系数储热罐的活动频率就会明显上升。我自己做项目时会额外看一下储热罐的“年循环次数”这个指标——如果一年循环次数低于200次这个储热罐大概率是“配置过剩”了算经济账是不划算的。6.3 求解时间太长怎么优化MILP模型和纯LP模型在求解时间上完全是两个量级。如果算例规模大、机组台数多、时间颗粒度细求解时间蹭蹭往上涨可以考虑以下优化手段用分段线性化替代二次成本函数减少非线性约束引入的特殊序贯约束给二进制变量提供好的初始值warm startYalmip里可以用assign给变量赋初值Gurobi会利用这个初始解加速分支定界放宽求解精度sdpsettings(gurobi.mipgap, 0.01)把最优性间隙从默认的1e-4放宽到1%求解时间往往能缩短一个数量级而目标值差异基本在1%以内合并同类型约束减少约束数量Yalmip里尽量别用循环一条一条加约束用矩阵运算批量添加能快很多。最后一个技巧尤其容易被忽略。初版代码里我用for循环加约束200个时段的模型加起来慢得离谱后来改成矩阵化写约束同样的模型求解时间直接降了一个数量级。Matlab矩阵运算的优势在模型规模大的时候体现得非常明显。6.4 Yalmip版本兼容那点事Matlab本身的版本更新频率快Yalmip也在不断迭代。我遇到过最头疼的事是换了Matlab版本之后原来能跑的Yalmip代码突然报错——要么是求解器接口变了要么是某些语法在Yalmip新版本里被标记为deprecated。解决这个问题有两个办法一是固定开发环境装一个和项目初始开发时一致的Matlab和Yalmip版本不轻易升级二是每次更新Yalmip之后先跑一遍yalmiptest确认所有求解器接口正常再跑核心算例验证结果和之前的版本一致。另外Yalmip的官方GitHub仓库会持续更新建议定期把旧项目拉出来在新版本环境里跑一遍回归测试。这个习惯让我避免了很多次“上版能跑这版不能跑”的尴尬。6.5 一个容易忽略的细节时区和数据对齐做日前调度最怕的是数据对不齐。负荷数据用的北京时间、风电预测数据用的世界时、电价数据用的当地时区三个数据源一混合目标函数和约束就全错位了。我在一次项目里就吃过这个亏——排查了整整一天最后发现是风电数据的时间戳整体偏移了一个小时导致夜间风电大发时段的调度方案完全反过来。所以数据预处理阶段一定要统一时间戳格式如果涉及跨时区数据全部转换为同一标准时区并且在校验阶段画一张所有输入数据的叠加时序图看看曲线峰值是否落在合理的时间区间。这个习惯帮我省了无数排查时间。7. 从模型到项目的扩展思考7.1 模型怎么扩展成多能互补系统电热耦合只是综合能源系统的一个子集。如果你做完这个模型想往更大的方向扩展可以考虑加燃气、氢能、冷负荷等环节。比如耦合氢能时可以增加电解槽模型——风电大发时段多余的电用于电解水制氢氢气可以存储、可以用于燃料电池发电也可以卖给工业用户。这跟电锅炉的逻辑类似但氢能的跨时段储能能力更强。再比如考虑冷热电联供CCHP需要引入吸收式制冷机模型电、热、冷三网耦合约束关系更复杂但思路和电热耦合是一样的——找到各个能源网络之间的转换关系把转换效率写进约束然后在一个统一的目标函数下优化。7.2 与市场机制结合如果往前再走一步可以考虑把日前经济调度嵌入到电力市场的出清框架里。这时候目标函数从“系统总成本最小”变成“社会福利最大化”或者“购电费用最小”约束条件里还要加上市场报价、阻塞管理等电力市场特有的约束。储热罐和电锅炉在市场中扮演的角色则更加多元——它们既是价格接受者也可以做套利者。日前市场上电价低时充电蓄热电价高时放电供热赚取峰谷价差。这个思路和金融里的跨期套利本质上是同一回事。不过要提醒一句市场化环境下储热罐的充放策略不再单纯以系统消纳为目标而是以个体收益最大化为目标。如果系统调度和市场交易这双重身份叠加建模复杂度会显著上升需要决策者根据实际运营模式来取舍。7.3 深度强化学习会不会替代优化模型最近总是有人问DRL能不能用于电热综合能源系统调度。我的观点是在日前调度这个场景里传统优化方法仍然是主力原因有三第一日前调度是典型的有约束优化问题优化算法能保证解的可行性和最优性这是RL方法至今难以保证的第二模型回退、参数调整、结果可解释性传统优化方法都做得更好在工程落地中非常重要第三RL适合的是在线决策、高不确定性的场景比如实时调度、自动发电控制这些场景才是RL发挥优势的地方。所以我的建议是先用优化模型把确定性框架搭扎实再在需要处理不确定性的环节引入RL或者鲁棒优化两者结合而不是非此即彼。8. 给后来者的实操建议做了这么多电热系统调度的项目最后分享几个我觉得特别重要的实操经验。第一个经验先跑通再优化。初版代码不要一上来就追求模型多复杂、算法多先进。先用一个小算例——一两台机组、24个时段、简单的负荷曲线——把整个代码链路跑通包括数据读入、模型建立、求解、结果输出、画图。链路通了再逐步增加复杂性。这样能把“建模出错”和“代码出错”这两个问题隔离开排查效率倍增。第二个经验约束松弛是排查问题的万能钥匙。任何模型不可行的问题都可以通过逐步放松约束找到根源。我排查过的最棘手的一个案例是CHP可行域约束的参数维度搞错导致所有时段该约束都不满——这种问题靠肉眼看不出来必须靠系统性的约束检查。第三个经验Matlab代码的矩阵化思维。初版代码用循环写得越舒服算例规模变大之后就越痛苦。从第一天写约束开始就尽量用矩阵运算而不是循环。Yalmip支持变量矩阵直接参与约束构造花点时间把数据整理成矩阵形式后面求解效率高得多。第四个经验别忘了数据可视化。很多模型问题——数据错位、约束矛盾、储能利用率异常——在曲线图上一眼就能看出来但在数字表格里可能要盯半小时。所以养成画图的习惯每步结果都输出一张图比输出一堆数字有用得多。模型做到这个程度已经可以覆盖绝大多数研究和工程需求了。从纯电力调度到电热耦合、从确定性优化到考虑不确定性的鲁棒模型、从离线优化到在线决策每一步都是在前一步的基础上加新约束、换新算法、扩新场景。Matlab给了我们一个可以快速验证思路的平台而真正有价值的是建模的思维方式——看清系统里哪些因素耦合、哪些约束是核心、哪些参数是可调的。这个思维方式放在任何综合能源系统项目里都通用。