Note

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

Constraining the total capacity per bus and carrier

In this small example, we limit the nominal capacity of generators of the same production carrier at the same bus.

Therefore, we introduce a column nom_min_{carrier} and nom_max_{carrier} in the buses dataframe. These are then used as lower and upper bounds of generators of the same carrier at the same bus.

We start with importing a small example network.

[1]:
import pypsa
[2]:
n = pypsa.examples.ac_dc_meshed(from_master=True)
WARNING:pypsa.io:
Importing PyPSA from older version of PyPSA than current version.
Please read the release notes at https://pypsa.org/doc/release_notes.html
carefully to prepare your network for import.
Currently used PyPSA version [0, 18, 1], imported network file PyPSA version [0, 17, 1].

INFO:pypsa.io:Imported network ac-dc-meshed.nc has buses, carriers, generators, global_constraints, lines, links, loads

Now add a second wind generator at bus ‘Frankfurt’ and limit the combined capacity.

[3]:
n.add('Generator', 'Frankfurt Wind 2', bus='Frankfurt', capital_cost = 120,
      carrier='wind', p_nom_extendable=True)

n.buses.loc[['Frankfurt', 'Manchester'], 'nom_min_wind'] = 2000
n.buses.loc[['Frankfurt'],'nom_max_wind'] = 2200

We are running the lopf and check whether the constraint is fulfilled.

[4]:
n.lopf(pyomo=False)

print(n.generators.p_nom_opt)
INFO:pypsa.linopf:Prepare linear problem
INFO:pypsa.linopf:Total preparation time: 0.23s
INFO:pypsa.linopf:Solve linear problem using Glpk solver
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/tmp/ipykernel_291/4089323234.py in <module>
----> 1 n.lopf(pyomo=False)
      2
      3 print(n.generators.p_nom_opt)

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/components.py in lopf(self, snapshots, pyomo, solver_name, solver_options, solver_logfile, formulation, keep_files, extra_functionality, multi_investment_periods, **kwargs)
    648             return network_lopf(self, **args)
    649         else:
--> 650             return network_lopf_lowmem(self, **args)
    651
    652

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/linopf.py in network_lopf(n, snapshots, solver_name, solver_logfile, extra_functionality, multi_investment_periods, skip_objective, skip_pre, extra_postprocessing, formulation, keep_references, keep_files, keep_shadowprices, solver_options, warmstart, store_basis, solver_dir)
   1209     solve = eval(f'run_and_read_{solver_name}')
   1210     res = solve(n, problem_fn, solution_fn, solver_logfile,
-> 1211                 solver_options, warmstart, store_basis)
   1212
   1213     status, termination_condition, variables_sol, constraints_dual, obj = res

~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/linopt.py in run_and_read_glpk(n, problem_fn, solution_fn, solver_logfile, solver_options, warmstart, store_basis)
    682         command += solver_options
    683
--> 684     result = subprocess.Popen(command.split(' '), stdout=subprocess.PIPE)
    685     result.wait()
    686

~/.pyenv/versions/3.7.9/lib/python3.7/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors, text)
    798                                 c2pread, c2pwrite,
    799                                 errread, errwrite,
--> 800                                 restore_signals, start_new_session)
    801         except:
    802             # Cleanup if the child failed starting.

~/.pyenv/versions/3.7.9/lib/python3.7/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)
   1549                         if errno_num == errno.ENOENT:
   1550                             err_msg += ': ' + repr(err_filename)
-> 1551                     raise child_exception_type(errno_num, err_msg, err_filename)
   1552                 raise child_exception_type(err_msg)
   1553

FileNotFoundError: [Errno 2] No such file or directory: 'glpsol': 'glpsol'

Looks good! The generators of carrier ‘wind’ at bus ‘Frankfurt’ are just the limit of 2200 MW.