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

Buggy PF Switch Solutions #279

Open
sergio-dorado opened this issue May 6, 2024 · 6 comments
Open

Buggy PF Switch Solutions #279

sergio-dorado opened this issue May 6, 2024 · 6 comments

Comments

@sergio-dorado
Copy link

Hi. I am exploring the capabilities of GridCal for transmission reconfiguration studies. Are the switch models to be used inside power flow computations? My toy example is a three-bus system, shown below.

image

I change the model of substation 3 to a node breaker using a double-breaker double-bus configuration.

image

The reference parameters are from the pglib repository here. I created the node-breaker version of the case by hand, adding breakers in a double-bus double-breaker configuration. When I close all the breakers or close them to have an ordinary bus bar at bus 3, I get strange power flow results that do not match the bus branch case. For quick reference, here are the power flow results with the bus branch model:

image

And these are the ones with the node-breaker model:

image

I have also conducted my experiments with pandapower, and the results match (up to numerical error). What might be causing this behavior?

import GridCalEngine.api as gce

grid = gce.MultiCircuit(name="TNR_three_bus")

# SADR: object to encapsulate the elements within the reconfigurable substation.
s3 = gce.Substation(name="bus_3")
grid.add_substation(s3)

# SADR: substations modeled as bus-branch.
bus_1 = gce.Bus("bus_1", vnom=240, vmax=1.10, vmin=0.90)
bus_1.is_slack = True
grid.add_bus(bus_1)

bus_2 = gce.Bus("bus_2", vnom=240, vmax=1.10, vmin=0.90)
grid.add_bus(bus_2)

# SADR: substation modeled as a node-breaker model. 
# Busbars
busbar_1 = gce.BusBar('busbar_1')
grid.add_bus_bar(busbar_1)
busbar_2 = gce.BusBar('busbar_2')
grid.add_bus_bar(busbar_2)

# SADR: connectivity nodes for the elements connected to the original substation.
bus3_g3 = gce.Bus('bus3_g3', vnom=240, vmax=1.10, vmin=0.90)
grid.add_bus(bus3_g3)

bus3_l3 = gce.Bus('bus3_l3', vnom=240, vmax=1.10, vmin=0.90)
grid.add_bus(bus3_l3)

bus3_l13 = gce.Bus('bus3_l13', vnom=240, vmax=1.10, vmin=0.90)
grid.add_bus(bus3_l13)

bus3_l32 = gce.Bus('bus3_l32', vnom=240, vmax=1.10, vmin=0.90)
grid.add_bus(bus3_l32)

# SADR: generator at bus 1.
gen_1 = gce.Generator(name='gen_1', vset=1.00, 
    Pmin=0, Pmax=307, Qmin=-1000, Qmax=1000,
    Cost2=0.11, Cost=5.00, Cost0=0.00,
    P=153.5
)
grid.add_generator(bus_1, gen_1)

# SADR: generator at bus 2.
gen_2 = gce.Generator(name='gen_2',
    Pmin=0, Pmax=214, Qmin=-1000, Qmax=1000,
    Cost2=0.085, Cost=1.200, Cost0=0.00,
    P=107.0)
grid.add_generator(bus_2, gen_2)

# SADR: generator at bus 3 (synchronous condenser).
gen_3 = gce.Generator(name='gen_3',
    Pmin=0.0, Pmax=0.00, Qmin=-1000, Qmax=1000,
    Cost2=0.000, Cost=0.000, Cost0=0.000,
    P=0.0)
grid.add_generator(bus3_g3, gen_3)

# SADR: lines
grid.add_line(gce.Line(bus_1, bus3_l13, 'line 1-3',
    r=0.065, x=0.62, b=0.45, rate=9000))
grid.add_line(gce.Line(bus3_l32, bus_2, 'line 3-2',
    r=0.025, x=0.75, b=0.70, rate=50))
grid.add_line(gce.Line(bus_1, bus_2, 'line 1-2',
    r=0.042, x=0.90, b=0.30, rate=9000))

grid.add_load(bus_1, gce.Load('load1', P=147.08, Q=40.00));
grid.add_load(bus_2, gce.Load('load2', P=147.08, Q=40.00));
grid.add_load(bus3_l3, gce.Load('load3', P=127.03, Q=50.00));

cb_1 = gce.Switch(name="CB1", bus_from=bus3_g3, bus_to=busbar_1, is_open=False)
grid.add_switch(cb_1)
cb_5 = gce.Switch(name="CB5", bus_from=bus3_g3, bus_to=busbar_2, is_open=True)
grid.add_switch(cb_5)

cb_2 = gce.Switch(name="CB2", bus_from=bus3_l13, bus_to=busbar_1, is_open=False)
grid.add_switch(cb_2)
cb_6 = gce.Switch(name="CB6", bus_from=bus3_g3, bus_to=busbar_2, is_open=True)
grid.add_switch(cb_6)

cb_3 = gce.Switch(name="CB3", bus_from=bus3_l32, bus_to=busbar_1, is_open=False)
grid.add_switch(cb_3)
cb_7 = gce.Switch(name="CB7", bus_from=bus3_g3, bus_to=busbar_2, is_open=True)
grid.add_switch(cb_7)

cb_4 = gce.Switch(name="CB4", bus_from=bus3_l3, bus_to=busbar_1, is_open=False)
grid.add_switch(cb_4)
cb_8 = gce.Switch(name="CB8", bus_from=bus3_g3, bus_to=busbar_2, is_open=True)
grid.add_switch(cb_8)

options = gce.PowerFlowOptions(gce.SolverType.NR, verbose=True, control_q=False)
power_flow = gce.PowerFlowDriver(grid, options)

power_flow.run()
print(f"Converged: {power_flow.results.converged}")
if power_flow.results.converged:
    print(f"Error: {power_flow.results.error}")
    print(power_flow.results.get_bus_df())
    print(power_flow.results.get_branch_df())
@SanPen
Copy link
Owner

SanPen commented May 6, 2024

Hi Sergio!

I am precisely working on this stuff. Currently if you download the devel version of GridCal, you'll find a topology_processor function to deal with this issue.

The thing is that switches need to be eliminated from the equation before simulating.
If you don't mind, I'll use your example to test the new functionality.
Also, if you have suggestions regarding this, please let me know.

@SanPen
Copy link
Owner

SanPen commented May 6, 2024

BTW, you could help contributing a reconfiguration module using the already existing genetic algorithms coupled with this. See this.

Should be easy ;)

SanPen added a commit that referenced this issue May 6, 2024
@SanPen
Copy link
Owner

SanPen commented May 6, 2024

Check this out.
I re-worked your example with the appropriate shape. I get this is a bit confusing now, but I'll be posting examples. Possibly this one.

SanPen added a commit that referenced this issue May 6, 2024
SanPen added a commit that referenced this issue May 6, 2024
@sergio-dorado
Copy link
Author

sergio-dorado commented May 6, 2024

Great. Thanks a lot. Go ahead and use the case for what you need.

For the investing example, I am getting this error with the devel branch (the re-worked node-breaker case works perfectly):

ImportError: cannot import name 'SimulationTypes' from 'GridCalEngine.Simulations.driver_types'

For some reason, the rest of the content of the driver_types.py file was missing from the installation. I copied-pasted it from the GitHub page and it is working fine.

@SanPen
Copy link
Owner

SanPen commented May 7, 2024

Could you please paste the complete trace? that way I can see the files and line causing trouble.

@SanPen
Copy link
Owner

SanPen commented May 29, 2024

Hi @sergio-dorado, I've just published 5.1.9, where the topology processing is improved.
As I know you've cloned devel, you could just update that.

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

No branches or pull requests

2 participants