Problem 10.1#

Problem 10.1. Capacity and dispatch optimization in a network.

We build on the models described in Problems 8 and 9, however we add Denmark as a second node. Optimize the capacity and dispatch of solar PV, onshore wind, and Open Cycle Gas Turbine (OCGT) generators to supply the inelastic electricity demand throughout one year. To do this, take the time series for the wind and solar capacity factors for Portugal and Denmark in 2015 obtained from https://zenodo.org/record/3253876#.XSiVOEdS8l0 and https://zenodo.org/record/2613651#.X0kbhDVS-uV (select the file ‘pvoptimal.csv’) and the electricity demand from martavp/integrated-energy-grids. Assume that methane gas emits 0.198 tCO2 per MWh of thermal energy contained in the gas. We assume the distance between the two nodes is 2477 km, the distance between Copenhagen and Lisbon.

For all of the following subproblems, always calculate the following values:

  • Total system costs (in bn EUR)

  • Average electricity price (in EUR/MWh); number/share of hours with a price below 2 EUR/MWh

  • Congestion rent

  • Utilisation of transmission lines (in % of cap.)

  • Total generation per technology (in TWh)

  • Total CO2 emissions (in MtCO2)

a) Set up a network with two nodes and connect them with an overhead AC line (however, keep the capacity at 0 GW, and it cannot be extended).

b) Now assume the AC line connecting Portugal and Denmark has a capacity of 1 GW.

c) Now assume the AC line connecting Portugal and Denmark has a capacity of 10 GW.

d) Optimise the AC line capacity endogenously (assume it starts at 0 GW capacity).

import matplotlib.pyplot as plt
import pandas as pd
import pypsa

Prerequisites: handling technology data and costs#

We maintain a database (PyPSA/technology-data) which collects assumptions and projections for energy system technologies (such as costs, efficiencies, lifetimes, etc.) for given years, which we can load into a pandas.DataFrame. This requires some pre-processing to load (e.g. converting units, setting defaults, re-arranging dimensions):

year = 2030
url = f"https://raw.githubusercontent.com/PyPSA/technology-data/master/outputs/costs_{year}.csv"
costs = pd.read_csv(url, index_col=[0, 1])
costs.loc[costs.unit.str.contains("/kW"), "value"] *= 1e3
costs.unit = costs.unit.str.replace("/kW", "/MW")

defaults = {
    "FOM": 0,
    "VOM": 0,
    "efficiency": 1,
    "fuel": 0,
    "investment": 0,
    "lifetime": 25,
    "CO2 intensity": 0,
    "discount rate": 0.07,
}
costs = costs.value.unstack().fillna(defaults)

costs.at["OCGT", "fuel"] = costs.at["gas", "fuel"]
costs.at["OCGT", "CO2 intensity"] = costs.at["gas", "CO2 intensity"]
costs.at["CCGT", "CO2 intensity"] = costs.at["gas", "CO2 intensity"]

Let’s also write a small utility function that calculates the annuity to annualise investment costs. The formula is

\[ a(r, n) = \frac{r}{1-(1+r)^{-n}} \]

where \(r\) is the discount rate and \(n\) is the lifetime.

def annuity(r, n):
    return r / (1.0 - 1.0 / (1.0 + r) ** n)
annuity(0.07, 20)
0.09439292574325567

Based on this, we can calculate the marginal generation costs (€/MWh):

costs["marginal_cost"] = costs["VOM"] + costs["fuel"] / costs["efficiency"]

and the annualised investment costs (capital_cost in PyPSA terms, €/MW/a):

annuity = costs.apply(lambda x: annuity(x["discount rate"], x["lifetime"]), axis=1)
costs["capital_cost"] = (annuity + costs["FOM"] / 100) * costs["investment"]

We can now read the capital and marginal cost of onshore wind, solar and OCGT

costs.at["onwind", "capital_cost"] #EUR/MW/a
np.float64(101644.12332388277)
costs.at["solar", "capital_cost"] #EUR/MW/a
np.float64(51346.82981964593)
costs.at["OCGT", "capital_cost"] #EUR/MW/a
np.float64(47718.67056370105)
costs.at["OCGT", "marginal_cost"] #EUR/MWh
np.float64(64.6839512195122)

Retrieving time series data#

In this example, wind data from https://zenodo.org/record/3253876#.XSiVOEdS8l0 and solar PV data from https://zenodo.org/record/2613651#.X0kbhDVS-uV is used. The data is downloaded in csv format and saved in the ‘data’ folder. The Pandas package is used as a convenient way of managing the datasets.

For convenience, the column including date information is converted into Datetime and set as index

data_solar = pd.read_csv('data/pv_optimal.csv',sep=';')
data_solar.index = pd.DatetimeIndex(data_solar['utc_time'])

data_wind = pd.read_csv('data/onshore_wind_1979-2017.csv',sep=';')
data_wind.index = pd.DatetimeIndex(data_wind['utc_time'])

data_el = pd.read_csv('data/electricity_demand.csv',sep=';')
data_el.index = pd.DatetimeIndex(data_el['utc_time'])

The data format can now be analyzed using the .head() function to show the first lines of the data set

data_solar.head()
utc_time AUT BEL BGR BIH CHE CYP CZE DEU DNK ... MLT NLD NOR POL PRT ROU SRB SVK SVN SWE
utc_time
1979-01-01 00:00:00+00:00 1979-01-01T00:00:00Z 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1979-01-01 01:00:00+00:00 1979-01-01T01:00:00Z 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1979-01-01 02:00:00+00:00 1979-01-01T02:00:00Z 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1979-01-01 03:00:00+00:00 1979-01-01T03:00:00Z 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1979-01-01 04:00:00+00:00 1979-01-01T04:00:00Z 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

5 rows × 33 columns

We will use timeseries for Portugal and Denmark in this excercise

countries = ['PRT', 'DNK']
coordinates = {'PRT': (38.74, -9.15), 'DNK': (55.67, 12.57)}

a. Capacity and dispatch optimisation in a network, F = 0 GW#

For building the model, we start again by initialising an empty network, adding the snapshots, and the electricity buses per country.

n = pypsa.Network()
hours_in_2015 = pd.date_range('2015-01-01 00:00Z',
                              '2015-12-31 23:00Z',
                              freq='h')

n.set_snapshots(hours_in_2015.values)

for country in countries:
    n.add("Bus",
          country,
          y = coordinates[country][0],
          x = coordinates[country][1],
          carrier="AC"
          )
carriers = [
    "onwind",
    "solar",
    "OCGT",
]

n.madd(
    "Carrier",
    carriers,
    color=["dodgerblue", "gold", "indianred"],
    co2_emissions=[costs.at[c, "CO2 intensity"] for c in carriers],
)
/tmp/ipykernel_3019/3103334985.py:7: DeprecatedWarning: madd is deprecated as of 0.31 and will be removed in 1.0. Use `n.add` as a drop-in replacement instead.
  n.madd(
Index(['onwind', 'solar', 'OCGT'], dtype='object')

Add load to the buses.

# add load to the bus
for country in countries:
    n.add("Load",
        f"{country} load",
        bus=country,
        p_set=data_el[country].values,
        carrier = "AC")

Add generators to the buses.

for country in countries:
    n.add(
        "Generator",
        f"{country} OCGT",
        bus=country,
        carrier="OCGT",
        capital_cost=costs.at["OCGT", "capital_cost"],
        marginal_cost=costs.at["OCGT", "marginal_cost"],
        efficiency=costs.at["OCGT", "efficiency"],
        p_nom_extendable=True,
    )   
    CF_wind = data_wind[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} onwind",
        bus=country,
        carrier="onwind",
        capital_cost=costs.at["onwind", "capital_cost"],
        marginal_cost=costs.at["onwind", "marginal_cost"],
        p_max_pu=CF_wind.values,
        efficiency=costs.at["onwind", "efficiency"],
        p_nom_extendable=True,
    )
    CF_solar = data_solar[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} solar",
        bus=country,
        carrier="solar",
        capital_cost=costs.at["solar", "capital_cost"],
        marginal_cost=costs.at["solar", "marginal_cost"],
        p_max_pu=CF_solar.values,
        efficiency=costs.at["solar", "efficiency"],
        p_nom_extendable=True,
    )

Add an overhead AC line between the buses with 0 MW capacity.

n.add(
    "Line",
    "PRT-DNK",
    bus0="PRT",
    bus1="DNK",
    s_nom = 0,
    x = 1,
    r = 1,
)
Index(['PRT-DNK'], dtype='object')
n.plot(bus_sizes=1, margin=1)
/tmp/ipykernel_3019/2753408878.py:1: DeprecatedWarning: plot is deprecated. Use `n.plot.map()` as a drop-in replacement instead.
  n.plot(bus_sizes=1, margin=1)
{'nodes': {'Bus': <matplotlib.collections.PatchCollection at 0x7fbafe8e5710>},
 'branches': {'Line': <matplotlib.collections.LineCollection at 0x7fbafeafe690>},
 'flows': {}}
../_images/3b8b5881f766bf0ea645b4fb9944e9d4252353836dcc27c67c49313ccf61fe4d.png
n.optimize(solver_name="gurobi")
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['PRT', 'DNK'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following loads have carriers which are not defined:
Index(['PRT load', 'DNK load'], dtype='object', name='Load')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['PRT-DNK'], dtype='object', name='Line')
INFO:linopy.model: Solve problem using Gurobi solver
INFO:linopy.io:Writing objective.
Writing constraints.:   0%|          | 0/7 [00:00<?, ?it/s]
Writing constraints.:  43%|████▎     | 3/7 [00:00<00:00, 21.39it/s]
Writing constraints.:  86%|████████▌ | 6/7 [00:00<00:00, 14.24it/s]
Writing constraints.: 100%|██████████| 7/7 [00:00<00:00, 13.19it/s]

Writing continuous variables.:   0%|          | 0/3 [00:00<?, ?it/s]
Writing continuous variables.: 100%|██████████| 3/3 [00:00<00:00, 30.13it/s]
INFO:linopy.io: Writing time: 0.71s
Restricted license - for non-production use only - expires 2026-11-23
INFO:gurobipy:Restricted license - for non-production use only - expires 2026-11-23
Read LP format model from file /tmp/linopy-problem-8p9b3ij_.lp
INFO:gurobipy:Read LP format model from file /tmp/linopy-problem-8p9b3ij_.lp
Reading time = 0.16 seconds
INFO:gurobipy:Reading time = 0.16 seconds
obj: 140166 rows, 61326 columns, 236551 nonzeros
INFO:gurobipy:obj: 140166 rows, 61326 columns, 236551 nonzeros
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - "Ubuntu 24.04.2 LTS")
INFO:gurobipy:Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - "Ubuntu 24.04.2 LTS")

INFO:gurobipy:
CPU model: AMD EPYC 7763 64-Core Processor, instruction set [SSE2|AVX|AVX2]
INFO:gurobipy:CPU model: AMD EPYC 7763 64-Core Processor, instruction set [SSE2|AVX|AVX2]
Thread count: 2 physical cores, 4 logical processors, using up to 4 threads
INFO:gurobipy:Thread count: 2 physical cores, 4 logical processors, using up to 4 threads

INFO:gurobipy:
---------------------------------------------------------------------------
GurobiError                               Traceback (most recent call last)
Cell In[22], line 1
----> 1 n.optimize(solver_name="gurobi")

File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/pypsa/optimization/optimize.py:633, in OptimizationAccessor.__call__(self, *args, **kwargs)
    631 @wraps(optimize)
    632 def __call__(self, *args: Any, **kwargs: Any) -> Any:
--> 633     return optimize(self.n, *args, **kwargs)

