Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Doc not up to date + behaviour mismatch on ieee cases between pp3 and pp2 #2557

Open
5 of 6 tasks
BDonnot opened this issue Mar 13, 2025 · 5 comments
Open
5 of 6 tasks
Labels

Comments

@BDonnot
Copy link
Contributor

BDonnot commented Mar 13, 2025

Bug report checklis

  • Searched the issues page for similar reports

  • Read the relevant sections of the documentation

  • Browse the tutorials and tests for usefull code snippets and examples of use

  • Reproduced the issue after updating with pip install --upgrade pandapower (or git pull)

  • Tried basic troubleshooting (if a bug/error) like restarting the interpreter and checking the pythonpath

Reproducible Example

import numpy as np
import pandapower
import pandapower as pp
import pandapower.networks as pn
from importlib.metadata import version
from packaging.version import Version
import warnings

from lightsim2grid.gridmodel import init_from_pandapower
pp_ver_3 = Version(pandapower.__version__) >= Version("3")
tol = 1e-5

if pp_ver_3:
    from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_R, BR_X, BR_B, BR_G
else:
    from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_R, BR_X, BR_B
    
def _wye_delta_new(r, x, g, b, r_ratio=None, x_ratio=None):
    """taken from pandapower 3 source code"""
    if r_ratio is None:
        r_ratio = 0.5 + np.zeros_like(r)
    if x_ratio is None:
        x_ratio = 0.5 + np.zeros_like(x)
        
    tidx = (g != 0) | (b != 0)
    za_star = r[tidx] * r_ratio[tidx] + x[tidx] * x_ratio[tidx] * 1j
    zb_star = r[tidx] * (1 - r_ratio[tidx]) + x[tidx] * (1 - x_ratio[tidx]) * 1j
    zc_star = 1 / (g + 1j*b)[tidx]
    zSum_triangle = za_star * zb_star + za_star * zc_star + zb_star * zc_star
    zab_triangle = zSum_triangle / zc_star
    zac_triangle = zSum_triangle / zb_star
    zbc_triangle = zSum_triangle / za_star
    r[tidx] = zab_triangle.real
    x[tidx] = zab_triangle.imag
    yf = 1 / zac_triangle
    yt = 1 / zbc_triangle
    # 2 because in makeYbus Bcf, Bct are divided by 2:
    g[tidx] = yf.real * 2
    b[tidx] = yf.imag * 2
    g_asym = np.zeros_like(g)
    b_asym = np.zeros_like(b)
    g_asym[tidx] = 2 * yt.real - g[tidx]
    b_asym[tidx] = 2 * yt.imag - b[tidx]
    return r, x, g, b

print(f"pandapower version: {version('pandapower')}")
print(f"pandas version: {version('pandas')}")
print(f"numpy version: {version('numpy')}")
print(f"scipy version: {version('scipy')}")
print(f"lightsim2grid version: {version('lightsim2grid')}")

### main part of the code

# https://github.com/e2nIEE/pandapower/issues/2532
CASE = "case118"
net = pn.case118()

pp.runpp(net, lightims2grid=False, numba=False)
with warnings.catch_warnings():
    warnings.filterwarnings("ignore")
    gridmodel = init_from_pandapower(net)
    
# fix the "None" in the tap side
net.trafo.loc[np.array([el is None for el in net.trafo["tap_side"]]), "tap_side"] = "hv"

# doc equations
# https://pandapower.readthedocs.io/en/latest/elements/trafo.html

# n
v_ref_lvbus_trafo = net.trafo["vn_lv_kv"]
v_ref_hvbus_trafo = net.trafo["vn_hv_kv"]

theta = net.trafo["shift_degree"] # => always 0.

# impedance
cste = net.sn_mva / net.trafo["sn_mva"]
# cste = 100. / 10000.
r_k = net.trafo["vkr_percent"] * 0.01 * cste
z_k = net.trafo["vk_percent"] * 0.01 * cste
x_k = np.sqrt(z_k**2 - r_k**2)
z_k_cplx = r_k + 1j * x_k

# magnetising admittance
y_m = net.trafo["i0_percent"] * 0.01
g_m = net.trafo["pfe_kw"] / (net.trafo["sn_mva"] * 1000.) * cste
b_m = np.sqrt(y_m**2 - g_m**2)
y_m_cplx = g_m - 1j * b_m

