Note

You can download this example as a Jupyter notebook or start it in interactive mode.

Unit commitment

This tutorial runs through examples of unit commitment for generators at a single bus. Examples of minimum part-load, minimum up time, minimum down time, start up costs, shut down costs and ramp rate restrictions are shown.

To enable unit commitment on a generator, set its attribute committable = True.

[1]:
import pypsa
import pandas as pd

Minimum part load demonstration

In final hour load goes below part-load limit of coal gen (30%), forcing gas to commit.

[2]:
nu = pypsa.Network(snapshots=range(4))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    committable=True,
    p_min_pu=0.3,
    marginal_cost=20,
    p_nom=10000,
)

nu.add(
    "Generator",
    "gas",
    bus="bus",
    committable=True,
    marginal_cost=70,
    p_min_pu=0.1,
    p_nom=1000,
)

nu.add("Load", "load", bus="bus", p_set=[4000, 6000, 5000, 800])
[3]:
nu.lopf()
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 356000.0
  Upper bound: 356000.0
  Number of objectives: 1
  Number of constraints: 21
  Number of variables: 17
  Number of nonzeros: 41
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 1
      Number of created subproblems: 1
  Error rc: 0
  Time: 0.0024785995483398438
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[3]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[4]:
nu.generators_t.status
[4]:
Generator coal gas
snapshot
0 1.0 0.0
1 1.0 0.0
2 1.0 0.0
3 0.0 1.0
[5]:
nu.generators_t.p
[5]:
Generator coal gas
snapshot
0 4000.0 -0.0
1 6000.0 -0.0
2 5000.0 -0.0
3 -0.0 800.0

Minimum up time demonstration

Gas has minimum up time, forcing it to be online longer

[6]:
nu = pypsa.Network(snapshots=range(4))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    committable=True,
    p_min_pu=0.3,
    marginal_cost=20,
    p_nom=10000,
)

nu.add(
    "Generator",
    "gas",
    bus="bus",
    committable=True,
    marginal_cost=70,
    p_min_pu=0.1,
    up_time_before=0,
    min_up_time=3,
    p_nom=1000,
)

nu.add("Load", "load", bus="bus", p_set=[4000, 800, 5000, 3000])
[7]:
nu.lopf()
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 306000.0
  Upper bound: 306000.0
  Number of objectives: 1
  Number of constraints: 24
  Number of variables: 17
  Number of nonzeros: 51
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 1
      Number of created subproblems: 1
  Error rc: 0
  Time: 0.002612590789794922
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[7]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[8]:
nu.generators_t.status
[8]:
Generator coal gas
snapshot
0 1.0 1.0
1 0.0 1.0
2 1.0 1.0
3 1.0 0.0
[9]:
nu.generators_t.p
[9]:
Generator coal gas
snapshot
0 3900.0 100.0
1 -0.0 800.0
2 4900.0 100.0
3 3000.0 -0.0

Minimum down time demonstration

Coal has a minimum down time, forcing it to go off longer.

[10]:
nu = pypsa.Network(snapshots=range(4))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    committable=True,
    p_min_pu=0.3,
    marginal_cost=20,
    min_down_time=2,
    down_time_before=1,
    p_nom=10000,
)

nu.add(
    "Generator",
    "gas",
    bus="bus",
    committable=True,
    marginal_cost=70,
    p_min_pu=0.1,
    p_nom=4000,
)

nu.add("Load", "load", bus="bus", p_set=[3000, 800, 3000, 8000])
[11]:
nu.lopf()
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 486000.0
  Upper bound: 486000.0
  Number of objectives: 1
  Number of constraints: 24
  Number of variables: 17
  Number of nonzeros: 48
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 1
      Number of created subproblems: 1
  Error rc: 0
  Time: 0.0027272701263427734
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[11]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[12]:
nu.objective
[12]:
486000.0
[13]:
nu.generators_t.status
[13]:
Generator coal gas
snapshot
0 0.0 1.0
1 0.0 1.0
2 1.0 0.0
3 1.0 0.0
[14]:
nu.generators_t.p
[14]:
Generator coal gas
snapshot
0 -0.0 3000.0
1 -0.0 800.0
2 3000.0 -0.0
3 8000.0 -0.0

Start up and shut down costs