File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/pypsa/optimization/optimize.py:605, in optimize(n, snapshots, multi_investment_periods, transmission_losses, linearized_unit_commitment, model_kwargs, extra_functionality, assign_all_duals, solver_name, solver_options, compute_infeasibilities, **kwargs)
    603 if extra_functionality:
    604     extra_functionality(n, sns)
--> 605 status, condition = m.solve(solver_name=solver_name, **solver_options, **kwargs)
    607 if status == "ok":
    608     assign_solution(n)

File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/linopy/model.py:1206, in Model.solve(self, solver_name, io_api, explicit_coordinate_names, problem_fn, solution_fn, log_fn, basis_fn, warmstart_fn, keep_files, env, sanitize_zeros, sanitize_infinities, slice_size, remote, progress, **solver_options)
   1198             explicit_coordinate_names = False
   1199         problem_fn = self.to_file(
   1200             to_path(problem_fn),
   1201             io_api=io_api,
   (...)   1204             progress=progress,
   1205         )
-> 1206         result = solver.solve_problem_from_file(
   1207             problem_fn=to_path(problem_fn),
   1208             solution_fn=to_path(solution_fn),
   1209             log_fn=to_path(log_fn),
   1210             warmstart_fn=to_path(warmstart_fn),
   1211             basis_fn=to_path(basis_fn),
   1212             env=env,
   1213         )
   1215 finally:
   1216     for fn in (problem_fn, solution_fn):

File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/linopy/solvers.py:1039, in Gurobi.solve_problem_from_file(self, problem_fn, solution_fn, log_fn, warmstart_fn, basis_fn, env)
   1035     env_ = env
   1037 m = gurobipy.read(problem_fn_, env=env_)
-> 1039 return self._solve(
   1040     m,
   1041     solution_fn=solution_fn,
   1042     log_fn=log_fn,
   1043     warmstart_fn=warmstart_fn,
   1044     basis_fn=basis_fn,
   1045     io_api=io_api,
   1046     sense=sense,
   1047 )

File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/linopy/solvers.py:1113, in Gurobi._solve(self, m, solution_fn, log_fn, warmstart_fn, basis_fn, io_api, sense)
   1111 if warmstart_fn is not None:
   1112     m.read(path_to_string(warmstart_fn))
-> 1113 m.optimize()
   1115 if basis_fn is not None:
   1116     try:

File src/gurobipy/_model.pyx:903, in gurobipy._model.Model.optimize()

GurobiError: Model too large for size-limited license; visit https://gurobi.com/unrestricted for more information
# Total system costs
n.objective/1e9
5.1694758223180965
# Average electricity price
n.buses_t.marginal_price.mean()
Bus
PRT    61.105150
DNK    59.640202
dtype: float64
# Hours with almost zero price
n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count()
Bus
PRT    1244
DNK    1452
dtype: int64
# Share of hours with almost zero price
(n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count())/len(n.snapshots)
Bus
PRT    0.142009
DNK    0.165753
dtype: float64
# Congestion rent
((n.buses_t.marginal_price["PRT"] - n.buses_t.marginal_price["DNK"]) * n.lines_t.p0["PRT-DNK"]).sum()
np.float64(0.0)
# Utilisation of transmission line
n.lines_t.p0.abs().mean() / n.lines.s_nom_opt
Line
PRT-DNK   NaN
dtype: float64
# Total generation
n.generators_t.p.sum(axis=0).groupby([n.generators.bus, n.generators.carrier]).sum().div(1e6).round(1)
bus  carrier
DNK  OCGT       16.0
     onwind     15.2
     solar       1.6
PRT  OCGT       27.0
     onwind      9.4
     solar      12.5
dtype: float64
n.generators.efficiency
Generator
PRT OCGT      0.41
PRT onwind    1.00
PRT solar     1.00
DNK OCGT      0.41
DNK onwind    1.00
DNK solar     1.00
Name: efficiency, dtype: float64
# Total CO2 emissions
n.generators_t.p.sum(axis=0).groupby([n.generators.carrier]).sum()["OCGT"] * (costs.at["OCGT", "CO2 intensity"] / costs.at["OCGT", "efficiency"])
np.float64(20729628.597112708)

b. F = 1 GW#

Repeat the same procedure as in a.

n = pypsa.Network()
hours_in_2015 = pd.date_range('2015-01-01 00:00Z',
                              '2015-12-31 23:00Z',
                              freq='h')

n.set_snapshots(hours_in_2015.values)

for country in countries:
    n.add("Bus",
          country,
          y = coordinates[country][0],
          x = coordinates[country][1],
          carrier="AC"
          )

carriers = [
    "onwind",
    "solar",
    "OCGT",
]

n.madd(
    "Carrier",
    carriers,
    color=["dodgerblue", "gold", "indianred"],
    co2_emissions=[costs.at[c, "CO2 intensity"] for c in carriers],
)
# add load to the bus
for country in countries:
    n.add("Load",
        f"{country} load",
        bus=country,
        p_set=data_el[country].values,
        carrier = "AC")
for country in countries:
    n.add(
        "Generator",
        f"{country} OCGT",
        bus=country,
        carrier="OCGT",
        capital_cost=costs.at["OCGT", "capital_cost"],
        marginal_cost=costs.at["OCGT", "marginal_cost"],
        efficiency=costs.at["OCGT", "efficiency"],
        p_nom_extendable=True,
    )   
    CF_wind = data_wind[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} onwind",
        bus=country,
        carrier="onwind",
        capital_cost=costs.at["onwind", "capital_cost"],
        marginal_cost=costs.at["onwind", "marginal_cost"],
        p_max_pu=CF_wind.values,
        efficiency=costs.at["onwind", "efficiency"],
        p_nom_extendable=True,
    )
    CF_solar = data_solar[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} solar",
        bus=country,
        carrier="solar",
        capital_cost=costs.at["solar", "capital_cost"],
        marginal_cost=costs.at["solar", "marginal_cost"],
        p_max_pu=CF_solar.values,
        efficiency=costs.at["solar", "efficiency"],
        p_nom_extendable=True,
    )
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})

Add the overhead AC line between the buses with 1 GW capacity.

n.add(
    "Line",
    "PRT-DNK",
    bus0="PRT",
    bus1="DNK",
    s_nom = 1000,
    x = 1,
    r = 1,
)
n.optimize(solver_name="gurobi")
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/constraints.py:531: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  .groupby(n.loads.bus, axis=1)
INFO:linopy.model: Solve problem using Gurobi solver
Set parameter Username
INFO:gurobipy:Set parameter Username
Set parameter LicenseID to value 2609678
INFO:gurobipy:Set parameter LicenseID to value 2609678
Academic license - for non-commercial use only - expires 2026-01-14
INFO:gurobipy:Academic license - for non-commercial use only - expires 2026-01-14
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 7/7 [00:00<00:00, 26.64it/s]
Writing continuous variables.: 100%|██████████| 3/3 [00:00<00:00, 63.82it/s]
INFO:linopy.io: Writing time: 0.36s
Read LP format model from file /private/var/folders/zg/by4_k0616s98pw41wld9475c0000gp/T/linopy-problem-etxacq8b.lp
INFO:gurobipy:Read LP format model from file /private/var/folders/zg/by4_k0616s98pw41wld9475c0000gp/T/linopy-problem-etxacq8b.lp
Reading time = 0.13 seconds
INFO:gurobipy:Reading time = 0.13 seconds
obj: 140166 rows, 61326 columns, 236551 nonzeros
INFO:gurobipy:obj: 140166 rows, 61326 columns, 236551 nonzeros
Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (mac64[arm] - Darwin 24.3.0 24D81)
INFO:gurobipy:Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (mac64[arm] - Darwin 24.3.0 24D81)

INFO:gurobipy:
CPU model: Apple M3
INFO:gurobipy:CPU model: Apple M3
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
INFO:gurobipy:Thread count: 8 physical cores, 8 logical processors, using up to 8 threads

INFO:gurobipy:
Optimize a model with 140166 rows, 61326 columns and 236551 nonzeros
INFO:gurobipy:Optimize a model with 140166 rows, 61326 columns and 236551 nonzeros
Model fingerprint: 0x522d9a41
INFO:gurobipy:Model fingerprint: 0x522d9a41
Coefficient statistics:
INFO:gurobipy:Coefficient statistics:
  Matrix range     [1e-03, 1e+00]
INFO:gurobipy:  Matrix range     [1e-03, 1e+00]
  Objective range  [1e-02, 1e+05]
INFO:gurobipy:  Objective range  [1e-02, 1e+05]
  Bounds range     [0e+00, 0e+00]
INFO:gurobipy:  Bounds range     [0e+00, 0e+00]
  RHS range        [1e+03, 9e+03]
INFO:gurobipy:  RHS range        [1e+03, 9e+03]
Presolve removed 78821 rows and 8735 columns
INFO:gurobipy:Presolve removed 78821 rows and 8735 columns
Presolve time: 0.05s
INFO:gurobipy:Presolve time: 0.05s
Presolved: 61345 rows, 52591 columns, 148995 nonzeros
INFO:gurobipy:Presolved: 61345 rows, 52591 columns, 148995 nonzeros

INFO:gurobipy:
Concurrent LP optimizer: primal simplex, dual simplex, and barrier
INFO:gurobipy:Concurrent LP optimizer: primal simplex, dual simplex, and barrier
Showing barrier log only...
INFO:gurobipy:Showing barrier log only...

INFO:gurobipy:
Ordering time: 0.01s
INFO:gurobipy:Ordering time: 0.01s

INFO:gurobipy:
Barrier statistics:
INFO:gurobipy:Barrier statistics:
 Dense cols : 6
INFO:gurobipy: Dense cols : 6
 AA' NZ     : 9.641e+04
INFO:gurobipy: AA' NZ     : 9.641e+04
 Factor NZ  : 5.642e+05 (roughly 50 MB of memory)
INFO:gurobipy: Factor NZ  : 5.642e+05 (roughly 50 MB of memory)
 Factor Ops : 5.571e+06 (less than 1 second per iteration)
INFO:gurobipy: Factor Ops : 5.571e+06 (less than 1 second per iteration)
 Threads    : 6
INFO:gurobipy: Threads    : 6

INFO:gurobipy:
                  Objective                Residual
INFO:gurobipy:                  Objective                Residual
Iter       Primal          Dual         Primal    Dual     Compl     Time
INFO:gurobipy:Iter       Primal          Dual         Primal    Dual     Compl     Time
   0   3.69032254e+10 -4.67469621e+10  4.54e+04 0.00e+00  1.66e+07     0s
INFO:gurobipy:   0   3.69032254e+10 -4.67469621e+10  4.54e+04 0.00e+00  1.66e+07     0s
   1   4.09409335e+10 -1.07093146e+11  3.77e+03 2.18e+02  2.93e+06     0s
INFO:gurobipy:   1   4.09409335e+10 -1.07093146e+11  3.77e+03 2.18e+02  2.93e+06     0s
   2   2.55520931e+10 -1.58805991e+10  7.28e-12 6.24e+00  3.13e+05     0s
INFO:gurobipy:   2   2.55520931e+10 -1.58805991e+10  7.28e-12 6.24e+00  3.13e+05     0s
   3   1.16019556e+10 -1.03665148e+09  2.18e-11 6.46e-01  8.96e+04     0s
INFO:gurobipy:   3   1.16019556e+10 -1.03665148e+09  2.18e-11 6.46e-01  8.96e+04     0s
   4   9.00074571e+09  6.16011452e+08  2.00e-11 4.69e-01  5.88e+04     0s
INFO:gurobipy:   4   9.00074571e+09  6.16011452e+08  2.00e-11 4.69e-01  5.88e+04     0s
   5   7.35858685e+09  1.81084301e+09  2.55e-11 3.96e-01  3.86e+04     0s
INFO:gurobipy:   5   7.35858685e+09  1.81084301e+09  2.55e-11 3.96e-01  3.86e+04     0s
   6   6.33968507e+09  2.73795791e+09  3.27e-11 2.52e-01  2.49e+04     0s
