Matlab数学建模详解之发电机的最佳调度实现

🔗 运行环境:Matlab、Python

🚩 撰写作者:左手の明天

🥇 精选专栏:《python》

🔥  推荐专栏:《算法研究》

#### 防伪水印——左手の明天 ####

💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗

💗今天分享matlab数学建模算法——发电机的最佳调度💗

📆  最近更新:2023 年 12 月 03 日,左手の明天的第 298 篇原创博客

📚 更新于专栏:matlab

#### 防伪水印——左手の明天 ####


一、发电机的最佳调度

发电机的最佳调度,即如何以最佳方式调度两台燃气发电机,即收益减去成本的值最大。它是一个复杂的问题,需要考虑多种因素,包括负载调节、动态调速和调节励磁电流。

  1. 负载调节:通过调节发电机负载电流大小来调节发电机电量。在电气负荷变化较大时,可通过增加或减少负载电流的方式来调节发电机输出电量。
  2. 动态调速:通过调整发电机的转速来调节发电机输出电量。这种方法适用于机械负载较大、稳定性要求高的情况。
  3. 调节励磁电流:通过调节发电机的励磁电流来控制发电机输出电量。增大励磁电流可提高输出电量,减小励磁电流则可降低输出电量。

为了实现最佳调度,可以结合实际用电负荷的情况,考虑预测误差等因素,并采用适当的优化算法,确定每个时间段内发电机的最优调度策略。在某些情况下,还需要考虑发电机的启动和关闭时间,以及不同发电机之间的协同工作等问题。

总之,发电机的最佳调度需要综合考虑多种因素和技术手段,以达到提高供电可靠性和经济性的目的。


二、实现步骤

实现发电机的最佳调度需要使用到许多数学和计算机技术,其中MATLAB是一个非常强大的工具。以下是一个简单的步骤,说明如何使用MATLAB实现发电机的最佳调度:

1、数据收集与处理

首先,需要收集发电机运行的数据,包括历史发电数据、实时发电数据、电力需求数据、系统运行状态数据等。这些数据可以通过MATLAB的输入/输出函数(例如readtable、readmatrix)读取和处理。

2、负荷预测

利用收集到的历史负荷数据和实时数据,通过时间序列分析、机器学习或深度学习等方法进行负荷预测。MATLAB提供了大量的统计和机器学习工具箱,例如timeseries、neuralnet、ga等,可以用来进行负荷预测。

3、能源管理策略选择与建模

根据实际情况选择不同的能源管理策略,例如基于风能和太阳能的发电机组,以及基于天然气和石油等传统能源的发电机组。然后根据各种策略建立模型,这些模型可以包括功率平衡模型、优化模型等。

4、发电机组之间的协调和调度

针对多台发电机组之间的实时变化,进行协调和调度。这需要考虑到每台发电机的特性、运行状态、出力能力等因素,以及电力系统的稳定性要求和经济性要求。MATLAB的优化工具箱,例如quadprog、fmincon等,可以用来解决这类问题。

5、制定调度计划

根据负荷预测结果、能源管理策略和发电机组的协调和调度要求,制定合理的调度计划。MATLAB的日期和时间函数(例如datetime、now、adddays等)可以用来处理日期和时间问题,帮助制定合理的调度计划。

6、优化算法应用

利用MATLAB的优化工具箱,例如linprog、quadprog、fmincon等,对调度计划进行优化。这可以帮助找到更经济、更高效的调度方案,提高电力系统的运行效率。

7、实施调度与监控

根据优化后的调度计划,对发电机进行实际调度。在实施过程中,需要密切关注电力系统的运行状态和发电机的运行情况,及时调整调度计划以确保电力系统的稳定性和安全性。MATLAB的图形界面设计功能可以帮助设计一个实时的监控界面。

8、数据分析与评估

对调度过程中的数据进行深入分析,评估调度计划的实施效果。MATLAB的数据处理和分析工具箱,例如mean、std、corrcoef等,可以帮助进行数据分析。同时也可以根据数据分析结果对发电机的维护策略进行改进提高维护水平和效率。

以上步骤是一个基本的框架,具体实现还需要根据实际情况进行调整和完善。


