I. 简介
在大多数地方(至少在发达国家),人们从国家电网获得能源。这些能源来自不同的发电厂,如核电站或水电站。但在许多其他与世隔绝的地方,如岛屿(例如法国的韦桑岛),实施新的小型电网来满足岛上居民的电力需求更为恰当。建立一个新的电网比用海底电缆将岛屿连接到国家电网更具有成本效益。
一个小岛的电力需求显然不是整个地区的需求,所以核电站可以从一开始就被抛弃,水坝也是如此。通常可以归结为几个可再生能源生产基地和一台柴油发电机,以确保稳定的能源生产(主要是在太阳落山,风停止吹的时候)。
然而,在拿起你的锤子和螺丝刀之前,你必须准确地知道你的微型电网的尺寸。 电网的电力需求是多少?,我们可以估计到多少太阳和风资源?,我们应该建造多少光伏和风车?,我们的电池应该多大?,等等。所有这些问题都要经过优化:有多种成本需要优化,但主要是常规成本和环境成本,即二氧化碳排放。
不难看出,这就是一个多目标的优化问题,其中的变量仅仅是每个装置的大小(每个能源生产基地提供多少电力)。
因此,本项目的目的是给出一个端到端的程序,以优化电网规格的需求。输入应该是负荷(在一年中,每小时的电力需求是多少),以及一些限制条件(不超过3个风车,不超过一英亩的光伏,你的名字)。这个程序的输出主要是经过优化的多个成本函数的值,最重要的是,每个发电厂设施的大小。
II. 快速启动
首先在你的机器上用git 克隆这个仓库,然后下载以下软件包,如果它们在你的环境中已经存在或没有。
II.A. 软件包
- numpy 👉Python的基本科学库,内置数学函数和简单的数组处理。
- time 👉 仅用于打印计算时间。
- platypus 👉多目标优化库和它的库
- matplotlib.pyplot 👉用于绘制图形。
- pandas👉用于操作数据帧,这是一个Python对象,当我们操作大型数据集时,会很方便。
II.B. 代码执行
为了确保一切工作正常,在你最喜欢的编译器(Pyzo, Spyder, ...)中打开main.py并执行该文件。你应该看到弹出的图画。它们显示了优化过程的结果。
然后,如果你想更进一步,用你自己的数据运行优化器,我们更鼓励你修改optimizerTest()函数里面的参数。你应该在代码中寻找这些变量,并相应地修改它们。
fixedParameters =
{
"gridComponents": {
.
.
.
"strategy" : "LF"
}
constraints =
{
"diesel": {
"upperBound": 2000,
.
.
. "lowerBound": 0
}
III. 架构
以下是我们项目的架构。它被细分为多个包和模块,都有一个主要功能,就是帮助最终用户正确设计微电网的任务。
-
📑 README.md
-
📑 .gitignore
-
📑 main.py
-
📁 优化器
-
📑 optimizer.py
-
📑 optimizerV2.py
-
📁 模拟器
-
📁 调度
- 📑 dispatchingLoop.py
- 📑 dispatchingStrategy.py
-
📁 费用
-
📁 美元
-
📑 dollarCost.py
-
📁 电池
- 📑 auxilliaryCostFunctions.py
- 📑 batteryCost.py
-
📁 光伏
- 📑 auxilliaryCostFunctions.py
- 📑 pvCostAlt.py
- 📑 pvCost.py
-
📁 柴油
- 📑 auxilliaryCostFunctions.py
- 📑 dgCostAlt.py
- 📑 dgCost.py
-
📁 风车
- 📑 windCost.py
-
-
📁 碳排放
- 📑 carbonCost.py
-
-
-
IV. 模拟器
模拟器是一个简化的软件包,在给定电网各组成部分的尺寸后,可得出微电网的各种成本。例如。
项目的寿命是25年。我知道这个地方一整年的负荷情况。如果我有一个5千瓦时的电池,2个各2千瓦的风力涡轮机,价值3千瓦的光伏和3千瓦的柴油发电机(dg),需要多少钱(💸和⛽)?
dollarCost.py和carbonCost.py的函数计算了整个项目的全球成本和全球二氧化碳排放量。这些是优化器旨在最小化成本函数。
IV.A. 调度
在一年中,根据太阳辐照度或风速,你可能会交替开启和关闭柴油发电机,甚至在电池中储存能量以满足未来需求。例如,在夏季,有一个更高的太阳辐照,超过了白天的电力需求。因此,由于光伏和电池的存在,一部分能量可以直接消耗,而多余的能量可以储存在电池中。电池将在晚上太阳落山后放电。
在调度方面,我们可以采取两种不同的调度策略。 循环充电和负载跟随。
| 负载如下 | 循环充电 |
|---|---|
| 当可再生能源不足以为电网提供足够的能量时,我们可能想打开dg。如果我们遵循负载跟踪策略,我们首先检查电池中是否有足够的能量来完成能源供应。如果没有,我们就以精确地满足负载的速度开启数据中心。 | 这个案例与前一个案例完全相同,但这次我们不是以较低的速度打开DG,而是以既能满足负载又能为电池充满电的速度打开。 |
无论我们选择哪种策略,调度算法都会在每个时间段计算电池中储存的能量,以及在每个时间段计算dg的功能功率。它直接影响到燃料的消耗量以及电池的寿命,例如。
IV.B. 费用
IV.B.1. 电池
电池的成本是用以下公式计算的。
总成本 = 投资成本+(更换成本-残值成本)+运营成本
其中 :
- 投资成本基本上是指电池的价格。
- 更换成本是电池的价格乘以你在整个项目的生命周期内应该更换的次数,其中 :
- 残值成本是指在项目结束时,考虑到电池的剩余寿命,你可以期望出售电池的价格。
- 运营成本是你为你的劳动力操作和维护电池而支付的价格。
电池成本依赖于上述的调度。事实上,调度严重影响了电池的吞吐量(有多少能量流经电池),从而影响了电池的寿命,进而影响了更换的数量,最终影响成本。
IV.B.2. 柴油发电机
柴油发电机的成本是用以下公式计算的。
总成本 = 资本成本 + (更换成本 - 残值成本) + 运行和维护成本 + 燃料成本
其中 :
- 资本成本是柴油发电机的初始购买价格。
- 更换成本是指在发电机使用寿命结束时更换发电机的成本。
- 运行和维护成本是每年运行和维护发电机的成本。
- 残值成本是指在项目结束时,考虑到柴油发电机的剩余寿命,你可以预期出售的价格。
- 燃料成本是根据柴油的市场价格计算出的燃料消耗价格。
就像电池一样,柴油发电机的成本受到调度的严重影响。事实上,根据策略和调度结果,我们不能以相同的工作小时数来计算柴油发电机的成本,比如说。如果工作小时数不一样,寿命也不一样,因此替换的数量也不一样。 更换次数越多,费用越高。
IV.B.3. 光伏电池板
光伏的成本是用以下公式计算的:
总成本 = 资本成本+(更换成本-残值成本)+运营和维护成本
其中 :
- 资本成本是光伏的初始购买价格。
- 替换成本是指在光伏电池寿命结束时替换的成本。
- 运营和维护成本是每年运营和维护光伏的成本。
- 残值成本是指在项目结束时,考虑到光伏发电的剩余寿命,你可以期望出售的价格。
IV.B.4. 风力涡轮机
风力涡轮机的成本是用以下公式计算的:
总成本 = 资本成本 + (重置成本 - 残值成本) + 运行和维护成本
其中 :
- 资本成本是风轮机的初始购买价格。
- 更换成本是指在风轮机使用寿命结束时更换风轮机的成本。
- 运行和维护成本是每年运行和维护风轮机的成本。
- 残值成本是指在项目结束时,考虑到风轮机的剩余寿命,你可以期望以什么价格出售它们。
总成本 💸
综上所述的4个成本函数,我们可以计算出项目的总成本,以美元计。这将是优化器试图最小化的第一个成本函数。
二氧化碳排放量 ♻️
costCarbon.py模块的输入与dollarsCost.py模块的输入相同。costCarbon.emissionCO2()函数的输出将是整个项目生命周期的平均二氧化碳排放量(kgCO2e/h)。
输出的值(kgCO2e/h)取决于:
- 发电机的大小
- 电池的储存能力
- 光伏的额定功率
- 正在使用的调度策略
该函数中使用的固定参数是:
- 每升柴油消耗的二氧化碳排放量=2.65 kgCO2e/L
- 柴油发电机的上游系数=1.2(上游系数考虑到了柴油发电机的整个生命周期的碳足迹)
- 电池每个制造能力的二氧化碳排放量=0.72公斤二氧化碳/千瓦时
- 光伏的二氧化碳排放足迹=6gCO2e/kWh
碳成本函数将是我们的优化器旨在最小化的第二个函数。
V. 优化器
优化器是基于预先存在的python模块。给定一组要最小化的成本函数,优化器返回每个组件的尺寸,以便在平均时间内最小化成本函数。例如:
我想使成本和二氧化碳排放量最小化。我的光伏发电和风力发电机的数量有限,我的燃油机不能大于x,但我的电池没有限制。优化器将返回每个组件的功率规格,以使成本和碳排放最小化。
我们使用了用户友好的plapytus模块,不需要很多参数,它是这个项目里完美的 "黑匣子"。
我使用的具体算法是NSGA-II算法。它是一种非支配排序的遗传算法。我们尝试用不同的种群规模来比较这个算法的结果。结果图表展示了由优化变量产生的可行解决方案的集合(两个轴是要最小化的两个目标函数)。如图所示,我们能够确定帕累托前沿,以显示2个目标函数之间的可能权衡。
V.A. 成本函数
要最小化的两个成本函数是在模拟器中实现的 "美元成本 "和 "碳排放成本"。这些函数被作为参数传递给优化器。
V.B. 界限和参数
优化器迭代的参数是电池最大存储容量,发电机最大输出功率和太阳能安装功率。简单地说:每次迭代后,优化器都会稍微改变这三个值,看看它对 "美元成本 "和 "碳成本 "有什么影响,以便找到能够同时使两个函数最小化的三个值。该最优值被称为帕雷托最优值。
然而,由于我们没有无限的资源,我们不得不为三个变量中的每一个添加下限和上限(我们不能有负值也不能有无限的值)。
最后,这里是问题定义的样子。
problem = Problem(3, 2)
problem.types[:] = [Real(constraints["battery"]["lowerBound"], constraints["battery"]["upperBound"]), Real(constraints["diesel"]["lowerBound"], constraints["diesel"]["upperBound"]), Real(constraints["photovoltaic"]["lowerBound"], constraints["photovoltaic"]["upperBound"])]
problem.function = costFunction # 该函数返回[美元成本,碳成本]。
algorithm = NSGAII(problem) # NSGAII是用于解决优化问题的求解器
algorithm.run(1)
VI. 展望
VI.A. 效率
不幸的是,整个优化过程是计算昂贵的。事实上,在plytapus优化器的每次迭代之后,程序必须计算调度策略的结果(整个过程中dg和电池存储的功率输出),然后在多个长的列表中迭代,以计算各种成本("美元成本 "和 "碳成本")。
在这种配置下,对于一个1年的模拟和一个25年的项目,优化器运行一次,计算和显示结果需要较长时间。
一个解决方案是使用谷歌的资源来运行优化器(更多信息请见谷歌合作网站)。
VI.B. 只用一个求解器
我们只使用了plytapus提供的NSGAII求解器,而该库提供了许多其他求解器。我们应该尝试不同的求解器来比较它们的效率。
VI.C. 用户界面
这个项目的一个可能的扩展是编写一个友好的用户界面,由Python运行的本地服务器(例如Django或Flask)提供网页。更确切地说,可以有一个用html、css和js编码的网页,用户可以在那里输入和设置他的模拟参数。这些参数可以被发送到运行Python代码的本地服务器,然后在网页上动态地呈现优化的结果。
VII. 鸣谢
我们的工作经常得到我们的老师@CentraleSupélec的审查和指导。 Nabil Sadou和Pierre Haessig。
VIII. 许可证
本项目是根据CentraleSupélec许可证的条款授权的。
只要有提到贡献者或这个资源库,就允许复制和修改。
IX. 贡献者
- Yun Bin Choh - Student @ CentraleSupélec - lukecyb8687
- Paula Rayol - Student @ CentraleSupélec - paularayol
- Bastien Velitchkine - Student @ CentraleSupélec - Bassvelitchkine
{
grid Components: {
"电池": {
"initialStorage":介于0和1之间的浮点数,电池初始储能占其最大容量的百分比。
"maxInputPow":浮点数,对于1kWh的电池,电池的最大充电功率,单位是千瓦。实际值将通过乘以最大存储容量而得到。
"maxOutputPow": 浮点数,1kWh电池的最大放电功率,单位是kW。实际值将通过乘以最大存储容量而得到。
"SOC_min": 浮点数,电池中可以储存的最小能量,占最大储存容量的百分比。
"maxThroughput":浮点数,我们用最大存储量乘以该数字,得到电池在其寿命期间可以流入和流出的最大能量(千瓦时)。
"lifetime":int,电池的额定寿命,单位是小时。这是我们在没有超过最大吞吐量的情况下必须更换它的时间。
"capitalCost": float, 一个1kWh电池的成本,单位是美元。
"replacementCost": 浮点数,更换1kWh电池的成本,单位为美元。
"运行成本":浮动值,每小时运行和维护电池的成本($)。
},
"柴油": {
"fuelCost": 浮动的,1升燃料的成本($)。
"fuelCostGrad": float, 有一条燃料曲线,模拟了柴油机的功能功率和它每千瓦的升油消耗之间的关系。这个参数是模型曲线的斜率。
"fuelCostIntercept": 浮动,有一条燃料曲线,模拟了dg的功能功率和它每千瓦的升油消耗之间的关系。这个参数是模型曲线的截点。
"寿命": int, dg的额定寿命,以小时为单位。
"资本成本":浮动,dg的成本,单位是美元。
"替换成本":浮点数,替换dg的成本,单位是美元。
"运营成本":浮动,每小时的运营和维护成本。
},
"光伏": {
"寿命": int, 通道的额定寿命(小时)。
"capitalCost": float, 通道的成本,单位是美元。
"replacementCost": float, 替换一个通道的成本,单位是美元。
"运行成本":浮动,每小时运行和维护通道的成本(美元)。
"powerTimeVector": numpy数组,通道在每个时间步长的功率输出(千瓦)。
}
},
timeStep: float,产生负载的模拟时间步长,单位是小时。
loadVector: numpy数组,电网的电力需求(千瓦)。
projectDuration: int, 整个项目的持续时间,以小时为单位(如25 * 365 * 24)。
discountRate: float, 折扣率。
策略:"LF "或 "CC",分别表示"负载跟踪 " 或 "循环充电"
constraints{
"柴油"
{
"upperBound": float,发电机最大功率(千瓦)值的上限。
"lowerBound": float, 发电机最大功率(千瓦)值的下限。
},
"电池"
{
"upperBound": float,电池最大储存容量(千瓦时)的上限。
"lowerBound": float, 电池最大储存容量的下限(千瓦时)。
},
"光伏"
{
"upperBound": float, pv 最大功率 (千瓦) 值的上限。
"lowerBound": float, pv 最大功率 (千瓦) 值的上下限。
},
}
OUTPUT:
{
"参数"
{
"电池":浮动值,电池存储容量(千瓦时)。
"柴油":浮动值,发电机最大功率(千瓦)。
"光伏":浮动值,光伏的最大功率(千瓦)
},
"成本"
{
"美元":浮动,项目的成本,单位是美元。
"碳":浮动,项目产生的碳排放量(公斤)。
}
}
}