e2nIEE / pandapower

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

Pandapower is missing generator from 9-bus ieee case #2322

Open Paulnkk opened 4 months ago

Paulnkk commented 4 months ago

Feature Checklist

Issue

Hey,

I currently want to use pandapower in order to generate instances for optimal power flow by:

def extract_opf_data(mat_file_path): 
    # Convert MATPOWER case to pandapower network 
    net = pc.from_mpc(
        mat_file_path, f_hz=50, casename_mpc_file="mpc", validate_conversion=False
    )

where mat_file_path is a path that leads to case9Tree.m from [https://www.dropbox.com/scl/fi/ohc1xd4g03u1ch0356zgj/Tree-Library.zip?dl=0&e=1&file_subpath=%2FTree+Library&rlkey=crey52c766o03chsxgjytsrfa]. Now if I want to access the generator indices by:

generator_indices = {bus - 1 for bus in net.gen["bus"].values}

I just get two indices {0, 1} instead of {0, 1, 2}. From the pure matlab file, I can see that 3 generators should be returned.

What am I doing wrong here ?

Thank you and best,

Paul

Label

KS-HTK commented 4 months ago

Using the case9.m from matpower repo to test. I think what happend here is that the first gen is converted to an ext_grid. This ext_grid is connected to bus 0. But I am not sure if that is desired behavior. If it is, it is not Documented. This also matches with the case9 from pandapower.networks See Docs.

Paulnkk commented 3 months ago

@KS-HTK thanks for the response but what does that technically mean? Is this bus irrelevant for power generation and not considered in the objective function (as costs). I am not too familiar currently with the technical aspects since I am from the applied mathematics side and try to solve the sdp relaxation from here: https://ieeexplore.ieee.org/document/7056568 (2a) - (2i) with (2i) as rotated second-order-cone

Edit: I kind of fixed the issue for myself but I see a general problem in library; since the first generator is not considered and when I try to extract for instance active and reactive power limits:

    for _, row in net.gen.iterrows():
        bus_idx = int(row["bus"])  
        gen_cost_idx = net.gen.index[_]  
        costs[bus_idx] = net.poly_cost.at[
            gen_cost_idx, "cp1_eur_per_mw"
        ]  # Assuming linear cost for simplicity
        p_min[bus_idx] = row["min_p_mw"] / base_unit
        p_max[bus_idx] = row["max_p_mw"] / base_unit
        q_min[bus_idx] = row["min_q_mvar"] / base_unit
        q_max[bus_idx] = row["max_q_mvar"] / base_unit

net.gen does not include all generators, so that the opf model is not accurately constructed here. Probably there is another way to do this, I am not sure

Paulnkk commented 3 months ago

One question; how to deal with the situation when a non-generator bus ends-up in net.ext_grid but the logic is build such as I need to recover the set of all indices that relate to generators ? Because when extracting all generator buses, I need to rely on some logic to do so

Edit: The question would be; besides slack buses, what other kind of buses could be in ext_grid since if ext_grid only includes slack buses potentially, I can assume every slack bus to be a generator and then proceed with this logic

vogt31337 commented 3 months ago

@Paulnkk, I am not sure If I get your problems and questions. So in pandapower you have static generators and generators. You need to decide which one to use. For solving the loadflow equations you NEED a slack bus aka ext_grid. This table ONLY contains ext_grids, nothing else. There are networks containing multiple slacks.

But I think you want to hear, that you don't need to have an entry in the ext_grid, since you can set a flag on one generator to let it act as a ext_grid. See https://pandapower.readthedocs.io/en/latest/elements/gen.html, it is in the parameter list but missing in the documentation below...

Paulnkk commented 3 months ago

@vogt31337 thanks for your response! My problem is that I want to solve the radial opf network from here with a self-written customized solver: https://ieeexplore.ieee.org/document/7056568 specifically (2a) - (2i) with (2i) relaxed as rotated second-order cone. To initialize my instances for the solver, I need the information which buses are referring to generator buses. I will assume that all buses that will be included in the ext_grid as slack buses are automatically generators (from what I have seen, this is in most cases true).

Edit: Do you mean that ext_grid is missing in the docs ? I can not find it. If this is helpful I am happy to make a quick PR to the docs and fix this

vogt31337 commented 3 months ago

@Paulnkk, it's Not incorrect documentation. IT IS how the powerflow works: See Page 35 in https://matpower.org/docs/MATPOWER-manual-8.0.pdf for example. To be able to define the loadflow equations, there is one "slack Bus" Type == 3 needed. That is Not a Generator, it is the slack Bus. Regarding your gen stuff I will Take a Look later into your source. BR

Paulnkk commented 3 months ago

@vogt31337 Thanks for the response, I understand now

For my use-case, it is important to know which buses are generators and which are not and I encountered the case based on my datasets mentioned above that generator buses were slack buses and therefore ended up in ext_grid but not in net.gen["bus"].values (which refers to the generator bus indices from what I understand). Here I assumed that this bus would also appear net.gen["bus"].values and not only in ext_grid

vogt31337 commented 3 months ago

@Paulnkk, no that is not correct. Pandapower is based on matpower (or pypower), so the matrix describing gen and sgens are internally converted to the bus matrix, and the type is set to either type = 1 or type = 2. The slack bus is special since it is needed to solve the equations, otherwise the whole system would be ill conditioned, and therefore it has type = 3 and normally only one exists. Thats why it has its own table. There is also support for distributed slack in pandapower. Also the slack bus has always pu = 1.0 and va = 0° by definition.

Propably the best for your application would be to look into the ppc / ppci structure. Because there you get this bus table and can simply analyse the type field. This is compatible to the matpower definitions.