三、问题定义

电力市场在一天的不同时段有不同用电价格。如果使用发电机供电,可以根据这种可变价格,安排发电机在用电价格高时运行。假设控制两台发电机。每台发电机有三个功率水平(关、低和高)。每台发电机在每个功率水平下都有指定的燃料消耗率和发电量。发电机关闭时,燃料消耗为 0。

可以为每台发电机在一天中的每个半小时区间(24 小时分为 48 个区间)分配一个功率水平。根据历史记录,假设知道在每个时间区间内每兆瓦时 (MWh) 的收入。

可以将调度问题表示为二元整数规划问题。定义索引 ij 和 k,以及二元调度向量 y,如下所示:

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

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

  • 对于此示例,j = 发电机索引,1 <= j <= 2。

  • 在时间段 i 中,发电机 j 在功率水平 k 上运行,表示为 y(i,j,k) = 1。让低功率为 k = 1,高功率为 k = 2。当 sum_k y(i,j,k) = 0 时,发电机关闭。

确定发电机关闭后何时启动。为此,定义辅助二元变量 z(i,j),该变量指示在时间段 i 中是否加电以启动发电机 j

  • 发电机 j 在时间段 i 关闭,但在时间段 i + 1 打开,表示为 z(i,j) = 1。在其他时间段 z(i,j) = 0。换句话说,当 sum_k y(i,j,k) = 0 时 z(i,j) = 1,且 sum_k y(i+1,j,k) = 1

需要一种基于 y 的设置自动设置 z 的方法。以下线性约束可处理此设置。

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

  • poolPrice(i) - i 区间内每兆瓦时的收入(以美元为单位)

  • gen(j,k) - 发电机 j 在功率水平 k 时产生的兆瓦数

  • fuel(j,k) - 发电机 j 在功率水平 k 时使用的燃料

  • totalFuel - 一天内可用的燃料

  • startCost - 发电机关闭后启动的成本(以美元为单位)

  • fuelPrice - 单位燃料的成本


四、matlab实现

🔰数据汇总分析

load dispatchPrice; % Get poolPrice, which is the revenue per MWh
bar(poolPrice,.5)
xlim([.5,48.5])
xlabel('Price per MWh at each period')

🔰按如下所示设置其他参数

fuelPrice = 3;
totalFuel = 3.95e4;
nPeriods = length(poolPrice); % 48 periods
nGens = 2; % Two generators
gen = [61,152;50,150]; % Generator 1 low = 61 MW, high = 152 MW
fuel = [427,806;325,765]; % Fuel consumption for generator 2 is low = 325, high = 765
startCost = 1e4; % Cost to start a generator after it has been off

🔰发电机效率

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

efficiency = gen./fuel; % Calculate electricity per unit fuel use
rr = efficiency'; % for plotting
h = bar(rr);
h(1).FaceColor = 'g';
h(2).FaceColor = 'c';
legend(h,'Generator 1','Generator 2','Location','NorthEastOutside')
ax = gca;
ax.XTick = [1,2];
ax.XTickLabel = {'Low','High'};
ylim([.1,.2])
ylabel('Efficiency')

请注意,在对应的工作点(低和高)上,发电机 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,nGens,{'Low','High'},'Type','integer','LowerBound',0,...
    'UpperBound',1);
z = optimvar('z',nPeriods,nGens,'Type','integer','LowerBound',0,...
    'UpperBound',1);

🔰线性约束

要确保功率水平最多只有一个等于 1 的分量,可设置线性不等式约束。

powercons = y(:,:,'Low') + y(:,:,'High') <= 1;

每个时间段的运行成本就是该时间段的燃料成本。对于在 k 水平上运行的发电机 j,成本为 fuelPrice * fuel(j,k)

创建表达式 fuelUsed 以说明使用的所有燃料。

yFuel = zeros(nPeriods,nGens,2);
yFuel(:,1,1) = fuel(1,1); % Fuel use of generator 1 in low setting
yFuel(:,1,2) = fuel(1,2); % Fuel use of generator 1 in high setting
yFuel(:,2,1) = fuel(2,1); % Fuel use of generator 2 in low setting
yFuel(:,2,2) = fuel(2,2); % Fuel use of generator 2 in high setting