INFO:gurobipy:   6   6.33968507e+09  2.73795791e+09  3.27e-11 2.52e-01  2.49e+04     0s
   7   6.26202300e+09  3.37798786e+09  2.91e-11 1.64e-01  1.98e+04     0s
INFO:gurobipy:   7   6.26202300e+09  3.37798786e+09  2.91e-11 1.64e-01  1.98e+04     0s
   8   6.12060866e+09  3.55572950e+09  7.80e-09 1.65e-01  1.76e+04     0s
INFO:gurobipy:   8   6.12060866e+09  3.55572950e+09  7.80e-09 1.65e-01  1.76e+04     0s
   9   5.89133720e+09  3.79679906e+09  1.12e-09 1.05e-01  1.44e+04     0s
INFO:gurobipy:   9   5.89133720e+09  3.79679906e+09  1.12e-09 1.05e-01  1.44e+04     0s
  10   5.60340745e+09  4.29175282e+09  3.41e-09 4.50e-02  8.97e+03     0s
INFO:gurobipy:  10   5.60340745e+09  4.29175282e+09  3.41e-09 4.50e-02  8.97e+03     0s
  11   5.35550281e+09  4.60362066e+09  4.49e-09 3.69e-02  5.13e+03     1s
INFO:gurobipy:  11   5.35550281e+09  4.60362066e+09  4.49e-09 3.69e-02  5.13e+03     1s
  12   5.23979951e+09  4.77826178e+09  1.61e-08 2.19e-02  3.15e+03     1s
INFO:gurobipy:  12   5.23979951e+09  4.77826178e+09  1.61e-08 2.19e-02  3.15e+03     1s
  13   5.17411808e+09  4.82657502e+09  2.95e-08 1.75e-02  2.37e+03     1s
INFO:gurobipy:  13   5.17411808e+09  4.82657502e+09  2.95e-08 1.75e-02  2.37e+03     1s
  14   5.15205601e+09  4.86292976e+09  2.64e-08 1.39e-02  1.97e+03     1s
INFO:gurobipy:  14   5.15205601e+09  4.86292976e+09  2.64e-08 1.39e-02  1.97e+03     1s
  15   5.09132844e+09  4.90014650e+09  6.95e-08 1.02e-02  1.30e+03     1s
INFO:gurobipy:  15   5.09132844e+09  4.90014650e+09  6.95e-08 1.02e-02  1.30e+03     1s
  16   5.06117716e+09  4.94880536e+09  2.62e-08 5.16e-03  7.65e+02     1s
INFO:gurobipy:  16   5.06117716e+09  4.94880536e+09  2.62e-08 5.16e-03  7.65e+02     1s
  17   5.04329009e+09  4.96517846e+09  3.50e-08 3.58e-03  5.32e+02     1s
INFO:gurobipy:  17   5.04329009e+09  4.96517846e+09  3.50e-08 3.58e-03  5.32e+02     1s
  18   5.03113036e+09  4.97129205e+09  5.54e-08 3.00e-03  4.08e+02     1s
INFO:gurobipy:  18   5.03113036e+09  4.97129205e+09  5.54e-08 3.00e-03  4.08e+02     1s
  19   5.02135327e+09  4.97741753e+09  1.75e-07 2.42e-03  3.00e+02     1s
INFO:gurobipy:  19   5.02135327e+09  4.97741753e+09  1.75e-07 2.42e-03  3.00e+02     1s
  20   5.01660073e+09  4.98155209e+09  6.73e-08 2.04e-03  2.39e+02     1s
INFO:gurobipy:  20   5.01660073e+09  4.98155209e+09  6.73e-08 2.04e-03  2.39e+02     1s
  21   5.01139899e+09  4.98435343e+09  1.81e-07 1.77e-03  1.85e+02     1s
INFO:gurobipy:  21   5.01139899e+09  4.98435343e+09  1.81e-07 1.77e-03  1.85e+02     1s
  22   5.00931175e+09  4.99006277e+09  1.63e-07 1.24e-03  1.32e+02     1s
INFO:gurobipy:  22   5.00931175e+09  4.99006277e+09  1.63e-07 1.24e-03  1.32e+02     1s
  23   5.00805337e+09  4.99128506e+09  1.36e-07 1.13e-03  1.15e+02     1s
INFO:gurobipy:  23   5.00805337e+09  4.99128506e+09  1.36e-07 1.13e-03  1.15e+02     1s
  24   5.00706870e+09  4.99231207e+09  1.31e-07 1.03e-03  1.01e+02     1s
INFO:gurobipy:  24   5.00706870e+09  4.99231207e+09  1.31e-07 1.03e-03  1.01e+02     1s
  25   5.00649779e+09  4.99317112e+09  8.23e-08 9.48e-04  9.14e+01     1s
INFO:gurobipy:  25   5.00649779e+09  4.99317112e+09  8.23e-08 9.48e-04  9.14e+01     1s
  26   5.00573928e+09  4.99580951e+09  2.84e-07 6.94e-04  6.81e+01     1s
INFO:gurobipy:  26   5.00573928e+09  4.99580951e+09  2.84e-07 6.94e-04  6.81e+01     1s
  27   5.00533128e+09  4.99638388e+09  1.27e-07 6.40e-04  6.14e+01     1s
INFO:gurobipy:  27   5.00533128e+09  4.99638388e+09  1.27e-07 6.40e-04  6.14e+01     1s
  28   5.00510313e+09  4.99657375e+09  1.32e-07 6.22e-04  5.85e+01     1s
INFO:gurobipy:  28   5.00510313e+09  4.99657375e+09  1.32e-07 6.22e-04  5.85e+01     1s
  29   5.00479799e+09  4.99696311e+09  1.45e-07 5.83e-04  5.38e+01     1s
INFO:gurobipy:  29   5.00479799e+09  4.99696311e+09  1.45e-07 5.83e-04  5.38e+01     1s
  30   5.00462640e+09  4.99731721e+09  1.65e-07 5.49e-04  5.02e+01     1s
INFO:gurobipy:  30   5.00462640e+09  4.99731721e+09  1.65e-07 5.49e-04  5.02e+01     1s
  31   5.00448569e+09  4.99751938e+09  1.35e-07 5.30e-04  4.79e+01     1s
INFO:gurobipy:  31   5.00448569e+09  4.99751938e+09  1.35e-07 5.30e-04  4.79e+01     1s
  32   5.00426131e+09  4.99785436e+09  2.78e-07 4.97e-04  4.40e+01     1s
INFO:gurobipy:  32   5.00426131e+09  4.99785436e+09  2.78e-07 4.97e-04  4.40e+01     1s
  33   5.00416903e+09  4.99820416e+09  3.08e-07 4.63e-04  4.10e+01     1s
INFO:gurobipy:  33   5.00416903e+09  4.99820416e+09  3.08e-07 4.63e-04  4.10e+01     1s
  34   5.00389811e+09  4.99905986e+09  4.29e-07 3.80e-04  3.33e+01     1s
INFO:gurobipy:  34   5.00389811e+09  4.99905986e+09  4.29e-07 3.80e-04  3.33e+01     1s
  35   5.00367542e+09  5.00009028e+09  3.39e-07 2.27e-04  2.46e+01     1s
INFO:gurobipy:  35   5.00367542e+09  5.00009028e+09  3.39e-07 2.27e-04  2.46e+01     1s
  36   5.00349573e+09  5.00026542e+09  5.92e-05 2.13e-04  2.22e+01     1s
INFO:gurobipy:  36   5.00349573e+09  5.00026542e+09  5.92e-05 2.13e-04  2.22e+01     1s
  37   5.00342027e+09  5.00083219e+09  1.27e-04 1.66e-04  1.78e+01     1s
INFO:gurobipy:  37   5.00342027e+09  5.00083219e+09  1.27e-04 1.66e-04  1.78e+01     1s
  38   5.00339743e+09  5.00092004e+09  1.45e-04 1.59e-04  1.70e+01     1s
INFO:gurobipy:  38   5.00339743e+09  5.00092004e+09  1.45e-04 1.59e-04  1.70e+01     1s
  39   5.00328416e+09  5.00130717e+09  2.50e-04 1.28e-04  1.36e+01     1s
INFO:gurobipy:  39   5.00328416e+09  5.00130717e+09  2.50e-04 1.28e-04  1.36e+01     1s
  40   5.00325508e+09  5.00136164e+09  2.83e-04 1.23e-04  1.30e+01     1s
INFO:gurobipy:  40   5.00325508e+09  5.00136164e+09  2.83e-04 1.23e-04  1.30e+01     1s
  41   5.00321153e+09  5.00174191e+09  3.25e-04 9.19e-05  1.01e+01     1s
INFO:gurobipy:  41   5.00321153e+09  5.00174191e+09  3.25e-04 9.19e-05  1.01e+01     1s
  42   5.00319841e+09  5.00199853e+09  3.33e-04 6.37e-05  8.23e+00     1s
INFO:gurobipy:  42   5.00319841e+09  5.00199853e+09  3.33e-04 6.37e-05  8.23e+00     1s
  43   5.00307541e+09  5.00215639e+09  3.64e-04 5.12e-05  6.31e+00     1s
INFO:gurobipy:  43   5.00307541e+09  5.00215639e+09  3.64e-04 5.12e-05  6.31e+00     1s
  44   5.00303532e+09  5.00230961e+09  3.73e-04 3.51e-05  4.98e+00     1s
INFO:gurobipy:  44   5.00303532e+09  5.00230961e+09  3.73e-04 3.51e-05  4.98e+00     1s
  45   5.00299298e+09  5.00233710e+09  3.64e-04 3.33e-05  4.51e+00     1s
INFO:gurobipy:  45   5.00299298e+09  5.00233710e+09  3.64e-04 3.33e-05  4.51e+00     1s
  46   5.00292127e+09  5.00259332e+09  3.53e-04 1.01e-05  2.25e+00     1s
INFO:gurobipy:  46   5.00292127e+09  5.00259332e+09  3.53e-04 1.01e-05  2.25e+00     1s
  47   5.00291875e+09  5.00260488e+09  3.47e-04 9.65e-06  2.15e+00     1s
INFO:gurobipy:  47   5.00291875e+09  5.00260488e+09  3.47e-04 9.65e-06  2.15e+00     1s
  48   5.00291078e+09  5.00265272e+09  3.29e-04 6.03e-06  1.77e+00     2s
INFO:gurobipy:  48   5.00291078e+09  5.00265272e+09  3.29e-04 6.03e-06  1.77e+00     2s
  49   5.00290546e+09  5.00266633e+09  3.13e-04 5.57e-06  1.64e+00     2s
INFO:gurobipy:  49   5.00290546e+09  5.00266633e+09  3.13e-04 5.57e-06  1.64e+00     2s
  50   5.00289164e+09  5.00269470e+09  2.77e-04 4.64e-06  1.35e+00     2s
INFO:gurobipy:  50   5.00289164e+09  5.00269470e+09  2.77e-04 4.64e-06  1.35e+00     2s
  51   5.00288129e+09  5.00275965e+09  2.46e-04 1.45e-06  8.31e-01     2s
INFO:gurobipy:  51   5.00288129e+09  5.00275965e+09  2.46e-04 1.45e-06  8.31e-01     2s
  52   5.00287391e+09  5.00280676e+09  2.20e-04 4.58e-07  4.55e-01     2s
INFO:gurobipy:  52   5.00287391e+09  5.00280676e+09  2.20e-04 4.58e-07  4.55e-01     2s
  53   5.00286311e+09  5.00281001e+09  1.67e-04 3.89e-07  3.60e-01     2s
INFO:gurobipy:  53   5.00286311e+09  5.00281001e+09  1.67e-04 3.89e-07  3.60e-01     2s
  54   5.00285918e+09  5.00281132e+09  1.51e-04 3.63e-07  3.25e-01     2s