Now there are associated costs for shutting down, etc

[15]:
nu = pypsa.Network(snapshots=range(4))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    committable=True,
    p_min_pu=0.3,
    marginal_cost=20,
    min_down_time=2,
    start_up_cost=5000,
    p_nom=10000,
)

nu.add(
    "Generator",
    "gas",
    bus="bus",
    committable=True,
    marginal_cost=70,
    p_min_pu=0.1,
    shut_down_cost=25,
    p_nom=4000,
)

nu.add("Load", "load", bus="bus", p_set=[3000, 800, 3000, 8000])
[16]:
nu.lopf(nu.snapshots)
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 491025.0
  Upper bound: 491025.0
  Number of objectives: 1
  Number of constraints: 32
  Number of variables: 25
  Number of nonzeros: 71
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 1
      Number of created subproblems: 1
  Error rc: 0
  Time: 0.0027704238891601562
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[16]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[17]:
nu.objective
[17]:
491025.0
[18]:
nu.generators_t.status
[18]:
Generator coal gas
snapshot
0 0.0 1.0
1 0.0 1.0
2 1.0 0.0
3 1.0 0.0
[19]:
nu.generators_t.p
[19]:
Generator coal gas
snapshot
0 0.0 3000.0
1 -0.0 800.0
2 3000.0 -0.0
3 8000.0 -0.0

Ramp rate limits

[20]:
nu = pypsa.Network(snapshots=range(6))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    marginal_cost=20,
    ramp_limit_up=0.1,
    ramp_limit_down=0.2,
    p_nom=10000,
)

nu.add("Generator", "gas", bus="bus", marginal_cost=70, p_nom=4000)

nu.add("Load", "load", bus="bus", p_set=[4000, 7000, 7000, 7000, 7000, 3000])
[21]:
nu.lopf()
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 950000.0
  Upper bound: 950000.0
  Number of objectives: 1
  Number of constraints: 17
  Number of variables: 13
  Number of nonzeros: 33
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 0
      Number of created subproblems: 0
  Error rc: 0
  Time: 0.002530336380004883
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[21]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[22]:
nu.generators_t.p
[22]:
Generator coal gas
snapshot
0 4000.0 0.0
1 5000.0 2000.0
2 6000.0 1000.0
3 7000.0 0.0
4 5000.0 2000.0
5 3000.0 0.0
[23]:
nu = pypsa.Network(snapshots=range(6))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    marginal_cost=20,
    ramp_limit_up=0.1,
    ramp_limit_down=0.2,
    p_nom_extendable=True,
    capital_cost=1e2,
)

nu.add("Generator", "gas", bus="bus", marginal_cost=70, p_nom=4000)

nu.add("Load", "load", bus="bus", p_set=[4000, 7000, 7000, 7000, 7000, 3000])
[24]:
nu.lopf(nu.snapshots)
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 1675000.0
  Upper bound: 1675000.0
  Number of objectives: 1
  Number of constraints: 29
  Number of variables: 14
  Number of nonzeros: 61
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 0
      Number of created subproblems: 0
  Error rc: 0
  Time: 0.0026738643646240234
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[24]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[25]:
nu.generators.p_nom_opt
[25]:
Generator
coal    5000.0
gas     4000.0
Name: p_nom_opt, dtype: float64
[26]:
nu.generators_t.p
[26]:
Generator coal gas
snapshot
0 4000.0 0.0
1 4500.0 2500.0
2 5000.0 2000.0
3 5000.0 2000.0
4 4000.0 3000.0
5 3000.0 0.0
[27]:
nu = pypsa.Network(snapshots=range(7))

nu.add("Bus", "bus")

# Can get bad interactions if SU > RU and p_min_pu; similarly if SD > RD
nu.add(
    "Generator",
    "coal",
    bus="bus",
    marginal_cost=20,
    committable=True,
    p_min_pu=0.05,
    initial_status=0,
    ramp_limit_start_up=0.1,
    ramp_limit_up=0.2,
    ramp_limit_down=0.25,
    ramp_limit_shut_down=0.15,
    p_nom=10000.0,
)

nu.add("Generator", "gas", bus="bus", marginal_cost=70, p_nom=10000)

