主要内容

基于问题的发电机最优调度

这个例子展示了如何最优地调度两台燃气发电机,这意味着获得最大的收入减去成本。虽然这个例子并不完全现实,但它确实说明了如何考虑取决于决策时机的成本。

有关此问题的基于求解器的方法,请参见基于求解器的发电机最优调度

问题定义

电力市场在一天的不同时间有不同的价格。如果你有发电机供应电力,你可以利用这个可变定价,安排你的发电机在价格高的时候运行。假设您控制两个生成器。每个发电机有三个功率级(关闭、低和高)。每台发电机在每个功率级都有指定的燃料消耗率和发电量。当发电机关闭时,燃料消耗为0。

您可以为每个发电机分配一天中每半个小时的时间间隔(24小时,也就是48个间隔)的功率级别。根据历史记录,假设您知道在每个时间间隔中收到的每兆瓦时(MWh)收入。本例的数据来自澳大利亚能源市场运营商https://www.nemweb.com.au/REPORTS/CURRENT/2013年中期,按照他们的条款使用https: //www。aemo。com。非盟/privacy-and-legal-notices /copyright-permissions

负载dispatchPrice获取poolPrice,这是每兆瓦时的收入栏(poolPrice。5)xlim([5, 48.5])包含(“每个时期每兆瓦时的价格”

图中包含一个axes对象。axes对象包含一个bar类型的对象。

在发电机关闭后再启动是有成本的。此外,当天的最大燃料使用量也有限制。这种限制的存在是因为你会提前一天购买燃料,所以你只能使用刚刚购买的燃料。

问题符号和参数

您可以将调度问题表述为一个二进制整数规划问题。定义索引j,k和一个二进制调度向量y,如下所示:

  • nPeriods=时间段的数量,在本例中为48。

  • =一个时间段,1 <=< = 48。

  • j=生成器索引,1 <=j对于本例,<= 2。

  • y (i, j, k) = 1当时间、发电机j是否在功率级运行k.让低功率成为现实k = 1,和高功率是k = 2.发电机关闭时Sum_k y(i,j,k) = 0

确定发电机在关闭后何时启动。为此,定义辅助二进制变量z (i, j)指示是否为打开发电机收费j在期

  • z (i, j) = 1当发电机j在某段时间关闭,但在期间是开的我+ 1z (i, j) = 0否则。换句话说,z (i, j) = 1Sum_k y(i,j,k) = 0而且Sum_k y(i+1,j,k) = 1

你需要一个方法来设置z自动根据的设置y.下面的线性约束处理此设置。

您还需要关于成本、每个发电机的发电水平、发电机的消耗水平和可用燃料的问题参数。

  • poolPrice(我)——以美元/兆瓦时为单位的收入

  • 创(j, k)——发电机产生的MWj在功率k

  • 燃料(j, k)——发电机使用的燃料j在功率k

  • totalFuel一天可用燃料

  • startCost——发电机关闭后启动的成本(以美元计)

  • fuelPrice——单位燃料的成本

你有poolPrice当你执行加载dispatchPrice;.其他参数设置如下。

fuelPrice = 3;totalFuel = 3.95 e4;nPeriods =长度(poolPrice);% 48期ngen = 2;%两个发电机创= (61152;50150);%发电机1低= 61 MW,高= 152 MW燃料= (427806;325765);2号发电机的%油耗低= 325,高= 765startCost = 1 e4;%发电机关闭后启动的费用

发电机效率

检查两台发电机在其两个工作点的效率。

效率= /燃料将军;计算每单位燃料使用的电量rr =效率”;%的策划h =酒吧(rr);h(1)。FaceColor =‘g’;h(2)。FaceColor =“c”;传奇(h,发电机1的《发电机2》“位置”“NorthEastOutside”) ax = gca;斧子。XTick = [1, 2];斧子。XTickLabel = {“低”“高”};ylim ([1, 2]) ylabel (“效率”

图中包含一个axes对象。坐标轴对象包含两个bar类型的对象。这些对象表示Generator 1和Generator 2。

注意,在其相应的工作点(低和高)上,发电机2比发电机1更有效率,但发电机1在其高工作点上比发电机2在其低工作点上更有效率。

变量的解决方案

要设置问题,需要以问题的形式对所有问题数据和约束进行编码。的变量y (i, j, k)表示问题的解,以及辅助变量z (i, j)指示是否为打开发电机收费。y是一个nPeriods-by-nGens-by-2数组,并z是一个nPeriods-by-nGens数组中。所有变量都是二进制的。

y = optimvar (“y”nPeriods ngen, {“低”“高”},“类型”“整数”下界的0,...“UpperBound”1);z = optimvar (“z”nPeriods ngen,“类型”“整数”下界的0,...“UpperBound”1);

线性约束条件

为了保证功率级别中不存在一个等于1的分量,可以设置一个线性不等式约束。

powercons = y (:,:“低”) + y (:,:“高”) < = 1;

每一时期的运行成本是该时期的燃料成本。为发电机j操作的级别k,成本为fuelPrice *燃料(j, k)

创建一个表达式fuelUsed这就是所用的所有燃料。

yFuel = 0 (nPeriods ngen 2);yFuel(:, - 1, - 1) =燃料(1,1);发电机1在低设置下的燃料使用量yFuel(:, 1, 2) =燃料(1、2);1号发电机在高设定时的燃料使用量yFuel(: 2 1) =燃料(2,1);2号发电机在低设置下的燃料使用量yFuel(: 2 2) =燃料(2,2);2号发电机在高设定时的燃料使用量fuelUsed =总和(总和(sum (y。* yFuel)));

限制是使用的燃料不能超过可用的燃料。

fuelcons = fuelUsed <= totalFuel;

设置发电机启动指示器变量

如何让解算器设置z变量自动匹配的激活/关闭周期y变量?回想一下要满足的条件是z (i, j) = 1什么时候Sum_k y(i,j,k) = 0而且Sum_k y(i+1,j,k) = 1

请注意,Sum_k (- y(i,j,k) + y(i+1,j,k)) > 0当你想的时候z (i, j) = 1

因此,在问题的表述中包含这些线性不等式约束。

Sum_k (- y(i,j,k) + y(i+1,j,k)) - z(i,j) < = 0

此外,包括z目标函数中的变量代价。与z对于目标函数中的变量,求解器会尝试降低它们的值,这意味着它会尝试将它们全部设置为0。但是当发电机启动的时候,线性不等式就产生了z (i, j)等于1。

创建一个辅助变量w代表y (i + 1 j k) - y (i, j, k).将发电机启动不等式表示为w

w = optimexpr (nPeriods ngen);%分配widx = 1:(nPeriods-1);w (idx:) = y (idx + 1:“低”) - y (idx:,“低”) + y (idx + 1:“高”) - y (idx:,“高”);w (nPeriods:) = y (1:“低”) - y (nPeriods:,“低”) + y (1:“高”) - y (nPeriods:,“高”);Switchcons = w - z <= 0;

定义目标

目标函数包括运行发电机的燃料成本、运行发电机的收入和启动发电机的成本。

generatorlevel = 0(大小(yFuel));generatorlevel(:, - 1, - 1) =创(1,1);填写关卡generatorlevel(:, 1, 2) =创(1、2);generatorlevel(: 2 1) =创(2,1);generatorlevel(: 2 2) =创(2,2);

收入= y* generatorlevel。* poolPrice

收入= optimexpr(大小(y));2 = 1: nPeriods收入(ii):,:) = poolPrice (ii) * y (ii):,:)。* generatorlevel (ii):,:);结束