INFO:gurobipy:  54   5.00285918e+09  5.00281132e+09  1.51e-04 3.63e-07  3.25e-01     2s
  55   5.00285028e+09  5.00281900e+09  1.12e-04 8.43e-08  2.12e-01     2s
INFO:gurobipy:  55   5.00285028e+09  5.00281900e+09  1.12e-04 8.43e-08  2.12e-01     2s
  56   5.00283360e+09  5.00282701e+09  2.37e-05 2.91e-11  4.46e-02     2s
INFO:gurobipy:  56   5.00283360e+09  5.00282701e+09  2.37e-05 2.91e-11  4.46e-02     2s
  57   5.00283057e+09  5.00282937e+09  4.67e-06 1.31e-09  8.13e-03     2s
INFO:gurobipy:  57   5.00283057e+09  5.00282937e+09  4.67e-06 1.31e-09  8.13e-03     2s
  58   5.00282999e+09  5.00282951e+09  2.18e-07 8.73e-10  3.31e-03     2s
INFO:gurobipy:  58   5.00282999e+09  5.00282951e+09  2.18e-07 8.73e-10  3.31e-03     2s
  59   5.00282996e+09  5.00282994e+09  2.15e-07 8.44e-10  1.71e-04     2s
INFO:gurobipy:  59   5.00282996e+09  5.00282994e+09  2.15e-07 8.44e-10  1.71e-04     2s
  60   5.00282996e+09  5.00282996e+09  1.56e-10 5.53e-10  5.80e-07     2s
INFO:gurobipy:  60   5.00282996e+09  5.00282996e+09  1.56e-10 5.53e-10  5.80e-07     2s
  61   5.00282996e+09  5.00282996e+09  7.28e-12 1.86e-09  1.14e-10     2s
INFO:gurobipy:  61   5.00282996e+09  5.00282996e+09  7.28e-12 1.86e-09  1.14e-10     2s

INFO:gurobipy:
Barrier solved model in 61 iterations and 1.71 seconds (1.34 work units)
INFO:gurobipy:Barrier solved model in 61 iterations and 1.71 seconds (1.34 work units)
Optimal objective 5.00282996e+09
INFO:gurobipy:Optimal objective 5.00282996e+09

INFO:gurobipy:
Crossover log...
INFO:gurobipy:Crossover log...

INFO:gurobipy:
    4407 DPushes remaining with DInf 0.0000000e+00                 2s
INFO:gurobipy:    4407 DPushes remaining with DInf 0.0000000e+00                 2s
       0 DPushes remaining with DInf 0.0000000e+00                 2s
INFO:gurobipy:       0 DPushes remaining with DInf 0.0000000e+00                 2s

INFO:gurobipy:
    7137 PPushes remaining with PInf 0.0000000e+00                 2s
INFO:gurobipy:    7137 PPushes remaining with PInf 0.0000000e+00                 2s
       0 PPushes remaining with PInf 0.0000000e+00                 2s
INFO:gurobipy:       0 PPushes remaining with PInf 0.0000000e+00                 2s

INFO:gurobipy:
  Push phase complete: Pinf 0.0000000e+00, Dinf 1.7993651e-09      2s
INFO:gurobipy:  Push phase complete: Pinf 0.0000000e+00, Dinf 1.7993651e-09      2s

INFO:gurobipy:

INFO:gurobipy:
Solved with barrier
INFO:gurobipy:Solved with barrier
Iteration    Objective       Primal Inf.    Dual Inf.      Time
INFO:gurobipy:Iteration    Objective       Primal Inf.    Dual Inf.      Time
   11547    5.0028300e+09   0.000000e+00   0.000000e+00      2s
INFO:gurobipy:   11547    5.0028300e+09   0.000000e+00   0.000000e+00      2s

INFO:gurobipy:
Solved in 11547 iterations and 1.83 seconds (1.44 work units)
INFO:gurobipy:Solved in 11547 iterations and 1.83 seconds (1.44 work units)
Optimal objective  5.002829957e+09
INFO:gurobipy:Optimal objective  5.002829957e+09
INFO:linopy.constants: Optimization successful: 
Status: ok
Termination condition: optimal
Solution: 61326 primals, 140166 duals
Objective: 5.00e+09
Solver model: available
Solver message: 2

/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/optimize.py:355: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.

For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.


  n.df(c)[attr + "_opt"].update(df)
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-ext-p-lower, Generator-ext-p-upper, Line-fix-s-lower, Line-fix-s-upper were not assigned to the network.
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/optimize.py:473: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  .groupby(level=0, axis=1)
('ok', 'optimal')
# Total system costs
n.objective/1e9
5.002829956537811
# Average electricity price
n.buses_t.marginal_price.mean()
Bus
PRT    61.053013
DNK    59.363296
dtype: float64
# Hours with almost zero price
n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count()
Bus
PRT    1254
DNK    1491
dtype: int64
# Share of hours with almost zero price
(n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count())/len(n.snapshots)
Bus
PRT    0.143151
DNK    0.170205
dtype: float64
# Congestion rent
((n.buses_t.marginal_price["PRT"] - n.buses_t.marginal_price["DNK"]) * n.lines_t.p0["PRT-DNK"]).sum()
np.float64(-100293619.69608223)
# Utilisation of transmission line
n.lines_t.p0.abs().mean() / n.lines.s_nom_opt
Line
PRT-DNK    0.889165
dtype: float64
# Total generation
n.generators_t.p.sum(axis=0).groupby([n.generators.bus, n.generators.carrier]).sum().div(1e6).round(1)
bus  carrier
DNK  OCGT        9.3
     onwind     18.4
     solar       0.0
PRT  OCGT       29.4
     onwind     11.1
     solar      13.6
dtype: float64
# Total CO2 emissions
n.generators_t.p.sum(axis=0).groupby([n.generators.carrier]).sum()["OCGT"] * (costs.at["OCGT", "CO2 intensity"] / costs.at["OCGT", "efficiency"])
np.float64(18675041.17898809)

c. Unlimited F.#

Assume F = 10 GW which is larger than maximal load in both countries.

n = pypsa.Network()
hours_in_2015 = pd.date_range('2015-01-01 00:00Z',
                              '2015-12-31 23:00Z',
                              freq='h')

n.set_snapshots(hours_in_2015.values)

for country in countries:
    n.add("Bus",
          country,
          y = coordinates[country][0],
          x = coordinates[country][1],
          carrier="AC"
          )

carriers = [
    "onwind",
    "solar",
    "OCGT",
]

n.madd(
    "Carrier",
    carriers,
    color=["dodgerblue", "gold", "indianred"],
    co2_emissions=[costs.at[c, "CO2 intensity"] for c in carriers],
)
# add load to the bus
for country in countries:
    n.add("Load",
        f"{country} load",
        bus=country,
        p_set=data_el[country].values,
        carrier = "AC")
for country in countries:
    n.add(
        "Generator",
        f"{country} OCGT",
        bus=country,
        carrier="OCGT",
        capital_cost=costs.at["OCGT", "capital_cost"],
        marginal_cost=costs.at["OCGT", "marginal_cost"],
        efficiency=costs.at["OCGT", "efficiency"],
        p_nom_extendable=True,
    )   
    CF_wind = data_wind[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} onwind",
        bus=country,
        carrier="onwind",
        capital_cost=costs.at["onwind", "capital_cost"],
        marginal_cost=costs.at["onwind", "marginal_cost"],
        p_max_pu=CF_wind.values,
        efficiency=costs.at["onwind", "efficiency"],
        p_nom_extendable=True,
    )
    CF_solar = data_solar[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} solar",
        bus=country,
        carrier="solar",
        capital_cost=costs.at["solar", "capital_cost"],
        marginal_cost=costs.at["solar", "marginal_cost"],
        p_max_pu=CF_solar.values,
        efficiency=costs.at["solar", "efficiency"],
        p_nom_extendable=True,
    )
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
n.add(
    "Line",
    "PRT-DNK",
    bus0="PRT",
    bus1="DNK",
    s_nom = 10000,
    x = 1,
    r = 1,
)
n.optimize(solver_name="gurobi")
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/constraints.py:531: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  .groupby(n.loads.bus, axis=1)
INFO:linopy.model: Solve problem using Gurobi solver
Set parameter Username
INFO:gurobipy:Set parameter Username
Set parameter LicenseID to value 2609678
INFO:gurobipy:Set parameter LicenseID to value 2609678
Academic license - for non-commercial use only - expires 2026-01-14
INFO:gurobipy:Academic license - for non-commercial use only - expires 2026-01-14
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 7/7 [00:00<00:00, 21.56it/s]
Writing continuous variables.: 100%|██████████| 3/3 [00:00<00:00, 48.55it/s]
INFO:linopy.io: Writing time: 0.44s
Read LP format model from file /private/var/folders/zg/by4_k0616s98pw41wld9475c0000gp/T/linopy-problem-7534hy7j.lp
INFO:gurobipy:Read LP format model from file /private/var/folders/zg/by4_k0616s98pw41wld9475c0000gp/T/linopy-problem-7534hy7j.lp
Reading time = 0.14 seconds
INFO:gurobipy:Reading time = 0.14 seconds
obj: 140166 rows, 61326 columns, 236551 nonzeros
INFO:gurobipy:obj: 140166 rows, 61326 columns, 236551 nonzeros
Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (mac64[arm] - Darwin 24.3.0 24D81)
INFO:gurobipy:Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (mac64[arm] - Darwin 24.3.0 24D81)

INFO:gurobipy:
CPU model: Apple M3
INFO:gurobipy:CPU model: Apple M3
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
INFO:gurobipy:Thread count: 8 physical cores, 8 logical processors, using up to 8 threads

INFO:gurobipy:
Optimize a model with 140166 rows, 61326 columns and 236551 nonzeros
INFO:gurobipy:Optimize a model with 140166 rows, 61326 columns and 236551 nonzeros
Model fingerprint: 0xf8cc0859
INFO:gurobipy:Model fingerprint: 0xf8cc0859
Coefficient statistics:
INFO:gurobipy:Coefficient statistics:
  Matrix range     [1e-03, 1e+00]
INFO:gurobipy:  Matrix range     [1e-03, 1e+00]
  Objective range  [1e-02, 1e+05]
INFO:gurobipy:  Objective range  [1e-02, 1e+05]
  Bounds range     [0e+00, 0e+00]
INFO:gurobipy:  Bounds range     [0e+00, 0e+00]
  RHS range        [2e+03, 1e+04]
INFO:gurobipy:  RHS range        [2e+03, 1e+04]
Presolve removed 87581 rows and 17495 columns
INFO:gurobipy:Presolve removed 87581 rows and 17495 columns
Presolve time: 0.07s
INFO:gurobipy:Presolve time: 0.07s
Presolved: 52585 rows, 43831 columns, 131475 nonzeros
INFO:gurobipy:Presolved: 52585 rows, 43831 columns, 131475 nonzeros

INFO:gurobipy:
Concurrent LP optimizer: primal simplex, dual simplex, and barrier
INFO:gurobipy:Concurrent LP optimizer: primal simplex, dual simplex, and barrier
Showing barrier log only...
INFO:gurobipy:Showing barrier log only...

INFO:gurobipy:
Ordering time: 0.00s
INFO:gurobipy:Ordering time: 0.00s

INFO:gurobipy:
Barrier statistics:
INFO:gurobipy:Barrier statistics:
 Dense cols : 5
INFO:gurobipy: Dense cols : 5
 AA' NZ     : 7.013e+04
INFO:gurobipy: AA' NZ     : 7.013e+04
 Factor NZ  : 3.188e+05 (roughly 34 MB of memory)