# deal with tap steps (no steps here)

# tap changer
n_tap = 1 + (net.trafo["tap_pos"] - net.trafo["tap_neutral"]) * net.trafo["tap_step_percent"] * 0.01
n_tap[~np.isfinite(n_tap)] = 1.
vn_hv_trafo = np.where(net.trafo["tap_side"] == "hv", net.trafo["vn_hv_kv"] * n_tap, net.trafo["vn_hv_kv"]) 
vn_lv_trafo = np.where(net.trafo["tap_side"] == "lv", net.trafo["vn_lv_kv"] * n_tap, net.trafo["vn_lv_kv"]) 

# convert to pu
V_n = vn_lv_trafo
S_n = net.sn_mva
Z_n = V_n**2 / S_n
Z_ref_trafo = V_n**2 * S_n / net.trafo["sn_mva"]
z_cplx = z_k_cplx * Z_ref_trafo / Z_n
y_cplx = y_m_cplx * Z_n / Z_ref_trafo

r_pi = z_cplx.values.real
x_pi = z_cplx.values.imag
g_pi = y_cplx.values.real
b_pi = y_cplx.values.imag

y_cplx_pp = y_cplx
r_T, x_T, g_T, b_T = _wye_delta_new(z_cplx.values.real, z_cplx.values.imag, y_cplx_pp.values.real, y_cplx_pp.values.imag)

# extract values computed by pandapower
if pp_ver_3:
    r_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_R]
    x_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_X]
    g_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_B]
    b_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_G]
else:
    r_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_R].real
    x_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_X].real
    g_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_B].real
    b_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_B].imag

# extract values computed by lightsim2grid
r_ls = np.array([el.r_pu for el in gridmodel.get_trafos()])
x_ls = np.array([el.x_pu for el in gridmodel.get_trafos()])
h_ls = np.array([el.h_pu for el in gridmodel.get_trafos()])
g_ls = h_ls.real
b_ls = h_ls.imag


tr_id = 7
print(f"r (computed) = {r_comp[tr_id]}")
print(f"x (computed) = {x_comp[tr_id]}")
print(f"g (computed) = {g_comp[tr_id]}")
print(f"b (computed) = {b_comp[tr_id]}")
print("----------------")
print(f"r (from doc) = {r_T[tr_id]}")
print(f"x (from doc) = {x_T[tr_id]}")
print(f"g (from doc) = {g_T[tr_id]}")
print(f"b (from doc) = {b_T[tr_id]}")
print("----------------")
print(f"r (from lightsim) = {r_ls[tr_id]}")
print(f"x (from lightsim) = {x_ls[tr_id]}")
print(f"g (from lightsim) = {g_ls[tr_id]}")
print(f"b (from lightsim) = {b_ls[tr_id]}")
print("----------------")
print(f"Mismatch with the doc (z): {(np.abs(r_comp - r_T) + np.abs(x_comp - x_T)).max()}")
print(f"Mismatch with the doc (y): {(np.abs(g_T + b_comp) + np.abs(b_T - g_comp)).max()}")
print(f"Mismatch lightsim (z): {(np.abs(r_ls - r_comp) + np.abs(x_ls - x_comp)).max()}")
print(f"Mismatch with lightsim (y): {(np.abs(g_ls + b_comp) + np.abs(b_ls - g_comp)).max()}")

Issue Description and Traceback

Here What I am doing:

I create two virtual environment with exactly the same packages except for pandapower. In one of the venv pandapower is 2.14.11 and in the other it's 3.0.0, exact details here:

requirements_pp2.txt
requirements_pp3.txt

Then I run the above code which will:

  1. load the ieee case 118
  2. run a powerflow without lightsim2grid and without numba (to keep venv as clean as possible)
  3. convert the pp network into lightsim2grid

and then I compare 6 things:

a) the "z" parameters of the trafo model in the doc (implementation in the script)
b) the "z" parameters of the trafo model, as computed directly by pandapower (looking at the _ppc["branch"])
c) the "z" parameters of the trafo model as computed by lightsim2grid
d->f) I do the same for the y parameter of the trafo model.

Expected Behavior

I am expecting that:

I. documentation (especially of trafo, see here https://pandapower.readthedocs.io/en/latest/elements/trafo.html) details what is implemented in the code. This is not the case for both pandapower 2 and pandapower 3.

II. the computed parameters for ieee grids does not change between pandapower versions.

For point I

I got, for pandapower 2:
Mismatch with the doc (z): 0.002986873550935059
Mismatch with the doc (y): 0.8196779804309017

This means that the maximum different for (my own) understanding of the doc leads to a maximum difference value of 0.003 for the z component and 0.8 for the y component (everything is per unit here)

And for pandapower 3:
Mismatch with the doc (z): 0.0017865851613352059
Mismatch with the doc (y): 0.7969200083782807

For the y part, I think the doc is missing a "multiplication by 100." somewhere, but I don't really know where. And also I cannot manage (despite some deep understanding of powerflow) to match the exact behaviour of pandapower by reading the doc (without reverse engineering the code)

For point II

I use the implementation of lightsim2grid to compare the trafo parameters obtained by pandapower 2 and pandapower 3. I do this because 1) lightsim2grid fully match pandapower 2 up to numerical precision, se bellow) and 2) lightsim2grid version is the same on both virtual envs (not affected by the change in pandapower).

For pandapower 2 I obtain:
Mismatch lightsim (z): 6.938893903907228e-18
Mismatch with lightsim (y): 2.2215302514227986e-16

So as you can see, errors are neglectible and pandapower and lightsim2grid are perfectly aligned and understand the same way the "ieee grid".

For pandapower 3 I get:
Mismatch lightsim (z): 0.0012002883895998497
Mismatch with lightsim (y): 1.6165979888091822

And here you see quite drastic changes, especially in the "y" part which lead to some impactful changes in the output flow and voltages.

Despite taking few hours (on multiple days) to try to "fix" this, i did not manage to "align" pandapower 2 and pandapower 3. This might be related to issue #2532

Installed Versions

  • deepdiff==8.3.0
  • LightSim2Grid==0.10.2
  • networkx==3.4.2
  • numpy==1.26.4
  • orderly-set==5.3.0
  • packaging==24.2
  • pandas==2.2.3
  • pybind11==2.13.6
  • python-dateutil==2.9.0.post0
  • pytz==2025.1
  • scipy==1.13.1
  • setuptools==76.0.0
  • six==1.17.0
  • tqdm==4.67.1
  • tzdata==2025.1

With two changes (because I compare 2 venvs):

  • pandapower==2.14.11 for the venv with pandapower 2
  • pandapower==3.0.0 for the venv with pandapower 3

Label

  • Relevant labels are selected
@BDonnot BDonnot added the bug label Mar 13, 2025
@vogt31337
Copy link
Contributor

@BDonnot thanks for bringing this up. Could you by any chance add the version of lightsim2grid you were using? Since ls2g needed to be patched to be fully compatible.

@BDonnot
Copy link
Contributor Author

BDonnot commented Mar 13, 2025

Yes of course, lightsim2grid is 0.10.2 as shown in the last paragraph :-)

What bothers me here is that the ieee 118 leads to different results (flows and voltages) depending on pandapower version. I am not sure this is desirable.

