e2nIEE / pandapower

Convenient Power System Modelling and Analysis based on PYPOWER and pandas
https://www.pandapower.org
Other
839 stars 478 forks source link

Short circuit: handling of series gen + trafo #583

Open chefPony opened 4 years ago

chefPony commented 4 years ago

Hello, I would like to run a 3ph short circuit calculation of a MV net (15 kv) with some LV generators (0.4 kv). My generators are characterized by a subtransient reactance (xdss_pu_gen) + short circuit reactance of the transformer (xcc_pu_trafo) on the network side. My first question is how should I model this situation in pandapower? The first 2 alternatives that come to mind are:

My second question is: shouldn't the two approach above be equivalent ? I made a simple test to illustrate this situation and it appears they are not.

Import

import pandapower as pp
import pandapower.build_branch as bbr
import pandapower.shortcircuit as pp_sc

# In the following I will assume xdss_pu_gen = 2 and xcc_pu_trafo = 1

First approach: simple net 1

# ext_grid---bus0------bus1--generator
#             |
#           load

bus = pd.DataFrame([])
bus['vn_kv'] = [15.0, 15.0]

line = {'from_bus': 0.0,
        'to_bus': 1.0,
        'length_km': 1.0,
        'r_ohm_per_km': 1.0,
        'x_ohm_per_km': 1.0,
        'c_nf_per_km': 10.0,
        'g_us_per_km': 0.0,
        'max_i_ka': 0.33}

gen =  {'bus': 1,
        'p_mw': 0.47,
        'vm_pu': 1.1,
        'sn_mva': 0.55,
        'scaling': 1.0,
        'slack': False,
        'in_service': True,
        'vn_kv': 0.4,
        'xdss_pu': 3, # xdss_pu_gen + xcc_pu_trafo
        'rdss_pu': 0.0,
        'cos_phi': 1.0}

load = {'bus': 0,
         'p_mw': 0.2592,
         'q_mvar': 0.1255362895739714,
         'const_z_percent': 0.0,
         'const_i_percent': 0.0,
         'sn_mva': 0.324,
         'scaling': 1.0,
         'in_service': True}

ext_grid = {'bus': 0,
            'vm_pu': 1.0,
            'va_degree': 0.0,
            'in_service': True,
            's_sc_max_mva': 1.1000000000000002e+19, # assuming infinite 
            'rx_max': 0.0}

simple_net = pp.create_empty_network()

for _, b in bus.iterrows():
    pp.create_bus(simple_net, **b)

pp.create_gen(simple_net, **gen)    
pp.create_line_from_parameters(simple_net, **line)
pp.create_load(simple_net, **load)
pp.create_ext_grid(simple_net, **ext_grid)

Second approach:

# ext_grid---bus0------bus1--trafo--bus2--generator
#              |
#            load

# This approach needs 3 buses instead of 2
bus_2 = pd.DataFrame([])
bus_2['vn_kv'] = [15.0, 15.0, 0.4]

gen_2 =  gen
gen_2['bus'] = 2

Subtransient reactance now is equal to xdss_pu_gen
gen_2['xdss_pu'] = 2 

Short circuit impedance of transformer, without correction is 1.
trafo = {'hv_bus': 1,
         'lv_bus': 2,
         'sn_mva': 0.63,
         'vn_hv_kv': 15.0,
         'vn_lv_kv': 0.4,
         'vk_percent': 6.3, #vk_percent = sn_mva*10 implies xcc_pu_trafo = 1 (not considering transformer impedance correction factor)
         'parallel':1,
         'vkr_percent': 0.0,
         'pfe_kw': 0.0,
         'i0_percent': 0.0,
         'shift_degree': 0.0,
         'df': 1.0,
         'in_service': True}

simple_net_2 = pp.create_empty_network()

for _, b in bus_2.iterrows():
    pp.create_bus(simple_net_2, **b)

pp.create_gen(simple_net_2, **gen_2)    
pp.create_line_from_parameters(simple_net_2, **line)
pp.create_load(simple_net_2, **load)
pp.create_ext_grid(simple_net_2, **ext_grid)
pp.create_transformer_from_parameters(simple_net_2, **trafo)

First I have to get rid of the transformer correction factor so to have the same equivalent impedance in the two circuits:

# This is only to force the transformer correction factor to be equal  to 1.
# so that the two models should be equivalent

def _transformer_no_correction_factor(vk, vkr, sn, cmax):
    """
        2W-Transformer impedance correction factor in short circuit calculations,
        based on the IEC 60909-0:2016 standard.
        Args:
            vk: transformer short-circuit voltage, percent
            vkr: real-part of transformer short-circuit voltage, percent
            sn: transformer rating, kVA
            cmax: voltage factor to account for maximum worst-case currents, based on the lv side
        Returns:
            kt: transformer impedance correction factor for short-circuit calculations
        """

    zt = vk / 100 / sn
    rt = vkr / 100 / sn
    xt = np.sqrt(zt ** 2 - rt ** 2)
    kt = 0.95 * cmax / (1 + .6 * xt * sn)
    kt = np.round(kt / kt)   # kt=1
    return kt

