pandapower最优潮流计算tutorial

pandapower最优潮流计算[pandapower Optimal Power Flow]

This is an introduction into the usage of the pandapower optimal power flow. It shows how to set the constraints and the cost factors into the pandapower element tables.

该notebook主要是介绍pandapower最优潮流计算的使用。它展示了如何将约束和成本因子设置进入pandapower的元件列表。

示例网络[Example Network]

We use the following four bus example network for this tutorial:

我们的教程使用下图的4节点示例网络:

4节点示例网络

We first create this network in pandapower:

我们首先在pandapower中创建网络:

import pandapower as pp
import numpy as np
net = pp.create_empty_network()

#create buses
bus1 = pp.create_bus(net, vn_kv=220.)
bus2 = pp.create_bus(net, vn_kv=110.)
bus3 = pp.create_bus(net, vn_kv=110.)
bus4 = pp.create_bus(net, vn_kv=110.)

#create 220/110 kV transformer
pp.create_transformer(net, bus1, bus2, std_type="100 MVA 220/110 kV")

#create 110 kV lines
pp.create_line(net, bus2, bus3, length_km=70., std_type='149-AL1/24-ST1A 110.0')
pp.create_line(net, bus3, bus4, length_km=50., std_type='149-AL1/24-ST1A 110.0')
pp.create_line(net, bus4, bus2, length_km=40., std_type='149-AL1/24-ST1A 110.0')

#create loads
pp.create_load(net, bus2, p_kw=60e3, controllable = False)
pp.create_load(net, bus3, p_kw=70e3, controllable = False)
pp.create_load(net, bus4, p_kw=10e3, controllable = False)

#create generators
eg = pp.create_ext_grid(net, bus1, min_p_kw = -1e9, max_p_kw = 1e9)
g0 = pp.create_gen(net, bus3, p_kw=-80*1e3, min_p_kw=-80e3, max_p_kw=0,vm_pu=1.01, controllable=True)
g1 = pp.create_gen(net, bus4, p_kw=-100*1e3, min_p_kw=-100e3, max_p_kw=0, vm_pu=1.01, controllable=True)

网损最小化[Loss Minimization]

We specify the same costs for the power at the external grid and all generators to minimize the overall power feed in. This equals an overall loss minimization:

我们特别指出外部电网和所有的发电机具有相同的电能成本,并最小化总的电能供应。这相当于整体网损的最小化。

costeg = pp.create_polynomial_cost(net, 0, 'ext_grid', np.array([-1, 0]))
costgen1 = pp.create_polynomial_cost(net, 0, 'gen', np.array([-1, 0]))
costgen2 = pp.create_polynomial_cost(net, 1, 'gen', np.array([-1, 0]))
print(costeg, costgen1, costgen2)
0 1 2

pp.create_polynomial_cost()为元件的多项式成本创建一个条目,返回已经创建的成本条目的ID

We run an OPF:

我们运行一个最优潮流计算:

pp.runopp(net, verbose=True)
The OPF cost definition has changed! Please check out the tutorial 'opf_changes-may18.ipynb' or the documentation!


PYPOWER Version 5.1.4, 27-June-2018 -- AC Optimal Power Flow
Python Interior Point Solver - PIPS, Version 1.0, 07-Feb-2011
Converged!

let’s check the results:

让我们看下结果:

net.res_ext_grid
p_kwq_kvar
0-56530.125753-1974.470643
net.res_gen
p_kwq_kvarva_degreevm_pu
0-71313.3919971969.654771-3.7128101.000009
1-12299.7719851451.159898-3.7127771.000010

Since all costs were specified the same, the OPF minimizes overall power generation, which is equal to a loss minimization in the network. The loads at buses 3 and 4 are supplied by generators at the same bus, the load at Bus 2 is provided by a combination of the other generators so that the power transmission leads to minimal losses.

因为所有的成本都看成相同的,最优潮流计算最小化总的发电量后的结果和网络的损失最小化结果相同。母线3和母线4的负荷由各自母线上的发电机供应,而母线2上的负荷是由其他发电机联合供应因此电能的传输达到了最小的损失。

个体发电机成本[Individual Generator Costs]

Let’s now assign individual costs to each generator.