Also, if you have a script that convert the "old" grid to the new grid then i'd be happy to have it. Because we stored lots of grid in pandapower format for the l2rpn competitions / grid2op eco system and I can't convert them unfortunately :-(

@pawellytaev
Copy link
Contributor

Hi @BDonnot,
Thanks for bringing this up!
Took a brief look into this and found the reason why there is the mismatch in powerflow results between 2.14.11 and 3.0
TL;DR: the i0_percent of the trafos is negative in the case118.json. If you multiply it with -1, the results match with ls2g. I added these lines in your script:

...
CASE = "case118"
net = pn.case118()
if pp_ver_3:
    net.trafo.i0_percent *= -1
...

... which gives me these results:

Image

Detailed answer:
As we split the BR_B (complex) in pp3.0 into BR_B and BR_G, both float, we found some weird formulas in pandapower 2.X when calculating the trafo BR_B (which was in fact b - 1j*g). For example, here we saw that if i0 was smaller than 0, the b_img was smaller than 0 and then - if it is the case - set to 0 in the next line and then multiplied with np.sign(i0) in line 382 again.

We thought, why is there even a negative i0_percent? Technically this doesn't make sense: the no-load current of a trafo will always flow from phase to ground, and not vice-versa. So we fixed the formulas, see here.
We still have the b_mva_squared[b_mva_squared < 0] = 0 here, but b_mva_squared actually cannot be smaller than 0 as the admittance of the trafo shall always be greater or equal to its conductance y >= g.

As we changed all of this, we got failing tests in the from_ppc converter, which has the purpose of importing pypower ppc "files" into pandapower, which we also changed so we import positive i0_percent values, see here:

i0_percent = np.sqrt(br_b**2 + br_g[is_trafo]**2) * 100 * baseMVA / sn

and apparently we changed only the test files there and not the json files used by pandapower.networks.caseXYZ()

We are currently working on the re-conversion of matpower files via from_ppc to pandapower. We will then update the corrected caseXYZ.json to the repo. I will be out of office from tomorrow until 25th, so I can continue working on that only from then on.

@BDonnot please remember some trafos will be handled as impedances as pointed out by Roman here: Grid2op/lightsim2grid#88 ... I guess the issue here is also related to your answer

As a quick fix in grid2op, you can multiply the i0_percent after importing the grid.json files with -1, and we'll keep you posted here as soon as we updated the json's in pandapower.

Summary of To-Do's:

  • document the BR_B (complex) to BR_G and BR_B (float) changes somewhere or more clear
  • re-convert the caseXYZ.json and match them with matpower/pypower (found a few mismatches between matpower and pandapower)
  • update the trafo documentation accordingly (thanks for pointing it out!)

BR Pawel

@pawellytaev
Copy link
Contributor

pawellytaev commented Mar 13, 2025

P.S. Although the Z and Y mismatches are better than before, the Y mismatch is still off, can't figure out why right now... will need to comparte the ppc['branch'] on both versions in detail. Here is the updated script with a csv export and a bit of pandas.DataFrame.describe() added:

import numpy as np
import pandapower
import pandapower as pp
import pandapower.networks as pn
from importlib.metadata import version
from packaging.version import Version
import warnings
import pandas as pd

from lightsim2grid.gridmodel import init_from_pandapower
pp_ver_3 = Version(pandapower.__version__) >= Version("3")
tol = 1e-5

if pp_ver_3:
    from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_R, BR_X, BR_B, BR_G
else:
    from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_R, BR_X, BR_B
    
def _wye_delta_new(r, x, g, b, r_ratio=None, x_ratio=None):
    """taken from pandapower 3 source code"""
    if r_ratio is None:
        r_ratio = 0.5 + np.zeros_like(r)
    if x_ratio is None:
        x_ratio = 0.5 + np.zeros_like(x)
        
    tidx = (g != 0) | (b != 0)
    za_star = r[tidx] * r_ratio[tidx] + x[tidx] * x_ratio[tidx] * 1j
    zb_star = r[tidx] * (1 - r_ratio[tidx]) + x[tidx] * (1 - x_ratio[tidx]) * 1j
    zc_star = 1 / (g + 1j*b)[tidx]
    zSum_triangle = za_star * zb_star + za_star * zc_star + zb_star * zc_star
    zab_triangle = zSum_triangle / zc_star
    zac_triangle = zSum_triangle / zb_star
    zbc_triangle = zSum_triangle / za_star
    r[tidx] = zab_triangle.real
    x[tidx] = zab_triangle.imag
    yf = 1 / zac_triangle
    yt = 1 / zbc_triangle
    # 2 because in makeYbus Bcf, Bct are divided by 2:
    g[tidx] = yf.real * 2
    b[tidx] = yf.imag * 2
    g_asym = np.zeros_like(g)
    b_asym = np.zeros_like(b)
    g_asym[tidx] = 2 * yt.real - g[tidx]
    b_asym[tidx] = 2 * yt.imag - b[tidx]
    return r, x, g, b

print(f"pandapower version: {version('pandapower')}")
print(f"pandas version: {version('pandas')}")
print(f"numpy version: {version('numpy')}")
print(f"scipy version: {version('scipy')}")
print(f"lightsim2grid version: {version('lightsim2grid')}")

### main part of the code

# https://github.com/e2nIEE/pandapower/issues/2532
CASE = "case118"
net = pn.case118()
if pp_ver_3:
    net.trafo.i0_percent *= -1

pp.runpp(net, lightims2grid=False, numba=False)
with warnings.catch_warnings():
    warnings.filterwarnings("ignore")
    gridmodel = init_from_pandapower(net)
    
# fix the "None" in the tap side
net.trafo.loc[np.array([el is None for el in net.trafo["tap_side"]]), "tap_side"] = "hv"

# doc equations
# https://pandapower.readthedocs.io/en/latest/elements/trafo.html

# n
v_ref_lvbus_trafo = net.trafo["vn_lv_kv"]
v_ref_hvbus_trafo = net.trafo["vn_hv_kv"]

theta = net.trafo["shift_degree"] # => always 0.

# impedance
cste = net.sn_mva / net.trafo["sn_mva"]
# cste = 100. / 10000.
r_k = net.trafo["vkr_percent"] * 0.01 * cste
z_k = net.trafo["vk_percent"] * 0.01 * cste
x_k = np.sqrt(z_k**2 - r_k**2)
z_k_cplx = r_k + 1j * x_k

# magnetising admittance
y_m = net.trafo["i0_percent"] * 0.01
g_m = net.trafo["pfe_kw"] / (net.trafo["sn_mva"] * 1000.) * cste
b_m = np.sqrt(y_m**2 - g_m**2)
y_m_cplx = g_m - 1j * b_m

# deal with tap steps (no steps here)

# tap changer
n_tap = 1 + (net.trafo["tap_pos"] - net.trafo["tap_neutral"]) * net.trafo["tap_step_percent"] * 0.01
n_tap[~np.isfinite(n_tap)] = 1.
vn_hv_trafo = np.where(net.trafo["tap_side"] == "hv", net.trafo["vn_hv_kv"] * n_tap, net.trafo["vn_hv_kv"]) 
vn_lv_trafo = np.where(net.trafo["tap_side"] == "lv", net.trafo["vn_lv_kv"] * n_tap, net.trafo["vn_lv_kv"]) 

# convert to pu
V_n = vn_lv_trafo
S_n = net.sn_mva
Z_n = V_n**2 / S_n
Z_ref_trafo = V_n**2 * S_n / net.trafo["sn_mva"]
z_cplx = z_k_cplx * Z_ref_trafo / Z_n
y_cplx = y_m_cplx * Z_n / Z_ref_trafo

r_pi = z_cplx.values.real
x_pi = z_cplx.values.imag
g_pi = y_cplx.values.real
b_pi = y_cplx.values.imag

y_cplx_pp = y_cplx
r_T, x_T, g_T, b_T = _wye_delta_new(z_cplx.values.real, z_cplx.values.imag, y_cplx_pp.values.real, y_cplx_pp.values.imag)

# extract values computed by pandapower
if pp_ver_3:
    r_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_R]
    x_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_X]
    g_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_B]
    b_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_G]