fuelUsed = sum(sum(sum(y.*yFuel)));

约束是所用燃料不得超过可用燃料。

fuelcons = fuelUsed <= totalFuel;

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

如何让求解器自动设置 z 变量以匹配 y 变量的活动/关闭时间段?要满足的条件是当 sum_k y(i,j,k) = 0 且 sum_k y(i+1,j,k) = 1 时,z(i,j) = 1

请注意,当需要 z(i,j) = 1 时,sum_k ( - y(i,j,k) + y(i+1,j,k) ) > 0

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

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

此外,将 z 变量加入目标函数成本中。使用目标函数中的 z 变量,求解器尝试降低其值,这意味着它尝试将它们都设置为 0。但是,对于发电机开启的那些时间区间,线性不等式强制 z(i,j) 等于 1。

创建表示 y(i+1,j,k) - y(i,j,k) 的辅助变量 w。用 w 表示发电机启动不等式。

w = optimexpr(nPeriods,nGens); % Allocate w
idx = 1:(nPeriods-1);
w(idx,:) = y(idx+1,:,'Low') - y(idx,:,'Low') + y(idx+1,:,'High') - y(idx,:,'High');
w(nPeriods,:) = y(1,:,'Low') - y(nPeriods,:,'Low') + y(1,:,'High') - y(nPeriods,:,'High');
switchcons = w - z <= 0;

🔰定义目标

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

generatorlevel  = zeros(size(yFuel));
generatorlevel(:,1,1) = gen(1,1); % Fill in the levels
generatorlevel(:,1,2) = gen(1,2);
generatorlevel(:,2,1) = gen(2,1);
generatorlevel(:,2,2) = gen(2,2); 

收入 = y.*generatorlevel.*poolPrice

revenue = optimexpr(size(y));
for ii = 1:nPeriods
    revenue(ii,:,:) = poolPrice(ii)*y(ii,:,:).*generatorlevel(ii,:,:);
end

总燃料成本 = fuelUsed*fuelPrice

fuelCost = fuelUsed*fuelPrice;

发电机启动成本 = z*startCost

startingCost = z*startCost;

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

profit = sum(sum(sum(revenue))) - fuelCost - sum(sum(startingCost));

🔰求解问题

创建一个优化问题并加入目标和约束。

dispatch = optimproblem('ObjectiveSense','maximize');
dispatch.Objective = profit;
dispatch.Constraints.switchcons = switchcons;
dispatch.Constraints.fuelcons = fuelcons;
dispatch.Constraints.powercons = powercons;

为了节省空间,隐藏迭代输出。

options = optimoptions('intlinprog','Display','final');

求解。

[dispatchsol,fval,exitflag,output] = solve(dispatch,'options',options);
Solving problem using intlinprog.

Optimal solution found.

Intlinprog stopped because the objective value is within a gap tolerance of the optimal value, options.RelativeGapTolerance = 0.0001. The intcon variables are integer within tolerance, options.IntegerTolerance = 1e-05.

🔰检查解

将解绘制为时间的函数。

subplot(3,1,1)
bar(dispatchsol.y(:,1,1)*gen(1,1)+dispatchsol.y(:,1,2)*gen(1,2),.5,'g')
xlim([.5,48.5])
ylabel('MWh')
title('Generator 1 Optimal Schedule','FontWeight','bold')
subplot(3,1,2)
bar(dispatchsol.y(:,2,1)*gen(2,1)+dispatchsol.y(:,2,2)*gen(2,2),.5,'c')
title('Generator 2 Optimal Schedule','FontWeight','bold')
xlim([.5,48.5])
ylabel('MWh')
subplot(3,1,3)
bar(poolPrice,.5)
xlim([.5,48.5])
title('Energy Price','FontWeight','bold')
xlabel('Period')
ylabel('$ / MWh')

发电机 2 比发电机 1 运行时间长,这是您所期望的结果,因为这样效率更高。发电机 2 只要处于运行状态就以其高功率水平运行。发电机 1 主要在其高功率水平下运行,但在一个时间单位内降至低功率。每个发电机每天运行一组连续的时间段,因此每天只发生一次启动成本。

