多微电网案例——分布式能源交易(Matlab代码实现)

简介: 多微电网案例——分布式能源交易(Matlab代码实现)

💥1 概述

在人类、工业和电动汽车的能源需求的推动下,全球能源需求预计将在未来几年稳步增长;更准确地说,预计到 2030 年增长将达到 40%。这种需求是由人类日益依赖能源的生活方式、电动汽车作为主要交通工具的出现以及机器将促进流程的进一步自动化。在当今的电网中,能源是在集中式和大型能源工厂(微电网能源发电)中生产的;然后,将能量传输到最终客户端,通常是通过非常远的距离并通过复杂的能量传输网格。如此复杂的结构,灵活性降低,难以适应需求增长,从而增加了电网不稳定和停电的概率。影响是巨大的,最近欧洲和北美的停电造成了数百万欧元的损失就证明了这一点。


在这种情况下,微电网正在成为一种有前途的能源解决方案,其中分布式(可再生)能源正在满足当地需求。当当地生产无法满足微电网要求时,从主要公用事业公司购买能源。设想微电网将提供许多好处,例如电力输送的可靠性(例如,通过岛屿),通过增加可再生能源的普及率来提高效率和可持续性,可扩展性和投资延期,以及提供辅助服务。孤岛是微电网的突出特征之一,是指能够断开微电网负荷与主电网的连接,并通过当地能源专门为其供电。在主电网无法支持总需求和/或运营商检测到一些可能退化为停电的主要电网问题的情况下,将执行预期孤岛。在这些情况下,微电网可以提供足够的能量,至少可以保证基本的电力服务。一旦整个系统再次稳定,将恢复与主电网的连接。显然,这些都是可能导致不稳定的重要功能。


为了提高智能电网的能力,一种典型的方法是考虑几个微电网相互交换能量的情况,即使这些微电网是孤岛的,即与主电网断开连接。换言之,在一组连续的微电网内部存在能量流,但在微电网和主电网之间不存在能量流动。在这种背景下,最优潮流问题最近引起了相当大的关注。例如,Ochoa 和 Harrison 联合考虑了协调电压控制的潮流问题。或者,相关文献中的工作侧重于不平衡配电网络,并提出了一种基于牛顿下降法解决三相潮流问题的方法。由于这些集中式解决方案可能会受到可扩展性和隐私问题的影响,一般来说,最优潮流问题是非凸的;因此,精确的解决方案可能太复杂而无法计算。因此,经常采用次优方法。一些文献中采用所谓的乘法器交替方向方法(参以分布式方式解决潮流问题。、


在本文中,为孤岛微电网之间的能源交易开发了一个分布式凸优化框架。更具体地说,该问题由几个孤岛微电网组成,这些电网通过任意拓扑交换能量流。由于可扩展性问题,为了保护成本函数的局部信息,讲解了一种基于次梯度的成本最小化算法,该算法在实际迭代次数内收敛到最优解。此外,这种方法允许进行非常直观的经济学解释,从“供需模型”和“市场清算”的角度解释算法迭代数值结果给出了算法的收敛速度和不同网络拓扑的实现成本。


📚2 运行结果

考虑一个由 M 个相互连接的微电网组成的多微电网系统,该微电网在孤岛模式下运行。在每个调度间隔期间,每个微电网 产生个单位的电能并消耗个单位的电能。此外,可以允许出售电能),并从)购买能量。然后,内的电能平衡需要:  


         

部分代码:

%% 创建成本函数
    %=====发电机成本函数======
    C = cell(1,M);
    C_prime = cell(1,M);
    C_primeInv = cell(1,M);
    for m=1:M
        [C{m}, C_prime{m}, C_primeInv{m}] = create_cost_func(generators{m}, .98*Pmax(m));
    end
    %====变压器成本函数==========
    [gamma_cost, gamma_prime, gamma_primeInv] = create_cost_func(a, b, c, CableCapacity);
    %% 调试
    if IsDebug || verbose
        lambda_fig = figure;
        title('Lambdas');
        xlabel('迭代次数');
        cost_fig = figure;
        title('Local Costs');
        xlabel('iterations');
        gap_fig = figure;
        title('Duality Gap');
        xlabel('迭代次数');
        ellipse = figure;
        hold on
    end
    %% 为 Lambda 找到(松散的)边界
    Lambdas_min = inf;
    Lambdas_max = -inf;
    for mm = 1:M
        tmp = C_prime{mm}(0);
        if Lambdas_min > tmp
            Lambdas_min = tmp;
        end
        tmp = C_prime{mm}(1.01*max(Pmax(mm),E_c(mm)));
        if Lambdas_max < tmp
            Lambdas_max = tmp;
        end
    end
    % Initialize Lambdas and containing ellipsoid
    Lambdas = (Lambdas_min + Lambdas_max)/2*ones(M,1);
    radius2 = (Lambdas_max - Lambdas_min)^2/2;
    ElpsMatrix = eye(M) * radius2;
    if IsDebug || verbose
        updateplots(lambda_fig,1,Lambdas);
        if M == 2
            figure(ellipse)
            line([Lambdas_min*[1 1] Lambdas_max*[1 1]], [Lambdas_min Lambdas_max*[1 1] Lambdas_min])
            plotellipse(ElpsMatrix, Lambdas(1), Lambdas(2))
            plot(Lambdas(1), Lambdas(2), 'xk')
            set(gca,'DataAspectRatio',[1 1 1])
        end
    end
    %% 主要算法
    E_min = zeros(M);
    E_sell = zeros(M,1);
    counter = 1;
    cost = zeros(M,1);
    cost2 = zeros(M,1);
    duality_gap = 10;
    Cbest = -inf;
    subg_nrmlz = inf;
    while counter < MaxIterations && (subg_nrmlz > MaxEpsilon)% || abs(duality_gap) > MaxDualityGap)
        counter = counter+1;
        %===对于给定的Lambdas,解决微电网局部问题====
        for ii=1:M
            [E_sell(ii), E_min(:,ii)] = local_problem(E_c(ii), A(:,ii), Lambdas(ii), Lambdas, C_prime{ii}, C_primeInv{ii}, gamma_prime, gamma_primeInv);
        end
        %=====计算对偶成本函数的次梯度=====
        subgradient = sum(E_min,2) - E_sell;
        %====并对解椭球进行归一化处理======
        subg_nrmlz = sqrt(subgradient'*ElpsMatrix*subgradient);
        subgradient = subgradient / subg_nrmlz;
        %====计算给定Lambdas的总成本=====
        tmp = 0;
        for mm = 1:M
            tmp = tmp + C{mm}(E_c(mm) + E_sell(mm) - sum(E_min(:,mm))) + sum(gamma_cost(E_min(:,mm))) + sum(Lambdas.*E_min(:,mm)) - Lambdas(mm)*E_sell(mm);
        end
        if Cbest < tmp
            Cbest = tmp;
        end
        %====更新Lambdas并包含椭球体=============
        alpha_step = 0;%(Cbest - tmp)/subg_nrmlz;
        jump = ElpsMatrix * subgradient;
        Lambdas_old = Lambdas;
        Lambdas = Lambdas + (1 + M*alpha_step)/(M+1) * jump;
        ElpsMatrix_old = ElpsMatrix;
        ElpsMatrix = M^2/(M^2-1)*(1-alpha_step^2)*(ElpsMatrix - 2*(1+M*alpha_step)/(M+1)/(1+alpha_step)*(jump*jump'));
        %====确保解决方案是可以接受的====
        radi = eig(ElpsMatrix);
        if any(radi<-.1)
            alpha_step = 0;
            Lambdas = Lambdas_old + (1 + M*alpha_step)/(M+1) * jump;
            ElpsMatrix = M^2/(M^2-1)*(1-alpha_step^2)*(ElpsMatrix_old - 2*(1+M*alpha_step)/(M+1)/(1+alpha_step)*(jump*jump'));
        end
        radi = eig(ElpsMatrix);
        if any(radi)<-.1
            fprintf('cucu')
        end
        %====检查新的 Lambas 是否在原来的范围内======
        while any(Lambdas < Lambdas_min)
            for mm = 1:M
                if Lambdas(mm) < Lambdas_min
                    subgradient = zeros(M,1);
                    subgradient(mm) = -1;
                    subg_nrmlz = sqrt(ElpsMatrix(mm,mm));
                    subgradient = subgradient / subg_nrmlz;
                    alpha_step = (-Lambdas(mm)+Lambdas_min)/subg_nrmlz;
                    jump = ElpsMatrix * subgradient;
                    Lambdas = Lambdas - (1 + M*alpha_step)/(M+1) * jump;
                    ElpsMatrix = M^2/(M^2-1)*(1-alpha_step^2)*(ElpsMatrix - 2*(1+M*alpha_step)/(M+1)/(1+alpha_step)*(jump*jump'));
                    subg_nrmlz = inf;
                end
            end
        end
        %====这不完全是对偶差距,但有助于说明收敛性====
        duality_gap = sum(Lambdas.*(sum(E_min,2)-E_sell));
        if (IsDebug && mod(counter,1)==0) || (verbose && mod(counter,50)==0)
            fprintf('Iteration %d: volume = %e --- epsilon = %f --- duality gap = %f\n', counter, prod(radi), subg_nrmlz, duality_gap)
            fprintf('\nLambdas =\n');
            fprintf('        %-10.4f\n',Lambdas);
            fprintf('E_min =\n');
            fprintf(['        ' repmat('%-10g',1,M) '\n'],E_min');
            updateplots(lambda_fig,counter,Lambdas);
            fprintf('\nE_sell = \n');
            fprintf('        %-10g \n',E_sell');
            E_gen = E_c+sum(E_min,2)-sum(E_min,1)';
            fprintf('\nE_gen =           E_c = \n');
            fprintf('        %-10g       %-10g\n',[E_gen E_c]');
            for m=1:M
                cost(m) = C{m}(E_gen(m)) + sum(gamma_cost(E_min(:,m)));
                cost2(m) = C{m}(E_c(m) + E_sell(m) - sum(E_min(:,m),1)) + sum(gamma_cost(E_min(:,m))) ...
                    + sum(Lambdas.*E_min(:,m)) - Lambdas(m) * E_sell(m);
            end
            fprintf('\nTotal energy cost: %f (%f) USD per hour.\n\n', sum(cost), sum(cost2));
            updateplots(cost_fig,counter,cost);
            updateplots(gap_fig,counter,duality_gap);
            if M==2
                figure(ellipse)
                plotellipse(ElpsMatrix,Lambdas(1),Lambdas(2))
                plot(Lambdas(1),Lambdas(2),'xk')
            end
            fprintf([repmat('-',1,50) '\n']);
            pause(1);
        end
    end
    if IsDebug
        updateplots(lambda_fig,counter,Lambdas);
        updateplots(cost_fig,counter,cost);
        updateplots(gap_fig,counter,duality_gap);
    end
    %% 输出
    fprintf('\nSimulation ended after %d iterations.', counter);
    fprintf('\nFinal duality gap: %f.\n\n', duality_gap);
    fprintf('Lambdas =\n');
    fprintf('        %-10.4f\n',Lambdas);
    fprintf('E_min =\n');
    fprintf(['        ' repmat('%-12g',1,M) '\n'],E_min');
    fprintf('\nE_sell = \n');
    fprintf('        %10g   (%10g)\n',[ sum(E_min,2)'; E_sell']);
    E_gen = E_c+sum(E_min,2)-sum(E_min,1)';
    fprintf('\nE_gen =             E_c = \n');
    fprintf('        %-12g       %-12g\n',[E_gen E_c]');
    gen_cost = zeros(M,1);
    tx_cost = zeros(M,1);
    for m=1:M
        gen_cost(m) = C{m}(E_gen(m));
        tx_cost(m) =  sum(gamma_cost(E_min(:,m)));
        cost2(m) = C{m}(E_c(m) + E_sell(m) - sum(E_min(:,m),1)) + sum(gamma_cost(E_min(:,m))) ...
            + sum(Lambdas.*E_min(:,m)) - Lambdas(m) * E_sell(m);
    end
    cost = gen_cost + tx_cost;
    uGcosts(:,icase) = cost2;
    fprintf('\nTotal energy cost per microgrid:')
    fprintf('\n            Generation         Transmission       Total\n')
    fprintf('            %-12g       %-12g       %-12g\n',[gen_cost tx_cost cost]')
    fprintf('\nTotal energy cost: %f (%f) USD per hour.\n\n', sum(cost), sum(cost2));
    Sell4(icase) = sum(E_min(M,:));
    Price(icase) = Lambdas(M);
end
%% 可视化
figure
plot(inputdata{:,end-2},uGcosts'/1000)
xlabel('E_4^{(c)} [MWh]')
ylabel('成本[k$]')
grid
axis([0 12 0 1.4])
hold
plot(inputdata{:,end-2},C{1}(inputdata{:,1})/1000,'k--')
plot(inputdata{:,end-2},C{1}(inputdata{:,end-2})/1000,'k-.')
legend('uG1','uG2','uG3','uG4','disc. {1,2,3}','disc. 4','Location','northwest')
saveas(gcf, 'local_costs.png')
figure
hh = plotyy(inputdata{:,end-2},Sell4,inputdata{:,end-2},[Price Sell4.*Price]/1000);
xlabel('E_4^{(c)} [MWh]')
ylabel(hh(1),'[MWh]')
ylabel(hh(2),'[k$]')
grid
axis(hh(1),[0 12 0 3.6])
set(hh(1),'YTick',0:3)
axis(hh(2),[0 12 0 1.8])
set(hh(2),'YTick',0:.5:1.5)
legend('售出电能', '单价', '收益')
saveas(gcf, 'trading.png')

🎉3 参考文献

部分理论来源于网络,如有侵权请联系删除。

[1]David Gregoratti, Javier Matamoros (2018) Distributed Energy Trading: The Multiple-Microgrid Case.


[2]李长宇,唐文秀.基于数据驱动的多微电网互联系统分布鲁棒运行优化[J].智慧电力,2022,50(05):1-8.

🌈4 Matlab代码实现

相关文章
|
3月前
|
存储 监控 固态存储
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN 分布式存储虚拟化平台VMDK文件1KB问题数据恢复案例
在一例vSAN分布式存储故障中,因替换故障闪存盘后磁盘组失效,一台采用RAID0策略且未使用置备的虚拟机VMDK文件受损,仅余1KB大小。经分析发现,该VMDK文件与内部虚拟对象关联失效导致。恢复方案包括定位虚拟对象及组件的具体物理位置,解析分配空间,并手动重组RAID0结构以恢复数据。此案例强调了深入理解vSAN分布式存储机制的重要性,以及定制化数据恢复方案的有效性。
94 5
|
17天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
22天前
|
程序员
后端|一个分布式锁「失效」的案例分析
小猿最近很苦恼:明明加了分布式锁,为什么并发还是会出问题呢?
30 2
|
1月前
|
分布式计算 NoSQL Java
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
43 2
|
3月前
|
存储 固态存储 虚拟化
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN ESXi超融合HCI分布式存储数据恢复案例
近期,我司处理了一个由10台华为OceanStor存储组成的vSAN超融合架构,其中一台存储闪存盘出现故障,用户取下后用新的闪存盘代替,然后对该闪存盘所在的磁盘组进行重建,导致集群中一台使用0置备策略的虚拟机数据丢失。
78 6
|
4月前
|
分布式计算 API 对象存储
Ray是一个开源的分布式计算框架,用于构建和扩展分布式应用。它提供了简单的API,使得开发者可以轻松地编写并行和分布式代码,而无需担心底层的复杂性。
Ray是一个开源的分布式计算框架,用于构建和扩展分布式应用。它提供了简单的API,使得开发者可以轻松地编写并行和分布式代码,而无需担心底层的复杂性。
786 11
|
5月前
|
缓存 NoSQL 安全
玩转Redis!非常强大的Redisson分布式集合,少写60%代码
Redisson是Java的Redis客户端,提供实时数据平台服务,简化了分布式环境下的数据管理。它包含RList、RSet、RMap等分布式集合,支持ConcurrentMap和Set接口,确保线程安全和数据一致性。例如,RMap实现了本地缓存和监听器功能,允许数据监听和本地加速读取。此外,还提供了RSet的排序和去重功能,以及RQueue和RBlockingQueue等队列实现,支持阻塞操作。通过Redisson,开发者能轻松处理分布式系统的数据同步和操作。
|
4月前
|
缓存 Devops 微服务
微服务01好处,随着代码越多耦合度越多,升级维护困难,微服务技术栈,异步通信技术,缓存技术,DevOps技术,搜索技术,单体架构,分布式架构将业务功能进行拆分,部署时费劲,集连失败如何解决
微服务01好处,随着代码越多耦合度越多,升级维护困难,微服务技术栈,异步通信技术,缓存技术,DevOps技术,搜索技术,单体架构,分布式架构将业务功能进行拆分,部署时费劲,集连失败如何解决
|
6月前
|
存储 监控 分布式数据库
Scala代码在局域网监控软件中的分布式处理
该文介绍了如何使用Scala进行局域网监控数据的分布式处理。通过示例展示了利用Scala的并发能力进行数据收集,使用集合操作进行数据处理与分析,以及如何将处理结果存储到分布式数据库(如Cassandra)和自动提交到网站。Scala的并发处理能力和丰富库支持使其在分布式处理中表现出色。
126 3
|
6月前
|
供应链 算法
基于分布式优化的多产消者非合作博弈能量共享(Matlab代码)
基于分布式优化的多产消者非合作博弈能量共享(Matlab代码)