Note
You can download this example as a Jupyter notebook or start it in interactive mode.
Multi-Link usage: CHP with fixed heat-power ratio
This notebook if a demonstration of Link with multiple outputs: Combined-Heat-and-Power (CHP) with fixed heat-power ratio
For a CHP with a more complicated heat-power feasible operational area, see the power-to-gas example
This example demonstrates a Link component with more than one bus output (“bus2” in this case). In general links can have many output buses.
In this example a CHP must be heat-following because there is no other supply of heat to the bus “Frankfurt heat”.
[1]:
import pypsa, numpy as np
First tell PyPSA that links will have a 2nd bus by overriding the component_attrs. This can be done for as many buses as you need with format busi for i = 2,3,4,5,….
[2]:
override_component_attrs = pypsa.descriptors.Dict({k : v.copy() for k,v in pypsa.components.component_attrs.items()})
override_component_attrs["Link"].loc["bus2"] = ["string",np.nan,np.nan,"2nd bus","Input (optional)"]
override_component_attrs["Link"].loc["efficiency2"] = ["static or series","per unit",1.,"2nd bus efficiency","Input (optional)"]
override_component_attrs["Link"].loc["p2"] = ["series","MW",0.,"2nd bus output","Output"]
[3]:
network = pypsa.Network(override_component_attrs=override_component_attrs)
network.add("Bus", "Frankfurt", carrier="AC")
network.add("Load", "Frankfurt", bus="Frankfurt", p_set=5)
network.add("Bus", "Frankfurt heat", carrier="heat")
network.add("Load", "Frankfurt heat", bus="Frankfurt heat", p_set=3)
network.add("Bus", "Frankfurt gas", carrier="gas")
network.add("Store",
"Frankfurt gas",
e_initial=1e6,
e_nom=1e6,
bus="Frankfurt gas")
network.add("Link",
"OCGT",
bus0="Frankfurt gas",
bus1="Frankfurt",
p_nom_extendable=True,
capital_cost=600,
efficiency=0.4)
network.add("Link",
"CHP",
bus0="Frankfurt gas",
bus1="Frankfurt",
bus2="Frankfurt heat",
p_nom_extendable=True,
capital_cost=1400,
efficiency=0.3,
efficiency2=0.3)
[4]:
network.lopf();
INFO:pypsa.opf:Performed preliminary steps
INFO:pypsa.opf:Building pyomo model using `kirchhoff` formulation
INFO:pypsa.opf:Solving model using glpk
WARNING:pyomo.solvers:Could not locate the 'glpsol' executable, which is required for solver 'glpk'
---------------------------------------------------------------------------
ApplicationError Traceback (most recent call last)
/tmp/ipykernel_362/3801474310.py in <module>
----> 1 network.lopf();
~/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)
646
647 if pyomo:
--> 648 return network_lopf(self, **args)
649 else:
650 return network_lopf_lowmem(self, **args)
~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/opf.py in network_lopf(network, snapshots, solver_name, solver_io, skip_pre, extra_functionality, multi_investment_periods, solver_logfile, solver_options, keep_files, formulation, ptdf_tolerance, free_memory, extra_postprocessing)
1663 solver_logfile=solver_logfile, solver_options=solver_options,
1664 keep_files=keep_files, free_memory=free_memory,
-> 1665 extra_postprocessing=extra_postprocessing)
~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pypsa/opf.py in network_lopf_solve(network, snapshots, formulation, solver_options, solver_logfile, keep_files, free_memory, extra_postprocessing)
1563 network.results = network.opt.solve(*args, suffixes=["dual"], keepfiles=keep_files, logfile=solver_logfile, options=solver_options)
1564 else:
-> 1565 network.results = network.opt.solve(*args, suffixes=["dual"], keepfiles=keep_files, logfile=solver_logfile, options=solver_options)
1566
1567 if logger.isEnabledFor(logging.INFO):
~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pyomo/opt/base/solvers.py in solve(self, *args, **kwds)
510 """ Solve the problem """
511
--> 512 self.available(exception_flag=True)
513 #
514 # If the inputs are models, then validate that they have been
~/checkouts/readthedocs.org/user_builds/pypsa-docs-staging/envs/latest/lib/python3.7/site-packages/pyomo/opt/solver/shellcmd.py in available(self, exception_flag)
123 if exception_flag:
124 msg = "No executable found for solver '%s'"
--> 125 raise ApplicationError(msg % self.name)
126 return False
127 return True
ApplicationError: No executable found for solver 'glpk'
[5]:
network.loads_t.p
[5]:
| now |
|---|
[6]:
network.links_t.p0
[6]:
| now |
|---|
[7]:
network.links_t.p1
[7]:
| now |
|---|
[8]:
network.links_t.p2
[8]:
| now |
|---|