检查在发电机启动的时间段内 z 变量是否为 1。

starttimes = find(round(dispatchsol.z) == 1); % Use round for noninteger results
[theperiod,thegenerator] = ind2sub(size(dispatchsol.z),starttimes)
theperiod = 2×1

    23
    16

thegenerator = 2×1

     1
     2

发电机启动的时间段与绘图相匹配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/213220.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

String类 ---java

目录 一. 常用的字符串的构造 二. 字符串的源代码 三. 字符串比较 1. 是不能比较字符串的值的 ​编辑 2.比较两个字符串 --- compareTo() 3. 忽略大小写比较 ---compareToIgnoreCase() 四. 字符串转化 1. 数字转字符串 valueOf() 2. 字符串转数字 3. 小写转大写 to…

树莓派多串口通信

树莓派多串口通信 串口配置串口通信函数分析串口通信示例代码 参考博文1&#xff1a;树莓派 4 UART 多串口配置通信参考博文2&#xff1a;树莓派wiringPi库详解关于树莓派相关其他环境配置可参考&#xff1a;快速上手树莓派关于wiringPi库初始化与IO口开发可参考&#xff1a;树…

OpenLayer库的学习入门总结

前言&#xff1a; 作者跟随视频学习ol库的调用与功能实现&#xff0c;进行初步总结与回顾。 声明&#xff1a;参考新中地的文档&#xff0c;进行作者日后复习再次学习的简化。 1、WebGIS简介 GIS的核心概念 GIS&#xff08;Geographic Information System&#xff09;是一…

第 374 场 LeetCode 周赛题解