nu.add("Load", "load", bus="bus", p_set=[0.0, 200.0, 7000, 7000, 7000, 2000, 0])
WARNING:pypsa.components:Generator has no attribute initial_status, ignoring this passed value.
[28]:
nu.lopf()
WARNING:pypsa.components:Solving optimisation problem with pyomo.In PyPSA version 0.21 the default will change to ``n.lopf(pyomo=False)``.Explicitly set ``n.lopf(pyomo=True)`` to retain current behaviour.
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
INFO:pypsa.opf:Optimization successful
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
  Lower bound: 1149000.0
  Upper bound: 1149000.0
  Number of objectives: 1
  Number of constraints: 34
  Number of variables: 22
  Number of nonzeros: 91
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
  Termination condition: optimal
  Statistics:
    Branch and bound:
      Number of bounded subproblems: 1
      Number of created subproblems: 1
  Error rc: 0
  Time: 0.0028066635131835938
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
  number of solutions displayed: 0
[28]:
(<SolverStatus.ok: 'ok'>, <TerminationCondition.optimal: 'optimal'>)
[29]:
nu.generators_t.p
[29]:
Generator coal gas
snapshot
0 -0.0 0.0
1 -0.0 200.0
2 1000.0 6000.0
3 3000.0 4000.0
4 4000.0 3000.0
5 1500.0 500.0
6 -0.0 0.0
[30]:
nu.generators_t.status
[30]:
Generator coal gas
snapshot
0 0.0 1.0
1 0.0 1.0
2 1.0 1.0
3 1.0 1.0
4 1.0 1.0
5 1.0 1.0
6 0.0 1.0
[31]:
nu.generators.loc["coal"]
[31]:
attribute
bus                         bus
control                   Slack
type
p_nom                   10000.0
p_nom_extendable          False
p_nom_min                   0.0
p_nom_max                   inf
p_min_pu                   0.05
p_max_pu                    1.0
p_set                       0.0
q_set                       0.0
sign                        1.0
carrier
marginal_cost              20.0
build_year                    0
lifetime                    inf
capital_cost                0.0
efficiency                  1.0
committable                True
start_up_cost               0.0
shut_down_cost              0.0
min_up_time                   0
min_down_time                 0
up_time_before                1
down_time_before              0
ramp_limit_up               0.2
ramp_limit_down            0.25
ramp_limit_start_up         0.1
ramp_limit_shut_down       0.15
p_nom_opt               10000.0
Name: coal, dtype: object

Rolling horizon example

This example solves sequentially in batches

[32]:
sets_of_snapshots = 6
p_set = [4000, 5000, 700, 800, 4000]

nu = pypsa.Network(snapshots=range(len(p_set) * sets_of_snapshots))

nu.add("Bus", "bus")

nu.add(
    "Generator",
    "coal",
    bus="bus",
    committable=True,
    p_min_pu=0.3,
    marginal_cost=20,
    min_down_time=2,
    min_up_time=3,
    up_time_before=1,
    ramp_limit_up=1,
    ramp_limit_down=1,
    ramp_limit_start_up=1,
    ramp_limit_shut_down=1,
    shut_down_cost=150,
    start_up_cost=200,
    p_nom=10000,
)

nu.add(
    "Generator",
    "gas",
    bus="bus",
    committable=True,
    marginal_cost=70,
    p_min_pu=0.1,
    up_time_before=2,
    min_up_time=3,
    shut_down_cost=20,
    start_up_cost=50,
    p_nom=1000,
)

nu.add("Load", "load", bus="bus", p_set=p_set * sets_of_snapshots)
[33]:
overlap = 2
for i in range(sets_of_snapshots):
    nu.lopf(nu.snapshots[i * len(p_set) : (i + 1) * len(p_set) + overlap], pyomo=False)
