文章目录
在本系列中,我们将介绍虚拟电厂多个实际应用场景中的智能决策,包括智慧楼宇、零碳园区等。
案例来源:https://opt.aliyun.com/example/aqIv2uBnQZfe/src/01_%E5%85%89%E5%82%A8%E8%8D%B7%E7%BB%8F%E6%B5%8E%E6%80%A7%E8%B0%83%E5%BA%A6.ipynb
案例作者:蒋蔚(蔚绛)
背景
近年来,在实现“双碳”目标的道路上,以风、光为代表的可再生能源作为缓解能源压力、促进可持续发展的重要途径广受关注。虚拟电厂作为一种区域性多能源聚合形式,实现了可再生能源大量接入电力系统运行,推动城市能源系统绿色高效发展。研究大规模常态化运行的虚拟电厂关键技术成为亟待解决的问题。分布式光伏、分布式储能及可控负荷等灵活性资源具有容量小、资源种类多、数量庞大等特点,难以直接参与电网互动运行。虚拟电厂有效聚合电源、负荷、储能等各类资源,参与电力市场,响应价格信号,为电网提供调峰、调频、调压与备用等辅助服务。
在电力市场价格、用户负荷需求、电源功率调节范围等参数随时间变化的情况下,我们考虑多时段优化问题,在满足各时刻功率平衡约束和设备固有约束的条件下,实现经济性调度最优,提供调度决策指令参考值。
在实际情况下,我们考虑虚拟电厂调度的问题难点主要包括以下两条:
- 不确定性:可再生能源、储能及负荷等单独运行时,电源容量较小,且具有较大的随机性、波动性、间歇性。例如:
- 发电功率:从产生原理来看,光伏、风力的发电和天气息息相关,具有不稳定性。
- 用电负荷:用户端用电规律会随时间变化,同时,不同的用电场景(例如居民楼、商业楼、写字楼)具有不同的负荷特性。
- 多目标优化:在并网状态下,虚拟电厂与大电网同步运行,在孤网状态下,虚拟电厂需要自动控制电压和频率的平衡。在用电设备可控的情况下,我们可以联合调节用电负荷和储能设备实现虚拟电厂内部设备的协同和与电网的互动;但是,在本案例中,为了不影响居民或产业正常用电,我们希望在不削减负荷需求的情况下,通过控制虚拟电厂的储能单元,确保电力系统经济(降低电费)、低碳(降低碳排)、安全(削峰填谷)地运行。
为了应对以上问题,我们考虑不确定性存在情况下的决策。
- 首先,采用数学规划进行问题建模,确定决策变量、约束条件和目标函数;
- 然后,通过MindOpt建模语言(MindOpt Algebra Programming Language, 简称为MAPL)将数学模型"翻译"为求解器可以理解的机器模型;
- 最后,调用数学规划求解器(Solver)进行求解,进而得到最优决策。
光储荷经济性调度
本篇将以最简单的虚拟电厂场景为例,帮助快速理解。
1. 问题描述
我们考虑单个光伏、单个用户和单个储能设备在内的虚拟电厂场景中,在满足用户负荷需求的条件下,较短调度周期内(例如,四小时)的经济性最优目标。光伏可以发电给用户直用,也可以存储于储能设备中,在未来放电给用户使用;同时,光储不能覆盖的用户需求,可以从大电网中消费。
为了得到该调度问题的答案,我们首先需要将问题建模为数学规划问题,然后调用数学规划求解器来求解。
2. 数学规划模型
数学规划问题由三个要素组成: 决策变量,目标 和 约束条件,在该问题中具体如下:
考虑 T T T时间段调度问题,输入以下参数:
- 用户净负荷需求(负荷和光伏功率的差值): L = ( l t ) ∈ R T L = (l_{t}) \in {\mathbb{R}}^{T} L=(lt)∈RT (单位:kWh)
- 电价: P = ( p t ) ∈ [ 0 , ∞ ) T P = (p_t) \in {[0, \infty)}^{T} P=(pt)∈[0,∞)T (单位: $/kWh)
- 储能充电效率: c 1 ∈ [ 0 , 1 ] c_1 \in [0,1] c1∈[0,1]
- 储能放电效率: c 2 ∈ [ 0 , 1 ] c_2 \in [0,1] c2∈[0,1]
- 储能单次充放电限制: α ∈ [ 0 , 1 ] \alpha \in [0,1] α∈[0,1]
决策变量为各时刻归一化的储能动作:
- 充电变量: X = ( x t ) ∈ [ 0 , α ] T X = (x_{t}) \in [0,\alpha]^{T} X=(xt)∈[0,α]T
- 放电变量: Y = ( y t ) ∈ [ − α , 0 ] T Y = (y_{t}) \in [-\alpha,0]^{T} Y=(yt)∈[−α,0]T
- 储能设备能量状态: S = ( s t ) ∈ [ 0 , 1 ] T S = (s_{t}) \in[0,1]^{T} S=(st)∈[0,1]T
最小化经济性最优目标:
m i n i m i z e X , Y , S Cost = ∑ t = 1 T ( l i t + x i t + y i t ) ⋅ p t \mathop{\mathrm{minimize}}_{X,Y,S} \quad \text{Cost} = \sum_{t=1}^T \left(l_{it}+x_{it}+y_{it}\right)\cdot p_t minimizeX,Y,SCost=∑t=1T(lit+xit+yit)⋅pt
满足以下约束条件:
- 储能设备功率约束: 0 ≤ x i t ≤ α , − α ≤ y i t ≤ 0 , i = 1 , … , I , t = 1 , … , T 0 \le x_{it} \le \alpha\,, \, -\alpha \le y_{it} \le 0\,, \quad i = 1,\ldots,I,\,\,t=1,\ldots, T 0≤xit≤α,−α≤yit≤0,i=1,…,I,t=1,…,T
- 储能能量状态更新: s i 0 = 0 , s i t = s i , t − 1 + c 1 ⋅ x i t + 1 c 2 ⋅ y i t , i = 1 , … , I , t = 1 , … , T s_{i0} = 0\,,\, s_{it} = s_{i,t-1} + c_1 \cdot x_{it} + \frac{1}{c_2} \cdot y_{it}\,, \quad i = 1,\ldots,I,\,\,t=1,\ldots, T si0=0,sit=si,t−1+c1⋅xit+c21⋅yit,i=1,…,I,t=1,…,T
- 储能能量状态约束: 0 ≤ s i t ≤ 1 , i = 1 , … , I , t = 1 , … , T 0\le s_{it} \le 1\,, \quad i = 1,\ldots,I,\,\,t=1,\ldots, T 0≤sit≤1,i=1,…,I,t=1,…,T
3. 使用MindOpt APL建模和求解
根据MindOpt APL的建模语法,建立此经济调度的完整模型,可如下两种方式运行。
3.1. 方法1:cell中直接输入代码
直接在cell中输入建模和求解的代码:
clear model; #清除环境内存,多次run的时候使用
option modelname ../model/vpp_single; #定义存储文件名
#### 多时段优化问题
set T := 1..4;
set T0 := 1..5; # T时段前后共T+1个状态点
#### 功率和负荷
param load[T] := <1> 0.15, <2> 0.12, <3> 0.12, <4> 0.22;
param power[T] := <1> 0.10, <2> 0.05, <3> 0.01, <4> 0.03;
#### 单位电价
param price[T] := <1> 0.54, <2> 0.22, <3> 0.32, <4> 0.24;
#### 充放电损耗系数
param charge_efficiency := 0.91;
param discharge_efficiency := 0.95;
#### 储能单次充放电限制
param nominal_power := 0.8;
#### 在不使用储能情况下的各指标,作为评测的对比基准值
param cost_base := sum{t in T} (load[t] - power[t]) * price[t];
#### 定义优化问题的变量
var x[T] >= 0 <= nominal_power; # 充电变量
var y[T] <= 0 >= - nominal_power; # 放电变量
var soc[T0] >= 0 <= 1; # State-of-Charge 储能设备状态
#### 定义优化目标函数
minimize Cost: sum{t in T} (load[t] - power[t] + x[t] + y[t]) * price[t] / cost_base;
#### 定义约束条件
subto State_of_Charge_Init: # 储能设备初始状态
soc[1] == 0;
subto State_of_Charge_Update: # 储能设备状态更新
forall {t in T} do
soc[t+1] == soc[t] + x[t] * charge_efficiency + y[t] / discharge_efficiency;
option solver mindopt; # 指定求解用的求解器
solve; # 求解
#### 展示结果
print "-----------------Display---------------";
print "Charging(+) / Discharging (-) Solution:";
forall {t in T} print 'Time {}: Solution {}' % t, x[t] + y[t];
forall {t in T0} print 'Time {}: State-of-Charge {}' % t-1, soc[t];
#### 评测指标
print "-----------------Evaluation Metrics---------------";
print "Cost = ";
print sum{t in T} (load[t] - power[t] + x[t] + y[t]) * price[t] / cost_base;
运行结果如下:
Running mindoptampl
wantsol=1
mip_integer_tolerance=1e-9
MindOpt Version 0.23.0 (Build date: 20221129)
Copyright (c) 2020-2022 Alibaba Cloud.
Start license validation (current time : 02-MAR-2023 13:48:19).
License validation terminated. Time : 0.002s
Model summary.
- Num. variables : 13
- Num. constraints : 4
- Num. nonzeros : 16
- Bound range : [8.0e-01,1.0e+00]
- Objective range : [1.8e+00,4.4e+00]
- Matrix range : [9.1e-01,1.1e+00]
Presolver started.
Presolver terminated. Time : 0.000s
Simplex method started.
Model fingerprint: =Y2dmZ2dvd3Y
Iteration Objective Dual Inf. Primal Inf. Time
0 -1.45041e+00 0.0000e+00 2.1141e+00 0.00s
3 6.32208e-01 0.0000e+00 0.0000e+00 0.00s
Postsolver started.
Simplex method terminated. Time : 0.002s
OPTIMAL; objective 0.63
3 simplex iterations
Completed.
-----------------Display---------------
Charging(+) / Discharging (-) Solution:
Time 1: Solution 0
Time 2: Solution 0.8
Time 3: Solution -0.6915999999999991
Time 4: Solution 0
Time 0: State-of-Charge 0
Time 1: State-of-Charge 0
Time 2: State-of-Charge 0.7280000000000001
Time 3: State-of-Charge 0
Time 4: State-of-Charge 0
-----------------Evaluation Metrics---------------
Cost =
0.6322077922077942
3.2. 方法2:导入.mapl文件来运行
我们可将建模部分的代码保存为 vpp_single.mapl
文件。然后运行如下code,进行建模和求解。
clear model; # 清除模型的内存
model ../model/vpp_single.mapl; # 链接.mapl模型文件,建模
option solver mindopt; # 指定求解用的求解器
solve; # 求解
#### 展示结果
print "-----------------Display---------------";
print "Charging(+) / Discharging (-) Solution:";
forall {t in T} print 'Time {}: Solution {}' % t, x[t] + y[t];
forall {t in T0} print 'Time {}: State-of-Charge {}' % t-1, soc[t];
#### 评测指标
print "-----------------Evaluation Metrics---------------";
print "Cost = ";
print sum{t in T} (load[t] - power[t] + x[t] + y[t]) * price[t] / cost_base;
运行结果与方法一一致。
4. 结果解析
- 在执行
model
命令后,MAPL将.mapl
中声明的数学规划模型转化成机器可以理解的模型。 - 在执行
solve
命令后,MAPL将启动mindopt求解器进行求解,此时屏幕会打印出mindopt的求解过程。同时会在.mapl文件的同目录下生成待求解问题文件vpp_single.nl
和解文件vpp_single.sol
。 - 在执行
print
命令后,MAPL将打印如下结果:
-----------------Display---------------
Charging(+) / Discharging (-) Solution:
Time 1: Solution 0
Time 2: Solution 0.8
Time 3: Solution -0.6931199999999991
Time 4: Solution 0
Time 0: State-of-Charge 0
Time 1: State-of-Charge 0
Time 2: State-of-Charge 0.7296
Time 3: State-of-Charge 0
Time 4: State-of-Charge 0
-----------------Evaluation Metrics---------------
Cost =
0.6282597402597423
其中显示了各时段储能决策变量的最优值分别为:
- 第一个小时:不进行储能操作(即:光伏直用,剩余需求从电网购买)。
- 第二个小时:充电80%。
- 第三个小时:放电69.3%。
- 第四个小时:不进行操作。
最终,我们可以得到最优目标函数为0.63,即上述最优储能调度对比不使用储能,可以节省37%电费。
为了简明起见,这个例子只用了4个时间段变量,但是相同的模型可以扩展到任意多个时间段,以满足更全面和准确的调度分析需求。