INFO:gurobipy: Factor NZ  : 3.188e+05 (roughly 34 MB of memory)
 Factor Ops : 2.502e+06 (less than 1 second per iteration)
INFO:gurobipy: Factor Ops : 2.502e+06 (less than 1 second per iteration)
 Threads    : 6
INFO:gurobipy: Threads    : 6

INFO:gurobipy:
                  Objective                Residual
INFO:gurobipy:                  Objective                Residual
Iter       Primal          Dual         Primal    Dual     Compl     Time
INFO:gurobipy:Iter       Primal          Dual         Primal    Dual     Compl     Time
   0   5.35677064e+10  0.00000000e+00  9.32e+04 0.00e+00  2.57e+07     0s
INFO:gurobipy:   0   5.35677064e+10  0.00000000e+00  9.32e+04 0.00e+00  2.57e+07     0s
   1   7.18055530e+10 -6.14869369e+10  7.70e+03 3.49e+02  5.14e+06     0s
INFO:gurobipy:   1   7.18055530e+10 -6.14869369e+10  7.70e+03 3.49e+02  5.14e+06     0s
   2   4.47082187e+10 -1.42932200e+10  1.46e-11 6.78e+00  6.20e+05     0s
INFO:gurobipy:   2   4.47082187e+10 -1.42932200e+10  1.46e-11 6.78e+00  6.20e+05     0s
   3   1.69928130e+10 -1.02710038e+09  2.55e-11 9.39e-01  1.77e+05     0s
INFO:gurobipy:   3   1.69928130e+10 -1.02710038e+09  2.55e-11 9.39e-01  1.77e+05     0s
   4   1.10869909e+10  9.56030563e+08  1.16e-10 5.56e-01  9.84e+04     0s
INFO:gurobipy:   4   1.10869909e+10  9.56030563e+08  1.16e-10 5.56e-01  9.84e+04     0s
   5   8.78098305e+09  1.65413554e+09  8.00e-11 4.30e-01  6.90e+04     0s
INFO:gurobipy:   5   8.78098305e+09  1.65413554e+09  8.00e-11 4.30e-01  6.90e+04     0s
   6   7.88868412e+09  2.29103602e+09  1.95e-10 3.03e-01  5.40e+04     0s
INFO:gurobipy:   6   7.88868412e+09  2.29103602e+09  1.95e-10 3.03e-01  5.40e+04     0s
   7   7.64568598e+09  2.85509020e+09  1.24e-09 2.03e-01  4.61e+04     0s
INFO:gurobipy:   7   7.64568598e+09  2.85509020e+09  1.24e-09 2.03e-01  4.61e+04     0s
   8   6.92697085e+09  3.21323807e+09  2.15e-08 1.56e-01  3.57e+04     0s
INFO:gurobipy:   8   6.92697085e+09  3.21323807e+09  2.15e-08 1.56e-01  3.57e+04     0s
   9   6.74254729e+09  3.52248936e+09  2.10e-08 1.18e-01  3.09e+04     0s
INFO:gurobipy:   9   6.74254729e+09  3.52248936e+09  2.10e-08 1.18e-01  3.09e+04     0s
  10   6.00484988e+09  3.87858916e+09  2.91e-08 6.75e-02  2.04e+04     0s
INFO:gurobipy:  10   6.00484988e+09  3.87858916e+09  2.91e-08 6.75e-02  2.04e+04     0s
  11   5.66686952e+09  4.21140048e+09  1.85e-08 4.12e-02  1.39e+04     0s
INFO:gurobipy:  11   5.66686952e+09  4.21140048e+09  1.85e-08 4.12e-02  1.39e+04     0s
  12   5.43415306e+09  4.40991679e+09  1.23e-08 2.71e-02  9.80e+03     0s
INFO:gurobipy:  12   5.43415306e+09  4.40991679e+09  1.23e-08 2.71e-02  9.80e+03     0s
  13   5.29268716e+09  4.54480730e+09  1.49e-08 1.85e-02  7.15e+03     0s
INFO:gurobipy:  13   5.29268716e+09  4.54480730e+09  1.49e-08 1.85e-02  7.15e+03     0s
  14   5.16915079e+09  4.58304361e+09  3.62e-08 1.64e-02  5.61e+03     0s
INFO:gurobipy:  14   5.16915079e+09  4.58304361e+09  3.62e-08 1.64e-02  5.61e+03     0s
  15   5.10495113e+09  4.61557701e+09  5.09e-08 1.45e-02  4.68e+03     0s
INFO:gurobipy:  15   5.10495113e+09  4.61557701e+09  5.09e-08 1.45e-02  4.68e+03     0s
  16   5.03917152e+09  4.69566207e+09  8.34e-08 9.24e-03  3.29e+03     0s
INFO:gurobipy:  16   5.03917152e+09  4.69566207e+09  8.34e-08 9.24e-03  3.29e+03     0s
  17   4.99248942e+09  4.71960198e+09  3.76e-08 7.74e-03  2.61e+03     0s
INFO:gurobipy:  17   4.99248942e+09  4.71960198e+09  3.76e-08 7.74e-03  2.61e+03     0s
  18   4.97636788e+09  4.73119768e+09  6.70e-08 7.06e-03  2.35e+03     0s
INFO:gurobipy:  18   4.97636788e+09  4.73119768e+09  6.70e-08 7.06e-03  2.35e+03     0s
  19   4.95054656e+09  4.75813197e+09  5.74e-07 5.25e-03  1.84e+03     0s
INFO:gurobipy:  19   4.95054656e+09  4.75813197e+09  5.74e-07 5.25e-03  1.84e+03     0s
  20   4.94691945e+09  4.77293076e+09  5.38e-07 3.82e-03  1.66e+03     0s
INFO:gurobipy:  20   4.94691945e+09  4.77293076e+09  5.38e-07 3.82e-03  1.66e+03     0s
  21   4.89311900e+09  4.78779104e+09  1.34e-06 2.78e-03  1.01e+03     0s
INFO:gurobipy:  21   4.89311900e+09  4.78779104e+09  1.34e-06 2.78e-03  1.01e+03     0s
  22   4.87793614e+09  4.80072941e+09  1.42e-06 2.21e-03  7.41e+02     0s
INFO:gurobipy:  22   4.87793614e+09  4.80072941e+09  1.42e-06 2.21e-03  7.41e+02     0s
  23   4.86974987e+09  4.81030428e+09  1.66e-06 1.79e-03  5.70e+02     0s
INFO:gurobipy:  23   4.86974987e+09  4.81030428e+09  1.66e-06 1.79e-03  5.70e+02     0s
  24   4.86458528e+09  4.81834149e+09  6.29e-07 1.45e-03  4.44e+02     0s
INFO:gurobipy:  24   4.86458528e+09  4.81834149e+09  6.29e-07 1.45e-03  4.44e+02     0s
  25   4.86076096e+09  4.82977770e+09  5.91e-07 9.55e-04  2.97e+02     0s
INFO:gurobipy:  25   4.86076096e+09  4.82977770e+09  5.91e-07 9.55e-04  2.97e+02     0s
  26   4.85837538e+09  4.83492677e+09  4.55e-07 7.43e-04  2.25e+02     0s
INFO:gurobipy:  26   4.85837538e+09  4.83492677e+09  4.55e-07 7.43e-04  2.25e+02     0s
  27   4.85655938e+09  4.83741371e+09  4.81e-07 6.38e-04  1.84e+02     0s
INFO:gurobipy:  27   4.85655938e+09  4.83741371e+09  4.81e-07 6.38e-04  1.84e+02     0s
  28   4.85514803e+09  4.84020588e+09  4.67e-07 5.21e-04  1.44e+02     0s
INFO:gurobipy:  28   4.85514803e+09  4.84020588e+09  4.67e-07 5.21e-04  1.44e+02     0s
  29   4.85400102e+09  4.84484221e+09  3.94e-07 3.25e-04  8.81e+01     0s
INFO:gurobipy:  29   4.85400102e+09  4.84484221e+09  3.94e-07 3.25e-04  8.81e+01     0s
  30   4.85360032e+09  4.84617755e+09  4.42e-07 2.69e-04  7.14e+01     1s
INFO:gurobipy:  30   4.85360032e+09  4.84617755e+09  4.42e-07 2.69e-04  7.14e+01     1s
  31   4.85329453e+09  4.84673889e+09  1.02e-06 2.36e-04  6.31e+01     1s
INFO:gurobipy:  31   4.85329453e+09  4.84673889e+09  1.02e-06 2.36e-04  6.31e+01     1s
  32   4.85315955e+09  4.84785404e+09  6.77e-07 1.82e-04  5.11e+01     1s
INFO:gurobipy:  32   4.85315955e+09  4.84785404e+09  6.77e-07 1.82e-04  5.11e+01     1s
  33   4.85307304e+09  4.84851021e+09  9.44e-07 1.58e-04  4.39e+01     1s
INFO:gurobipy:  33   4.85307304e+09  4.84851021e+09  9.44e-07 1.58e-04  4.39e+01     1s
  34   4.85297888e+09  4.84910238e+09  3.09e-07 1.26e-04  3.73e+01     1s
INFO:gurobipy:  34   4.85297888e+09  4.84910238e+09  3.09e-07 1.26e-04  3.73e+01     1s
  35   4.85291819e+09  4.84944615e+09  4.48e-07 1.11e-04  3.34e+01     1s
INFO:gurobipy:  35   4.85291819e+09  4.84944615e+09  4.48e-07 1.11e-04  3.34e+01     1s
  36   4.85287949e+09  4.85041456e+09  4.48e-07 7.19e-05  2.37e+01     1s
INFO:gurobipy:  36   4.85287949e+09  4.85041456e+09  4.48e-07 7.19e-05  2.37e+01     1s
  37   4.85280420e+09  4.85067309e+09  4.55e-07 6.26e-05  2.05e+01     1s
INFO:gurobipy:  37   4.85280420e+09  4.85067309e+09  4.55e-07 6.26e-05  2.05e+01     1s
  38   4.85278968e+09  4.85124354e+09  1.50e-04 4.59e-05  1.49e+01     1s
INFO:gurobipy:  38   4.85278968e+09  4.85124354e+09  1.50e-04 4.59e-05  1.49e+01     1s
  39   4.85278104e+09  4.85133537e+09  1.97e-04 4.23e-05  1.39e+01     1s
INFO:gurobipy:  39   4.85278104e+09  4.85133537e+09  1.97e-04 4.23e-05  1.39e+01     1s
  40   4.85277874e+09  4.85154630e+09  2.09e-04 3.43e-05  1.19e+01     1s
INFO:gurobipy:  40   4.85277874e+09  4.85154630e+09  2.09e-04 3.43e-05  1.19e+01     1s
  41   4.85277891e+09  4.85165450e+09  2.21e-04 3.14e-05  1.08e+01     1s
INFO:gurobipy:  41   4.85277891e+09  4.85165450e+09  2.21e-04 3.14e-05  1.08e+01     1s
  42   4.85277251e+09  4.85194579e+09  2.27e-04 2.09e-05  7.96e+00     1s
INFO:gurobipy:  42   4.85277251e+09  4.85194579e+09  2.27e-04 2.09e-05  7.96e+00     1s
  43   4.85277278e+09  4.85247180e+09  1.93e-04 3.19e-06  2.90e+00     1s
INFO:gurobipy:  43   4.85277278e+09  4.85247180e+09  1.93e-04 3.19e-06  2.90e+00     1s
  44   4.85276459e+09  4.85274801e+09  6.70e-05 1.43e-09  1.58e-01     1s
INFO:gurobipy:  44   4.85276459e+09  4.85274801e+09  6.70e-05 1.43e-09  1.58e-01     1s
  45   4.85276344e+09  4.85276294e+09  2.65e-06 4.07e-10  4.79e-03     1s