WARNING:pypsa.linopf:Unit commitment is not yet completely implemented for optimising without pyomo. Thus minimum up time, minimum down time, start up costs, shut down costs will be ignored.
INFO:pypsa.linopf:Prepare linear problem
INFO:pypsa.linopf:Total preparation time: 0.1s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
WARNING:pypsa.linopt:Shadow prices of MILP couldn't be parsed
INFO:pypsa.linopf:Optimization successful. Objective value: 5.45e+05
WARNING:pypsa.linopf:Unit commitment is not yet completely implemented for optimising without pyomo. Thus minimum up time, minimum down time, start up costs, shut down costs will be ignored.
INFO:pypsa.linopf:Prepare linear problem
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:338: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += (limit_up - limit_start) * status_prev_fix
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:380: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += -limit_shut * status_prev_fix
INFO:pypsa.linopf:Total preparation time: 0.1s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
WARNING:pypsa.linopt:Shadow prices of MILP couldn't be parsed
INFO:pypsa.linopf:Optimization successful. Objective value: 5.45e+05
WARNING:pypsa.linopf:Unit commitment is not yet completely implemented for optimising without pyomo. Thus minimum up time, minimum down time, start up costs, shut down costs will be ignored.
INFO:pypsa.linopf:Prepare linear problem
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:338: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += (limit_up - limit_start) * status_prev_fix
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:380: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += -limit_shut * status_prev_fix
INFO:pypsa.linopf:Total preparation time: 0.11s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
WARNING:pypsa.linopt:Shadow prices of MILP couldn't be parsed
INFO:pypsa.linopf:Optimization successful. Objective value: 5.45e+05
WARNING:pypsa.linopf:Unit commitment is not yet completely implemented for optimising without pyomo. Thus minimum up time, minimum down time, start up costs, shut down costs will be ignored.
INFO:pypsa.linopf:Prepare linear problem
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:338: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += (limit_up - limit_start) * status_prev_fix
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:380: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += -limit_shut * status_prev_fix
INFO:pypsa.linopf:Total preparation time: 0.1s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
WARNING:pypsa.linopt:Shadow prices of MILP couldn't be parsed
INFO:pypsa.linopf:Optimization successful. Objective value: 5.45e+05
WARNING:pypsa.linopf:Unit commitment is not yet completely implemented for optimising without pyomo. Thus minimum up time, minimum down time, start up costs, shut down costs will be ignored.
INFO:pypsa.linopf:Prepare linear problem
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:338: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += (limit_up - limit_start) * status_prev_fix
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:380: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += -limit_shut * status_prev_fix
INFO:pypsa.linopf:Total preparation time: 0.1s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
WARNING:pypsa.linopt:Shadow prices of MILP couldn't be parsed
INFO:pypsa.linopf:Optimization successful. Objective value: 5.45e+05
WARNING:pypsa.linopf:Unit commitment is not yet completely implemented for optimising without pyomo. Thus minimum up time, minimum down time, start up costs, shut down costs will be ignored.
INFO:pypsa.linopf:Prepare linear problem
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:338: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += (limit_up - limit_start) * status_prev_fix
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.0/lib/python3.10/site-packages/pypsa/linopf.py:380: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  rhs.loc[sns[0]] += -limit_shut * status_prev_fix
INFO:pypsa.linopf:Total preparation time: 0.1s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
WARNING:pypsa.linopt:Shadow prices of MILP couldn't be parsed
INFO:pypsa.linopf:Optimization successful. Objective value: 3.65e+05
[34]:
pd.concat(
    {"Active": nu.generators_t.status.astype(bool), "Output": nu.generators_t.p}, axis=1
)
[34]:
Active Output
Generator coal gas coal gas
snapshot
0 True False 4000.0 0.0
1 True False 5000.0 0.0
2 False True 0.0 700.0
3 False True 0.0 800.0
4 True False 4000.0 0.0
5 True False 4000.0 0.0
6 True False 5000.0 0.0
7 False True 0.0 700.0
8 False True 0.0 800.0
9 True False 4000.0 0.0
10 True False 4000.0 0.0
11 True False 5000.0 0.0
12 False True 0.0 700.0
13 False True 0.0 800.0
14 True False 4000.0 0.0
15 True False 4000.0 0.0
16 True False 5000.0 0.0
17 False True 0.0 700.0
18 False True 0.0 800.0
19 True False 4000.0 0.0
20 True False 4000.0 0.0
21 True False 5000.0 0.0
22 False True 0.0 700.0
23 False True 0.0 800.0
24 True False 4000.0 0.0
25 True False 4000.0 0.0
26 True False 5000.0 0.0
27 False True 0.0 700.0
28 False True 0.0 800.0
29 True False 4000.0 0.0