bbr._transformer_correction_factor = _transformer_no_correction_factor
r, x, y = bbr._calc_r_x_y_from_dataframe(simple_net_2, pd.DataFrame(trafo, index=[0]), 0.4, 0.4, 10)
print(f"trafo r: {r.values[0]}, x:{x.values[0]}")

# trafo r: 0.0, x:1.0

If I solve the shortcircuit for the two circuits:

bbr._transformer_correction_factor = _transformer_no_correction_factor

pp_sc.calc_sc(simple_net, branch_results=True, ip=False, ith=False, 
        tk_s=0.4, 
        case='max',fault='3ph')

pp_sc.calc_sc(simple_net_2, branch_results=True, ip=False, ith=False, 
        tk_s=0.4, 
        case='max',fault='3ph')

simple_net.res_bus_sc
# 
# S-bus0------bus1--gen
#    |   
#   load  
# 
#    ikss_ka
#0 : 4.233902e+17
#1 : 6.925296e+00

simple_net_2.res_bus_sc

# S-bus0------bus1---trafo---bus2-gen
#      |   
#    load
#
#       ikss_ka
#0 : 4.233902e+17
#1 : 6.743221e+00
#2 : 1.629790e+01

I would have expected ikss_ka at bus 1 to be identical in the two cases but it's not, is this expected?

lthurner commented 4 years ago

My first question is how should I model this situation in pandapower?

As you know, the standard has correction factors that are specific to transformer, generators etc. which are applied internally. So I would always use the transformer model to model transformers and the generator model to model a generator, instead of combining multiple elements into one.

My second question is: shouldn't the two approach above be equivalent ?

If you account for all the correction factors, and the fact that the voltage level that the elements are connected to (15/0.4) have an impact on the impedances if they are given in per unit, both approaches should in fact be the same.

I made a simple test to illustrate this situation and it appears they are not.

On the surface your approach looks valid, but there are a lot of factors to take into account, and the calculation of the correction factors is not trivial, especially because of the different voltage levels. However, I don't have the time right now to go through your calculations in detail... I would focus on how to model the elements seperately correctly, not on combining them into one.

chefPony commented 4 years ago

On the surface your approach looks valid, but there are a lot of factors to take into account, and the calculation of the correction factors is not trivial, especially because of the different voltage levels. However, I don't have the time right now to go through your calculations in detail... I would focus on how to model the elements seperately correctly, not on combining them into one.

In the simple example above the correction factor for transformers was explicitly neglected, which other correction factors are you referring to? My understanding is that all impedances are given, or converted internally, in per unit so different voltage levels should not be of concern. I'll follow your advice and model the elements separately since this should be the correct approach. However, my suggestion is to investigate this further since "on paper" the two calculation should give identical results; the fact it seems they are not, in pandapower, could be a bug.

ZdenekDolezal commented 4 years ago

While posting my own issue I have found this example, it seemed intriguing enough, so I recopied the code and tried to get the same bus1 ikss values for both models. In process I did some little changes to the model and found one unclear place in Pandapower, description follows. 1) In the first model the 0.4 kV generator is connected to 15 kV bus, I have changed generator vn_kv to 15 kV, i. e. the vn_kv spec has been changed to 'vn_kv': 15.0 For the second model the generator is connected to 0.4 kV bus, so under the lines gen_2 = gen gen_2['bus'] = 2 was added this line gen_2['vn_kv'] = 0.4. During the short circuit calculation the value xdss_pu=3 is changed to 6 ( multiplication by "kg / sn_gen" in routine "_add_gen_sc_impedance" in build_bus.py ) and the value xdss_pu=2 is changed in similar way to 4. So the difference that must be "covered" by trafo is 6-4=2, i.e. : trf_vk_perc / 100.0 / trf_sn net_sn = 2.0 because net_sn=1.0 trf_vk_perc = 2.0 trf_sn 100.0 = 2.0 0.63 100.0 = 126.0 % With this value for vk_percent in trafo definition and with the gen voltage level adjusted to the connection bus, the resulting ikss in bus1 were the same for both models. 2) While stepping through Pandapower code I have found one place that is unclear to me : module "build_bus.py", routine "_add_gen_sc_impedance", calculation of kg kg = vn_gen / vn_net cmax / (1 + xdss_pu np.sin(phi_gen)) In my edition of IEC 60909-0, 6.6.1, (18) KG = Un / UrG cmax ... i.e. the order of Un and UrG is reversed.