INFO:gurobipy:  45   4.85276344e+09  4.85276294e+09  2.65e-06 4.07e-10  4.79e-03     1s
  46   4.85276339e+09  4.85276339e+09  5.23e-10 4.37e-10  1.12e-06     1s
INFO:gurobipy:  46   4.85276339e+09  4.85276339e+09  5.23e-10 4.37e-10  1.12e-06     1s
  47   4.85276339e+09  4.85276339e+09  7.45e-10 1.14e-09  1.20e-12     1s
INFO:gurobipy:  47   4.85276339e+09  4.85276339e+09  7.45e-10 1.14e-09  1.20e-12     1s

INFO:gurobipy:
Barrier solved model in 47 iterations and 0.67 seconds (0.81 work units)
INFO:gurobipy:Barrier solved model in 47 iterations and 0.67 seconds (0.81 work units)
Optimal objective 4.85276339e+09
INFO:gurobipy:Optimal objective 4.85276339e+09

INFO:gurobipy:
Crossover log...
INFO:gurobipy:Crossover log...

INFO:gurobipy:
    4427 DPushes remaining with DInf 0.0000000e+00                 1s
INFO:gurobipy:    4427 DPushes remaining with DInf 0.0000000e+00                 1s
       0 DPushes remaining with DInf 0.0000000e+00                 1s
INFO:gurobipy:       0 DPushes remaining with DInf 0.0000000e+00                 1s

INFO:gurobipy:
    1788 PPushes remaining with PInf 0.0000000e+00                 1s
INFO:gurobipy:    1788 PPushes remaining with PInf 0.0000000e+00                 1s
       0 PPushes remaining with PInf 0.0000000e+00                 1s
INFO:gurobipy:       0 PPushes remaining with PInf 0.0000000e+00                 1s

INFO:gurobipy:
  Push phase complete: Pinf 0.0000000e+00, Dinf 1.5786849e-09      1s
INFO:gurobipy:  Push phase complete: Pinf 0.0000000e+00, Dinf 1.5786849e-09      1s

INFO:gurobipy:

INFO:gurobipy:
Solved with barrier
INFO:gurobipy:Solved with barrier
Iteration    Objective       Primal Inf.    Dual Inf.      Time
INFO:gurobipy:Iteration    Objective       Primal Inf.    Dual Inf.      Time
    6218    4.8527634e+09   0.000000e+00   0.000000e+00      1s
INFO:gurobipy:    6218    4.8527634e+09   0.000000e+00   0.000000e+00      1s

INFO:gurobipy:
Use crossover to convert LP symmetric solution to basic solution...
INFO:gurobipy:Use crossover to convert LP symmetric solution to basic solution...
Crossover log...
INFO:gurobipy:Crossover log...

INFO:gurobipy:
       0 DPushes remaining with DInf 0.0000000e+00                 1s
INFO:gurobipy:       0 DPushes remaining with DInf 0.0000000e+00                 1s

INFO:gurobipy:
    8012 PPushes remaining with PInf 0.0000000e+00                 1s
INFO:gurobipy:    8012 PPushes remaining with PInf 0.0000000e+00                 1s
       0 PPushes remaining with PInf 0.0000000e+00                 1s
INFO:gurobipy:       0 PPushes remaining with PInf 0.0000000e+00                 1s

INFO:gurobipy:
  Push phase complete: Pinf 0.0000000e+00, Dinf 2.4590132e-09      1s
INFO:gurobipy:  Push phase complete: Pinf 0.0000000e+00, Dinf 2.4590132e-09      1s

INFO:gurobipy:
Iteration    Objective       Primal Inf.    Dual Inf.      Time
INFO:gurobipy:Iteration    Objective       Primal Inf.    Dual Inf.      Time
   14299    4.8527634e+09   0.000000e+00   0.000000e+00      1s
INFO:gurobipy:   14299    4.8527634e+09   0.000000e+00   0.000000e+00      1s

INFO:gurobipy:
Solved in 14299 iterations and 0.87 seconds (0.95 work units)
INFO:gurobipy:Solved in 14299 iterations and 0.87 seconds (0.95 work units)
Optimal objective  4.852763389e+09
INFO:gurobipy:Optimal objective  4.852763389e+09
INFO:linopy.constants: Optimization successful: 
Status: ok
Termination condition: optimal
Solution: 61326 primals, 140166 duals
Objective: 4.85e+09
Solver model: available
Solver message: 2

/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/optimize.py:355: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.

For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.


  n.df(c)[attr + "_opt"].update(df)
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-ext-p-lower, Generator-ext-p-upper, Line-fix-s-lower, Line-fix-s-upper were not assigned to the network.
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/optimize.py:473: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  .groupby(level=0, axis=1)
('ok', 'optimal')
# Total system costs
n.objective/1e9
4.852763388966909
# Average electricity price
n.buses_t.marginal_price.mean()
Bus
PRT    57.214036
DNK    57.214036
dtype: float64
# Hours with almost zero price
n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count()
Bus
PRT    1787
DNK    1787
dtype: int64
# Share of hours with almost zero price
(n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count())/len(n.snapshots)
Bus
PRT    0.203995
DNK    0.203995
dtype: float64
# Congestion rent
((n.buses_t.marginal_price["PRT"] - n.buses_t.marginal_price["DNK"]) * n.lines_t.p0["PRT-DNK"]).sum()
np.float64(0.0)
# Utilisation of transmission line
n.lines_t.p0.abs().mean() / n.lines.s_nom_opt
Line
PRT-DNK    0.191488
dtype: float64
# Total generation
n.generators_t.p.sum(axis=0).groupby([n.generators.bus, n.generators.carrier]).sum().div(1e6).round(1)
bus  carrier
DNK  OCGT        3.2
     onwind     24.8
     solar       0.0
PRT  OCGT       27.5
     onwind     11.9
     solar      14.3
dtype: float64
# Total CO2 emissions
n.generators_t.p.sum(axis=0).groupby([n.generators.carrier]).sum()["OCGT"] * (costs.at["OCGT", "CO2 intensity"] / costs.at["OCGT", "efficiency"])
np.float64(14834697.56278273)

d. Optimise F endogenously (assume it starts at 0 GW capacity).#

n = pypsa.Network()
hours_in_2015 = pd.date_range('2015-01-01 00:00Z',
                              '2015-12-31 23:00Z',
                              freq='h')

n.set_snapshots(hours_in_2015.values)

for country in countries:
    n.add("Bus",
          country,
          y = coordinates[country][0],
          x = coordinates[country][1],
          carrier="AC"
          )

carriers = [
    "onwind",
    "solar",
    "OCGT",
]

n.madd(
    "Carrier",
    carriers,
    color=["dodgerblue", "gold", "indianred"],
    co2_emissions=[costs.at[c, "CO2 intensity"] for c in carriers],
)
# add load to the bus
for country in countries:
    n.add("Load",
        f"{country} load",
        bus=country,
        p_set=data_el[country].values,
        carrier = "AC")
for country in countries:
    n.add(
        "Generator",
        f"{country} OCGT",
        bus=country,
        carrier="OCGT",
        capital_cost=costs.at["OCGT", "capital_cost"],
        marginal_cost=costs.at["OCGT", "marginal_cost"],
        efficiency=costs.at["OCGT", "efficiency"],
        p_nom_extendable=True,
    )   
    CF_wind = data_wind[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} onwind",
        bus=country,
        carrier="onwind",
        capital_cost=costs.at["onwind", "capital_cost"],
        marginal_cost=costs.at["onwind", "marginal_cost"],
        p_max_pu=CF_wind.values,
        efficiency=costs.at["onwind", "efficiency"],
        p_nom_extendable=True,
    )
    CF_solar = data_solar[country][[hour.strftime("%Y-%m-%dT%H:%M:%SZ") for hour in n.snapshots]]
    n.add("Generator",
        f"{country} solar",
        bus=country,
        carrier="solar",
        capital_cost=costs.at["solar", "capital_cost"],
        marginal_cost=costs.at["solar", "marginal_cost"],
        p_max_pu=CF_solar.values,
        efficiency=costs.at["solar", "efficiency"],
        p_nom_extendable=True,
    )
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/components.py:323: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '[]' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
  attrs.loc[bool_b, "default"] = attrs.loc[bool_b].isin({True, "True"})
costs.at["HVAC overhead", "capital_cost"]
np.float64(42.007473674372484)
costs.at["onwind", "capital_cost"]
np.float64(101644.12332388277)

Add captial costs and distance between the buses, and endogenise the capacity of the overhead AC line.

n.add(
    "Line",
    "PRT-DNK",
    bus0="PRT",
    bus1="DNK",
    s_nom = 0,
    x = 1,
    r = 1,
    capital_cost = costs.at["HVAC overhead", "capital_cost"] * 2477,
    s_nom_extendable = True
)
n.optimize(solver_name="gurobi")
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/constraints.py:531: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  .groupby(n.loads.bus, axis=1)
INFO:linopy.model: Solve problem using Gurobi solver
Set parameter Username
INFO:gurobipy:Set parameter Username
Set parameter LicenseID to value 2609678
INFO:gurobipy:Set parameter LicenseID to value 2609678
Academic license - for non-commercial use only - expires 2026-01-14
INFO:gurobipy:Academic license - for non-commercial use only - expires 2026-01-14
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 9/9 [00:00<00:00, 14.63it/s]
Writing continuous variables.: 100%|██████████| 4/4 [00:00<00:00, 76.00it/s]
INFO:linopy.io: Writing time: 0.72s
Read LP format model from file /private/var/folders/zg/by4_k0616s98pw41wld9475c0000gp/T/linopy-problem-hm27jsa0.lp
INFO:gurobipy:Read LP format model from file /private/var/folders/zg/by4_k0616s98pw41wld9475c0000gp/T/linopy-problem-hm27jsa0.lp
Reading time = 0.26 seconds
INFO:gurobipy:Reading time = 0.26 seconds
obj: 140167 rows, 61327 columns, 254072 nonzeros
INFO:gurobipy:obj: 140167 rows, 61327 columns, 254072 nonzeros
Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (mac64[arm] - Darwin 24.3.0 24D81)
INFO:gurobipy:Gurobi Optimizer version 12.0.0 build v12.0.0rc1 (mac64[arm] - Darwin 24.3.0 24D81)

INFO:gurobipy:
CPU model: Apple M3
INFO:gurobipy:CPU model: Apple M3
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
INFO:gurobipy:Thread count: 8 physical cores, 8 logical processors, using up to 8 threads

INFO:gurobipy:
Optimize a model with 140167 rows, 61327 columns and 254072 nonzeros
INFO:gurobipy:Optimize a model with 140167 rows, 61327 columns and 254072 nonzeros
Model fingerprint: 0x8ae06ae3
INFO:gurobipy:Model fingerprint: 0x8ae06ae3
Coefficient statistics:
INFO:gurobipy:Coefficient statistics:
  Matrix range     [1e-03, 1e+00]
INFO:gurobipy:  Matrix range     [1e-03, 1e+00]
  Objective range  [1e-02, 1e+05]
INFO:gurobipy:  Objective range  [1e-02, 1e+05]
  Bounds range     [0e+00, 0e+00]
INFO:gurobipy:  Bounds range     [0e+00, 0e+00]
  RHS range        [2e+03, 9e+03]
INFO:gurobipy:  RHS range        [2e+03, 9e+03]
Presolve removed 70062 rows and 17495 columns
INFO:gurobipy:Presolve removed 70062 rows and 17495 columns
Presolve time: 0.70s
INFO:gurobipy:Presolve time: 0.70s
Presolved: 70105 rows, 43832 columns, 191955 nonzeros
INFO:gurobipy:Presolved: 70105 rows, 43832 columns, 191955 nonzeros