else:
    r_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_R].real
    x_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_X].real
    g_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_B].real
    b_comp = net._ppc["branch"][-net.trafo.shape[0]:, BR_B].imag

# extract values computed by lightsim2grid
r_ls = np.array([el.r_pu for el in gridmodel.get_trafos()])
x_ls = np.array([el.x_pu for el in gridmodel.get_trafos()])
h_ls = np.array([el.h_pu for el in gridmodel.get_trafos()])
g_ls = h_ls.real
b_ls = h_ls.imag


tr_id = 7
print(f"r (computed) = {r_comp[tr_id]}")
print(f"x (computed) = {x_comp[tr_id]}")
print(f"g (computed) = {g_comp[tr_id]}")
print(f"b (computed) = {b_comp[tr_id]}")
print("----------------")
print(f"r (from doc) = {r_T[tr_id]}")
print(f"x (from doc) = {x_T[tr_id]}")
print(f"g (from doc) = {g_T[tr_id]}")
print(f"b (from doc) = {b_T[tr_id]}")
print("----------------")
print(f"r (from lightsim) = {r_ls[tr_id]}")
print(f"x (from lightsim) = {x_ls[tr_id]}")
print(f"g (from lightsim) = {g_ls[tr_id]}")
print(f"b (from lightsim) = {b_ls[tr_id]}")
print("----------------")
print(f"Mismatch with the doc (z): {(np.abs(r_comp - r_T) + np.abs(x_comp - x_T)).max()}")
print(f"Mismatch with the doc (y): {(np.abs(g_T + b_comp) + np.abs(b_T - g_comp)).max()}")
print(f"Mismatch lightsim (z): {(np.abs(r_ls - r_comp) + np.abs(x_ls - x_comp)).max()}")
print(f"Mismatch with lightsim (y): {(np.abs(g_ls + b_comp) + np.abs(b_ls - g_comp)).max()}")


