ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python实现电力系统碳排放流计算:节点碳势求解与碳流率分析

Python实现电力系统碳排放流计算:节点碳势求解与碳流率分析 简介面向电力系统研究人员与工程技术人员这是一份基于Python复现电力系统碳排放流计算方法的开源项目资源包。资源聚焦碳排放流计算模型构建与仿真分析模型涵盖电力网络结构、电源与负荷分布、碳排放系数等关键要素可用于碳排放流的计算、验证与仿真为减排政策制定、能源结构优化和电力系统低碳运行提供量化工具。压缩包共4个文件以Python脚本、txt说明和docx文档为主整体约36KB。Python脚本为核心采用模块化设计集成了算法实现、数据加载与处理、模型构建、仿真分析等模块txt与docx文档则记录了实现步骤、参数设置、使用说明和额外补充材料方便对照学习与二次开发。借助NumPy、Pandas、NetworkX等开源库使用者可快速搭建计算环境验证不同运行工况下的碳排放流分布还可扩展清洁能源接入、负荷变化等场景的模拟辅助理解碳排放流的产生与转移规律。目前已有69人学习适合电力系统低碳化研究、课程设计或毕业设计选型参考。1. 碳排放流计算把发电侧的碳排分摊到每个负荷节点碳排放流计算在电力系统里解决的问题很明确电能混着输碳排却得一笔一笔算清楚。发电厂的直接排放好数点一下煤耗和气耗就有数但负荷节点用的是整张网的混输电谁也说不出自己这度电来自哪台机组。碳排放流计算以潮流结果为载体把发电侧的碳排放沿有功传输路径逐级分摊到节点、支路和负荷输出节点碳势、支路碳流率和负荷碳流率报表。这个开源项目就是用 Python 把这套方法完整复现了一遍输入两张表、输出三张表适合做碳排放核算、绿电溯源和低碳规划方向的研究者做仿真分析也适合拿去做课程设计的改造底稿。2. 基本盘先立住有功潮流是碳流唯一的载体2.1 为什么碳排放能“流”起来三个前提假设碳流计算不是凭空造概念它的成立依赖三个物理层面的前提。第一个前提是有功潮流是碳流的唯一载体碳是燃烧产物电能是它的运输工具电从机组送到负荷的同时碳排的责任也跟着转移。无功功率不承担这个责任所以整个计算只看有功。第二个前提是节点掺混假设流入同一个节点的多股功率会完全混合混合后的电能拥有相同的碳流密度下游无法区分这股电来自哪台机组。这个假设和电网的实际运行状态基本一致交流电网里电压和频率是全网统一的电能确实混在一起传输。第三个前提是碳流沿潮流方向单向流动支路碳流从首端节点流向末端节点方向与有功潮流方向一致。如果潮流方向在某个时段反转碳流方向也跟着反转这是后续排错时最容易出问题的地方。这三个前提决定了算法的整体走向先算潮流拿到各支路的有功功率和方向再沿潮流方向追踪碳流的分配。换句话说潮流计算的质量直接决定碳流计算的质量。很多复现项目跑出来的结果不对回头一查不是碳流算法错了而是潮流数据本身没收敛干净。2.2 三个核心变量节点碳势、支路碳流率、负荷碳流率整个计算围绕三个变量展开先把单位搞明白后面代码才不会写乱。变量符号单位含义节点碳势e_itCO2/MWh节点每消纳 1 MWh 电能对应的碳排放支路碳流率R_ltCO2/h线路每小时运载的碳排量负荷碳流率R_DitCO2/h节点负荷每小时对应的碳排量节点碳势是整个方法的核心量它表示这个节点上流动电能的“含碳浓度”。一个纯煤电节点碳势就是煤电机组的碳强度一个纯水电节点碳势就是零一个混合节点碳势是各路注入按功率加权平均的结果。支路碳流率和负荷碳流率都是节点碳势派生出来的乘积量计算公式分别是 R_l |P_l| × e_from 和 R_Di P_Di × e_i。这里有一个新手最容易绕晕的点节点碳势不是机组碳强度直接取平均。比如节点上有一台 100 MW 煤电和一台 100 MW 风电碳强度分别是 0.85 和 0节点碳势不是 0.425而是要看潮流分配关系如果风电全就地消化、煤电全部外送节点碳势可能接近 0.85。碳势永远跟着功率走不是跟着装机容量走。2.3 计算流程从潮流结果到碳流报表的五个步骤完整跑一遍碳流计算大致五个步骤步骤做什么输入输出1潮流计算或数据准备拓扑、机组出力、负荷节点注入功率、支路有功潮流2数据对齐潮流结果、机组碳强度对齐后的 buses、lines 表3节点碳势求解buses、lines 表各节点碳势 e_i4支路与负荷碳流率节点碳势、潮流数据R_l、R_Di5报表汇总上述全部结果节点碳势表、支路碳流表、负荷碳流表第 3 步是整个流程的核心。无环网络可以按拓扑顺序从电源节点逐级往下推有环网就要做迭代求解直到所有节点碳势收敛。第 5 步的报表看着简单但在实际项目里最花时间因为要跟调度系统的设备台账、用户档案做关联。2.4 为什么用 Python 做这件事这套流程用商业电力分析软件也能做但商业软件的问题是把潮流和碳流耦合在内部黑匣子里换一个机组碳强度、改一条线路参数都得整包重跑批量场景仿真很不方便。Python 的优势在于生态完整numpy 和 pandas 管矩阵与表格pandapower 可以算潮流matplotlib 画碳流分布图改参数只需要改一行赋值。GitHub 上常见的电力开源项目也大多是这种组织方式一个 data 目录放原始数据一个 core 目录放核心算法一个 cases 目录放算例脚本。这个压缩包的目录结构也按这个思路组织拿到手之后结构成本很低。3. 核心代码拆解顺流追踪法求解节点碳势的落地实现3.1 两种算法路线顺流追踪与分布因子法怎么选碳流计算的实现路线主要有两种。一种是顺流追踪法从电源节点出发沿着潮流方向逐级分摊碳流。它的物理意义直观每一步都能解释清楚“碳去了哪里”适合教学演示和中小规模系统的复现。遇到环网时顺流追踪需要迭代计算但收敛速度一般可以接受。另一种是分布因子法基于潮流分布矩阵直接求节点碳势。它的优势是计算一步到位不需要迭代但需要构造节点功率分布矩阵并求逆矩阵病态时数值稳定性差大规模系统里对内存和精度都有要求。这个项目的核心代码采用顺流追踪迭代版本。原因很务实对复现者来说顺流追踪的每个中间量都能打印出来检查出问题好定位对扩展来说后续如果要把算法接到 pandapower 的潮流输出上只需要改数据入口追踪逻辑不用动。3.2 数据组织buses 表与 lines 表整个计算只需要两张表。buses 表描述节点节点编号、机组出力、机组碳强度、节点负荷。lines 表描述支路首端节点、末端节点、有功潮流值。字段类型说明bus_idint节点编号全表唯一P_gfloat (MW)该节点机组有功出力E_gfloat (tCO2/MWh)该节点机组碳排放强度P_dfloat (MW)该节点负荷有功功率字段类型说明fromint支路首端节点编号toint支路末端节点编号P_linefloat (MW)从 from 流向 to 的有功潮流数据准备代码import pandas as pd buses pd.DataFrame({ bus_id: [1, 2, 3, 4, 5, 6], P_g: [80.0, 40.0, 0.0, 0.0, 15.0, 0.0], # MW节点5接入新能源 E_g: [0.85, 0.0, 0.0, 0.0, 0.0, 0.0], # tCO2/MWh煤电0.85水电/风光为0 P_d: [0.0, 0.0, 70.0, 10.0, 25.0, 30.0], # MW }) lines pd.DataFrame({ from: [1, 1, 2, 2, 3, 4, 5], to: [3, 4, 3, 5, 6, 6, 6], P_line: [60.0, 20.0, 30.0, 10.0, 20.0, 10.0, 0.0], # MW正方向为 from - to })这里 P_line 的方向和数值必须来自潮流计算结果不能随意设定。第 5 章会专门说 P_line 出现负值的情况。E_g 取 0 表示该节点机组在运行边界内不计碳排放水电、风电、光伏都按这个口径处理。3.3 核心函数实现碳势迭代与碳流率计算核心计算函数如下import numpy as np def carbon_flow_tracing(buses, lines, eps1e-6, max_iter50): 基于顺流追踪的碳流计算 buses : DataFrame字段 [bus_id, P_g, E_g, P_d] lines : DataFrame字段 [from, to, P_line] 返回 : 节点碳势数组、支路碳流率数组 n len(buses) bus_id buses[bus_id].values idx {v: i for i, v in enumerate(bus_id)} # 节点编号 - 行索引 f_idx lines[from].map(idx).values t_idx lines[to].map(idx).values P_line lines[P_line].values P_inj buses[P_g].values - buses[P_d].values # 节点净注入功率 carbon_gen buses[P_g].values * buses[E_g].values # 机组碳流率, tCO2/h e_bus np.zeros(n) for _ in range(max_iter): e_new e_bus.copy() for i in range(n): inflow carbon_gen[i] # 先算机组本地注入碳流 for k in range(len(lines)): if t_idx[k] i and P_line[k] 0: # 只统计流入本节点的支路 inflow e_bus[f_idx[k]] * P_line[k] if abs(P_inj[i]) eps: e_new[i] inflow / max(P_inj[i], eps) if np.max(np.abs(e_new - e_bus)) eps: # 全节点碳势收敛判断 e_bus e_new break e_bus e_new carbon_line np.zeros(len(lines)) for k in range(len(lines)): if P_line[k] 0: carbon_line[k] e_bus[f_idx[k]] * P_line[k] return e_bus, carbon_line逻辑上这个函数把每个节点当成一个混合池流入节点的碳流包括本地机组产生的碳流以及所有上游支路送进来的碳流把总碳流除以节点净注入功率就得到该节点的碳势。支路碳流率则用首端节点碳势乘以支路有功功率得到。参数说明eps 是收敛阈值单位是 tCO2/MWh取 1e-6 足够覆盖大多数场景如果追求更高精度可以压到 1e-8但迭代次数会明显增加。max_iter 是最大迭代次数50 次对中小规模系统足够。P_inj 接近 0 的节点会被跳过这类节点通常是纯中转节点或功率平衡节点碳势由邻接节点决定不直接求解。3.4 跑一次最小示例两张表进、报表出用 3.2 的数据直接调用e_bus, carbon_line carbon_flow_tracing(buses, lines) result buses.copy() result[e_bus] e_bus result[R_D] buses[P_d].values * e_bus # 负荷碳流率 tCO2/h print(result[[bus_id, P_d, e_bus, R_D]]) lines_out lines.copy() lines_out[R_line] carbon_line print(lines_out[[from, to, P_line, R_line]])输出的节点碳势单位是 tCO2/MWh负荷碳流率单位是 tCO2/h。这里没有额外的换算系数是因为 E_g 已经用了 tCO2/MWh如果原始数据里机组碳强度是 gCO2/kWh需要先除以 1000 再做运算否则结果会整体放大一千倍这个坑在第 5 章会详细说。3.5 参数怎么定碳强度取值与时间分辨率机组碳强度是整个计算最重要的外部参数取值口径不同结果差异很大。常用参考值如下机组类型碳强度参考范围 (tCO2/MWh)燃煤电厂0.82 ~ 0.89燃气电厂0.39 ~ 0.45生物质电厂0.03 ~ 0.05水电 / 风电 / 光伏0实际项目里不建议直接抄表最好用机组最近一个结算周期的实际供电煤耗换算再考虑厂用电率。时间分辨率方面小时级数据是起步配置做高比例新能源场景分析建议用 15 分钟级数据。光伏出力的午间尖峰和晚高峰负荷之间只隔几个小时小时级平均会把碳势波动抹平看起来“很平稳”实际上错过了关键变化。4. 仿真分析六节点参考系统跑通全过程4.1 参考系统设计思路煤电、水电、风光同网为了完整演示碳流计算我搭了一个六节点参考系统。设计目标很明确让煤电、水电、新能源三种电源和五种负荷同时出现在一张网里这样能看到纯高碳节点、纯清洁节点、混合节点三种典型情况。节点设置如下节点电源类型P_g (MW)E_g (tCO2/MWh)P_d (MW)1煤电800.8502水电40003无电源00704无电源00105新能源150256无电源0030线路潮流方向与数值1→3 为 60 MW1→4 为 20 MW2→3 为 30 MW2→5 为 10 MW3→6 为 20 MW4→6 为 10 MW5→6 为 0 MW。总出力 135 MW总负荷 135 MW功率平衡。节点 5 自身有 15 MW 新能源出力加上从节点 2 送入的 10 MW正好覆盖 25 MW 负荷所以与节点 6 之间没有功率交换。这个系统的巧妙之处在于节点 3 是一个典型的混合节点同时接受煤电和水电节点 6 更复杂同时从节点 3、4、5 三个方向受电能验证多路汇入时的碳势加权逻辑。4.2 基准场景结果解读高碳节点和低碳路径一眼看出来运行第 3 章的函数得到节点碳势和负荷碳流率如下节点P_d (MW)节点碳势 e (tCO2/MWh)负荷碳流率 R_D (tCO2/h)100.8500020003700.566739.674100.85008.50525006300.661119.83节点 1 和节点 4 的碳势最高0.85 就是煤电的原始碳强度因为这两个节点完全由煤电供电。节点 3 的碳势 0.5667 是 60 MW 煤电碳流和 30 MW 水电碳流混合后的加权平均结果。节点 6 的碳势高于节点 3是因为它同时接收了来自节点 4纯煤电的功率拉高了整体碳势。支路碳流率方面1→3 支路为 51 tCO2/h1→4 为 17 tCO2/h3→6 为 11.33 tCO2/h4→6 为 8.5 tCO2/h。2→3、2→5、5→6 三条支路的碳流率都是 0因为上游节点碳势为 0。这里有一个值得注意的细节2→5 支路有 10 MW 的有功功率但碳流率是 0说明输电路径不等于碳排放路径水流过去不代表碳也流过去。4.3 场景对比增加新能源装机后碳势怎么变把场景改一下节点 5 的新能源出力从 15 MW 增加到 30 MW节点 1 的煤电从 80 MW 压到 65 MW总出力不变。线路潮流相应调整1→3 变为 50 MW1→4 变为 15 MW3→6 变为 10 MW4→6 变为 5 MW5→6 变为 15 MW。对比结果节点基准场景碳势新能源场景碳势变化30.56670.5313-6.2%40.85000.8500060.66110.3188-51.8%节点 4 的碳势没变因为它仍然完全由煤电供电新能源出力增加后并没有改变它的供电路径。节点 6 的碳势下降了一半多因为新增的风电通过 5→6 支路直接送入节点 6替代了原先从节点 3 和节点 4 过来的煤电功率。这说明新能源替代对碳势的影响是局部性的体现的是“就近替代”效应而不是全网平均下降。这个仿真分析验证了两个结论碳势变化与潮流分布强相关下游节点能否受益取决于供电路径是否经过清洁电源单纯增加新能源装机而不改变输电通道结构部分节点可能完全享受不到减碳红利。4.4 结果能用到哪绿电溯源与规划辅助节点碳势表可以直接用于负荷侧的碳排放核算替代省级电网平均排放因子核算精度从“全省一个数”细化到“节点一个数”。支路碳流率表可以用于输电网的碳责任分摊分析一条输电通道每年“运送”了多少碳辅助规划部门判断新建清洁能源通道的减碳效果。实际项目中还可以把碳流结果叠加到地理接线图上生成碳流热力图汇报和审查时直观得多。5. 避坑指南五个最容易翻车的复现细节5.1 潮流负方向炸出“负碳流”现象跑完计算碳流率表里出现负值甚至节点碳势为负明显不合理。原因碳流追踪逻辑大概率只处理了 P_line[k] 0 的情况或者反过来只取了绝对值没有区分真正方向。潮流计算软件输出的线路有功功率可能带符号负号表示实际潮流与定义的“from→to”方向相反。碳流的方向必须采用实际潮流方向而不是表里写死的首末端方向。解决统一约定方向规则。在两表中都写清“P_line 为正是 from→to为负是 to→from”在核心函数里遇到负值时把功率取绝对值、同时把首末端对调参与计算。我在第 3 章代码里只处理了正值分支实际落地时要补上方向反转逻辑。5.2 净注入功率为负的倒灌节点现象某些节点计算出的碳势异常大或干脆不更新。原因P_inj P_g - P_d如果节点负荷大于本地出力净注入为负说明这个节点实际上在从电网“抽功率”。直接用 inflow / P_inj 会得到负碳势或错误数值。解决对倒灌节点单独处理先判断 P_inj 的符号。如果为负它的碳势应该等于所有流入支路的加权平均碳势而不是按发电侧计算。我一般在预处理阶段就把这类节点标记出来先算正常节点再用流入支路碳势插值。5.3 碳强度单位混用结果放大一千倍现象负荷碳流率算出几千几万的量级跟机组总排放量明显对不上。原因原始数据里机组碳强度用的是 gCO2/kWh代码里却按 tCO2/MWh 参与运算。1 tCO2/MWh 1000 gCO2/kWh量纲差 1000 倍计算误差会直接传导到所有结果。解决数据入口做统一换算。我习惯在读取数据后立刻加一行断言E_g 的最大值如果超过 1.0就提示检查单位。0.85 是煤电常见碳强度0.85 kgCO2/kWh 也是常见口径这两个数之间恰好差一个数量级稍不注意就翻车。5.4 环网迭代震荡不收敛现象max_iter 跑满还没有收敛或者碳势在两个值之间跳变。原因网络存在闭环顺流追踪的更新顺序导致前后两次计算结果互相覆盖形成振荡。典型场景是双回线环网供电或联络线转供。解决给迭代加阻尼系数。迭代更新改为 e_new alpha * e_candidate (1 - alpha) * e_oldalpha 取 0.3 到 0.5牺牲一点收敛速度换取稳定性。我在代码里没加阻尼因为六节点算例没有环网但换到实际配电网络时这个参数几乎必调。5.5 时序数据没对齐结果整体漂移现象新能源出力高的时段节点碳势偏低但负荷碳流率却出现背离曲线形状跟出力曲线对不上。原因新能源出力用的是 15 分钟级数据负荷用的是小时级数据两者直接拼接后在时间轴上错位碳势在时间维度上不等于真实物理状态。解决统一重采样把全部数据插值到同一时间分辨率。对波动剧烈的光伏出力用线性插值即可对负荷数据建议按出力曲线的时间点进行前向填充避免引入未来数据。对齐之后再做碳流计算结果曲线才可解释。6. 守恒校验与追踪表反查让碳流结果自己证明自己6.1 三个必做的硬校验碳流计算跑完先别急着出报告做三个校验。第一个是总量守恒全网机组碳流率总和必须等于全网负荷碳流率总和偏差超过 0.1% 就说明潮流数据或追踪逻辑有问题。第二个是边界值校验纯煤电节点的碳势必须严格等于该机组碳强度纯水电节点碳势必须为 0。第三个是方向一致性任何一条支路的碳流率非零它的上游节点碳势必须非零。total_gen np.sum(buses[P_g] * buses[E_g]) total_load np.sum(buses[P_d] * e_bus) assert abs(total_gen - total_load) / total_gen 1e-3, 守恒校验失败校验通过后整张碳流报表才具备解释价值。6.2 追踪表反查一个负荷节点到底是谁在供以节点 6 为例反查它的碳流构成。基准场景下节点 6 的 30 MW 负荷由三路功率供应分别是节点 3 送 20 MW、节点 4 送 10 MW、节点 5 送 0 MW。逐级往前追节点 3 的功率又来自节点 1 的煤电 60 MW 和节点 2 的水电 30 MW节点 4 的功率全部来自节点 1。最终节点 6 的 30 MW 负荷中20 MW 来自煤电路径、10 MW 来自煤电路径、0 MW 来自清洁路径碳流追踪表可以精确到“哪条线路、哪个电源、多少 MW”的粒度。负荷节点上游路径功率 (MW)碳势来源碳流率 (tCO2/h)63→620节点3混合碳势11.3364→610节点4煤电碳势8.5065→60节点5清洁碳势06.3 我的习惯我从第一次复现碳流计算开始就养成了一个习惯任何一组数据跑完第一件事不是看碳势表而是做总量守恒校验。这个习惯帮我拦住过至少三次错误——一次是潮流数据漏了一条线路一次是单位换算少除了 1000一次是新能源场站出力没对齐时间戳。从那以后我每次跑仿真都强制走一遍校验流程先把守恒偏差压到 0.1% 以内再看任何分析结论。希望这份实践笔记能让你在复现时少走几步弯路顺利把碳流计算跑通并用到自己的场景里。本文还有配套的精品资源点击获取
返回列表