现在给每台发电机赋予各自的发电成本。

We assign a cost of 10 ct/kW for the external grid, 15 ct/kw for the generator g0 and 12 ct/kw for generator g1:

我们给外部电网赋予10ct/kW的成本,发电机g0赋予15ct/kW的成本以及发电机g1赋予12ct/kW的成本:

net.polynomial_cost.c.at[costeg] = np.array([[-0.1, 0]])
net.polynomial_cost.c.at[costgen1] = np.array([[-0.15, 0]])
net.polynomial_cost.c.at[costgen2] = np.array([[-0.12, 0]])

And now run an OPF:

现在运行最优潮流运算:

pp.runopp(net, verbose=True)
The OPF cost definition has changed! Please check out the tutorial 'opf_changes-may18.ipynb' or the documentation!


PYPOWER Version 5.1.4, 27-June-2018 -- AC Optimal Power Flow
Python Interior Point Solver - PIPS, Version 1.0, 07-Feb-2011
Converged!
net.res_ext_grid
p_kwq_kvar
0-144559.444871-9193.066456
net.res_gen
p_kwq_kvarva_degreevm_pu
0-0.011910-8601.802715-16.4268690.967619
1-0.033788-10594.678350-13.4810420.989756

We can see that all active power is provided by the external grid. This makes sense, because the external grid has the lowest cost of all generators and we did not define any constraints.

我们可以看出所有的有功都是由外部电网提供。这是合理的,因为外部电网拥有最低的发电成本,而且我们没有定义任何的约束。

The dispatch costs are given in net.res_cost:

dispatch成本可以由net.res_cost给出:

net.res_cost
14455.950328285478

变压器约束[Transformer Constraint]

Since all active power comes from the external grid and subsequently flows through the transformer, the transformer is overloaded with a loading of about 145%:

因为所有的有功功率都来自与外部电网,接着潮流流过了变压器,变压器过载运行,负载约为145%:

net.res_trafo
p_hv_kwq_hv_kvarp_lv_kwq_lv_kvarpl_kwql_kvari_hv_kai_lv_kaloading_percent
0144559.4448719193.066457-143959.51633215993.742384599.92853925186.8088410.3801360.759988144.85146

We now limit the transformer loading to 50%:

现在设置变压器的负载约束为50%:

net.trafo["max_loading_percent"] = 50

(the max_loading_percent parameter can also be specified directly when creating the transformer)
and run the OPF:

(max_loading_percent参数也可以在创建变压器时直接指定)
然后运行最优潮流计算:

pp.runopp(net)
The OPF cost definition has changed! Please check out the tutorial 'opf_changes-may18.ipynb' or the documentation!

We can see that the transformer complies with the maximum loading:

我们可以看到变压器以最大负荷运行:

net.res_trafo
p_hv_kwq_hv_kvarp_lv_kwq_lv_kvarpl_kwql_kvari_hv_kai_lv_kaloading_percent
049953.864488-2147.313884-49833.8138125167.453489120.0506763020.1396050.1312160.26215349.999995

And power generation is now split between the external grid and generator 1 (which is the second cheapest generation unit):

现在有功功率的产生主要来自于外部电网和发电机g1(g1是发电成本第二低的发电机组)

net.res_ext_grid
p_kwq_kvar
0-49953.8644882147.313884
net.res_gen
p_kwq_kvarva_degreevm_pu
0-0.005754-2993.145845-6.2328290.985230
1-93304.077572-3453.343461-1.2378841.025709

This comes of course with an increase in dispatch costs:

这样的结果就导致了dispatch成本的上升:

net.res_cost
16191.876620556373

线路负载约束[Line Loading Constraints]

We now look at the line loadings:

我们现在关注于线路负载:

net.res_line
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwql_kvari_from_kai_to_kai_kaloading_percent
019780.009515-2479.435419-19341.6952901104.393239438.314225-1375.0421800.1043090.1032070.10430922.193320
1-50658.2989571888.75260652783.697109921.0641012125.3981522809.8167070.2700610.2701400.27014057.476548
230520.3804642532.279360-29946.195703-2688.018070574.184761-155.7387100.1567120.1573230.15732333.472994

and run the OPF with a 50% loading constraint:

然后在线路50%负载水平条件下运行最优潮流计算:

net.line["max_loading_percent"] = 50
pp.runopp(net, verbose=True)
The OPF cost definition has changed! Please check out the tutorial 'opf_changes-may18.ipynb' or the documentation!


PYPOWER Version 5.1.4, 27-June-2018 -- AC Optimal Power Flow
Python Interior Point Solver - PIPS, Version 1.0, 07-Feb-2011
Converged!

Now the line loading constraint is complied with:

现在线路的负载约束编译后:

net.res_line
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwql_kvari_from_kai_to_kai_kaloading_percent
016727.519781-3194.974086-16412.7250221534.133994314.794759-1660.8400920.0888490.0871300.08884918.903945
1-44451.195382868.87622946059.937188830.8158361608.7418061699.6920650.2349990.2350000.23500049.999998
227533.0804314051.080417-27060.140775-4429.078165472.939657-377.9977480.1419640.1430570.14305730.437636

And all generators are involved in supplying the loads:

所有的发电机都开始供应负荷:

net.res_ext_grid
p_kwq_kvar
0-49787.593544603.760721
net.res_gen
p_kwq_kvarva_degreevm_pu
0-9136.079301-2403.009062-5.8149540.992994
1-83593.017290-4881.895570-1.5116561.028899

This of course comes with a once again rising dispatch cost:

这导致了dispatch成本又一次的提升:

net.res_cost
16380.333324014753

电压约束[Voltage Constraints]

Finally, we have a look at the bus voltage:

最后,我们在关注一下电压:

net.res_bus
vm_puva_degreep_kwq_kvarlam_plam_q
01.0000000.000000-49787.5935404603.760721100.000000-2.642153e-21
11.006025-3.40883260000.0000000.000000130.952263-5.410268e-01
20.992994-5.81495460863.920699-2403.009062149.9999731.192009e-21
31.028899-1.511656-73593.017290-4881.895570120.0000142.988530e-21

and constrain it:

加以约束,并运行最优潮流计算:

net.bus["min_vm_pu"] = 1.0
net.bus["max_vm_pu"] = 1.02
pp.runopp(net)
The OPF cost definition has changed! Please check out the tutorial 'opf_changes-may18.ipynb' or the documentation!

We can see that all voltages are within the voltage band:

net.res_bus
vm_puva_degreep_kwq_kvarlam_plam_q
01.0000000.000000-49906.8472193050.617054100.000000-6.408104e-22
11.004168-3.42101560000.0000000.000000131.268596-2.133663e-01
21.000000-5.97609459278.204655-14858.933373149.9999923.120534e-21
31.020000-1.366892-71863.4913219172.691847120.000005-1.926105e-21

And all generators are once again involved in supplying the loads:

所有的发电机又一次都参与了负荷的供应:

net.res_ext_grid
p_kwq_kvar
0-49906.8472193050.617054
net.res_gen
p_kwq_kvarva_degreevm_pu
0-10721.795345-14858.933373-5.9760941.00
1-81863.4913219172.691847-1.3668921.02

This of course comes once again with rising dispatch costs:

又一次导致了dipatch成本的提升:

net.res_cost
16422.572982172846

直流最优潮流计算[DC OPF]

pandapower also provides the possibility of running a DC Optimal Power Flow:

pandapower也可以提供了运行直流最优潮流计算的可能:

pp.rundcopp(net)

Since voltage magnitudes are not included in the DC power flow formulation, voltage constraints canot be considered in the DC OPF:

因为直流潮流公式中不考虑电压幅值,所以在直流潮流计算中并不考虑电压约束:

net.res_bus
vm_puva_degreep_kwq_kvarlam_plam_q
0NaN0.000000-49999.999965NaN100.0000000.0
1NaN-3.43696760000.000000NaN130.9090910.0
2NaN-5.70856661488.746680NaN150.0000000.0
3NaN-1.362340-71488.746715NaN120.0000000.0

Line and transformer loading limits are however complied with:

线路和变压器负载限制编译后为:

net.res_line
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwql_kvari_from_kai_to_kai_kaloading_percent
016715.2333290.0-16715.2333290.00.00.00.0877320.0877320.08773218.666430
1-44773.5133510.044773.5133510.00.00.00.2350000.2350000.23500050.000000
226715.2333630.0-26715.2333630.00.00.00.1402190.1402190.14021929.833747
net.res_trafo
p_hv_kwq_hv_kvarp_lv_kwq_lv_kvarpl_kwql_kvari_hv_kai_lv_kaloading_percent
049999.9999650.0-49999.9999650.00.00.00.1312160.26243250.0

As are generator limits:

发电机限制为:

net.gen
namebusp_kwvm_pusn_kvamin_q_kvarmax_q_kvarscalingin_servicetypemin_p_kwmax_p_kwcontrollable
0None2-80000.01.01NaNNaNNaN1.0TrueNone-80000.00.0True
1None3-100000.01.01NaNNaNNaN1.0TrueNone-100000.00.0True
net.res_gen
p_kwq_kvarva_degreevm_pu
0-8511.253320NaN-5.7085661.0
1-81488.746715NaN-1.3623401.0

The cost function is the same for the linearized OPF as for the non-linear one:

线性最优潮流计算和非线性潮流计算的成本函数一致:

net.res_cost
16055.337600298368

Piecewise linear cost functions
The OPF also offers us piecewise linear cost functions. Let us first check the actual cost function setup:

分段线性成本函数
最优潮流九三也提供了分段线性成本函数。我们首先看一下实际的成本函数设置:

net.polynomial_cost
typeelementelement_typec
0p0ext_grid[[-0.1, 0.0]]
1p0gen[[-0.15, 0.0]]
2p1gen[[-0.12, 0.0]]

An element can either have polynomial costs or piecewise linear costs at the same time. So let us first delete the polynomial costs in order to avoid confusion and errors:

一个元件的成本函数只能是多项式或者分段线性中的一种。因此,让我们首先删除多项式成本函数,以免产生困惑和错误:

net.polynomial_cost= net.polynomial_cost.drop(net.polynomial_cost.index.values)

The results above have been produced with polynomial cost functions, that were linear. Let’s try to reproduce the results using piecewise linear cost functions. Note: The cost functions need to have the same gradient!

上面的计算结果是采用多项式成本函数计算的,是线性的。现在我们使用分段线性函数重新计算结果。需要强调的是:成本函数需要拥有相同的梯度!

pp.create_piecewise_linear_cost(net, 0, "gen", np.array([[-1 , 0.15] ,[0, 0]]))
pp.create_piecewise_linear_cost(net, 1, "gen", np.array([[-1, 0.12], [0, 0]]))
pp.create_piecewise_linear_cost(net, 0, "ext_grid", np.array([[-1, 0.1], [0, 0]]))
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-42-5d2a2efd8ee4> in <module>
----> 1 pp.create_piecewise_linear_cost(net, 0, "gen", np.array([[-1 , 0.15] ,[0, 0]]))
      2 pp.create_piecewise_linear_cost(net, 1, "gen", np.array([[-1, 0.12], [0, 0]]))
      3 pp.create_piecewise_linear_cost(net, 0, "ext_grid", np.array([[-1, 0.1], [0, 0]]))


~/.local/lib/python3.5/site-packages/pandapower/create.py in create_piecewise_linear_cost(net, element, element_type, data_points, type, index)
   2469             if not (net[element_type].max_p_kw.at[element] <= max(p) and
   2470                     net[element_type].min_p_kw.at[element] >= min(p)):
-> 2471                 raise ValueError("Cost function must be defined for whole power range of the "
   2472                                  "generator")
   2473         if type == "q":


ValueError: Cost function must be defined for whole power range of the generator

What we forgot is that the piecewise linear function should be defined for the whole range of the generator. The range is determined by p_max and p_min. Let’s check:

额…错误信息是ValueError: Cost function must be defined for whole power range of the generator,让我们检查一下:

net.gen.max_p_kw
0    0.0
1    0.0
Name: max_p_kw, dtype: float64
net.gen.min_p_kw
0    -80000.0
1   -100000.0
Name: min_p_kw, dtype: float64

We try again:

我们再试一下:

