-
Notifications
You must be signed in to change notification settings - Fork 169
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
Linopy transition #796
base: main
Are you sure you want to change the base?
Linopy transition #796
Changes from all commits
08c4643
28e1168
23dcbc4
4bb5327
3dd5078
f2945c4
7ca9ee5
bf4c5ab
f11d5da
4c2d346
97b24e6
004a850
f19c69c
3d72eee
f94362b
6b302f8
28877d3
060b973
e953d5a
5fd8060
f86da66
0e7d145
a2a48f7
2be7fe1
70b6d04
377455e
a01f188
644c2ea
d210ce1
c4016e2
5669f31
5991ca7
32674db
87ff6dd
7026712
c444005
a7db9bb
ac4e5a5
2074e18
5998973
f932c6a
be6905d
fef6951
a6ee0a5
577464c
417bf62
6b060d0
cfb251f
26849ab
60faf63
f54d1f6
cbea30e
6a7e770
e7bd8bb
0e50477
d014acc
56ce52e
c1155c3
a3cbd04
671dbb5
78ca7d0
564fd05
0ea2125
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -513,6 +513,18 @@ def base_network( | |
|
||
if hvdc_as_lines_config: | ||
lines = pd.concat([lines_ac, lines_dc]) | ||
lines.drop( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally, I'd recommend to do the converse: |
||
labels=[ | ||
"bus0_lon", | ||
"bus0_lat", | ||
"bus1_lon", | ||
"bus1_lat", | ||
"bus_0_coors", | ||
"bus_1_coors", | ||
], | ||
axis=1, | ||
inplace=True, | ||
) | ||
n.import_components_from_dataframe(lines, "Line") | ||
else: | ||
lines_dc = _set_electrical_parameters_links(links_config, lines_dc) | ||
|
@@ -522,6 +534,18 @@ def base_network( | |
axis=1, | ||
result_type="reduce", | ||
) | ||
lines_ac.drop( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above |
||
labels=[ | ||
"bus0_lon", | ||
"bus0_lat", | ||
"bus1_lon", | ||
"bus1_lat", | ||
"bus_0_coors", | ||
"bus_1_coors", | ||
], | ||
axis=1, | ||
inplace=True, | ||
) | ||
n.import_components_from_dataframe(lines_ac, "Line") | ||
# The columns which names starts with "bus" are mixed up with the third-bus specification | ||
# when executing additional_linkports() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,15 +125,14 @@ | |
from functools import reduce | ||
|
||
import geopandas as gpd | ||
import linopy | ||
import numpy as np | ||
import pandas as pd | ||
import pyomo.environ as po | ||
import pypsa | ||
from _helpers import ( | ||
REGION_COLS, | ||
configure_logging, | ||
create_logger, | ||
get_aggregation_strategies, | ||
sets_path_to_root, | ||
update_p_nom_max, | ||
) | ||
|
@@ -336,47 +335,22 @@ def distribute_clusters( | |
distribution_factor.sum(), 1.0, rtol=1e-3 | ||
), f"Country weights L must sum up to 1.0 when distributing clusters. Is {distribution_factor.sum()}." | ||
|
||
m = po.ConcreteModel() | ||
|
||
def n_bounds(model, *n_id): | ||
""" | ||
Create a function that makes a bound pair for pyomo. | ||
|
||
Use n_bounds(model, n_id) if N is Single-Index | ||
Use n_bounds(model, *n_id) if N is Multi-Index | ||
Example: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Variables.html | ||
|
||
Returns | ||
------- | ||
bounds = A function (or Python object) that gives a (lower,upper) bound pair i.e.(1,10) for the variable | ||
""" | ||
return (1, N[n_id]) | ||
|
||
m.n = po.Var(list(distribution_factor.index), bounds=n_bounds, domain=po.Integers) | ||
m.tot = po.Constraint(expr=(po.summation(m.n) == n_clusters)) | ||
m.objective = po.Objective( | ||
expr=sum( | ||
(m.n[i] - distribution_factor.loc[i] * n_clusters) ** 2 | ||
for i in distribution_factor.index | ||
), | ||
sense=po.minimize, | ||
m = linopy.Model() | ||
clusters = m.add_variables( | ||
lower=1, upper=N, coords=[L.index], name="n", integer=True | ||
) | ||
|
||
opt = po.SolverFactory(solver_name) | ||
if not opt.has_capability("quadratic_objective"): | ||
logger.warning( | ||
f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `ipopt`." | ||
m.add_constraints(clusters.sum() == n_clusters, name="tot") | ||
# leave out constant in objective (L * n_clusters) ** 2 | ||
m.objective = (clusters * clusters - 2 * clusters * L * n_clusters).sum() | ||
if solver_name == "gurobi": | ||
logging.getLogger("gurobipy").propagate = False | ||
elif solver_name != "scip": | ||
logger.info( | ||
f"The configured solver `{solver_name}` does not support quadratic objectives. Falling back to `scip`." | ||
) | ||
opt = po.SolverFactory("ipopt") | ||
|
||
results = opt.solve(m) | ||
assert ( | ||
results["Solver"][0]["Status"] == "ok" | ||
), f"Solver returned non-optimally: {results}" | ||
|
||
return ( | ||
pd.Series(m.n.get_values(), index=distribution_factor.index).round().astype(int) | ||
) | ||
solver_name = "scip" | ||
m.solve(solver_name=solver_name) | ||
return m.solution["n"].to_series().astype(int) | ||
|
||
|
||
def busmap_for_gadm_clusters(inputs, n, gadm_level, geo_crs, country_list): | ||
|
@@ -577,9 +551,10 @@ def clustering_for_n_clusters( | |
extended_link_costs=0, | ||
focus_weights=None, | ||
): | ||
bus_strategies, generator_strategies = get_aggregation_strategies( | ||
aggregation_strategies | ||
) | ||
line_strategies = aggregation_strategies.get("lines", dict()) | ||
line_strategies.update({"geometry": "first", "bounds": "first"}) | ||
generator_strategies = aggregation_strategies.get("generators", dict()) | ||
one_port_strategies = aggregation_strategies.get("one_ports", dict()) | ||
|
||
if not isinstance(custom_busmap, pd.Series): | ||
if alternative_clustering: | ||
|
@@ -605,12 +580,20 @@ def clustering_for_n_clusters( | |
clustering = get_clustering_from_busmap( | ||
n, | ||
busmap, | ||
bus_strategies=bus_strategies, | ||
aggregate_generators_weighted=True, | ||
aggregate_generators_carriers=aggregate_carriers, | ||
aggregate_one_ports=["Load", "StorageUnit"], | ||
line_length_factor=line_length_factor, | ||
line_strategies=line_strategies, | ||
generator_strategies=generator_strategies, | ||
bus_strategies={ | ||
"lat": "mean", | ||
"lon": "mean", | ||
"tag_substation": "first", | ||
"tag_area": "first", | ||
"country": "first", | ||
}, | ||
Comment on lines
+589
to
+595
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit widely duplicated across scripts. v_nom is also not here, may this be somewhat linked to the issue by Emmanuel? |
||
one_port_strategies=one_port_strategies, | ||
scale_link_capital_costs=False, | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In pypsa-eur the option is named "runtime" and has a slightly different naming option, e.g. 12h, though it may be compatible.
Do you think we can adopt the same naming and writing convention?