尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于蒙特卡洛模拟的电动汽车充电负荷预测与Matlab实现

基于蒙特卡洛模拟的电动汽车充电负荷预测与Matlab实现 电动汽车充电负荷预测这个事做配电网规划的朋友应该都不陌生。要评估一个小区、一座园区或者一片区域在新增电动汽车之后会有多少充电负荷、什么时候出现用电高峰不能靠拍脑袋估个数得有一套能把用户随机行为反映出来的方法。我这次用的就是蒙特卡洛模拟在Matlab里把每辆车的充电行为当成随机事件去抽样跑几千辆车叠加成区域负荷曲线整个建模到出图的代码量并不大但对概率模型的理解要求比较高。这个方法适合来做充电桩容量配置、配变容量校核、有序充电策略的底座分析也适合正在做课程设计或毕业论文的同学直接作为负荷预测模块的主算法。核心思路一句话讲透用大量随机样本逼近真实场景把随机性背后的统计规律挖出来。用到的东西主要有Matlab版本要求不高R2019b以上就够、随机数生成函数和基础矩阵运算不需要额外的专业工具箱有统计工具箱当然更方便没有也能用基础函数补上。1. 内容整体设计与思路拆解1.1 为什么是蒙特卡洛相比确定性方法的优势蒙特卡洛这个词听起来唬人其实思想特别朴素。你可以理解成“撒豆子统计”想知道豆子落在某个区域的比例不用把每颗豆子的轨迹算得清清楚楚只要撒足够多统计落在每个格子里的数量就接近真实概率。充电负荷也是一样每辆车几点到家、今天跑了多远、电池剩多少电、插上充电枪功率多大全是随机事件直接给一个平均值算出来的曲线会丢掉太多真实世界的波动信息。传统确定性算法会把所有变量取典型值比如假设所有车辆统一在晚上19点插枪、统一需要充3小时得到的结果是一条光滑但偏理想的曲线。实际情况下通勤距离有长有短到家时间受路况和加班影响晚高峰不能用一条均值曲线来代表。蒙特卡洛的优势在于每次模拟都产生一个“可能的世界”跑几百上千次之后不仅能拿到最可能出现的负荷曲线还能给出概率区间。做配变容量选择时光看平均曲线是不够的要看P90甚至P95场景下的峰值否则夏天傍晚容易跳闸。另外蒙特卡洛不需要历史负荷数据也能建模这对新建小区、电动汽车渗透率快速提升的规划场景特别有用。你只需要确定“用户行为服从什么分布”剩下的交给随机抽样和统计收敛。比起神经网络、时间序列这类依赖数据量的算法它的可解释性也更好算出来峰值偏高或偏低能直接追溯到是哪个参数分布设置不合理调试起来方向非常明确。1.2 整体技术路线与适用场景整个项目分六步走第一步确定输入参数和对应的概率分布第二步初始化一个车辆队列每辆车带好自己的电池容量、充电功率等属性第三步对每天每辆车抽取起始充电时间、日行驶里程、初始SOC这些随机变量第四步计算每辆车的充电需求电量和充电时长第五步把每辆车的充电功率映射到24小时时间轴上逐点累加第六步多次重复仿真统计负荷的均值、分位数曲线。这套流程最典型的应用是居民区慢充场景因为家用充电桩绝大多数是慢充功率集中在3.5kW到7kW之间充电行为高度集中在傍晚到深夜对配电网晚高峰影响最明显。公共快充站则要换一套参数体系来建模比如起始充电时间更分散、功率高很多、充电时长短很多建模思路可以复用但概率分布的参数必须重新标定。我在后面的示例中会以居民区慢充为基准来展开需要扩展快充场景的话替换分布参数和功率配置即可。这里也要说明一下模型边界。本文做的是“无序充电”场景也就是车辆到家就充、充满为止不考虑价格激励或者智能调度对充电行为的挪移。有序充电涉及的是优化问题需要在负荷预测基础上叠加控制策略那是另一个话题。先把无序充电的负荷预测做扎实后续加策略才有可靠的基线。2. 核心参数与概率模型选择2.1 影响充电负荷的四个关键变量充电负荷是大量用户行为的叠加结果但真正主导曲线形状的变量其实就四个起始充电时间、日行驶里程、动力电池容量和充电功率。理解了这四个变量整个模型就已经完成了一半。起始充电时间决定了负荷迁移到傍晚的具体位置。绝大多数私家车用户下班回家后插枪所以起始时间大概率集中在17点到21点之间峰值在19点左右这个规律不同城市的调研数据都高度一致。日行驶里程决定电池消耗了多少、需要补多少电正常情况下是右偏分布大部分用户每天跑三四公里到四五十公里少数跑长途的会到一两百公里甚至更多。电池容量和车型相关微型车可能在30kWh上下中型轿车五六十长续航车型可到80甚至100kWh不同车型混在一起要按比例混合。充电功率由充电桩决定私人慢充桩常见3.5kW和7kW两档公共慢充也有7kW但本文场景先以家用桩为主功率相对统一。这四个变量不是孤立存在的它们通过充电需求电量公式串起来。日行驶里程越大到达时剩余电量比例越低需要充入的电量越多充电时长就越长。起始充电时间越晚加上充电时长之后充电结束时间直接关系到有没有跨过零点、并入第二天的负荷曲线。所以建模的时候不能只单独抽样每个变量要按逻辑链条逐步计算最后才能得到物理上自洽的结果。2.2 概率分布选择的依据与参数设定概率分布怎么选我建议优先看调研数据画出来的直方图长什么样然后去匹配常见分布族。起始充电时间在实测里通常表现为单峰、左右基本对称用正态分布描述是业界最普遍的做法均值在18到19点之间标准差大约2到2.5小时。日行驶里程则是典型的右偏长尾分布对数正态分布是最常用的选择因为里程不可能为负且大多数人的里程集中在一个相对较低的区间少数人的里程特别长对数正态的偏态形状正好贴合这个特征。电池容量和充电功率如果模拟的是单一车型或单一小区可以直接用固定值和两三个离散档位来建模没必要强上连续分布。如果要做城市级或者多车型混行的预测就用正态分布并配合车型比例做混合抽样。充电效率这个参数很多人会忽略实际从电网侧取电到电池存储中间有车载充电机和电池管理系统的损耗一般取0.85到0.92具体看充电方式慢充效率略高一些。下面这张表是我在做仿真时常用的一组参数基线参考了多篇公开文献里美国家庭出行调查和国内部分城市的出行统计结果具体数值可以根据你手头的实际数据替换参数分布/取值典型值备注起始充电时间正态分布N(18.5, 2.5^2)单位小时以0点为0日行驶里程对数正态分布均值e^(3.2)方差0.88单位km取lognrnd(3.2,0.88)电池容量分段常数/正态分布40~60 kWh按车型比例混合百公里电耗固定值15 kWh/100km或按车型细分充电功率分段常数3.5kW / 7kW慢充为主充电效率固定值0.9慢充典型效率目标SOC固定值1.0充满为止这里要特别提醒一个新手很容易踩的坑对数正态分布的参数不是直接填“均值”而是填对数域上的均值mu和标准差sigma。如果看到文献里写“日行驶里程均值为32km标准差为20km”直接拿这两个数填lognrnd就错了需要先转换到对数域或者用分布拟合工具从原始数据里估计mu和sigma。我自己第一次做的时候就犯过这个错误结果模拟出来的充电负荷峰值特别离谱检查半天才发现是分布参数没转换。3. Matlab代码实现与核心环节拆解3.1 代码总体框架与初始化设置整个Matlab程序不需要多复杂的结构一个主脚本就能跑通全部流程建议再加一个参数配置区放在文件头部这样调参不用满文件翻。我习惯把仿真参数分成两类一类是模型本身的物理参数比如电池容量、充电功率、效率另一类是蒙特卡洛的控制参数比如模拟车辆数、仿真天数、时间分辨率。区分清楚之后后面做参数敏感性分析会很方便。时间分辨率建议设成10分钟或者15分钟也就是DT 1/6小时太粗会丢失高峰细节太细会让计算量成倍增长。24小时对应144个时间槽单次叠加上千辆车在Matlab里也就是毫秒级运算不用担心性能。循环部分建议把“模拟天数”和“车辆数”分开因为每天的重随机抽样是独立的画最终曲线时用一个“场景”的概念每一天就是一次场景抽样所有天数的结果汇总后取均值和分位数。初始化部分还有一个习惯值得养成——固定随机数种子。代码开头加上rng(2024)或者任意你喜欢的数字就能保证每次运行结果完全一致。这对调试阶段和论文可复现性都特别重要。如果没有固定种子每次跑出来的曲线细微差别会被误判成算法问题实际上只是随机波动白白浪费时间排查。下面这段是参数配置和初始化区的骨架%% 参数设置区 N_VEH 1000; % 单日模拟车辆数 N_DAY 200; % 模拟天数用于统计概率区间 DT 1/6; % 时间分辨率单位小时10分钟 T_SLOTS 24 / DT; % 24小时对应的时间槽数量 rng(2024); % 固定随机种子保证可复现 % 车辆与充电参数 batteryCap 50; % 电池容量kWh powerCharge 7; % 充电功率kW chargeEff 0.9; % 充电效率 energyPerKM 15/100; % 百公里电耗15kWh 每公里0.15kWh targetSOC 1.0; % 目标SOC默认充满3.2 核心环节一车辆行为随机抽样抽样是整个蒙特卡洛模型的心脏。每次模拟开始前要为每辆车抽取三个核心随机数起始充电时间、日行驶里程、以及可能的车型参数。这里的技巧是向量化操作也就是一次性生成N辆车的数据而不是用for循环逐辆车抽样。Matlab对向量化运算的优化非常好几百辆车的循环体感觉不出来但如果后续扩展到上万辆循环和向量化的效率差距就非常明显了。起始充电时间用normrnd生成正态分布随机数日行驶里程用lognrnd生成对数正态随机数这一步对应前面选好的概率模型。生成完参数后紧接着计算每辆车到达时的剩余SOC。计算公式是到达SOC 1 - 日行驶里程 / (电池容量 / 每公里能耗)。这里行驶里程如果超过续航里程说明电池完全耗尽但现实中用户一般会提前充电所以要对SOC设置一个下限比如不低于0.1防止出现负SOC导致充电时长计算异常。这里有个细节值得讲一下起始充电时间和到家时间不完全是一回事。调研数据显示不少用户回到家并不会立刻插枪可能先吃饭、处理些杂事再充电这个时间差本身也可以建模成一段随机延迟。在基础模型中我更倾向于直接把“起始充电时间”作为抽样对象而不是先抽到家时间再叠加延迟。因为很多文献给出的统计参数本身就是针对插枪时刻的直接使用可以减少一个环节的假设误差。如果你手里只有到家时间的数据再加上一个均值30到60分钟的伽马分布延迟是更严谨的做法。抽样部分的核心代码如下%% 单日场景抽样 % 起始充电时间正态分布均值19点标准差2.2小时 arriveHour normrnd(19, 2.2, N_VEH, 1); % 日行驶里程对数正态分布单位km mileage lognrnd(3.2, 0.88, N_VEH, 1); % 计算到达时SOC下限截断到0.1 socArrive 1 - mileage ./ (batteryCap / energyPerKM); socArrive max(socArrive, 0.1); % 充电需求电量 energyNeed batteryCap .* (targetSOC - socArrive) / chargeEff; % 充电时长 chargeHours energyNeed / powerCharge; % 充电结束时刻 endHour arriveHour chargeHours;3.3 核心环节二充电负荷在时间轴上的聚合每辆车的充电功率是多少、什么时候开始、什么时候结束这些信息都有了接下来要做的就是把所有充电过程叠加到24小时的时间轴上。叠加方法有两种一种是把每辆车的充电区间按时间槽切分挨个往对应的槽里加功率另一种是按矩阵索引的方式用向量化操作一次性完成累加。第一种好理解第二种效率高实际使用中我更倾向于先用循环把每辆车的起止槽位算清楚再用accumarray来聚合代码简洁也不容易出错。跨零点充电的情况必须处理。假设辆车19点开始充电需要充6小时直接算到凌晨1点如果索引只有24个槽位就会越界报错。我习惯的做法是把时间轴拉长到48小时也就是用T_SLOTS * 2个槽位每辆车在起始时间和起始时间加充电时长内映射功率最后只取前24小时的数据作为当天负荷后24小时的数据丢弃。这样处理跨天充电比较自然也方便后续做连续多日仿真时拼接曲线。聚合计算的代码可以是%% 负荷聚合 % 计算起止槽位时间轴扩展到48小时 startSlot floor(arriveHour / DT) 1; endSlot floor((arriveHour chargeHours) / DT) 1; loadCurve zeros(T_SLOTS * 2, 1); for k 1:N_VEH s startSlot(k); e min(endSlot(k), T_SLOTS * 2); if e s, continue; end loadCurve(s:e) loadCurve(s:e) powerCharge; end % 只取前24小时的负荷 loadToday loadCurve(1:T_SLOTS);用循环处理聚合是因为不同车辆的区间长度不同向量化写法在边界处理上比较绕。N_VEH是1000时循环完全能接受如果车辆规模到了几万辆觉得循环慢了再考虑用cellfun或者accumarray的进阶写法。性能问题不是这个模型的主要矛盾正确性和可调试性才是。3.4 外部循环与概率区间统计单日负荷曲线有了接下来就是蒙特卡洛最核心的重复模拟过程。外层循环N_DAY次每次独立抽样得到一条日负荷曲线最后把所有天的曲线存进一个矩阵里行是时间槽列是模拟天数。然后对每一行求均值就得到平均负荷曲线求5%和95%分位数就能得到概率区间带。这一整套操作非常直白但对结果的理解要到位均值和分位数的差反映的是“随机性带来的不确定范围”而不是测量误差。绘制概率区间时我会用fill函数把P10到P90的区间涂上浅色再用深色实线画均值曲线这样一张图就能同时表达最可能场景和风险边界。论文或者报告里的典型配图基本就是这种样式。如果只想看某一置信水平的极端场景直接画P95曲线就行配变容量校核一般参考的就是这个级别的峰值。多日仿真与区间统计的代码框架如下%% 多日蒙特卡洛仿真 dailyProfiles zeros(T_SLOTS, N_DAY); for d 1:N_DAY % 这里放入3.2和3.3的抽样与聚合代码 dailyProfiles(:, d) loadToday; end % 统计平均曲线及分位数区间 avgLoad mean(dailyProfiles, 2); p10Load prctile(dailyProfiles, 10, 2); p90Load prctile(dailyProfiles, 90, 2); % 画图 t (0:T_SLOTS-1) * DT; figure; fill([t fliplr(t)], [p10Load; flipud(p90Load)], b, FaceAlpha, 0.2, EdgeColor, none); hold on; plot(t, avgLoad, b-, LineWidth, 1.8); xlabel(时刻小时); ylabel(负荷功率kW);## 4. 仿真实验与结果解读 ### 4.1 三种典型场景的参数对比 算法跑通之后最有价值的应用就是做场景对比。我整理了三个典型场景来做演示基准居民区场景、高渗透率场景、快充混入场景。基准场景全部是7kW慢充车辆电池容量统一取50kWh起始充电时间集中在19点左右这就是一个典型的城市居民区。高渗透率场景把车辆数从1000提升到3000相当于电动汽车渗透率更高的小区其他参数不变看负荷峰值随数量的变化关系。 快充混入场景稍微复杂一些假设有20%的车辆使用60kW快充桩充电行为不集中在晚间而是分散在白天和傍晚。快充的充电功率高、时间短对电网的冲击形态和慢充完全不同。参数对比表如下 | 场景 | 车辆数 | 充电功率 | 起始时间分布 | 平均充电时长 | |---|---|---|---|---| | 基准居民区 | 1000 | 7kW | N(19, 2.2) | 约3.5h | | 高渗透率 | 3000 | 7kW | N(19, 2.2) | 约3.5h | | 快充混入 | 800慢充200快充 | 7kW / 60kW | 慢充晚间快充全天 | 慢充约3.5h快充约0.8h | 这组对比能回答两个实际问题第一小区电动汽车数量增加一倍晚高峰配变容量是否需要跟着翻倍第二引入快充桩后负荷曲线形状会发生什么变化是否需要额外配置储能来削峰。在做这些分析之前先把三个场景跑一遍把曲线画出来心里就有底了。 ### 4.2 结果曲线的典型规律与解读 基准场景跑完曲线的形态一定有这些特征下午四五点之前负荷几乎为零因为用户基本还没开始充电傍晚六七点开始陡增到晚上八点到九点之间达到峰值随后缓慢下降到凌晨三四点彻底归零。峰值时刻比起始充电时间分布的均值略晚原因很简单——负荷是功率的叠加结果到达时间集中在均值附近叠加后峰值自然滞后了一些。 概率区间在高峰时段最宽低谷时段几乎为零。这个现象不难解释在高峰时段哪些车来了、哪些车没来、来了充多久各种随机性全部叠加在一起波动自然最大而在凌晨时段几乎所有车都充完了随机性没有发挥空间。这也是为什么单日模拟曲线没有参考价值必须用大量天数做统计才能看到稳定的规律。 高渗透率场景的峰值不是简单按车辆数线性增长。因为负荷曲线本身就是多辆车充电区间的叠加车辆数增加时峰值区间变宽叠加更加充分峰值增长率会略低于车辆数增长率。这就是蒙特卡洛方法的体现——它能帮你发现简单的倍数估算容易忽略的“随机性平滑效应”。快充混入场景则要注意白天的负荷会明显抬高但是晚高峰的抬升幅度并没有想象中那么高因为快充桩本身的利用率分散在全天。 ## 5. 常见问题与排查技巧实录 ### 5.1 高频问题速查表 做这个项目过程中最容易遇到下面几类问题我整理成了一张速查表每一条都是实际踩过坑之后总结出来的 | 问题现象 | 可能原因 | 解决思路 | |---|---|---| | 负荷曲线出现负值或SOC小于0 | 行驶里程大于续航SOC计算超出范围 | 对SOC做下限截断或过滤掉超长里程样本 | | 模拟结果每次运行都不一样 | 没有固定随机种子 | 在代码开头加rng函数固定种子 | | 峰值时刻和预期偏差很大 | 起始充电时间的分布参数设置不合理 | 核对是不是把标准差设太大或者均值偏了 | | 充电结束时索引越界报错 | 起始时刻加充电时长超过24小时 | 把时间轴扩展到48小时后截取前24小时 | | 负荷曲线毛刺特别多不光滑 | 模拟天数太少或车辆数太少 | 增加N_DAY和N_VEH随机波动会被平均掉 | | 不同车型混合时曲线有突兀跳变 | 电池容量或功率按比例混合时概率没归一化 | 检查车型比例之和是否为1抽样逻辑是否写对 | ### 5.2 实操避坑心得 第一个心得是分布检验。很多同学从论文里抄来分布参数抄完直接跑根本不验证抽样数据长什么样。我建议每次抽样完先对抽样结果做一次简单的可视化检查比如histogram画一下起始充电时间看是不是符合预期的钟形分布。再计算一下抽样均值和标准差和理论的设定值做对比偏差太大多半是参数理解有误。如果数据量允许用Matlab的fitdist函数对原始调研数据做分布拟合比抄参数可靠得多。 第二个心得是关于收敛性判断。蒙特卡洛的结果依赖样本量那到底模拟多少天才够我判断收敛的方式很简单把模拟天数从50逐步增加到500记录峰值的变化如果峰值随天数增加还在明显波动说明还没收敛如果峰值变化缩小到1%以内基本就够了。实际操作中200天到500天通常就能得到稳定的均值曲线分位数区间再多的天数差别也不大没必要一味追求上万次模拟。 第三个心得是收敛性检验的另一面不要以为固定了随机种子、结果稳定了就代表模型正确。固定种子只能保证“可复现”不能保证“正确”。如果某个分布的参数输错了结果每次会一致地错反而不容易发现。所以我会在不同的随机种子下跑几次对比确认曲线的形态和量级基本一致同时用实际常识做验证——比如说1000辆车的居民小区晚间充电峰值大概在一两千千瓦这个数量级如果算出来峰值接近一万千瓦肯定哪里出了问题。 第四个心得和代码结构有关。我建议把参数配置、单日模拟、多日统计分别写成独立的section甚至函数方便调试。尤其是单日模拟逻辑单独封装成函数后可以直接在命令行测试抽样和聚合逻辑不用每次跑完整的多日循环。排查问题时先用一个很小的车辆数比如10辆车单步调试看每辆车的充电区间和聚合值是否符合预期确认无误后再放大规模。直接跑1000辆车还指望一眼看出问题不现实。 ## 6. 最后再分享一点扩展思路 蒙特卡洛负荷预测模型做到这个程度已经是一个可以直接交付的预测工具但它更像是整个配用电分析的第一块积木。往上可以加有序充电策略——把负荷预测结果当成优化模型的输入用价格信号或者功率限制来引导充电行为往旁边可以接入光伏出力的随机模拟结合本模型做光储充一体化项目的容量配置往下还可以把时间分辨率细化到分钟级研究单台配变或台区线路的短时过载风险。 我个人在实际使用中体会最深的一点是蒙特卡洛方法本身的代码实现并不难难的是对随机模型的敬畏。每个分布参数背后都是真实的用户行为需要花时间去校核、验证、修正而不能停留在“能跑出图”的层面。宁可多做几次分布检验和异常场景测试也别急着把结果拿去出报告——这一点在负荷预测这类直接关联电网投资决策的问题上尤其关键。
返回列表