branch = net._ppc['branch']
if pp_ver_3:
    branch_df = pd.DataFrame(branch, columns=["F_BUS", "T_BUS", "BR_R", "BR_X", "BR_B", "RATE_A", "RATE_B", "RATE_C",
             "TAP", "SHIFT", "BR_STATUS", "ANGMIN", "ANGMAX", "PF", "QF", "PT", "QT", "MU_SF", "MU_ST", "MU_ANGMIN", 
             "MU_ANGMAX", "BR_R_ASYM", "BR_X_ASYM", "BR_G", "BR_G_ASYM", "BR_B_ASYM"])
    branch_df.to_csv('ppc_branch_pp3.csv')

else:
    branch_df = pd.DataFrame(branch, columns=["F_BUS", "T_BUS", "BR_R", "BR_X", "BR_B", "RATE_A", "RATE_B", "RATE_C", 
                                              "TAP", "SHIFT", "BR_STATUS", "ANGMIN", "ANGMAX", "PF", "QF", "PT", "QT", 
                                              "MU_SF", "MU_ST", "MU_ANGMIN", "MU_ANGMAX", "BR_R_ASYM", "BR_X_ASYM"])
    branch_df.to_csv('ppc_branch_pp2.csv')

print("--- describe trafos ---")
print("Trafo vk")
print(net.trafo.vk_percent.describe())
print("Trafo vkr")
print(net.trafo.vkr_percent.describe())
print("Trafo pfe")
print(net.trafo.pfe_kw.describe())
print("Trafo i0")
print(net.trafo.i0_percent.describe())

print("--- describe lines ---")
print("Line R")
print((net.line.r_ohm_per_km * net.line.length_km).describe())
print("Line X")
print((net.line.x_ohm_per_km * net.line.length_km).describe())
print("Line C")
print((net.line.c_nf_per_km * net.line.length_km).describe())

I am also attaching the ppc['branch'] csv's here:

ppc_branch_pp2.csv
ppc_branch_pp3.csv

Maybe this helps...

@BDonnot
Copy link
Contributor Author

BDonnot commented Mar 18, 2025

Hello @pawellytaev

Thanks a lot for the fix, I will see if fixing it at import will solve (at least for the short term) my issue on old pandapower grid.

You also write:

We are currently working on the re-conversion of matpower files via from_ppc to pandapower. We will then update the corrected caseXYZ.json to the repo. I will be out of office from tomorrow until 25th, so I can continue working on that only from then on.

I think this is the right thing to do. And, if I may, I posted an "issue" a few months ago (see #2131). If you are to reconvert them again, from a user perspective, it would be better if the default grid matches the expected results with the default values of pp.runpp.
Because right now, if you want to run the case118 like in matpower or in any other software, you need to specify trafo_model='pi' because the data have been computed with trafo_model="pi" but in pandapower by default it's the "t".

We thought, why is there even a negative i0_percent? Technically this doesn't make sense: the no-load current of a trafo will always flow from phase to ground, and not vice-versa. So we fixed the formulas, see here.
We still have the b_mva_squared[b_mva_squared < 0] = 0 here, but b_mva_squared actually cannot be smaller than 0 as the admittance of the trafo shall always be greater or equal to its conductance y >= g.

This bothered me also back in 2020. I was trying to match the results of pandapower in lightsim2grid. I could not explain this piece of code but implemented finally in lightsim2grid without understanding it.

please remember some trafos will be handled as impedances as pointed out by Roman here: Grid2op/lightsim2grid#88 ... I guess the issue here is also related to your Grid2op/lightsim2grid#88 (comment)

Yes I remember that, but without any input grid and proper working example I cannot improve lightsim2grid with it :-/

It should not be that hard to do honestly. The hardest part is always "what to do exactly" (devil is in the details, here specifically in the "exactly")

As a quick fix in grid2op, you can multiply the i0_percent after importing the grid.json files with -1, and we'll keep you posted here as soon as we updated the json's in pandapower.

Yes I will do that when using the "PandaPowerBackend" and pandapower version 3 or above. When fixed, I will only do this if the "bug" is still present.

Thanks a lot :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants