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

Add ability to add DC lines with different Pmin and Pmax #355

Merged
merged 4 commits into from
Dec 16, 2020

Conversation

danielolsen
Copy link
Contributor

Purpose

Add ability to add DC lines with different Pmin and Pmax from the ChangeTable. Along with #352, this will enable us to model 'hybrid' power plants.
Closes #342.

At the same time, refactor the checking of new additions to the Grid via the ChangeTable. A new function is added which systematically checks for the right combinations of keys, and incorrect values now induce ValueErrors, rather than printing and returning, which a careless user might overlook in the middle of a large script.

What the code is doing

In change_table.py:

  • The ChangeTable._add_line method is refactored to allow new entries to be specified with either {"capacity" (for AC lines or DC)} or {"Pmax" & "Pmin"} (DC only) keys.
  • The ChangeTable._check_entry_keys method is added to provide a consistent interface to check keys for "new_bus", "new_plant", "new_branch", and "new_dcline". Right now we aren't checking much when we add storage capacity, but in the future we will probably want to enhance it to be able to specify more things (e.g. power to energy ratio, efficiency, etc.) and that feature will be able to use this checking function as well.
  • The add_bus, add_plant, and _add_line methods are updated to use the new _check_entry_keys method for checking keys, and to raise ValueErrors when something is wrong rather than printing an error and returning (the appropriate entry is still cleared either way).

In test_change_table.py:

  • We add new tests to ensure that the new DC line specification method works as expected.
    • test_add_dcline_Pmin_and_Pmax_success
    • test_add_dcline_Pmin_gt_Pmax
    • test_add_dcline_Pmin_and_Pmax_and_capacity
  • We refactor the existing dcline tests to expect the Pmin and Pmax keys, rather than capacity:
    • test_add_dcline_output
    • test_add_dcline_in_different_interconnect
  • We refactor tests that were expecting to see a certain print statement via checking capsys, now they're expecting an exception with a certain text via with pytest.raises(FooError) as excinfo.

In transform_grid.py, we interpret the new change table entries as appropriate.

Testing

Unit tests have been added for the new ways that we may specify DC lines.

Time estimate

Half an hour to an hour. There are a decent amount of changes, but mostly it's doing the same thing many times.

@danielolsen danielolsen added the new feature Feature that is currently in progress. label Dec 10, 2020
@danielolsen danielolsen self-assigned this Dec 10, 2020
return
elif (
if start == end:
raise ValueError("buses of line #%d must be different" % (i + 1))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could rephrase the error message to be more explicit, e.g., buses at each extremity of line #%d must be different

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a subset of the start lat/lon == end lat/lon condition?

Copy link
Collaborator

@rouille rouille Dec 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Same bus will have same coordinates. So it can be removed since it will be satisfied by the check on the distance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we keep it for now, so that we don't forget to check when we expand this to be able to add transformers (which can be at the same lat/lon but not the same bus)? It doesn't hurt.

if not isinstance(line[p], (int, float)):
raise ValueError(f"'{p}' must be a number (int/float)")
if line["Pmin"] > line["Pmax"]:
raise ValueError("Pmin cannot be greater than Pmax")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given either symmetric dclines or one-way dclines are supported, should we force "Pmin" to be greater or equal to 0 at this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's give the user maximum flexibility. If they want to do a line bounded within [-100, 200], or [100, 200], let's let them.

@rouille
Copy link
Collaborator

rouille commented Dec 10, 2020

Don't forget to update the README with this new feature and the previous one (new bus)

@danielolsen danielolsen force-pushed the daniel/one_way_dcline branch 3 times, most recently from 98018af to ffcff81 Compare December 11, 2020 01:40
@danielolsen
Copy link
Contributor Author

Don't forget to update the README with this new feature and the previous one (new bus)

Done.

@danielolsen danielolsen force-pushed the daniel/one_way_dcline branch 2 times, most recently from 05bba1a to a3a513d Compare December 16, 2020 01:20
@danielolsen
Copy link
Contributor Author

Integration testing has been successfully performed.

I created two scenarios using this branch: one using the new feature, and one control. Common to both:

from powersimdata.scenario.scenario import Scenario
scenario = Scenario('')
scenario.state.set_builder(["Western"])
scenario.state.builder.set_base_profile("demand", "v4")
scenario.state.builder.set_base_profile("hydro", "v2")
scenario.state.builder.set_base_profile("solar", "v4.1")
scenario.state.builder.set_base_profile("wind", "v5.2")
scenario.state.builder.set_time("2016-01-01 00:00:00", "2016-01-31 23:00:00", "24H")

For the test scenario, I disabled the biggest HVDC line in the interconnect, and replaced it with a pair of opposing one-way lines:

scenario.state.builder.change_table.scale_dcline_capacity(dcline_id={10: 0})
scenario.state.builder.change_table.add_dcline(
    [
        {"from_bus_id": 2013620, "to_bus_id": 2025332, "Pmin": 0, "Pmax": 3100},
        {"from_bus_id": 2013620, "to_bus_id": 2025332, "Pmin": -3100, "Pmax": 0},
    ]
)

Resulting in an anticipated DC line table of:

>>> scenario.state.get_grid().dcline[["Pmin", "Pmax", "from_bus_id", "to_bus_id"]]
    Pmin  Pmax  from_bus_id  to_bus_id
9  -2400  2400      2050383    2028847
10     0     0      2013620    2025332
15  -400   400      2021181    2021641
16     0  3100      2013620    2025332
17 -3100     0      2013620    2025332

These were both run with the code in Breakthrough-Energy/REISE.jl#91. Let's see what we get!

>>> real_dcline_pf = Scenario(1746).state.get_dcline_pf()[10]
[...truncated...]
>>> real_dcline_pf.min()
-3100.0
>>> real_dcline_pf.max()
3100.0
>>> fake_dcline_pf_a = Scenario(1747).state.get_dcline_pf()[16]
[...truncated...]
>>> fake_dcline_pf_b = Scenario(1747).state.get_dcline_pf()[17]
[...truncated...]
>>> fake_dcline_pf_a.min()
-0.0
>>> fake_dcline_pf_a.max()
3100.0
>>> fake_dcline_pf_b.min()
-3100.0
>>> fake_dcline_pf_b.max()
0.0
>>> fake_dcline = fake_dcline_pf_a + fake_dcline_pf_b
>>> fake_dcline_pf = fake_dcline_pf_a + fake_dcline_pf_b
>>> (real_dcline_pf - fake_dcline_pf).abs().max()
0.00048828125

As hoped, the new DC lines follow the bounds we have set for them, and the sum of the two of them is almost exactly equal (subject to some barrier cruft) to the behavior of the bi-directional line over the course of a one-month test!

[{"lat": 48, "lon": -125, "zone_id": 201, "baseKV": 138}])
scenario.state.builder.change_table.add_dcline(
[{"from_bus_id": 2090023, "to_bus_id": 20090024, "Pmin": 0, "Pmax": 200}])

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Copy link
Collaborator

@rouille rouille left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks for the test.

@danielolsen danielolsen force-pushed the daniel/one_way_dcline branch from 2cd2d70 to 70711dd Compare December 16, 2020 05:18
refactor: refactor TransformGrid to match new ChangeTable

refactor: refactor tests for new ChangeTable/TransformGrid

doc: add new change table features to README
refactor: use _check_new_entry in _add_line, add_plant, add_bus

refactor: update ChangeTable tests to match new Exceptions
@danielolsen danielolsen force-pushed the daniel/one_way_dcline branch from 70711dd to 1ed6ed2 Compare December 16, 2020 05:20
@danielolsen danielolsen merged commit f4a9f5b into develop Dec 16, 2020
@danielolsen danielolsen deleted the daniel/one_way_dcline branch December 16, 2020 05:23
@ahurli ahurli mentioned this pull request Mar 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature Feature that is currently in progress.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add one-way DC line
4 participants