INFO:gurobipy:
Concurrent LP optimizer: primal simplex, dual simplex, and barrier
INFO:gurobipy:Concurrent LP optimizer: primal simplex, dual simplex, and barrier
Showing barrier log only...
INFO:gurobipy:Showing barrier log only...

INFO:gurobipy:
Ordering time: 0.02s
INFO:gurobipy:Ordering time: 0.02s

INFO:gurobipy:
Barrier statistics:
INFO:gurobipy:Barrier statistics:
 Dense cols : 7
INFO:gurobipy: Dense cols : 7
 AA' NZ     : 1.744e+05
INFO:gurobipy: AA' NZ     : 1.744e+05
 Factor NZ  : 7.483e+05 (roughly 50 MB of memory)
INFO:gurobipy: Factor NZ  : 7.483e+05 (roughly 50 MB of memory)
 Factor Ops : 8.510e+06 (less than 1 second per iteration)
INFO:gurobipy: Factor Ops : 8.510e+06 (less than 1 second per iteration)
 Threads    : 6
INFO:gurobipy: Threads    : 6

INFO:gurobipy:
                  Objective                Residual
INFO:gurobipy:                  Objective                Residual
Iter       Primal          Dual         Primal    Dual     Compl     Time
INFO:gurobipy:Iter       Primal          Dual         Primal    Dual     Compl     Time
   0   4.74162353e+10  0.00000000e+00  9.69e+04 0.00e+00  2.08e+07     1s
INFO:gurobipy:   0   4.74162353e+10  0.00000000e+00  9.69e+04 0.00e+00  2.08e+07     1s
   1   5.72962595e+10 -7.59755270e+10  1.63e+04 2.65e+02  5.21e+06     1s
INFO:gurobipy:   1   5.72962595e+10 -7.59755270e+10  1.63e+04 2.65e+02  5.21e+06     1s
   2   4.07511813e+10 -3.44552017e+10  2.91e-11 4.83e+00  5.56e+05     1s
INFO:gurobipy:   2   4.07511813e+10 -3.44552017e+10  2.91e-11 4.83e+00  5.56e+05     1s
   3   1.24969540e+10 -9.17636724e+08  2.18e-11 2.75e-01  9.23e+04     1s
INFO:gurobipy:   3   1.24969540e+10 -9.17636724e+08  2.18e-11 2.75e-01  9.23e+04     1s
   4   7.97621588e+09  1.58008531e+09  1.02e-10 9.60e-02  4.35e+04     1s
INFO:gurobipy:   4   7.97621588e+09  1.58008531e+09  1.02e-10 9.60e-02  4.35e+04     1s
   5   7.03236504e+09  2.30239305e+09  1.82e-10 7.70e-02  3.21e+04     1s
INFO:gurobipy:   5   7.03236504e+09  2.30239305e+09  1.82e-10 7.70e-02  3.21e+04     1s
   6   6.98990268e+09  2.41435210e+09  1.67e-10 7.37e-02  3.10e+04     1s
INFO:gurobipy:   6   6.98990268e+09  2.41435210e+09  1.67e-10 7.37e-02  3.10e+04     1s
   7   6.80231225e+09  2.83242181e+09  1.82e-10 6.02e-02  2.69e+04     1s
INFO:gurobipy:   7   6.80231225e+09  2.83242181e+09  1.82e-10 6.02e-02  2.69e+04     1s
   8   6.15299645e+09  3.77387229e+09  4.52e-09 2.46e-02  1.61e+04     1s
INFO:gurobipy:   8   6.15299645e+09  3.77387229e+09  4.52e-09 2.46e-02  1.61e+04     1s
   9   5.86067535e+09  4.11415609e+09  4.19e-09 1.62e-02  1.18e+04     1s
INFO:gurobipy:   9   5.86067535e+09  4.11415609e+09  4.19e-09 1.62e-02  1.18e+04     1s
  10   5.55990825e+09  4.60073663e+09  2.73e-09 4.94e-03  6.47e+03     1s
INFO:gurobipy:  10   5.55990825e+09  4.60073663e+09  2.73e-09 4.94e-03  6.47e+03     1s
  11   5.43305626e+09  4.71349625e+09  4.40e-09 3.39e-03  4.85e+03     1s
INFO:gurobipy:  11   5.43305626e+09  4.71349625e+09  4.40e-09 3.39e-03  4.85e+03     1s
  12   5.36000388e+09  4.79794557e+09  6.98e-09 2.38e-03  3.79e+03     1s
INFO:gurobipy:  12   5.36000388e+09  4.79794557e+09  6.98e-09 2.38e-03  3.79e+03     1s
  13   5.29217666e+09  4.87997649e+09  1.21e-08 1.39e-03  2.78e+03     1s
INFO:gurobipy:  13   5.29217666e+09  4.87997649e+09  1.21e-08 1.39e-03  2.78e+03     1s
  14   5.23881707e+09  4.95639054e+09  5.85e-09 6.15e-04  1.90e+03     1s
INFO:gurobipy:  14   5.23881707e+09  4.95639054e+09  5.85e-09 6.15e-04  1.90e+03     1s
  15   5.20965030e+09  4.98740701e+09  1.14e-08 4.81e-04  1.50e+03     1s
INFO:gurobipy:  15   5.20965030e+09  4.98740701e+09  1.14e-08 4.81e-04  1.50e+03     1s
  16   5.18706084e+09  5.02447712e+09  5.83e-09 4.43e-04  1.10e+03     1s
INFO:gurobipy:  16   5.18706084e+09  5.02447712e+09  5.83e-09 4.43e-04  1.10e+03     1s
  17   5.16895631e+09  5.04686160e+09  5.16e-09 3.71e-04  8.22e+02     1s
INFO:gurobipy:  17   5.16895631e+09  5.04686160e+09  5.16e-09 3.71e-04  8.22e+02     1s
  18   5.15521217e+09  5.05217039e+09  3.37e-08 3.50e-04  6.94e+02     1s
INFO:gurobipy:  18   5.15521217e+09  5.05217039e+09  3.37e-08 3.50e-04  6.94e+02     1s
  19   5.14465599e+09  5.06860837e+09  2.51e-08 2.45e-04  5.12e+02     1s
INFO:gurobipy:  19   5.14465599e+09  5.06860837e+09  2.51e-08 2.45e-04  5.12e+02     1s
  20   5.13540944e+09  5.07253719e+09  1.56e-08 2.26e-04  4.24e+02     1s
INFO:gurobipy:  20   5.13540944e+09  5.07253719e+09  1.56e-08 2.26e-04  4.24e+02     1s
  21   5.13017518e+09  5.07637124e+09  1.46e-08 2.04e-04  3.62e+02     1s
INFO:gurobipy:  21   5.13017518e+09  5.07637124e+09  1.46e-08 2.04e-04  3.62e+02     1s
  22   5.12292050e+09  5.08065406e+09  1.42e-08 1.79e-04  2.85e+02     1s
INFO:gurobipy:  22   5.12292050e+09  5.08065406e+09  1.42e-08 1.79e-04  2.85e+02     1s
  23   5.11795300e+09  5.08522557e+09  2.74e-07 1.50e-04  2.21e+02     1s
INFO:gurobipy:  23   5.11795300e+09  5.08522557e+09  2.74e-07 1.50e-04  2.21e+02     1s
  24   5.11663186e+09  5.08710414e+09  2.07e-07 1.38e-04  1.99e+02     1s
INFO:gurobipy:  24   5.11663186e+09  5.08710414e+09  2.07e-07 1.38e-04  1.99e+02     1s
  25   5.11450133e+09  5.09207733e+09  1.59e-07 1.01e-04  1.51e+02     2s
INFO:gurobipy:  25   5.11450133e+09  5.09207733e+09  1.59e-07 1.01e-04  1.51e+02     2s
  26   5.11302319e+09  5.09290376e+09  1.39e-07 9.53e-05  1.36e+02     2s
INFO:gurobipy:  26   5.11302319e+09  5.09290376e+09  1.39e-07 9.53e-05  1.36e+02     2s
  27   5.11237519e+09  5.09371523e+09  5.61e-08 8.99e-05  1.26e+02     2s
INFO:gurobipy:  27   5.11237519e+09  5.09371523e+09  5.61e-08 8.99e-05  1.26e+02     2s
  28   5.11125954e+09  5.09715142e+09  1.16e-07 6.45e-05  9.51e+01     2s
INFO:gurobipy:  28   5.11125954e+09  5.09715142e+09  1.16e-07 6.45e-05  9.51e+01     2s
  29   5.11087291e+09  5.09757920e+09  1.53e-07 6.17e-05  8.96e+01     2s
INFO:gurobipy:  29   5.11087291e+09  5.09757920e+09  1.53e-07 6.17e-05  8.96e+01     2s
  30   5.11010106e+09  5.09785118e+09  1.56e-07 5.99e-05  8.26e+01     2s
INFO:gurobipy:  30   5.11010106e+09  5.09785118e+09  1.56e-07 5.99e-05  8.26e+01     2s
  31   5.10967197e+09  5.09849786e+09  9.42e-08 5.57e-05  7.54e+01     2s
INFO:gurobipy:  31   5.10967197e+09  5.09849786e+09  9.42e-08 5.57e-05  7.54e+01     2s
  32   5.10939154e+09  5.09907024e+09  3.09e-07 5.20e-05  6.96e+01     2s
INFO:gurobipy:  32   5.10939154e+09  5.09907024e+09  3.09e-07 5.20e-05  6.96e+01     2s
  33   5.10920726e+09  5.09934572e+09  2.65e-07 5.01e-05  6.65e+01     2s
INFO:gurobipy:  33   5.10920726e+09  5.09934572e+09  2.65e-07 5.01e-05  6.65e+01     2s
  34   5.10910936e+09  5.09982107e+09  1.77e-07 4.71e-05  6.26e+01     2s
INFO:gurobipy:  34   5.10910936e+09  5.09982107e+09  1.77e-07 4.71e-05  6.26e+01     2s
  35   5.10892500e+09  5.10037798e+09  1.69e-07 4.35e-05  5.76e+01     2s
INFO:gurobipy:  35   5.10892500e+09  5.10037798e+09  1.69e-07 4.35e-05  5.76e+01     2s
  36   5.10871565e+09  5.10072451e+09  2.18e-07 4.13e-05  5.39e+01     2s
INFO:gurobipy:  36   5.10871565e+09  5.10072451e+09  2.18e-07 4.13e-05  5.39e+01     2s
  37   5.10857313e+09  5.10122948e+09  3.37e-07 3.80e-05  4.95e+01     2s
INFO:gurobipy:  37   5.10857313e+09  5.10122948e+09  3.37e-07 3.80e-05  4.95e+01     2s
  38   5.10846412e+09  5.10144416e+09  2.44e-07 3.65e-05  4.74e+01     2s
INFO:gurobipy:  38   5.10846412e+09  5.10144416e+09  2.44e-07 3.65e-05  4.74e+01     2s
  39   5.10835076e+09  5.10189216e+09  3.15e-07 3.37e-05  4.36e+01     2s
INFO:gurobipy:  39   5.10835076e+09  5.10189216e+09  3.15e-07 3.37e-05  4.36e+01     2s
  40   5.10809279e+09  5.10233356e+09  1.27e-07 3.07e-05  3.89e+01     2s
INFO:gurobipy:  40   5.10809279e+09  5.10233356e+09  1.27e-07 3.07e-05  3.89e+01     2s
  41   5.10795242e+09  5.10267038e+09  2.13e-07 2.85e-05  3.56e+01     2s
INFO:gurobipy:  41   5.10795242e+09  5.10267038e+09  2.13e-07 2.85e-05  3.56e+01     2s
  42   5.10779719e+09  5.10306588e+09  6.13e-07 1.48e-05  3.19e+01     2s
INFO:gurobipy:  42   5.10779719e+09  5.10306588e+09  6.13e-07 1.48e-05  3.19e+01     2s
  43   5.10766721e+09  5.10345718e+09  6.56e-07 1.65e-06  2.84e+01     2s