pp.create_piecewise_linear_cost(net, 0, "gen", np.array([[-80000* 1 , 80000*0.15], [0, 0]]))
pp.create_piecewise_linear_cost(net, 1, "gen", np.array([[-100000*1, 100000*0.12], [0, 0]]))
1

An external grid usually has no operational limits, but this is a problem for the OPF:

外部电网通常没有运行限制,但这是OPF的一个问题:

pp.create_piecewise_linear_cost(net, 0, "ext_grid", np.array([[0, 0], [1, 0.1]]))
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-46-e06a56395857> in <module>
----> 1 pp.create_piecewise_linear_cost(net, 0, "ext_grid", np.array([[0, 0], [1, 0.1]]))


~/.local/lib/python3.5/site-packages/pandapower/create.py in create_piecewise_linear_cost(net, element, element_type, data_points, type, index)
   2469             if not (net[element_type].max_p_kw.at[element] <= max(p) and
   2470                     net[element_type].min_p_kw.at[element] >= min(p)):
-> 2471                 raise ValueError("Cost function must be defined for whole power range of the "
   2472                                  "generator")
   2473         if type == "q":


ValueError: Cost function must be defined for whole power range of the generator

So we set imaginary constraints, that we can choose very broad:

因此,我们虚构一个约束,将这个约束的范围设置的很广:

net.ext_grid["max_p_kw"] = 1e9
net.ext_grid["min_p_kw"] = -1e9
net.ext_grid
namebusvm_puva_degreein_servicemin_p_kwmax_p_kw
0None01.00.0True-1.000000e+091.000000e+09
pp.create_piecewise_linear_cost(net, 0, "ext_grid", np.array([[-1e9, 1e9*.1], [1e9, -1e9*0.1]]))
2

Let us check the results from the previous OPF again!

让我们再看一下之前的OPF运行结果:

net.res_bus
vm_puva_degreep_kwq_kvarlam_plam_q
0NaN0.000000-49999.999965NaN100.0000000.0
1NaN-3.43696760000.000000NaN130.9090910.0
2NaN-5.70856661488.746680NaN150.0000000.0
3NaN-1.362340-71488.746715NaN120.0000000.0
net.res_cost
16055.337600298368

We run the same OPF now with different cost function setup. We should get the exact same results:

我们运行了相同的OPF但是采用不同的成本函数,我们应该获得完全相同的结果:

pp.rundcopp(net)
net.res_cost
16055.337600298368
net.res_bus
vm_puva_degreep_kwq_kvarlam_plam_q
0NaN0.000000-49999.999965NaN100.0000000.0
1NaN-3.43696760000.000000NaN130.9090910.0
2NaN-5.70856661488.746680NaN150.0000000.0
3NaN-1.362340-71488.746715NaN120.0000000.0
  • 11
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
TensorFlow是一个开源的机器学习框架,用于构建和训练各种机器学习模型。TensorFlow提供了丰富的编程接口和工具,使得开发者能够轻松地创建、训练和部署自己的模型。 TensorFlow Tutorial是TensorFlow官方提供的学习资源,旨在帮助新手快速入门。该教程详细介绍了TensorFlow的基本概念、常用操作和各种模型的构建方法。 在TensorFlow Tutorial中,首先会介绍TensorFlow的基本工作原理和数据流图的概念。通过理解数据流图的结构和运行过程,可以更好地理解TensorFlow的工作方式。 接下来,教程会详细介绍TensorFlow的核心组件,例如张量(Tensor)、变量(Variable)和操作(Operation)。这些组件是构建和处理模型的基本元素,通过使用它们可以创建复杂的神经网络和其他机器学习模型。 在教程的后半部分,会介绍如何使用TensorFlow构建不同类型的模型,例如深度神经网络(DNN)、卷积神经网络(CNN)和递归神经网络(RNN)。每个模型都会有详细的代码示例和实践任务,帮助学习者掌握相关知识和技能。 此外,教程还包含了关于模型的训练、评估和优化的内容,以及如何使用TensorBoard进行可视化和调试。 总结来说,TensorFlow Tutorial提供了全面而详细的学习资源,通过学习该教程,可以快速入门TensorFlow,并且掌握构建和训练机器学习模型的方法。无论是初学者还是有一定经验的开发者,都可以从中受益并扩展自己的机器学习技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值