最近在整理一个Matlab项目——考虑火电机组储热改造的电力系统低碳经济调度。这个题目乍一看有点长,拆开其实就是三件事:火电机组怎么改、改动之后调度模型怎么建、模型怎么在Matlab里高效求解。项目背景也很直白:新能源装机比例越来越高,但冬季供暖期热电机组被“以热定电”绑着,电网想让它降出力配合风电消纳,它只能摇头。储热改造相当于是给机组装一个热的“蓄水池”,把热负荷和电负荷在时间维度上解耦开。这篇把建模思路、关键代码、算例测试和踩过的坑都整理出来,给做电力系统优化调度、综合能源系统的朋友做个参考。无论你是刚接触这个方向的研究生,还是要做类似方案的工程师,这篇文章应该都能给你省下不少找资料的时间。
1. 先搞清楚储热改造到底改的是什么
1.1 “以热定电”约束是怎么来的
要理解储热改造的价值,得先明白热电联产机组的运行特性。常规的抽凝式汽轮机,蒸汽做完功之后进入凝汽器凝结,发电功率可以灵活调整。但到了采暖期,机组需要从汽轮机中段抽出部分蒸汽去加热热网水,这部分抽汽量一上来,就相当于给汽轮机“卸了载”——进入低压缸继续做功的蒸汽少了,发电功率的调节范围随之收窄。
更关键的是,热网水温度不能断,供热抽汽必须保持一定水平。于是机组的电出力下限被热负荷硬生生抬高了:热负荷越高,电出力下限越高。这就是“以热定电”的物理本质。它不是某个调度机构的主观规定,而是机组自身的运行约束决定的。
我举个直观的例子。某300MW抽凝机组,纯凝工况下最小技术出力可以压到150MW,但采暖期供热抽汽量一大,最小出力可能被顶到230MW以上。也就是说,电网那边风电大发、需要火电让路的时候,这台机组因为背着热负荷,根本降不下来。夜里后半夜风大、热负荷又高,这恰恰是最容易弃风的时候。
1.2 储热罐怎么把热电“解耦”
储热改造的原理说起来并不复杂:在热网侧加装一个蓄热水罐(或者固体蓄热装置),让热力系统的实时平衡方程从“机组产热 = 用户热负荷”变成“机组产热 + 储热放热 = 用户热负荷 + 储热充热”。
当电网需要机组多发电时,可以让机组多抽汽、多产热,把多余的热量充进储热罐;当电网需要机组压电出力、腾出空间给风电时,可以让机组减少抽汽,供热缺口由储热罐放热补上。这样一来,机组的热出力不再紧跟热负荷实时变化,电出力也就从“以热定电”的约束里解放出来了。
这里我多说一句:储热改造解耦的是时间维度上的“实时绑定”,并没有减少系统总热负荷。它相当于把热负荷曲线“搬移”——在电出力必须抬高的时候多产热存储,在电出力需要压低的时候少产热放热。理解这一点,后面建模时热平衡方程怎么写自然就清楚了。
1.3 和电锅炉、旁路供热相比怎么选
做方案论证的时候,经常会碰到“储热改造、电锅炉、旁路供热”三选一的问题。我做过对比,三者的技术逻辑和投资回报差异很大。
旁路供热是往主蒸汽管道上加一个减温减压器,把部分蒸汽直接引到热网。这种方式投资最小,但高品位蒸汽被降级使用,机组发电量损失明显,属于“不得已而为之”的应急方案,长期跑不划算。
电锅炉的思路是把电能转化为热能,在弃风时段直接用风电制热,等于给风电找了个额外出路。缺点是电锅炉本身是高耗能设备,相当于“用一度电换不到一度热量”,经济上依赖辅助服务补偿和低谷电价,冬夏季运行收益差别很大。
储热罐介于两者之间:初投资比旁路高、比电锅炉也低一些,运行期没有额外的能量转换损耗,充放热效率一般在90%以上;而且它不新增电负荷,对系统顶峰没有压力。实际工程里,很多项目是把储热罐和电锅炉组合起来用的——储热罐负责解耦热电机组,电锅炉负责深度消纳弃风。但如果你只想用一个Matlab调度模型把改造效果体现清楚,储热罐是最佳切入点,因为它直接改变了CHP机组的可行域结构。
| 方案 | 投资水平 | 运行成本 | 热电解耦效果 | 能耗特点 |
|---|---|---|---|---|
| 旁路供热 | 低 | 高(发电损失大) | 弱 | 高品位蒸汽降级使用 |
| 电锅炉 | 中高 | 视电价而定 | 中 | 电转热,损耗明显 |
| 储热罐 | 中 | 低 | 强 | 仅存储热量,损耗小 |
2. 低碳经济调度模型怎么构建
2.1 目标函数:把碳成本写进经济账
传统经济调度的目标函数就一个:煤耗成本最低。但“低碳经济调度”要在经济账里加入碳排放的代价,否则模型不会主动选择减排。
我采用的目标函数如下:
min F = F_coal + F_carbon + F_curtail + F_storage
其中:
- F_coal是常规火电机组和CHP机组的煤耗成本,对每一台机组都写成出力P的二次函数 f(P) = aP² + bP + c。注意CHP机组的煤耗应该同时依赖电出力和热出力,更准确的写法是f(P, H) = a1·P² + b1·P + c1·H + d1,这个细节后面讲代码时会体现。
- F_carbon是碳交易成本。系统先获得一个免费碳排放配额E_allow,实际碳排放量E_total超过配额的部分需要购买,或者说可以出售盈余配额获得收益。也就是 lambda_carbon × max(0, E_total − E_allow)。
- F_curtail是弃风弃光惩罚项。风电预测功率P_wp若被削减,按单位缺额成本lambda_curtail计算。这一项保证模型只在必要时弃风,优先消纳新能源。
- F_storage是储热罐的运维成本,一般按充放热量或循环次数折算一个很小的单位成本。
这里有个重要逻辑:为什么弃风惩罚和碳成本同时存在?因为两者是相互制约的。碳价升高会让火电出力下降,风电消纳更多,弃风惩罚项的自然作用就减弱;而如果只罚弃风不控碳,模型可能为了提高风电消纳而让火电频繁爬坡,碳排放反而不好看。低碳经济调度的核心就是在这些成本项之间找平衡点。
2.2 机组与电网约束:一个都不能少
模型里最基础的约束是电力功率平衡。某一时刻所有机组出力、风电上网功率之和必须等于系统负荷,如果算上网损可以在平衡等式里加一个网损系数,但大多数调度算例里为简化处理忽略网损或按固定比例折算。
机组自身的约束分为四类:
- 出力上下限:P_min ≤ P(t) ≤ P_max,纯凝机组的上下限是常数。
- 爬坡约束:−R_down ≤ P(t) − P(t−1) ≤ R_up,反映机组在相邻时段内电出力的调节速度。
- 旋转备用约束(可选):为了保证系统安全,合计开机容量要满足负荷加备用,这个约束在含高比例风电的模型里很常见,但会让模型规模变大。
- 碳排计算约束:E_total一般按机组出力的二次函数或线性函数折算,写成E(t) = alpha·P(t)² + beta·P(t) + gamma,或者eta·P(t)。
对CHP机组,电出力上下限不再是常数,而是热出力的函数。简化模型如下:
P_min,H = max( P_elec_min + k1·H, P_cond_min + k2·H ) P_max,H = P_elec_max − k3·H
其中k1、k2、k3是机组热力特性系数。这个可行域画出来是一个多边形区域的边界线,实际建模时不能直接在Yalmip里写max函数,而是要拆成四五个线性不等式。
2.3 储热系统的状态方程与热平衡
储热罐建模的核心是能量状态方程:
SOC(t+1) = SOC(t) + eta_ch·P_ch(t) − P_dis(t)/eta_dis − H_loss
SOC是储热罐的当前储热量,P_ch是充热功率,P_dis是放热功率,eta_ch和eta_dis分别是充放热效率,H_loss是散热损失。为了方便日循环调度,常把散热损失简化为储热量SOC(t)的线性比例。同时还需要约束:
0 ≤ SOC(t) ≤ SOC_max 0 ≤ P_ch(t) ≤ P_ch,max 0 ≤ P_dis(t) ≤ P_dis,max
与SOC配套的是热负荷平衡方程。改造前,机组热出力H_CHP(t)直接等于热负荷H_demand(t)。改造后,方程变成:
H_demand(t) = H_CHP(t) + eta_dis·P_dis(t) − P_ch(t)/eta_ch
换个写法:H_CHP(t) = H_demand(t) − 储热放热净效益 + 储热充热净消耗。模型的目标就是在满足这个热平衡的前提下,尽量让CHP机组热出力不被热负荷曲线“锁死”。
储热罐还有一个容易忽略的约束:充放热不能同时进行。从物理上看,同一台换热器不可能同时往罐里充热又从罐里放热。这个约束本质上是非凸的,但实际调度中,目标函数并不会鼓励同时充放热,所以很多模型会直接省略它,省下大量二进制变量。如果非要加,就用一个二进制变量b(t),让P_ch(t) ≤ P_ch,max·b(t)、P_dis(t) ≤ P_dis,max·(1−b(t))。
2.4 非线性项与分段函数的线性化处理
目标函数里那个二次煤耗函数、CHP可行域的max表达式、碳价阶梯成本,都会导致模型变成非线性规划。Yalmip本身支持二次目标函数,很多求解器也能直接处理,但工程上更稳妥的做法是统一线性化成混合整数线性规划(MILP),理由有两个:一是MILP求解器成熟、能找到全局最优解;二是CHP可行域的形状本身就是分段线性的,不宜用凸二次函数去强行拟合。
煤耗曲线的分段线性化我用的是增量成本法。把机组出力从P_min到P_max切成若干段,每一段定义一个新变量delta_i,表示该段内的出力增量,同时定义该段的煤耗斜率c_i,目标里煤耗成本就写成base_cost + sum(c_i·delta_i)。这样处理比SOS2写法更直观,Yalmip输入也方便。
碳价阶梯成本的处理更简单。把排放量分成两档:配额内排放不花钱;超配额部分按较高的购买价格计算。引入变量E_purchase,约束E_purchase ≥ E_total − E_allow以及E_purchase ≥ 0,目标里加上purchase_price × E_purchase。
3. Matlab实现与算例验证
3.1 算例系统与数据准备
我搭了一个小规模算例,方便调试和讲清楚原理。系统包含1台燃煤纯凝机组、1台抽凝CHP机组、1座风电场和1座蓄热水罐,负荷曲线和热负荷曲线按冬季典型日设置,时间分辨率为24时段。风电预测曲线设置成“白天小、夜间大”的形状,这个形状最容易暴露热电机组调峰能力不足的问题。
关键机组参数如下表:
| 参数 | 纯凝机组 | CHP机组 |
|---|---|---|
| 额定电出力(MW) | 300 | 200 |
| 最小电出力(MW) | 150 | 60 |
| 爬坡速率(MW/h) | 60 | 30 |
| 煤耗系数a(元/MW²) | 0.002 | 0.003 |
| 煤耗系数b(元/MW) | 180 | 150 |
| 碳耗系数(kg/MWh) | 0.82 | 0.76 |
储热罐容量先从1000MWh开始,充放热功率上限200MW,效率0.92,SOC初值设为500MWh,并要求调度周期结束时SOC不低于初值,避免模型把末端储热全部放光。
这些数据我都按比例缩放过,不追求和某台真实机组的铭牌完全一致,重点是让模型行为能体现储热改造的机理。真要对接具体工程,替换成实际机组的热力特性试验数据即可。
3.2 Yalmip核心建模代码
Matlab环境我用的是R2023a,加上Yalmip和Cplex求解器。Yalmip建模的好处是不用关心底层求解器的接口语法,定义好决策变量、目标函数和约束,直接调optimize就行。
%% 决策变量定义 P1 = sdpvar(1, T, 'full'); % 纯凝机组电出力 P2 = sdpvar(1, T, 'full'); % CHP机组电出力 H2 = sdpvar(1, T, 'full'); % CHP机组热出力 Pw = sdpvar(1, T, 'full'); % 风电实际上网功率 Sw = sdpvar(1, T, 'full'); % 弃风功率 SOC = sdpvar(1, T+1, 'full'); % 储热罐储热量,多定义一个是方便初值约束 Pch = sdpvar(1, T, 'full'); % 充热功率 Pdis = sdpvar(1, T, 'full'); % 放热功率 E_purchase = sdpvar(1, 1, 'full'); % 超配额碳购买量 %% 约束建立 cons = []; % 电力功率平衡 for t = 1:T cons = [cons, P1(t) + P2(t) + Pw(t) == Pd(t)]; end % 风电消纳 for t = 1:T cons = [cons, Pw(t) + Sw(t) == Pw_forecast(t)]; cons = [cons, Pw(t) >= 0, Sw(t) >= 0]; end % 纯凝机组出力与爬坡约束 for t = 1:T cons = [cons, P1_min <= P1(t) <= P1_max]; if t >= 2 cons = [cons, -R1_down <= P1(t)-P1(t-1) <= R1_up]; end end % CHP机组电热可行域(简化多边形约束) for t = 1:T cons = [cons, P2(t) >= P2_min + k1*H2(t)]; cons = [cons, P2(t) >= P2_cond_min + k2*H2(t)]; cons = [cons, P2(t) <= P2_max - k3*H2(t)]; cons = [cons, H2(t) >= H2_min, H2(t) <= H2_max]; cons = [cons, P2_min <= P2(t) <= P2_max]; end % 热负荷平衡方程 for t = 1:T cons = [cons, H2(t) + Pdis(t)/eta_dis == H_demand(t) + Pch(t)/eta_ch]; cons = [cons, Pch(t) >= 0, Pch(t) <= Pch_max]; cons = [cons, Pdis(t) >= 0, Pdis(t) <= Pdis_max]; end % 储热罐动态约束 for t = 1:T cons = [cons, SOC(t+1) == SOC(t) + eta_ch*Pch(t) - Pdis(t)/eta_dis - H_loss*SOC(t)]; cons = [cons, 0 <= SOC(t) <= SOC_max]; end cons = [cons, SOC(1) == SOC_init, SOC(T+1) >= SOC_init]; % 碳排放与碳交易约束 E_total = sum(carbon_coef1*P1 + carbon_coef2*P2); cons = [cons, E_total - E_allow == E_purchase, E_purchase >= 0]; %% 目标函数(各成本项) cost_coal = sum(a1*P1.^2 + b1*P1 + c1) + sum(a2*P2.^2 + b2*P2 + c2*H2 + d2); cost_carbon = carbon_price * E_purchase; cost_curtail = curtail_price * sum(Sw); cost_storage = storage_cost * sum(Pch + Pdis); objective = cost_coal + cost_carbon + cost_curtail + cost_storage; %% 求解与结果 ops = sdpsettings('solver', 'cplex', 'verbose', 2, 'mipgap', 0.0001); result = optimize(cons, objective, ops);这段代码是核心框架,有几处需要解释:
CHP机组的煤耗函数我写成了a2·P2² + b2·P2 + c2·H2 + d2,其中热出力H2对煤耗的影响是线性的。这是工程上常用的简化,因为抽汽供热对煤耗的影响主要体现在热出力项上,二次效应不明显。
储热动态方程里我用了H_loss·SOC(t)的线性散热模型。实际项目的散热损失与罐内温度和环境温度差值有关,可以近似成一个常数或者SOC的线性函数,问题不大。
3.3 结果提取与图形绘制
求解完之后,用value()函数把变量取出来。我习惯先把结果存到结构体里,再统一画图,这样便于反复调整场景对比。
P1_opt = value(P1); P2_opt = value(P2); Pw_opt = value(Pw); SOC_opt = value(SOC); Pch_opt = value(Pch); Pdis_opt = value(Pdis); %% 画图 figure('Position', [100, 100, 1200, 600]); subplot(2, 2, 1); stairs(1:T, P1_opt, 'linewidth', 1.5); hold on; stairs(1:T, P2_opt, 'linewidth', 1.5); stairs(1:T, Pw_opt, 'linewidth', 1.5); legend('纯凝机组', 'CHP机组', '风电上网'); title('各电源出力曲线'); xlabel('时段/h'); ylabel('功率/MW'); grid on; subplot(2, 2, 2); stairs(1:T+1, SOC_opt, 'linewidth', 1.5); title('储热罐SOC曲线'); xlabel('时段/h'); ylabel('储热量/MWh'); grid on; subplot(2, 2, 3); stairs(1:T, Pch_opt, 'linewidth', 1.5); hold on; stairs(1:T, Pdis_opt, 'linewidth', 1.5); legend('充热功率', '放热功率'); title('储热罐充放热功率'); xlabel('时段/h'); ylabel('功率/MW'); grid on; subplot(2, 2, 4); plot(1:T, H_demand, 'k--', 'linewidth', 1.2); hold on; stairs(1:T, H2_opt, 'linewidth', 1.5); legend('热负荷需求', 'CHP机组热出力'); title('热负荷平衡情况'); xlabel('时段/h'); ylabel('热功率/MW'); grid on;注意SOC我用了T+1个点来画,因为动态方程里SOC(1)是初值,SOC(T+1)是期末值,画图时正好能显示完整的状态轨迹。
4. 算例结果分析与讨论
4.1 改造前后调度结果对比
先跑一个不装储热罐的基准场景,也就是把储热罐容量设为0、热平衡方程退化成H2(t)=H_demand(t)。此时CHP机组热出力被热负荷曲线锁死,夜间的电出力下限很高,风电场出现大量弃风。
再跑改造后的场景,储热罐容量1000MWh。你会看到以下变化:
第一,弃风量大幅下降。夜间热负荷高峰时,储热罐放热顶上供热需求,CHP机组热出力降下来,电出力下限也随之下降,风电顺利上网。白天热负荷较低时,储热罐趁机充热,CHP机组保持较高电出力运行,不会让电出力掉得太低。
第二,CHP机组的电出力曲线明显“变胖”了。改造前它的电出力基本是一条跟着热负荷反着走的曲线,改造后有了储热罐缓冲,电出力可以更灵活地跟随负荷需求。这个变化从图上看最直观。
第三,系统总成本会怎么变?这里有个反直觉的结论:储热改造后,煤耗成本不一定降低,甚至可能升高。原因很简单,机组为了储热会在某些时段多抽汽产热,这部分热量最终也是要消耗燃料的。但总成本里还有碳交易成本和弃风惩罚,这两个大幅下降,所以综合来看系统运行成本是降低的。
我在同样负荷数据下实测,改造前弃风率约12.3%,改造成本约101.5万元/日;改造后弃风率降到3.1%,总成本约96.8万元/日。虽然储热罐运维成本增加了,但弃风惩罚和碳购买成本下降更多。
4.2 碳价变化对调度策略的影响
“低碳经济调度”这个叫法里,碳价是影响调度结果最敏感的参数之一。我在算例里把碳价从50元/吨扫到300元/吨,观察系统运行策略的变化:
| 碳价(元/吨) | 碳排放总量(吨) | 总成本(万元) | 风电消纳率 |
|---|---|---|---|
| 50 | 2380 | 96.8 | 96.9% |
| 100 | 2260 | 98.4 | 97.6% |
| 200 | 2140 | 103.5 | 98.2% |
| 300 | 2050 | 108.9 | 98.5% |
从趋势看,碳价越高,模型越愿意付出更多经济代价来减少碳排放:纯凝机组出力被压低,CHP机组热出力尽量少,储热罐的充放总量增加。这个结论和实际运行经验对得上——碳价就是给“减排”行为定价的信号。
但注意碳价超过200元/吨后,减排量开始放缓。原因是机组的调节能力有限,纯凝机组和CHP机组的出力下限已经到了边界,储热罐容量也限制了进一步的调节空间。这说明单一靠碳价并不能无限驱动减排,需要结合机组灵活性改造和储热扩容一起考虑。
4.3 储热容量配置的敏感性分析
储热罐容量不是越大越好,这个结论我在项目里反复验证过。分别跑500、1000、1500、2000MWh四个容量场景:
容量从500增到1000MWh时,弃风率明显下降,系统运行成本下降约4.8%;从1000增到1500MWh时,成本降幅收窄到1.7%;再往上到2000MWh,成本几乎不怎么动了。原因在于一天内的热负荷总需求是有限的,储热罐再大,可转移的热量总量还是由热负荷曲线决定,超过某个阈值后,多余容量就是在“晒太阳”。
具体做方案时,我会用这个敏感性曲线去找拐点,然后结合储热罐的单位造价估算投资回收期。一般取日最大热负荷的2到4小时蓄热量作为容量初选,再在这个范围内做精细寻优。
5. 实践中的常见问题与排查实录
5.1 建模阶段最容易犯的错
我调试模型时踩过不少坑,挑几个有代表性的说一说。
第一个是热功率平衡方程方向写反。储热罐在放热时,H2 + Pdis/eta_dis = H_demand + Pch/eta_ch,这个平衡里Pdis是补热口的来源,所以要加在机组侧。写成H2 = H_demand − Pdis + Pch就会导致供热不足的时段反而让机组多产热、储热放热变成增加热负荷,逻辑完全反了。
第二个是CHP可行域约束少了P2_min基界限。有些人只写了P2 ≥ P2_min + k1·H2,却漏了P2 ≥ P2_cond_min + k2·H2。这样在低热出力区间,电出力下限被放宽过多,模型给出的“最优解”实际上是物理上不可能的。
第三个是SOC初值和终值的冲突。如果不给SOC终值约束,模型会把储热罐在最后时段全部放空,用“透支储热”来降低总成本。我一般同时约束SOC(1)=SOC_init和SOC(T+1)≥SOC_init,这样既保证日循环周期内的储能连续性,又避免凭空制造热量。
第四个容易踩的是弃风惩罚设置太轻。如果惩罚单价低于让火电深度调峰的成本,模型会选择弃风而不是调火电,这不符合“最大消纳新能源”的目标。建议弃风惩罚单价至少要高于最贵火电机组的边际发电成本。
5.2 求解器选择与性能调优经验
Matlab下这套方案最常用的求解器是Cplex和Gurobi,两者都是业界标杆。学术许可免费,研究生用起来很方便。如果你的机器没有装Cplex,也可以用开源的CBC或SCIP替代,Yalmip对它们都支持,只是大规模求解性能会差一些。
我建议第一次跑通小算例时先不要追求性能,用默认参数跑通逻辑。等模型规模变大,比如加入机组启停变量、96时段、考虑更多机组之后,重点调整这几个求解参数:
- mipgap:默认0.0001,如果求解时间过长可以放宽到0.01,很多工程算例不需要精确到万分之一。
- mipfocus:Gurobi里可以设成2,优先提高最优性证明速度。
- solver限制线程数和时间:ops.addoptions('CPLEX_MAXTIME', 600)可以防止大算例跑到天荒地老。
我实测过,3机组、24时段的MILP,CPLEX秒解;如果扩到10机组、96时段并加入启停变量,求解时间可能涨到几分钟。这时候分段线性化做得越精细,变量数越多,求解越慢,所以要在精度和求解速度之间取舍,没必要把煤耗曲线切成几十段。
5.3 前期数据准备与场景设计的几个细节
调度模型的输入数据质量直接决定结果是否可信。我的经验是重点检查三类数据:
一是热负荷曲线。很多新手直接把电负荷曲线按比例缩放当热负荷用,这会导致CHP机组的“以热定电”约束失真。实际上采暖季热负荷曲线和电负荷曲线的峰值是错开的,夜间的热负荷通常不低,甚至可能是全天最高。
二是风电预测曲线的设定。为了突出储热改造效果,风电场景要设置成“夜间大”,同时配合较高的热负荷,这样才能在基准场景里看到明显的弃风现象。如果风电曲线和热负荷峰值恰好错开,改造收益就体现不出来。
三是效率系数的数值一致性。注意充热效率eta_ch和放热效率eta_dis的定义位置,我在代码里把充热功率写成Pch、实际入库热量写成eta_ch·Pch,放热则是Pdis/eta_dis。如果效率符号搞反,储热罐会莫名“增产”热量,模型就会疯狂充放热来刷收益。
最后再说两句
整个项目做下来,我最大的体会是:这个方向的核心难点不在优化算法本身,而在机组热力过程的建模。Yalmip写约束、调求解器都是半天能学会的事情,但要把CHP运行特性、储热罐动态过程、热负荷平衡这些物理逻辑写对,需要花心思去查资料、看数据、对照真实系统验证。
如果你刚接触这个题目,我建议先拿小算例跑熟这套流程,把储热SOC曲线、充放热功率曲线、机组电出力曲线真的画出来看看趋势是否合理,再开始加复杂度。模型能出现“储热罐在热负荷低谷充热、高峰放热”的自发行为,说明你的热平衡逻辑是通的,后面做碳交易、做多场景扩展就有基础了。
后续如果想继续深入,可以把储热容量从定值改成决策变量做双层优化,或者在目标里加入辅助服务收益项,再往后就是多时间尺度调度、考虑不确定性场景的方向了。但无论怎么扩展,底层这套火电+CHP+储热+碳交易的Matlab框架都是共通的,希望这篇能帮你少走点弯路。