多微电网案例——分布式能源交易(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月前
|
安全
【2023高教社杯】D题 圈养湖羊的空间利用率 问题分析、数学模型及MATLAB代码
本文介绍了2023年高教社杯数学建模竞赛D题的圈养湖羊空间利用率问题,包括问题分析、数学模型建立和MATLAB代码实现,旨在优化养殖场的生产计划和空间利用效率。
199 6
【2023高教社杯】D题 圈养湖羊的空间利用率 问题分析、数学模型及MATLAB代码
|
3月前
|
存储 算法 搜索推荐
【2022年华为杯数学建模】B题 方形件组批优化问题 方案及MATLAB代码实现
本文提供了2022年华为杯数学建模竞赛B题的详细方案和MATLAB代码实现,包括方形件组批优化问题和排样优化问题,以及相关数学模型的建立和求解方法。
128 3
【2022年华为杯数学建模】B题 方形件组批优化问题 方案及MATLAB代码实现
|
3月前
|
数据采集 存储 移动开发
【2023五一杯数学建模】 B题 快递需求分析问题 建模方案及MATLAB实现代码
本文介绍了2023年五一杯数学建模竞赛B题的解题方法,详细阐述了如何通过数学建模和MATLAB编程来分析快递需求、预测运输数量、优化运输成本,并估计固定和非固定需求,提供了完整的建模方案和代码实现。
90 0
【2023五一杯数学建模】 B题 快递需求分析问题 建模方案及MATLAB实现代码
|
6月前
|
数据安全/隐私保护
地震波功率谱密度函数、功率谱密度曲线,反应谱转功率谱,matlab代码
地震波格式转换、时程转换、峰值调整、规范反应谱、计算反应谱、计算持时、生成人工波、时频域转换、数据滤波、基线校正、Arias截波、傅里叶变换、耐震时程曲线、脉冲波合成与提取、三联反应谱、地震动参数、延性反应谱、地震波缩尺、功率谱密度
|
1月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
3月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
110 2
基于Redis的高可用分布式锁——RedLock
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
7天前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
41 16
|
1月前
|
缓存 NoSQL Java
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
59 3
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
|
1月前
|
NoSQL Redis 数据库
计数器 分布式锁 redis实现
【10月更文挑战第5天】
47 1

热门文章

最新文章