INFO:gurobipy:  43   5.10766721e+09  5.10345718e+09  6.56e-07 1.65e-06  2.84e+01     2s
  44   5.10756118e+09  5.10369946e+09  7.25e-07 1.54e-06  2.61e+01     2s
INFO:gurobipy:  44   5.10756118e+09  5.10369946e+09  7.25e-07 1.54e-06  2.61e+01     2s
  45   5.10744640e+09  5.10409457e+09  3.58e-07 1.39e-06  2.26e+01     2s
INFO:gurobipy:  45   5.10744640e+09  5.10409457e+09  3.58e-07 1.39e-06  2.26e+01     2s
  46   5.10730304e+09  5.10425362e+09  4.64e-07 1.26e-09  2.06e+01     2s
INFO:gurobipy:  46   5.10730304e+09  5.10425362e+09  4.64e-07 1.26e-09  2.06e+01     2s
  47   5.10724880e+09  5.10462687e+09  5.85e-07 1.19e-09  1.77e+01     2s
INFO:gurobipy:  47   5.10724880e+09  5.10462687e+09  5.85e-07 1.19e-09  1.77e+01     2s
  48   5.10719651e+09  5.10483579e+09  3.74e-07 9.75e-10  1.59e+01     2s
INFO:gurobipy:  48   5.10719651e+09  5.10483579e+09  3.74e-07 9.75e-10  1.59e+01     2s
  49   5.10716365e+09  5.10487201e+09  2.57e-07 3.54e-09  1.55e+01     2s
INFO:gurobipy:  49   5.10716365e+09  5.10487201e+09  2.57e-07 3.54e-09  1.55e+01     2s
  50   5.10712807e+09  5.10514527e+09  3.15e-07 2.77e-09  1.34e+01     2s
INFO:gurobipy:  50   5.10712807e+09  5.10514527e+09  3.15e-07 2.77e-09  1.34e+01     2s
  51   5.10706371e+09  5.10541890e+09  2.38e-07 1.91e-09  1.11e+01     2s
INFO:gurobipy:  51   5.10706371e+09  5.10541890e+09  2.38e-07 1.91e-09  1.11e+01     2s
  52   5.10696425e+09  5.10547967e+09  2.90e-07 1.25e-09  1.00e+01     2s
INFO:gurobipy:  52   5.10696425e+09  5.10547967e+09  2.90e-07 1.25e-09  1.00e+01     2s
  53   5.10693793e+09  5.10576395e+09  2.26e-07 7.60e-10  7.92e+00     2s
INFO:gurobipy:  53   5.10693793e+09  5.10576395e+09  2.26e-07 7.60e-10  7.92e+00     2s
  54   5.10689143e+09  5.10582828e+09  7.76e-07 1.37e-09  7.18e+00     2s
INFO:gurobipy:  54   5.10689143e+09  5.10582828e+09  7.76e-07 1.37e-09  7.18e+00     2s
  55   5.10684344e+09  5.10601891e+09  3.45e-07 3.30e-09  5.56e+00     3s
INFO:gurobipy:  55   5.10684344e+09  5.10601891e+09  3.45e-07 3.30e-09  5.56e+00     3s
  56   5.10682260e+09  5.10618128e+09  3.70e-05 1.93e-09  4.33e+00     3s
INFO:gurobipy:  56   5.10682260e+09  5.10618128e+09  3.70e-05 1.93e-09  4.33e+00     3s
  57   5.10681942e+09  5.10619950e+09  4.30e-05 1.91e-09  4.18e+00     3s
INFO:gurobipy:  57   5.10681942e+09  5.10619950e+09  4.30e-05 1.91e-09  4.18e+00     3s
  58   5.10680175e+09  5.10622061e+09  7.81e-05 8.66e-10  3.92e+00     3s
INFO:gurobipy:  58   5.10680175e+09  5.10622061e+09  7.81e-05 8.66e-10  3.92e+00     3s
  59   5.10675979e+09  5.10646873e+09  1.75e-04 1.55e-09  1.96e+00     3s
INFO:gurobipy:  59   5.10675979e+09  5.10646873e+09  1.75e-04 1.55e-09  1.96e+00     3s
  60   5.10674641e+09  5.10653308e+09  1.38e-04 1.68e-09  1.44e+00     3s
INFO:gurobipy:  60   5.10674641e+09  5.10653308e+09  1.38e-04 1.68e-09  1.44e+00     3s
  61   5.10672491e+09  5.10657701e+09  8.10e-05 1.23e-09  9.98e-01     3s
INFO:gurobipy:  61   5.10672491e+09  5.10657701e+09  8.10e-05 1.23e-09  9.98e-01     3s
  62   5.10672397e+09  5.10658206e+09  7.84e-05 1.22e-09  9.57e-01     3s
INFO:gurobipy:  62   5.10672397e+09  5.10658206e+09  7.84e-05 1.22e-09  9.57e-01     3s
  63   5.10672179e+09  5.10658368e+09  7.27e-05 1.19e-09  9.32e-01     3s
INFO:gurobipy:  63   5.10672179e+09  5.10658368e+09  7.27e-05 1.19e-09  9.32e-01     3s
  64   5.10671709e+09  5.10659468e+09  6.07e-05 1.14e-09  8.26e-01     3s
INFO:gurobipy:  64   5.10671709e+09  5.10659468e+09  6.07e-05 1.14e-09  8.26e-01     3s
  65   5.10671046e+09  5.10668601e+09  4.07e-05 6.11e-10  1.64e-01     3s
INFO:gurobipy:  65   5.10671046e+09  5.10668601e+09  4.07e-05 6.11e-10  1.64e-01     3s
  66   5.10669831e+09  5.10669147e+09  1.07e-05 1.19e-09  4.59e-02     3s
INFO:gurobipy:  66   5.10669831e+09  5.10669147e+09  1.07e-05 1.19e-09  4.59e-02     3s
  67   5.10669446e+09  5.10669354e+09  1.61e-06 1.16e-10  6.13e-03     3s
INFO:gurobipy:  67   5.10669446e+09  5.10669354e+09  1.61e-06 1.16e-10  6.13e-03     3s
  68   5.10669374e+09  5.10669370e+09  6.47e-08 2.91e-10  2.62e-04     3s
INFO:gurobipy:  68   5.10669374e+09  5.10669370e+09  6.47e-08 2.91e-10  2.62e-04     3s
  69   5.10669371e+09  5.10669371e+09  1.11e-10 2.33e-09  8.61e-08     3s
INFO:gurobipy:  69   5.10669371e+09  5.10669371e+09  1.11e-10 2.33e-09  8.61e-08     3s
  70   5.10669371e+09  5.10669371e+09  7.28e-12 2.40e-09  1.34e-11     3s
INFO:gurobipy:  70   5.10669371e+09  5.10669371e+09  7.28e-12 2.40e-09  1.34e-11     3s

INFO:gurobipy:
Barrier solved model in 70 iterations and 2.86 seconds (1.94 work units)
INFO:gurobipy:Barrier solved model in 70 iterations and 2.86 seconds (1.94 work units)
Optimal objective 5.10669371e+09
INFO:gurobipy:Optimal objective 5.10669371e+09

INFO:gurobipy:
Crossover log...
INFO:gurobipy:Crossover log...

INFO:gurobipy:
    4431 DPushes remaining with DInf 0.0000000e+00                 3s
INFO:gurobipy:    4431 DPushes remaining with DInf 0.0000000e+00                 3s
       0 DPushes remaining with DInf 0.0000000e+00                 3s
INFO:gurobipy:       0 DPushes remaining with DInf 0.0000000e+00                 3s

INFO:gurobipy:
    7071 PPushes remaining with PInf 0.0000000e+00                 3s
INFO:gurobipy:    7071 PPushes remaining with PInf 0.0000000e+00                 3s
       0 PPushes remaining with PInf 0.0000000e+00                 3s
INFO:gurobipy:       0 PPushes remaining with PInf 0.0000000e+00                 3s

INFO:gurobipy:
  Push phase complete: Pinf 0.0000000e+00, Dinf 2.2106821e-09      3s
INFO:gurobipy:  Push phase complete: Pinf 0.0000000e+00, Dinf 2.2106821e-09      3s

INFO:gurobipy:

INFO:gurobipy:
Solved with barrier
INFO:gurobipy:Solved with barrier
Iteration    Objective       Primal Inf.    Dual Inf.      Time
INFO:gurobipy:Iteration    Objective       Primal Inf.    Dual Inf.      Time
   11505    5.1066937e+09   0.000000e+00   0.000000e+00      3s
INFO:gurobipy:   11505    5.1066937e+09   0.000000e+00   0.000000e+00      3s

INFO:gurobipy:
Solved in 11505 iterations and 2.97 seconds (2.06 work units)
INFO:gurobipy:Solved in 11505 iterations and 2.97 seconds (2.06 work units)
Optimal objective  5.106693708e+09
INFO:gurobipy:Optimal objective  5.106693708e+09
INFO:linopy.constants: Optimization successful: 
Status: ok
Termination condition: optimal
Solution: 61327 primals, 140167 duals
Objective: 5.11e+09
Solver model: available
Solver message: 2

/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/optimize.py:355: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.

For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.


  n.df(c)[attr + "_opt"].update(df)
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-ext-p-lower, Generator-ext-p-upper, Line-ext-s-lower, Line-ext-s-upper were not assigned to the network.
/opt/homebrew/Caskroom/miniforge/base/envs/integrated-energy-grids/lib/python3.12/site-packages/pypsa/optimization/optimize.py:473: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  .groupby(level=0, axis=1)
('ok', 'optimal')
# Total system costs
n.objective/1e9
5.106693707557892
# Average electricity price
n.buses_t.marginal_price.mean()
Bus
PRT    61.081714
DNK    59.417098
dtype: float64
# Hours with almost zero price
n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count()
Bus
PRT    1250
DNK    1483
dtype: int64
# Share of hours with almost zero price
(n.buses_t.marginal_price[n.buses_t.marginal_price < 2].count())/len(n.snapshots)
Bus
PRT    0.142694
DNK    0.169292
dtype: float64
# Congestion rent
((n.buses_t.marginal_price["PRT"] - n.buses_t.marginal_price["DNK"]) * n.lines_t.p0["PRT-DNK"]).sum()
np.float64(-93730605.83246996)
n.lines_t.p0["PRT-DNK"] * n.lines_t.p0["PRT-DNK"]
snapshot
2015-01-01 00:00:00    128100.934790
2015-01-01 01:00:00    257722.952776
2015-01-01 02:00:00    530208.540960
2015-01-01 03:00:00    811442.419235
2015-01-01 04:00:00    811442.419235
                           ...      
2015-12-31 19:00:00    811442.419235
2015-12-31 20:00:00    811442.419235
2015-12-31 21:00:00    811442.419235
2015-12-31 22:00:00    811442.419235
2015-12-31 23:00:00    811442.419235
Name: PRT-DNK, Length: 8760, dtype: float64
# Utilisation of transmission line
n.lines_t.p0.abs().mean() / n.lines.s_nom_opt
Line
PRT-DNK    0.854465
dtype: float64
# Total generation
n.generators_t.p.sum(axis=0).groupby([n.generators.bus, n.generators.carrier]).sum().div(1e6).round(1)
bus  carrier
DNK  OCGT       10.3
     onwind     18.4
     solar       0.0
PRT  OCGT       28.8
     onwind     10.7
     solar      13.5
dtype: float64
# Total CO2 emissions
n.generators_t.p.sum(axis=0).groupby([n.generators.carrier]).sum()["OCGT"] * (costs.at["OCGT", "CO2 intensity"] / costs.at["OCGT", "efficiency"])
np.float64(18886469.938808523)