A 找出峰值 枚举 class Solution { public:vector<int> findPeaks(vector<int> &mountain) {int n mountain.size();vector<int> res;for (int i 1; i < n - 1; i)if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i 1…

中断方式的数据接收2

Echo实验 回忆之前的实验因为数据处理的过程可以瞬间完成所以可以把数据处理的操作放在中断服务函数中执行 但是数据处理要是时间过长就将数据缓存处理 当使用中断方式接收数据的时候 一般有两种方式 数据处理的时间较短可放在中断服务函数内处理&#xff08;就地处理&#…

【Linux--进程】

目录 一、基本概念1.1描述进程-PCB1.2task_struct中内容分类 二、了解进程2.1查看进程2.2通过系统调用获取进程标识符 三、fork创建进程3.1fork()函数3.2写时拷贝 四、进程的状态4.1操作系统学科里的进程状态&#xff08;运行、阻塞、挂起&#xff09;4.具体的Linux状态是如何维…

LinuxBasicsForHackers笔记 --常用Linux命令

在终端中修改用户密码命令&#xff1a;passwd Linux的文件系统是逻辑文件系统。 Linux基本命令 pwd – print working directory. 返回你当前所在目录结构中的位置。 whoami – 查看您当前登录的用户身份。 cd – change directory. 从终端更改目录。 cd / – 移动到根目录…

大数据实战项目_电商推荐系统

一、 项目介绍 HadoopSpark (Python)Scala SparkSQLSparkStreaming MongoDB Redis Kafka Flume ( SpringMVC vue) 1 项目介绍 1.1 项目系统架构 项目以推荐系统建设领域知名的经过修改过的中文亚马逊电商数据集作为依托&#xff0c;以某电商网站真实业务数据架构为基…

openGauss学习笔记-139 openGauss 数据库运维-例行维护-检查应用连接数

文章目录 openGauss学习笔记-139 openGauss 数据库运维-例行维护-检查应用连接数139.1 操作步骤139.2 异常处理 openGauss学习笔记-139 openGauss 数据库运维-例行维护-检查应用连接数 如果应用程序与数据库的连接数超过最大值&#xff0c;则新的连接无法建立。建议每天检查连…

淘宝商家店铺注册流程

如果本身已经有淘宝账号了&#xff0c;直接从第三步骤&#xff1a;创建店铺开始就可以了。一、注册淘宝账号、支付宝账号 首先,如果你有买家账号,是可以直接拿来开店的&#xff0c;不用单独在注册淘宝账号开店。 注意事项: 1:淘宝账号注册后,不能修改,如果会员名有写错情况&a…

【多线程】-- 10线程同步synchronized方法/块

多线程 6 线程同步 同步方法 由于我们可以通过private关键字来保证数据对象只能被方法访问&#xff0c;所以我们只需要针对方法提出一套机制&#xff0c;这套机制就是synchronized关键字&#xff0c;它包括以下两种用法&#xff1a; ​ synchronized方法和synchronized块 …

初始化 Clouder Manager 数据库报错Unable to find JDBC driver for database type: MySQL

CDH部署初始化 Clouder Manager 数据库报错。 解决方法&#xff1a; 把mysql驱动放到 /usr/share/java/目录下面(没有的新建&#xff09;&#xff0c;驱动名称也要修改为mysql-connector-java.jar 再次执行后成功&#xff1a; sudo /opt/cloudera/cm/schema/scm_prepare_data…

javaweb mybatis(手动jar包)

基础&#xff1a;https://blog.csdn.net/qq_67832732/article/details/134764134 条件查询 在映射文件的SQL配置中配置参数 使用parameterType来指定参数类型 使用#{参数名}来接收参数的值 parameterType"string" 表示sql语句需要一个参数&#xff0c;类型为字符…

串行口的工作原理及应用

前言 对最近串行口的学习进行一下总结。 参考链接 【51单片机】串口通信 - 知乎 (zhihu.com) LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;_proteus数码管显示-CSDN博客 定时器/计数器的应用-CSDN博客 74ls164_百度百科 (baidu.com) 74ls165中文资…

Kafka 的特点和优势

Apache Kafka 作为一款分布式流处理平台&#xff0c;以其独特的特点和卓越的优势成为实时数据处理领域的瑰宝。本文将深入研究 Kafka 的各项特点和优势&#xff0c;并通过详实的示例代码展示其在不同场景下的强大应用。 高吞吐量和水平扩展 Kafka 的设计注重高吞吐量和水平扩…

使用外部编辑器编辑执行MAXScript代码的方法

如何使用外部编辑器编辑执行MAXScript代码&#xff1f;这里我们要借助一个3dMax插件程序MXSCOM&#xff0c;MXSCOM允许从外部代码编辑器编辑和执行3ds Max MaxScript和Python文件。 2005年&#xff0c;Simon Feltman发布了第一个MXSCOM&#xff0c;这是一个小型的Visual Basic …

【Delphi】实现彩色日志显示框

目录 一、前言 二、实现方法 1. 第一步 2. 第二步 3. 第三步 三、主程序代码 四、下载 1. 可执行程序 2. 程序源代码 一、前言 在用Delphi做日常开发的时候&#xff0c;经常需要显示程序运行的日志&#xff0c;一般我们会使用TMemo&#xff0c;使用起来简单&#xff0c…

根据关键词写作文章的软件,根据标题写作文章的工具

在当今信息化时代&#xff0c;人工智能技术的飞速发展&#xff0c;智能AI写作工具逐渐成为文案创作者的得力助手。这些工具不仅能够根据标题迅速生成文章&#xff0c;而且在提高创作效率的同时&#xff0c;也为我们节省了大量时间和精力。 人工智能的基本原理&#xff1a;人工智…

Python遥感开发之快速判断TIF数据为空

Python遥感开发之快速判断TIF数据为空 前言&#xff1a;介绍一下如何使用python下的gdal读取tif数据的时候&#xff0c;快速判断该tif数据是否为空&#xff0c;如果为空的话就把当前的tif删掉。 如图所示&#xff0c;通过arcgis查看箭头指向的为空值。 仅通过文件的大小无法判…

java 工具类: CompareUtils(比较对象字段值变化)

一、前言 我们在工作中&#xff0c;可能会在日志中记录数据的变化情况或者在公共处理的数据增加一个日志页面&#xff0c;记录每次修改的变化。我们可以根据CompareUtils工具类比较数据前后发生了怎样的变化, 这样我们就可以知道数据做了哪些改变. 二、条件限制 在写这个通用…