总燃料成本=fuelUsed * fuelPrice

fuelCost = fuelUsed * fuelPrice;

发电机启动成本=z * startCost

startingCost z = * startCost;

利润=收入-燃料总成本-启动成本。

利润= sum(sum(sum(revenue))) -燃料成本- sum(sum(startingCost));

解决这个问题

创建一个优化问题,包括目标和约束条件。

调度= optimproblem (“ObjectiveSense”“最大化”);调度。目标=利润;dispatch.Constraints.switchcons = switchcons;dispatch.Constraints.fuelcons = fuelcons;dispatch.Constraints.powercons = powercons;

为了节省空间,抑制迭代显示。

选择= optimoptions (“intlinprog”“显示”“最后一次”);

解决这个问题。

[dispatchsol, fval exitflag、输出]=解决(调度,“选项”、选择);
使用intlinprog解决问题。找到最优解。Intlinprog停止是因为目标值在最优值、选项的差距容忍范围内。RelativeGapTolerance = 0.0001(默认值)。intcon变量是公差范围内的整数,选项。IntegerTolerance = 1e-05(默认值)。

检查解决方案

把解画成时间的函数。

次要情节(1,1)栏(dispatchsol.y(:, 1, 1) *创(1,1)+ dispatchsol.y(:, 1, 2) *创(1、2),5,‘g’) xlim ([5, 48.5]) ylabel (“MWh”)标题(“Generator 1最优调度”“FontWeight”“大胆”次要情节(3、1、2)酒吧(dispatchsol.y(:, 2, 1) *(2, 1)一代+ dispatchsol.y(:, 2, 2) *创(2,2),5,“c”)标题(“Generator 2最优调度”“FontWeight”“大胆”) xlim ([5, 48.5]) ylabel (“MWh”) subplot(3,1,3) bar(poolPrice,.5) xlim([.5,48.5]) title(能源价格的“FontWeight”“大胆”)包含(“时间”) ylabel (“美元/千瓦时”

图中包含3个轴对象。标题为Generator 1 Optimal Schedule的Axes对象1包含一个类型为bar的对象。标题为Generator 2 Optimal Schedule的Axes对象2包含一个类型为bar的对象。标题为Energy Price的Axes对象3包含一个类型为bar的对象。

2号发电机运行的时间比1号发电机长,这是意料之中的,因为它的效率更高。2号发电机在开机时以高功率运行。发电机1主要运行在它的高功率水平,但下降到低功率的一次单位。每个发电机每天运行一组连续的周期,因此,每天只产生一个启动成本。

检查z变量为1表示发电机启动时的周期。

Starttimes = find(round(dispatchsol.z) == 1);%对非整数结果使用整数(年度变化平均数低于thegenerator] = ind2sub(大小(dispatchsol.z),开始时间)
年度变化平均数低于=2×123日16
thegenerator =2×11 2

生成器开始时的周期与图相匹配。

与较低的启动罚款相比

如果指定较低的值startCost,解决方案涉及多个生成周期。

startCost = 500;选择较低的惩罚启动发电机。startingCost z = * startCost;利润= sum(sum(sum(revenue))) -燃料成本- sum(sum(startingCost));调度。目标=利润;[dispatchsolnew, fvalnew exitflagnew outputnew] =解决(调度,“选项”、选择);
使用intlinprog解决问题。找到最优解。Intlinprog停止是因为目标值在最优值、选项的差距容忍范围内。RelativeGapTolerance = 0.0001(默认值)。intcon变量是公差范围内的整数,选项。IntegerTolerance = 1e-05(默认值)。
次要情节(1,1)栏(dispatchsolnew.y(:, 1, 1) *创(1,1)+ dispatchsolnew.y(:, 1, 2) *创(1、2),5,‘g’) xlim ([5, 48.5]) ylabel (“MWh”)标题(“Generator 1最优调度”“FontWeight”“大胆”次要情节(3、1、2)酒吧(dispatchsolnew.y(:, 2, 1) *(2, 1)一代+ dispatchsolnew.y(:, 2, 2) *创(2,2),5,“c”)标题(“Generator 2最优调度”“FontWeight”“大胆”) xlim ([5, 48.5]) ylabel (“MWh”) subplot(3,1,3) bar(poolPrice,.5) xlim([.5,48.5]) title(能源价格的“FontWeight”“大胆”)包含(“时间”) ylabel (“美元/千瓦时”

图中包含3个轴对象。标题为Generator 1 Optimal Schedule的Axes对象1包含一个类型为bar的对象。标题为Generator 2 Optimal Schedule的Axes对象2包含一个类型为bar的对象。标题为Energy Price的Axes对象3包含一个类型为bar的对象。

Starttimes = find(round(dispatchsolnew.z) == 1);%对非整数结果使用整数(年度变化平均数低于thegenerator] = ind2sub(大小(dispatchsolnew.z),开始时间)
年度变化平均数低于=3×122日16 45
thegenerator =3×11 2 2

相关的话题

Baidu
map