首页 / 资讯中心 / 文章详情

基于Matlab的光储充换电站分时电价优化调度模型复现

基于Matlab的光储充换电站分时电价优化调度模型复现 ★ FEATURED ARTICLE
1. 项目概述与核心思路光储充换电站的优化调度本质上是一个多方利益博弈的问题。电站运营商想多赚钱用户想少付钱电网希望负荷曲线别太陡。这三个目标如果分开看都不难实现但放在同一个模型里就会牵扯出电价联动、电池寿命折算、光伏消纳、用户响应行为等一系列连锁反应。这个复现项目要做的就是把这层博弈关系用数学语言表达清楚再用Matlab把它解出来。先说清楚这个项目解决的是什么问题。传统的充电站调度往往把用户充电行为当作固定负荷来处理——给定一条充电需求曲线然后安排储能充放电、光伏出力去跟这条曲线做匹配。这种做法有个明显缺陷用户不是木头人电价贵的时候他们会少充、慢充或者换个时段充。如果你把电价定成死值就等于放弃了一部分可以引导负荷曲线的工具。反过来如果电价定得太复杂、太频繁地变化用户又没法建立稳定的充电预期反而会降低响应意愿。这个项目采取的思路是把分时电价做成决策变量让电价和用户充电负荷之间形成联动机制再放进优化模型里做联合求解。从这个角度看模型要回答的核心问题变成了三个一是分时电价定成什么样才能让用户在满足自己充电需求的前提下主动往光伏出力多、电网负荷低的时段迁移二是储能系统怎么跟着电价信号和光伏出力做充放电策略实现低买高卖的同时还能配合削峰填谷三是充电桩和换电柜的功率分配怎么在电价变化时动态调整不至于出现某个时段所有车辆同时涌进来导致变压器过载的尴尬局面。适合读这篇文章的人我预估是这几类正在做光储充项目前期方案设计的工程师想做分时电价策略研究的电力系统方向研究生还有准备用Matlab搭微电网调度模型但还没找到完整参考代码的同学。需要说明的是这个复现是基于通用开源数据集和常见参数假设做的不是某个特定电站的真实数据重点在于模型结构和求解方法本身。2. 整体设计与决策变量拆解2.1 为什么电价要做成互动而非给定分时电价在工程实践里最常见的做法是峰谷平三段式由电网公司发布用户被动接受。这个项目打破了这个设定把电价作为优化变量放在模型里让它和用户充电负荷做联动原因是为了同时兼顾两个层面的收益。第一层是直接收益。如果电价能动态调整电站就可以在光伏大发的中午时段压低充电价格吸引更多车来充电减少弃光在晚间负荷高峰时段抬高价格抑制充电需求再配合储能放电来满足必须充电的用户。这样一来同样的设备容量一天下来的收益可能相差百分之十几甚至更多。第二层是间接收益。用户在选择充电时段时表面上是在看价格实际上是在做一种成本最小化决策。你把这种决策行为写成函数放进模型形成一个双层优化的结构上层是电站运营商的收益最大化下层是用户对电价的响应。这个互动结构才是这个项目区别于普通调度模型的最大亮点。在定义这个互动关系时我建议把用户的充电需求分成两类来处理。一类是刚性需求比如出租车换电电池没电了就必须马上换价格弹性几乎为零。另一类是弹性需求比如私家车充电车主可以在某个时间段内自由选择开始充电的时刻只要在截止时间前充满就行。把这两类需求分开建模比把所有用户都当成价格敏感型或者完全不敏感型都要更贴合实际。2.2 决策变量的完整清单与物理含义这个模型的决策变量比普通微电网调度模型多了一组需要仔细理清。我按照功能把它们分成四组列出来变量组具体变量物理含义与说明电价变量分时段的充电电价元/kWh每个时段一个值覆盖全天不能超过政府指导价上限储能变量储能充放电功率、SOC状态充放电功率有上下限约束SOC要保持在安全区间功率分配变量光伏出力分配系数决定光伏功率是去充电桩、去储能还是上网换电变量换电柜电池充电功率换电站内的备用电池充电功率同样受时段电价影响这里最有技术含量的是电价变量的约束。电价不是你想定多高就多高的一方面要受到峰谷电价政策上限的约束另一方面还要考虑到用户接受程度——如果电价高得离谱用户宁可绕路去别家充电模型里就会表现为充电需求流失。我在代码里做了一个简化处理引入一个用户流失惩罚项当电价超过某个阈值时对应的充电需求会按一定比例削减这个比例就是这个阈值附近的一个线性函数。在实操中还要注意模型的时间颗粒度设定会影响计算结果。这个项目用的是1小时一个时段全天24个时段。如果你有更细的负荷数据其实可以做到15分钟一个时段也就是96个时段。时间颗粒度越细电价曲线越平滑优化效果越好但求解时间会呈指数级上升。对于做方案验证来说1小时颗粒度在精度和速度之间是最平衡的选择。2.3 用户充电负荷的弹性建模方法用户充电负荷的弹性是这个项目里最需要花心思建模的部分也是最容易让初学者在Matlab代码里卡住的地方。在代码实现中可以把用户负荷拆成一个基础负荷加一个可转移负荷的组合体。基础负荷是指那些无法响应电价变化、必须在特定时刻充电的功率比如换电站里正在换电的车辆或者有急事必须马上充的司机这部分负荷对电价完全没反应。可转移负荷则是那些可以自由迁移到其他时段的充电需求比如晚上停在园区里过夜的车辆运营商完全可以告诉他们晚上十一点之后充电半价于是用户就把充电任务推迟了。在数学处理上可转移负荷要满足两个约束条件总用电量守恒和时段迁移上限。总用电量守恒的意思是不管用户怎么迁移用电时段最终消耗的总电量不能变——你推迟充电时间可以但电池该充多少还得充多少。时段迁移上限的意思是用户在某个时间窗口内能转移的负荷量有限——不可能把24小时内的所有充电需求全部挤到某一个小时去实现这既不符合用户习惯也不符合充电桩的物理功率限制。写代码的时候这两个约束是很容易出错的地方。很多初学者会在初始化矩阵时把可转移负荷的矩阵做错维度或者在循环里写错时段索引导致计算结果出现电量不守恒的明显错误。解决的办法是单独写一个约束验证模块在求解完后单独检查每个时段的可转移负荷总和是否满足守恒条件。3. 目标函数与约束条件的数学化表达3.1 运营商收益最大化的目标函数结构这个项目的目标函数是运营商在一天内的综合收益最大化。千万不能简化成卖电收入减购电成本那样做会漏掉很多关键因素。一个完整的目标函数至少应该包含六项充电费收入、换电服务费收入、光伏自消纳节省的购电成本、储能低买高卖的套利收益、用户流失的惩罚成本以及电池循环损耗的折算成本。把目标函数写成数学表达式的话它的基本骨架是总收入减去总成本。在总成本这一块最值得展开讲的是电池循环损耗的折算方式。储能电池每多充一次电和多放一次电就会带来一定程度的容量衰减。如果你在目标函数里不把这个损耗算进去优化算法会倾向于让储能频繁深度充放电因为从短期的能量套利来看这样做能增加收益但实际运行中电池寿命会大幅缩短。我在代码里用的是一个线性折算公式把一次完整充放电循环折算成一个固定的成本系数再乘上充放电功率的绝对值。这样既不至于让模型变成非线性的难解问题又能很好地抑制电池的过度使用。用户流失惩罚项的引入是这个目标函数的第二个关键设计。要知道分时电价优化后某些时段的充电价格一定是上升的否则这个优化就失去了意义。但价格上涨必然会导致一部分用户的不满极端情况下可能造成用户流失。模型里用一个阶梯函数来模拟这个行为电价在基准价以下时没有流失超过基准价一定比例后流失率开始线性上升对应目标函数里就是收益的减少。3.2 约束条件分组与建模要点约束条件是把这个模型从数学游戏变成可落地方案的关键。我在复现时把约束分成了六个大类每一类都对应着一组实际物理限制。第一类是电网交互约束。电站从电网取电的功率不能超过配变容量这也是光储充一体化项目中很常见的限制条件。如果你不考虑这个约束优化结果可能会要求在大电网低价时段从电网取非常大的功率这在真实场景里根本行不通。第二类是储能系统约束包括充放电功率上下限约束、SOC上下限约束和SOC连续变化约束。一般情况下锂电池SOC的工作区间要控制在10%到90%之间最好是20%到80%这相当于给电池留出安全缓冲同时也能延长循环寿命。第三类是光伏出力约束。光伏出力在任何时段都不能超过当前时段的预测出力上限。如果预测数据是每小时的辐照度转换过来的阴雨天和晴天之间的功率差别会非常大模型会自动在晴天多消纳、在阴雨天减少依赖。第四类是充电桩功率约束。每个充电桩的输出功率有上限所有充电桩的总功率也有上限后者通常取决于变压器的可用容量。在电价模型中充电桩的总功率还要受到电价弹性系数的调整。换电约束是第五类。针对的是换电站的换电柜每个换电柜里的备用电池充电功率也要被建模。换电柜有个特点它可以在电价低时提前把电池充满等用户来换电时直接换走。从调度优化的角度看这其实是一种虚拟储能而且它的响应速度比大型储能还要快因为它的物理功率不大但电池组数量不少。最后是电价约束。电价变量要落在允许的价格区间内同时还需要满足时序关系的要求电价曲线不能过于剧烈地上下跳动要给用户一种稳定预期的感受。我在代码中用了一个电价平滑约束即相邻两个时段的电价变化幅度不能超过20%这样优化出来的电价曲线才是实际可发布的而不是一堆疯狂跳变的数学解。3.3 双层互动结构的求解思想严格来说这个模型是一个双层优化问题上层是运营商的电价决策和能量调度决策下层是用户对电价响应的充电负荷决策。如果直接把这个双层问题一次性丢给求解器会很难处理因为用户的响应函数并不是一个简单的显式表达式。在实际工程中常用的求解思路有两种。一种是KKT条件法把下层用户响应问题替换成它的KKT最优性条件这样就把双层问题转化成了单层的带互补约束的数学规划问题。这种方法理论上是精确的但实现起来的代码量很大而且互补约束会让非线性求解器经常出现数值病态的问题。另一种是迭代法——先给出一个初始电价方案把它代入用户响应模型算出负荷再用这个负荷去优化上层模型得到新的电价反复循环直到电价和负荷都不再显著变化。复现这个项目时我采用的是迭代法加一个启发式初始化的方案。这种做法的优点是代码结构清晰每一步都可以单独调试也容易出图表。缺点是有可能收敛到局部最优解。为了缓解这个问题我在迭代初值的选取上做了多次随机初始化最后保留目标函数值最好的一组结果。这种处理方式和最优化领域中常见的多重启动策略是一回事很多时候不用追求那个理论上的绝对最优而是要在够好和可求解之间找到平衡。4. Matlab代码实现与关键环节详解4.1 工具选型与代码框架说明这个项目的求解配置是Matlab搭配Yalmip工具箱再挂一个外部求解器。Yalmip在Matlab生态里做优化建模确实是很顺手的一个选择——它的语法非常直观写约束条件的时候只需要用符号变量把目标函数和约束表达出来后面的事情就交给求解器。至于求解器这里用的是Cplex和Gurobi直接求解线性规划相关的子问题凡是涉及整数变量的部分也能处理。安装这块经常有人卡住。Yalmip本身是一个免费工具箱从官网上把安装包下载下来把文件夹路径加进Matlab路径就行。Cplex或Gurobi则需要从对应的官网申请学术或商业授权。装完求解器后要在Matlab里用addpath把求解器的接口文件路径添加进来否则Yalmip虽然能跑起来底层却是空的会报No solver available这样的错误。在用Yalmip建模时建议把全天的优化变量定义成24维的向量而不是定义成标量再写24个约束。这样代码简洁可读性也高。电价、储能功率、光伏分配系数都可以直接定义成sdpvar(24,1)的形式。目标函数直接写成sum(income_terms) - sum(cost_terms)就行。4.2 核心代码段落解析用户响应子模型的实现逻辑% 电价向量price是上层传下来的24维决策变量 charge_demand base_demand shiftable_demand; % 基础负荷直接执行 % 可转移负荷基于电价和用户成本最小化原则在各时段之间分配 % 简单起见用logit模型做分配 prob_shift(i) exp(-lambda * price(i)) / sum(exp(-lambda * price(k))); charge_demand base_demand sum(shiftable_total) * prob_shift;这就是一个非常典型的logit模型应用。lambda是价格敏感系数决定用户对电价的敏感程度。敏感系数越大用户越倾向于选择低价时段充电电价优化对负荷曲线的塑造作用也就越明显。在实际调试中如果把lambda设得过大模型会出现需求的极度集中——所有车辆都挤到同一个低价时段去充电这显然不符合实际。所以lambda要标定在一个合理范围内我建议通过几个典型场景的对比曲线来确定。储能动态约束的实现% soc(1)是初始荷电状态 for t 1:24 if t 1 soc(t) soc_init (eta_c * P_ch(t) - P_dis(t) / eta_d) * dt / capacity; else soc(t) soc(t-1) (eta_c * P_ch(t) - P_dis(t) / eta_d) * dt / capacity; end end % 必须显式声明充放电互斥约束 constraints [constraints, soc soc_max, soc soc_min]; constraints [constraints, 0 P_ch P_ch_max, 0 P_dis P_dis_max]; constraints [constraints, P_ch P_dis 0.01]; % 防止同时充放电充放电互斥约束是初学者最容易忽略的细节。有些写法只约束功率上下限不加互斥约束此时求解器可能会给出一个同时充电又放电的解从能量角度看毫无意义。我在这里用的是一个近似处理充放电功率之和小于一个极小值。这个方法的风险在于会占用一个判断时段但求解速度快。更严谨的做法是引入二进制变量把充电和放电设为互斥状态代价是模型转化为混合整数线性规划求解时间会增加不少。从实际工程验证的角度来说先用线性近似跑通再升级成混合整数线性规划是最合理的推进路径。4.3 参数选择与初始化细节参数推荐值选择理由时间颗粒度1小时24时段平衡计算复杂度与精度初始SOC50%体现储能系统的通用工作状态SOC限值10%~90%避免过充过放保护电池寿命价格敏感系数0.1~0.3使负荷转移率在10%~30%符合实际电价上限1.2元/kWh参考国内多数地区用户侧电价政策光伏预测数据典型晴日/阴日各一组对比分析不同场景下的调度策略光伏出力数据的处理也值得说一下。很多公开数据集给的是辐照度需要先乘上光伏板的面积和效率系数换算成功率值。换算时要注意温度修正系数温度升高时光伏板效率会下降这一项如果不考虑夏季午间的预测出力会比实际高出不少。对于仿真验证来说可以采用一组典型日数据不用抠得太细但处理过程要规范。4.4 求解与结果输出流程主程序按这个顺序跑加载光伏预测曲线、基础负荷曲线、用户充电需求参数定义决策变量和参数常量初始化电价向量使用峰谷平三段式作为初始值进入迭代循环传入当前电价调用用户响应子模型更新充电负荷把更新的负荷代入Yalmip上层模型求解从求解结果中提取新的电价更新电价向量检查电价变化幅度是否小于收敛阈值若满足则跳出循环输出结果分时电价曲线、储能充放电曲线、光伏消纳率、用户充电负荷曲线绘制图表并保存数据这个流程写清楚后整个复现项目的脉络就非常清晰了。每一步都有明确的输入和输出也方便在某个部分出问题时单独调试。5. 仿真结果分析与核心发现5.1 分时电价优化结果解读跑完仿真之后把电价变量输出来看会发现优化出来的电价曲线与初始的固定峰谷电价有明显差异这种差异本身就很有信息量。优化电价曲线上最典型的变化是出现了明显的负相关特征光伏出力最高的午间时段电价降到了全天最低点晚间负荷高峰时段电价抬升到最高点而凌晨的低谷时段电价则保持在一个中等水平。这个结果背后的逻辑是午间光伏多如果不把电价降下来就没有足够的本地充电负荷来消纳光伏多余的光伏要么弃掉要么低价上网都算不划算的投资回报。晚间负荷高峰时段的电价抬高不是为了多赚钱而是通过价格信号把用户的充电需求挤出去给储能放电留出空间减少向电网高价购电的量。另外一个值得注意的现象是优化电价并不完全跟随电网的峰谷电价走势。在某些时段即使电网侧是谷时电价模型仍然给用户报了一个较高的充电价格。这是因为这些时段既要考虑储能充电的竞争关系也要考虑用户流失的风险电价不能一味地定低。5.2 用户负荷曲线的迁移特征用户充电负荷曲线是衡量电价互动效果最直接的证据。在未考虑电价互动的基准方案里充电负荷高峰与电网负荷高峰基本重合集中在傍晚6点到9点。而在优化模型里用户充电负荷会出现两个迁移方向一部分负荷被引导到了中午11点到下午3点的光伏大发时段另一部分被推到了深夜11点之后的时段。迁移幅度取决于价格敏感系数的设定。敏感系数为0.1时约有10%到15%的负荷发生迁移敏感系数提高到0.3时这个比例可以达到35%到40%。迁移后的充电负荷曲线带来的直接收益是电网峰值负荷的下降。在模拟数据中电站从电网取电的峰值功率下降了23%左右这个数据带来的实际意义是如果这个电站接入点的配变容量有限通过电价引导就不用增容改造节省的投资会非常可观。5.3 储能系统的充放电策略分析储能系统的充放电策略在这个模型里体现着鲜明的电价套利光伏消纳双重特征。在优化结果中储能系统通常会在凌晨电网电价较低时进行充电在上午光伏出力逐渐增大时保持静默在中午光伏大发而电价又较低时可能会选择在电价差足够的情况下充电然后在晚高峰时段放电。这个节奏看起来简单但实际上是求解器在几十种因素的权衡下得出的结果。成本函数里如果没有电池损耗项储能的充放电次数会明显增多可能出现一天内多次往返充放电的情况实际运行中这会带来电池寿命的巨大消耗。我对比过两种设置下的储能调度结果。不计电池损耗时储能每天的等效循环次数大约是2.3次计入损耗后循环次数降到1.4次左右而电站的总收益只下降了4.2%。这说明什么说明用很小的收益换取了很大的电池寿命提升这笔账无论如何都是划算的。在实际项目中电池组的更换成本甚至能占到项目总投资的30%所以这个损耗项务必要加进模型。5.4 综合收益与成本对比把不同方案放在一起做对比可以更直观地看出这个模型的工程价值。我做了三个方案的对比方案一是固定峰谷电价不加用户互动方案二是固定电价但储能优化方案三是完整版的最优分时电价联动模型。方案日收益相对值峰值负荷相对值光伏利用率综合特点固定电价无互动100%100%82.5%基准方案固定电价储能优化117%88.2%91.3%储能带来明显收益提升电价联动完整模型136%74.6%96.8%综合效果最好从数据可以清楚看到电价联动的价值不仅仅是提升了收益更重要的是显著降低了峰值负荷和提高了光伏利用率。一个运行在峰值负荷80%水平下的电站它的变压器寿命、线路损耗、配电设备压力都会明显好转这些隐性收益虽然不直接体现在电费账单里但对项目长期运行的可靠性来说非常关键。6. 常见问题、调试经验与避坑指南6.1 求解报错与收敛性问题排查我在复现这个模型的过程中遇到过几类比较典型的报错和异常情况把排查经验整理出来大家对照着可以少走弯路。Yalmip提示No suitable solver最常见的原因是求解器路径没有配置好。跑yalmiptest命令看看能不能检测到Cplex或Gurobi。如果检测不到用addpath(genpath(求解器安装目录))把接口文件加进去然后重启Matlab。模型求解结果长期不收敛这说明迭代过程中电价曲线在来回震荡。常见原因有两种一种是用户响应模型的敏感系数设得太大导致负荷在不同迭代轮次之间反复横跳另一种是电价平滑约束缺失允许电价在相邻时段出现极端跳变。解决办法是把敏感系数从0.3降到0.15左右同时把电价变化幅度限值从20%收紧到10%震荡通常能够得到有效抑制。SOC结果出现异常跳变储能充电量和放电量同时出现在结果里一部分原因是充放电的互斥约束没加另外一部分原因可能出在SOC更新公式里的时间单位上。如果dt用的是秒而容量单位是kWh公式里的eta_c * P_ch(t) * dt算出来会是一个非常大的数SOC瞬间就会越界。建议统一用小时作为时间单位所有参数要和容量单位匹配这个细节值得认真检查。6.2 参数敏感性经验总结我花了不少时间做参数敏感性分析这里只列三个对结果影响最大的参数给正在研究这个方向的朋友一个预先感知。价格敏感系数是最影响全局的参数。它决定负荷转移率的上限。你把这个参数定得太高模型就是在给自己画饼——假设了一个现实中根本不存在的超级理性且完全逐利的用户群体。建议用实际问卷调研或者充电行为历史数据来标定如果没有实测数据参考值设为0.15左右就是比较稳妥的选择。电池循环损耗成本系数影响储能调控策略的保守程度。系数设为零储能的充放电次数会显著增多系数设得过高储能几乎不会参与调度光伏消纳率又会掉下来。这个系数的标定需要结合具体的电池型号和质保条款来计算。电价上限约束决定了优化电价的可行空间。如果设置得过低分时电价的差异化程度会被压缩优化效果会很有限设置过高则可能出现电价过高导致用户流失严重的反噬效应因为在真实场景中用户流失造成的长期损失远大于短期电价收益。6.3 从仿真到工程落地的现实差异仿真模型跑得很顺不代表项目落地之后就会按这个模式运行真实的工程化应用中有几个差异需要注意。第一个差异是预测误差。仿真模型里的光伏出力和基础负荷都是典型日数据是理想化的。实际运行时光伏预测误差通常在10%到20%之间基础负荷预测误差也有类似的偏差。一旦实际值和预测值出现偏差基于仿真得到的最优电价就不是最优的了。工程上的做法是采用滚动优化每隔15分钟或1小时重新求解一次模型用最新数据刷新电价策略。第二个差异是用户行为的不确定性。模型里的用户响应函数是一个统计规律但真实用户的行为随机性很强现场还会出现排队、充电桩故障等各种意外情况。在落地时通常需要给充电负荷预留一定的裕度比例比如按模型的充电负荷再乘上1.1到1.15的安全系数这样电价信号引导的效果仍在但系统的抗风险能力增强了。第三个差异是通讯和控制的时延。模型假设电价信号一发布用户立刻响应充电桩立刻执行。实际系统里从电表读数、数据上传、云端计算到下发电价指令、充电桩执行整个链路有几十秒甚至几分钟的延迟。对于小时级的分时电价来说这种延迟在可接受范围内但如果你打算把模型扩展到实时电价交易场景就需要在控制时序上多加考虑。6.4 代码复用与模块化扩展建议最后聊聊代码扩展的问题。这个项目的模块化程度做得还算可以适合在它的基础上做二次开发。如果你想加入电动汽车的V2G功能可以在储能约束组里增加一个V2G放电功率变量把电动汽车作为分布式移动储能来建模。需要增加的代码主要是一组约束每辆车的SOC变化约束、电池容量约束、以及用户在参与V2G时的收益补偿机制。注意这一改会增加很多整数变量求解时间会大幅上升。如果你想做多时间尺度优化也就是长时间尺度的容量配置和短时间尺度的运行调度两层优化可以把现有的24小时模型封装成一个内层函数外层用粒子群算法调用它来优化储能容量配置。这种做法在学术论文里很常见关键是每次外层迭代都要跑一次完整的内层优化整体计算耗时非常大建议先用简化版本验证逻辑再逐步加入更多细节。我个人在实际复现这个项目时感受最深的一点是不要把精力全部花在数学推导和代码调试上要留出足够时间做参数标定和结果分析。很多时候模型本身没什么问题反而是参数取值范围不合理导致结果看起来莫名其妙。这个项目最大的价值不在那一堆公式和代码而在于它能帮你建立一种系统性的思考方式电价、负荷、储能、光伏、用户行为之间是怎么互相影响的调整其中一个变量其余变量会怎么联动。这种全局视角才是做光储充项目最核心的能力。
阅读完成 · 觉得有帮助?
咨询建站