
1. 项目拆解碳排放流到底在算什么1.1 碳排放流方法的提出背景与核心矛盾做电力系统相关工作的朋友应该都有感受双碳目标提出来之后“碳排放核算”成了绕不开的话题。但电力系统有一个天然的特殊性电从发电厂出来经过输电网、配电网最后才到用户手里。中间经过那么多节点、那么多条线路到底哪个用户应该为那一台燃煤机组的排放买单这正是碳排放流方法要解决的问题。传统的核算方式很简单粗暴按发电量把碳排放全部分摊给本地的用电户或者按用电量乘以一个区域平均排放因子。这种做法在单一电网、单一发电结构下勉强能用但一旦涉及跨区送电、新能源占比提升、多市场主体交易问题就来了。比如某地用电负荷很高但本地清洁能源占比也高如果还按区域平均排放因子算就会把这个地方的“绿色属性”抹杀掉清洁电力的减排价值完全体现不出来。碳排放流方法的核心思路其实非常巧妙既然电能从发电机流向负荷的过程可以用潮流计算精确描述那么碳排放作为发电过程的“副产品”在物理上也是依附于电能一起流动的。只要给每台发电机组一个初始碳排放强度然后让这个“碳”顺着潮流网络流动就能把发电侧的碳排放责任精确地分摊到每一个节点、每一条支路、每一个负荷上。这就是所谓的“碳排放流”。1.2 碳流率、碳势、碳流密度三个核心概念刚接触碳排放流的人常常被一堆名词搞晕。我当时也是反复看了几篇EI论文才理清楚其实核心概念就三个。第一个是碳流率单位是tCO2/h或者kgCO2/h。它表示单位时间内流过某条支路或注入某个节点的二氧化碳量。你可以把它理解成“碳的潮流功率”跟电力系统里的有功功率P是同一个形态的量只是载体从电能变成了碳。第二个是碳势这是整个方法里最重要的概念。节点的碳势定义为该节点上单位电量所对应的碳排放量单位是kgCO2/kWh。它反映的是“在这个节点用电平均每度电对应多少碳”。不同节点的碳势不同这正是碳排放流方法能体现空间差异性的关键。第三个是支路碳流密度它描述的是某条支路上单位电量所承载的碳排放量。这里有一个比较重要的性质在稳态运行下一条支路的碳流密度等于其送端节点的碳势。也就是说碳流跟着有功功率从节点A流向节点B那么这条支路上“每一度电带多少碳”完全由送端节点决定。这几个量之间的关系构成了整个算法的基础。1.3 基于功率分布的分摊逻辑碳排放流的另一个优点是它完全复用潮流计算的结果。电力系统本来就要做潮流计算来获得各个节点电压、相角和各条支路的功率分布碳排放流不需要新增任何测量设备只需要在潮流结果的基础上做一次“碳的追踪”。具体来说它遵循一个基本假设流入某个节点的所有有功功率是完全混合的也就是说来自不同发电机的电能和它们携带的碳在该节点处均匀混合后再流向各条出线和本地负荷。这个假设很像化学反应里的完全混合模型虽然真实电网中电能并不会真的“混合”但在稳态分析框架下这种基于比例分摊的逻辑在学术和工程上都是被普遍接受的。基于这个假设计算过程就可以用一套线性方程组描述每个节点的碳势等于流入该节点的碳流率之和除以该节点的总注入有功功率。而流入节点的碳流率又由支路功率和送端节点碳势决定。这样一来整个网络就形成了一个线性系统节点碳势是这个系统的解。只要电力潮流分布已知碳势就能唯一确定。这个思路最大的工程价值在于不需要额外建模不需要改造电网不需要高频采样只靠已有的SCADA数据和调度系统里的潮流数据就能算出全网的碳排放分布。对双碳目标下的碳排放核算、碳追踪、绿色电力认证这些场景来说简直是低成本高收益的方案。2. 计算方法原理从潮流结果到碳流矩阵2.1 为什么必须先做潮流计算碳排放流的输入本质上就是一份完整的潮流断面数据。节点注入功率、支路潮流、网损、负荷分布这些数据全都来自潮流计算结果。我见过一些初学者试图跳过潮流计算直接用负荷数据“估”一个碳流分布出来结果完全对不上。原因很简单碳排放流的分配比例依赖于有功功率在每个节点的流向和大小如果这个基础数据是错的后面所有碳势、碳流密度都失去了物理意义。在IEEE 14节点系统的复现中最稳妥的做法是直接用牛拉法或者PQ分解法做一次常规潮流计算。考虑到IEEE 14节点规模很小节点数只有14个直接用牛拉法就可以了迭代次数少、收敛快也不用担心大电网里那种收敛性灾难。具体来说潮流计算需要给出的结果包括各节点的电压幅值和相角各条支路的有功功率包括送端和受端各节点的注入功率平衡节点的有功出力全网的总网损。有了这些碳排放流才有可能“依附”上去。我个人在实际操作中习惯先把潮流结果打印出来手动核验几个关键节点的功率平衡关系确认潮流结果没问题了再做碳流计算。这一步虽然多花几分钟但能避免后面排查问题时的各种怀疑人生。2.2 核心公式组与计算流程碳排放流的计算过程可以用下面这套逻辑串起来。第一步定义发电机节点的碳排放强度向量 E_G单位是kgCO2/kWh。它的物理含义是每台发电机每发一度电产生的碳排放。对于火电机组一般按供电煤耗和排放因子折算对于风、光等新能源机组碳排放强度通常取0。第二步构造注入功率矩阵和支路潮流分布矩阵。节点注入功率矩阵 P_N 是一个对角阵对角线元素是每个节点的净注入有功功率等于该节点上发电机出力减去负荷功率。对于纯负荷节点注入功率是负值对于既有发电机又有负荷的节点则是两者的差值。支路潮流分布矩阵 P_B 的维度是节点数乘支路数每列对应一条支路其行索引为该支路的送端节点元素值为对应支路的有功功率。第三步求解节点碳势向量 E_N。核心方程是[ E_N (P_N - P_B \cdot U^T)^{-1} \cdot (P_G \cdot E_G) ]其中 $P_G$ 是对角阵对角线元素为各发电机节点注入系统的有功功率$U$ 是节点-支路关联矩阵。这个方程的物理含义是节点碳势等于流入该节点的碳流率之和除以该节点的总注入功率。由于 $E_N$ 同时出现在方程两边通过 $P_B \cdot E_N$ 项传递因此需要求解一个线性方程组。第四步根据节点碳势求支路碳流密度和支路碳流率。支路碳流密度等于送端节点碳势该支路的碳流率等于支路有功功率乘以该密度。第五步求出各节点的负荷碳流率。节点负荷碳流率等于节点负荷有功功率乘以该节点碳势。这一步的结果直接回答了“这个用户的用电对应了多少碳排放”的问题。第六步计算网络的总碳排放量验证结果。总排放应该等于所有发电机碳排放强度乘以有功出力的总和也可以通过所有负荷碳流率之和加上网损对应的碳排放来校核。两次计算的结果如果偏差较大说明中间步骤有误。2.3 方法对比碳排放流与平均排放因子的差别很多人会问为什么不用简单的平均排放因子法我做一个对比你就明白了。对比项平均排放因子法碳排放流法空间分辨率全网统一无法区分节点差异每个节点一个碳势空间差异清晰可见时间分辨率通常按年/月平均可随潮流断面逐时计算数据要求只需要总发电量和总排放量需要完整的潮流断面数据对清洁能源的体现平均化无法体现本地清洁电力的减排价值清洁能源注入的节点碳势明显降低能精确体现计算复杂度极低中等需要求解线性方程组在做IEEE 14节点算例的时候你会发现一个非常有意思的现象同样一个电网如果所有负荷都按全网平均排放因子算每个节点的碳排放责任是完全一样的但用碳排放流方法算出来靠近燃煤机组的节点碳势明显偏高而靠近风电或者水电的节点碳势显著偏低。这种差异性正是碳市场、绿电交易、碳追踪这些场景里最需要的信息。3. IEEE 14节点系统数据集深度解析3.1 这个标准算例的结构特点IEEE 14节点系统是电力系统分析里最经典的小型测试系统之一几乎所有研究输电网的论文都用它做过验证。它包含14个节点、20条支路含变压器支路、5台同步发电机分布在节点1、2、3、6、8其中节点1是平衡节点。系统电压等级有132kV和33kV两个层级通过变压器连接。这个系统虽然规模不大但麻雀虽小五脏俱全。它有环形网络结构有多台发电机并列运行有负荷分布在不同区域还有多条变压器支路。对于碳排放流研究来说它足够用来展示方法的核心特征不同发电机的排放强度不同不同节点的碳势也会随之产生明显差异。同时它的规模又很小Matlab跑起来几乎是秒出结果非常适合用来做理论验证和论文复现。3.2 数据准备母线、支路和发电机参数在Matlab里复现这个算例首先要把系统数据准备好。该买的数据还是得买该下载的还是得下载IEEE标准数据在Matpower等工具里自带直接调用就行。如果不想用Matpower也可以手动录入数据核心数据包含三个部分母线数据包括母线编号、类型PQ/PV/平衡、有功负荷、无功负荷、电压幅值初值等。IEEE 14节点系统的总负荷约为259MW主要集中在节点2、3、4、5、9、13、14等。支路数据包括支路编号、首端节点、末端节点、电阻、电抗、对地电纳、变比等。其中有几条变压器支路如4-7、4-9、5-6处理时要注意变比和变压器支路的有功功率方向。发电机数据包括发电机所在节点、有功出力、无功出力、电压幅值设定值等。IEEE 14节点的发电机总出力约272MW其中有功出力最高的是节点1的平衡机承担了系统的大部分功率平衡任务。在碳排放流计算时还要给每台发电机定义一个碳排放强度参数。常规做法是节点1设为燃煤机组碳排放强度取值0.9kgCO2/kWh左右节点2设为燃气机组取值0.4kgCO2/kWh节点3设为水电或新能源取值0节点6、8也可以按新能源处理取值0。这样一来系统里同时包含高碳机组、低碳机组和零碳机组碳流分布会非常明显也方便读者理解结果。3.3 为什么选IEEE 14节点做复现验证用IEEE 14节点做碳排放流的复现在学术和工程上都有一个重要的好处它的数据公开、结果可验证。EI期刊审稿人看到这个算例基本不需要额外解释系统结构因为这是业内公认的标准测试系统。而且这个系统的碳排放流计算结果在很多论文里都有发表算出来的碳势分布规律是可以交叉验证的。从我个人的经验来看第一次复现碳排放流算法不建议直接上IEEE 118节点那种大系统。因为算法本身的逻辑需要先“跑通”在14节点系统上你可以非常直观地看到每条支路、每个节点的碳流走向方便校对每一步计算是否正确。等到逻辑完全理清了再往更大规模的系统上迁移只是数据规模的变化算法结构并不需要改动。4. Matlab代码实现过程从零到出图4.1 代码整体结构与模块划分我在实现这个项目时代码结构分成五个模块数据输入模块、潮流计算模块、碳排放流核心计算模块、结果输出模块和可视化模块。文件组织方式很简单主程序一个脚本每个模块用函数封装这样后续要换系统数据或者修改参数只需要改动对应的函数即可。主程序的流程如下% 主脚本IEEE14节点碳排放流计算 clc; clear; close all; % 1. 输入系统数据 [bus, branch, gen] ieee14_data(); % 2. 潮流计算 [V, theta, P_branch, P_inj] power_flow(bus, branch, gen); % 3. 碳排放流计算 E_G [0.9; 0.4; 0; 0; 0]; % 各发电机碳排放强度 kgCO2/kWh [E_N, R_branch, R_load] carbon_flow(bus, branch, gen, V, theta, E_G); % 4. 输出结果 print_results(E_N, R_branch, R_load); % 5. 可视化 plot_carbon_results(bus, E_N, R_branch);4.2 潮流计算模块的实现要点潮流计算是整个碳排放流的基础这一步不能出错。在Matlab里最简单的方式是直接调用Matpower的runpf函数几行代码就能拿到完整的潮流结果。但如果不想引入额外工具箱也可以自己写一个牛拉法潮流程序逻辑也不复杂。我建议初学者自己写一遍牛拉法因为这样对电力系统的理解会更扎实而且后续如果想要做更深入的研究比如把碳排放流嵌入最优潮流有自写的潮流程序会更灵活。牛拉法的关键步骤是形成节点导纳矩阵 Y初始化电压幅值和相角计算有功和无功不平衡量形成雅可比矩阵求解修正方程更新电压幅值和相角迭代至收敛。function [V, theta, P_branch, P_inj] power_flow(bus, branch, gen) % 形成导纳矩阵 Y form_Y(bus, branch); % 初始化 V0 bus(:, 8); % 电压幅值初值 theta0 bus(:, 9) * pi / 180; % 相角初值 % 牛拉法迭代 for iter 1:30 % 计算注入功率 [P_calc, Q_calc] calc_injection(V0, theta0, Y); % 构造不平衡量 [dP, dQ] mismatch(bus, gen, P_calc, Q_calc); % 形成雅可比矩阵并求解 J jacobian(V0, theta0, Y); dTheta_dV J \ [dP; dQ]; % 更新状态变量 theta0 theta0 dTheta_dV(1:length(theta0)); V0 V0 dTheta_dV(length(theta0)1:end); % 判断是否收敛 if max(abs([dP; dQ])) 1e-6 break; end end % 计算支路潮流 P_branch calc_branch_power(V0, theta0, branch, Y); P_inj P_calc; V V0; theta theta0; end这里需要注意的一个坑是雅可比矩阵的维度必须与系统中PV节点和PQ节点的数量匹配。IEEE 14节点系统中平衡节点不算在内其余节点需要区分PV和PQ。如果矩阵维度对不上Matlab会直接报维度错误。4.3 碳排放流核心计算模块碳排放流的核心计算模块比潮流模块简洁得多。关键是要正确构造几个矩阵。首先从潮流结果中提取节点注入有功功率 P_inj。这个是n维列向量n为节点数。其次构造发电机注入矩阵 P_G。它是一个n×n对角矩阵对角线上的元素是每个节点上发电机的有功出力。对于没有发电机的节点对应的对角元素为0。第三构造支路潮流分布矩阵 P_B。它是一个n×m矩阵m为支路数每一列对应一条支路该列在送端节点行上的元素为该支路有功功率其余元素为0。第四构造节点-支路关联矩阵 U。它是一个n×m矩阵每一列对应一条支路在送端节点为-1受端节点为1其余为0或者反过来取决于符号约定。有了这些矩阵计算碳势的核心代码就非常精简function [E_N, R_branch, R_load] carbon_flow(bus, branch, gen, V, theta, E_G) % 节点数 n size(bus, 1); m size(branch, 1); % 发电机出力和位置 P_G zeros(n, n); for k 1:size(gen, 1) bus_idx gen(k, 1); P_G(bus_idx, bus_idx) gen(k, 2); end % 节点注入功率含负荷 P_inj zeros(n, 1); for i 1:n P_inj(i) P_G(i, i) - bus(i, 3); % 发电机出力减负荷 end % 支路有功功率和关联矩阵 P_B zeros(n, m); U zeros(n, m); for k 1:m from branch(k, 1); to branch(k, 2); P_B(from, k) branch_power(k); U(from, k) -1; U(to, k) 1; end % 求解节点碳势 A diag(P_inj) - P_B * U; b P_G * E_G; E_N A \ b; % 支路碳流率 R_branch zeros(m, 1); for k 1:m from branch(k, 1); R_branch(k) P_B(from, k) * E_N(from); end % 负荷碳流率 R_load zeros(n, 1); for i 1:n R_load(i) bus(i, 3) * E_N(i); end end这里最关键的求解步骤就一行E_N A \ b。Matlab的矩阵左除运算符会自动选择合适的求解算法对于14节点这样的小系统速度完全不是问题。但要注意A矩阵在纯负荷节点上可能出现对角线元素接近0的情况导致矩阵奇异。这时候需要对节点注入功率做一个很小的修正或者妥善处理平衡节点的特殊情况。4.4 结果可视化和输出展示算完之后我喜欢用两个图来展示结果。第一个是柱状图展示每个节点的碳势值第二个是系统的地理接线图在节点位置标注碳势支路上标注碳流率这样整个网络的碳流分布一目了然。function plot_carbon_results(bus, E_N, R_branch) % 节点碳势柱状图 figure; bar(E_N); xlabel(节点编号); ylabel(节点碳势 (kgCO2/kWh)); title(IEEE 14节点系统各节点碳势); grid on; % 各节点负荷碳流率 figure; bar(R_load); xlabel(节点编号); ylabel(负荷碳流率 (tCO2/h)); title(各节点负荷碳排放流率); grid on; end在出了结果之后一定要做一个总排放量的守恒校验所有发电机的总碳排放量应该等于所有负荷的碳流率之和加上网络损耗对应的碳排放量。如果这个等式两边偏差超过0.1%说明计算过程中某个环节出了问题需要回头检查。5. 常见问题与排查技巧实录5.1 高频报错问题速查表在我自己复现这个项目以及帮别人排查的过程中遇到最多的是下面这几个问题。报错现象可能原因解决方法Matrix is singular to working precision节点注入功率矩阵奇异通常是因为负荷节点没有净注入功率检查P_inj的对角元素是否有零值必要时加入微小正数Dimensions of matrices being concatenated are not consistent雅可比矩阵维度与节点数不匹配检查PV、PQ节点数量确认dTheta和dV的维度与状态变量一致Out of memory系统规模大但迭代次数多矩阵存储过大IEEE 14节点基本不会出现注意清理循环中间变量Undefined function runpf未安装Matpower工具包安装Matpower或自写潮流程序碳势出现负值算法中支路潮流方向处理错误检查支路有功功率的参考方向需要和关联矩阵U的符号约定保持一致5.2 潮流计算不收敛的排查思路用牛拉法做IEEE 14节点潮流正常情况下3到5次迭代就能收敛。如果不收敛问题几乎总是出在初始化或者数据录入上。建议先用Matpower的runpf做一个基准结果然后和自己写的程序对比。如果Matpower能收敛而你的程序不能重点检查导纳矩阵的形成和支路参数的单位换算有没有出错。IEEE数据里的电阻、电抗单位通常已经是标幺值但有些版本可能需要自己除以基准值这个很坑。另外一个很隐蔽的问题是变压器支路的非标准变比符号。IEEE 14节点系统里有几条变压器支路它们的变比不是1:1如果符号处理反了潮流结果会偏差很大碳排放流算出来自然也不对。5.3 从算例到论文级别的细节建议如果你的目标是把这版代码用在EI论文的复现或者算法对比中有几个细节值得注意。第一发电机碳排放强度的来源要标注清楚。论文里最好能附一张表格列出每台机组的类型、容量、碳排放强度取值和参考文献。这样审稿人不会质疑你的参数设置是否随意。第二结果分析要做敏感性分析。一个常见的做法是改变其中一台发电机比如水电或风电的出力占比观察各节点碳势的变化曲线说明碳排放流方法能有效反映电源结构调整对碳排放空间分布的影响。第三如果有条件和大规模系统比如IEEE 39节点或者IEEE 118节点做一次对比实验。相同算法框架下规模越大碳排放流方法相较于平均排放因子法的价值体现得越明显。第四注意代码里的矩阵运算效率。IEEE 14节点当然无所谓但如果你后续要扩展到实际电网几千个节点用稀疏矩阵存储和求解能大幅提升性能。Matlab里把A矩阵声明为sparse格式左除运算会自动切换到稀疏求解器速度可以提升一到两个数量级。5.4 关于Matlab环境的几点实操经验这部分结合我自己的环境配置经历给新手提个醒。Matlab版本方面R2021b以上跑这套代码都没问题核心就是矩阵运算不涉及太新的工具箱。Network License或者校园版都行关键是确保安装了Optimization Toolbox如果后面要扩展做优化计算的话。工作目录和路径问题也经常出问题。把所有的函数.m文件和主脚本放在同一个文件夹下然后右键“Add to Path”添加到搜索路径。我就遇到过函数写好但Matlab找不到结果只是路径没加进去白白排查了半天。如果要用Matpower安装之后建议重启Matlab否则新加入的工具箱路径可能不会立即生效。这也是一个很小的坑但不注意会浪费很多时间。遇到中文路径导致的加载失败也是一个非常经典的问题尤其是从网上下载的数据文件放在桌面路径带中文用户名时Matlab读文件会报错。解决办法是把项目文件夹放到纯英文路径下。我个人在实际操作中还有一个体会写Matlab代码的时候变量的命名最好带上物理含义的单位后缀比如P_load_MW、E_N_kgCO2perkWh。这样虽然代码显得长一点但长时间之后回来看代码或者给别人讲解代码时一眼就能明白每个变量是什么调试效率高很多。最后的实操体会把这段代码真正跑通之后我有一个比较深的感受碳排放流本身并不是一个复杂的数学问题它更像是一个“理念转换”的产物把电力系统中非常成熟的功率追踪思路迁移到了碳排放核算领域。整个核心算法只需要二三十行Matlab代码就能实现难的不是代码本身而是理解每一步计算背后的物理意义以及保证每一条支路的功率方向、每一个节点的注入功率符号都准确无误。如果你正在复现这篇文献的代码我的建议是不要急于一次跑通所有模块先把潮流计算跑通了打印出每个节点的注入功率并手算验证再叠加碳排放流计算。这样循序渐进地调试虽然慢一点但能把这个方法的底层逻辑吃透。后续无论你是要做EI期刊的算法对比还是要把这套方法用在实际电网的碳排放监测项目里都能很快上手调整。最后再分享一个小技巧算完碳势之后可以试着把节点碳势做一次升序排序再看对应的节点上都挂的是什么类型的电源。你会发现碳势最低的几个节点几乎都挨着新能源机组碳势最高的几个节点都在火电机组附近。把这个图放进论文或者汇报PPT里比任何文字解释都有说服力。