Storages -> storage units
 %% Cell type:markdown id: tags: # Energy System Modelling - Solutions to Tutorial III %% Cell type:markdown id: tags: **Settings** %% Cell type:code id: tags:  python import pypsa import numpy as np import pandas as pd import matplotlib.pyplot as plt  %% Cell type:code id: tags:  python %matplotlib inline  %% Cell type:code id: tags:  python solver = "glpk"  %% Cell type:markdown id: tags: *** **(a) Build a network in PyPSA with the two buses North and South and attach the load at each bus and attach the wind and solar generators with availability according to $G_{N,w}(t) = Cf_w(1+A_w\sin \omega_w t)$ and $G_{S,s}(t) = Cf_s(1+A_s\sin \omega_s t)$ for a year (you have to call set_snapshots for the year) and with p_nom_extendable set to True. As help you should have a look at the [minimal lopf example](https://www.pypsa.org/examples/minimal_example_lopf.html), understand what the [components documentation](https://pypsa.org/doc/components.html) of PyPSA gives you and that you can find the underlying objective function and constraints in the [LOPF documentation](https://pypsa.org/doc/optimal_power_flow.html#linear-optimal-power-flow).** %% Cell type:markdown id: tags: Initialize network %% Cell type:code id: tags:  python network = pypsa.Network()  %% Cell type:markdown id: tags: Add North and South bus %% Cell type:code id: tags:  python network.add("Bus", "North", carrier="AC")  %% Cell type:code id: tags:  python network.add("Bus", "South", carrier="AC")  %% Cell type:markdown id: tags: Attach constant load %% Cell type:code id: tags:  python network.add("Load", "North Load", bus="North", p_set=20e3)  %% Cell type:code id: tags:  python network.add("Load", "South Load", bus="South", p_set=30e3)  %% Cell type:markdown id: tags: Attach renewable generators according to given parameters %% Cell type:code id: tags:  python network.set_snapshots(np.arange(0, 4*7*24))  %% Cell type:code id: tags:  python Cfw = 0.3 Aw = 0.9 omegaw = 2*np.pi/(7*24) Cfs = 0.12 As = 1. omegas = 2*np.pi/24 GNwt = Cfw * (1+Aw*np.sin(omegaw*network.snapshots.to_series())) GSst = Cfs * (1+As*np.sin(omegas*network.snapshots.to_series()))  %% Cell type:code id: tags:  python pd.concat([GNwt, GSst], keys=['wind', 'solar'], axis=1).loc[:4*7*24].plot()  %% Output %% Cell type:code id: tags:  python network.add("Generator", "Wind", bus="North", p_nom_extendable=True, capital_cost=1.2e6, p_max_pu=GNwt)  %% Cell type:code id: tags:  python network.add("Generator", "Solar", bus="South", p_nom_extendable=True, capital_cost=0.6e6, p_max_pu=GSst)  %% Cell type:markdown id: tags: *** **(b) Attach extendable storages at the North and the South! The storages have to be modelled as an H2-bus (a bus with carrier='H2') linked to the AC-bus North with a Link where p_nom_extendable=True with the capital_cost of the power capacity and an also extendable Store with the capital_cost of the energy capacity, for instance. The losses can be set on the links as efficiency.** **(b) Attach extendable storage units at the North and the South! The storages have to be modelled as an H2-bus (a bus with carrier='H2') linked to the AC-bus North with a Link where p_nom_extendable=True with the capital_cost of the power capacity and an also extendable Store with the capital_cost of the energy capacity, for instance. The losses can be set on the links as efficiency.** %% Cell type:code id: tags:  python for bus in ["North", "South"]: # H2 storage network.add("Bus", bus + " H2", carrier="H2") network.add("Store", bus + " H2 St.", bus=bus + " H2", e_nom_extendable=True, capital_cost=10e3) network.add("Link", bus + "->H2", bus0=bus, bus1=bus + " H2", p_nom_extendable=True, capital_cost=0.3e6, efficiency=0.75) network.add("Link", "H2->" + bus, bus0=bus + " H2", bus1=bus, p_nom_extendable=True, capital_cost=0.45e6, efficiency=0.58) # Battery storage network.add("Bus", bus + " Battery", carrier="Battery") network.add("Store", bus + " Battery St.", bus=bus + " Battery", e_nom_extendable=True, capital_cost=0.2e6) network.add("Link", bus + "->Battery", bus0=bus, bus1=bus + " Battery", p_nom_extendable=True, capital_cost=0.15e6, efficiency=0.9) network.add("Link", "Battery->" + bus, bus0=bus + " Battery", bus1=bus, p_nom_extendable=True, capital_cost=0.15e6, efficiency=0.9)  %% Cell type:markdown id: tags: *** **(c) Run an investment optimization by calling the lopf function.** %% Cell type:code id: tags:  python network.lopf(solver_name=solver)  %% Output INFO:pypsa.pf:Slack bus for sub-network 0 is North INFO:pypsa.pf:Slack bus for sub-network 1 is South WARNING:pypsa.pf:No generators in sub-network 2, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 2 is North H2 WARNING:pypsa.pf:No generators in sub-network 3, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 3 is North Battery WARNING:pypsa.pf:No generators in sub-network 4, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 4 is South H2 WARNING:pypsa.pf:No generators in sub-network 5, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 5 is South Battery INFO:pypsa.opf:Performed preliminary steps INFO:pypsa.opf:Building pyomo model using angles formulation /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/components.py:758: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. keys=self.passive_branch_components) INFO:pypsa.opf:Solving model using glpk INFO:pypsa.opf:Optimization successful # ========================================================== # = Solver Results = # ========================================================== # ---------------------------------------------------------- # Problem Information # ---------------------------------------------------------- Problem: - Name: unknown Lower bound: 360476623771.945 Upper bound: 360476623771.945 Number of objectives: 1 Number of constraints: 29569 Number of variables: 16143 Number of nonzeros: 55073 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: 4.201282262802124 # ---------------------------------------------------------- # Solution Information # ---------------------------------------------------------- Solution: - number of solutions: 0 number of solutions displayed: 0 /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/opf.py:1207: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. for c in network.iterate_components(network.controllable_one_port_components)}) \ ('ok', 'optimal') %% Cell type:markdown id: tags: *** **(d) How do your results objective and {generators,stores,links}.p_nom_opt compare with the results of III.1(d)?** %% Cell type:code id: tags:  python obj_v1 = network.objective / 1e9 # Mio. Euro obj_v1  %% Output 360.476623771945 %% Cell type:code id: tags:  python # (a) Capacities for wind and solar. res_cap_v1 = network.generators.p_nom_opt / 1e3 # GW res_cap_v1  %% Output Wind 87.381871 Solar 267.961955 Name: p_nom_opt, dtype: float64 %% Cell type:code id: tags:  python # (b) Store and dispatch power capacity. sto_cap_v1 = network.links.p_nom_opt / 1e3 # GW sto_cap_v1  %% Output North->H2 2.899018e+01 H2->North 2.984926e+01 North->Battery 1.357335e-02 Battery->North 7.330123e-02 South->H2 -5.788267e-15 H2->South -5.293786e-14 South->Battery 3.431087e+01 Battery->South 3.333333e+01 Name: p_nom_opt, dtype: float64 %% Cell type:code id: tags:  python # (c) Energy capacities. sto_engy_v1 = network.stores.e_nom_opt / 1e6 # TWh sto_engy_v1  %% Output North H2 St. 1.350790e+00 North Battery St. 1.832403e-04 South H2 St. -5.803564e-16 South Battery St. 2.450389e-01 Name: e_nom_opt, dtype: float64 %% Cell type:code id: tags:  python network.stores_t.e.plot()  %% Output %% Cell type:markdown id: tags: *** **(e) Now we lift the restriction against transmission and allow North and South to bridge their 500 km separation with a transmission line. How does the cost optimal technology mix change?** %% Cell type:markdown id: tags: Add extendable link between North and South: %% Cell type:code id: tags:  python network.add("Link", "North<->South", bus0="North", bus1="South", p_min_pu=-1, p_nom_extendable=True, capital_cost=0.2e6)  %% Cell type:markdown id: tags: Run LOPF: %% Cell type:code id: tags:  python network.lopf(solver_name=solver)  %% Output /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pandas/core/frame.py:6211: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. sort=sort) INFO:pypsa.pf:Slack bus for sub-network 0 is North INFO:pypsa.pf:Slack bus for sub-network 1 is South WARNING:pypsa.pf:No generators in sub-network 2, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 2 is North H2 WARNING:pypsa.pf:No generators in sub-network 3, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 3 is North Battery WARNING:pypsa.pf:No generators in sub-network 4, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 4 is South H2 WARNING:pypsa.pf:No generators in sub-network 5, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 5 is South Battery INFO:pypsa.opf:Performed preliminary steps INFO:pypsa.opf:Building pyomo model using angles formulation /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/components.py:758: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. keys=self.passive_branch_components) INFO:pypsa.opf:Solving model using glpk INFO:pypsa.opf:Optimization successful # ========================================================== # = Solver Results = # ========================================================== # ---------------------------------------------------------- # Problem Information # ---------------------------------------------------------- Problem: - Name: unknown Lower bound: 338496411380.838 Upper bound: 338496411380.838 Number of objectives: 1 Number of constraints: 30913 Number of variables: 16816 Number of nonzeros: 59105 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: 8.108036041259766 # ---------------------------------------------------------- # Solution Information # ---------------------------------------------------------- Solution: - number of solutions: 0 number of solutions displayed: 0 /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/opf.py:1207: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. for c in network.iterate_components(network.controllable_one_port_components)}) \ ('ok', 'optimal') %% Cell type:markdown id: tags: Get the results objective and {generators,stores,links}.p_nom_opt with real availability: %% Cell type:code id: tags:  python obj_v2 = network.objective / 1e9 # Mio. Euro obj_v2  %% Output 338.496411380838 %% Cell type:code id: tags:  python # (a) Capacities for wind and solar. res_cap_v2 = network.generators.p_nom_opt / 1e3 # GW res_cap_v2  %% Output Wind 130.539736 Solar 174.567156 Name: p_nom_opt, dtype: float64 %% Cell type:code id: tags:  python # (b) Store and dispatch power capacity. sto_cap_v2 = network.links.p_nom_opt / 1e3 # GW sto_cap_v2  %% Output North->H2 3.050408e+01 H2->North 4.681387e+01 North->Battery -2.328955e-13 Battery->North -6.652696e-14 South->H2 2.253023e+01 H2->South 1.654343e+01 South->Battery 4.278347e+00 Battery->South 6.495718e+00 North<->South 2.390357e+01 Name: p_nom_opt, dtype: float64 %% Cell type:code id: tags:  python # (c) Energy capacities sto_engy_v2 = network.stores.e_nom_opt / 1e6 # TWh sto_engy_v2  %% Output North H2 St. 1.400510e+00 North Battery St. -1.191108e-15 South H2 St. 7.131808e-01 South Battery St. 2.576810e-02 Name: e_nom_opt, dtype: float64 %% Cell type:code id: tags:  python network.stores_t.e.plot()  %% Output %% Cell type:markdown id: tags: *** **(e) Replace the approximated availability time-series of the wind and the solar generators with the ones from availability.csv computed from reanalysis weather data available on the [course website](https://nworbmot.org/courses/complex_renewable_energy_networks/) and re-run the LOPF. Compare the results! Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series!** **(e) Replace the approximated availability time-series of the wind and the solar generators with the ones from availability.csv computed from reanalysis weather data and re-run the LOPF. Compare the results! Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series!** %% Cell type:markdown id: tags: Adapt the network to new availabiltiy data: %% Cell type:code id: tags:  python network.remove("Generator", "Wind") network.remove("Generator", "Solar")  %% Cell type:code id: tags:  python availability = pd.read_csv("availability.csv", index_col=0, parse_dates=True) availability.head()  %% Output solar wind name 2012-01-01 00:00:00 0.0 0.402412 2012-01-01 01:00:00 0.0 0.480648 2012-01-01 02:00:00 0.0 0.542354 2012-01-01 03:00:00 0.0 0.586046 2012-01-01 04:00:00 0.0 0.641201 %% Cell type:code id: tags:  python availability.loc["2012-7"].plot()  %% Output %% Cell type:code id: tags:  python availability.loc["2012-7"].index  %% Output DatetimeIndex(['2012-07-01 00:00:00', '2012-07-01 01:00:00', '2012-07-01 02:00:00', '2012-07-01 03:00:00', '2012-07-01 04:00:00', '2012-07-01 05:00:00', '2012-07-01 06:00:00', '2012-07-01 07:00:00', '2012-07-01 08:00:00', '2012-07-01 09:00:00', ... '2012-07-31 14:00:00', '2012-07-31 15:00:00', '2012-07-31 16:00:00', '2012-07-31 17:00:00', '2012-07-31 18:00:00', '2012-07-31 19:00:00', '2012-07-31 20:00:00', '2012-07-31 21:00:00', '2012-07-31 22:00:00', '2012-07-31 23:00:00'], dtype='datetime64[ns]', name='name', length=744, freq=None) %% Cell type:code id: tags:  python network.set_snapshots(availability.loc["2012-7"].index)  %% Cell type:code id: tags:  python network.add("Generator", "Wind", bus="North", p_nom_extendable=True, capital_cost=1.2e6, p_max_pu=availability["wind"])  %% Cell type:code id: tags:  python network.add("Generator", "Solar", bus="South", p_nom_extendable=True, capital_cost=0.6e6, p_max_pu=availability["solar"])  %% Cell type:markdown id: tags: Run LOPF: %% Cell type:code id: tags:  python network.lopf(solver_name="glpk")  %% Output /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pandas/core/frame.py:6211: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. sort=sort) INFO:pypsa.pf:Slack bus for sub-network 0 is North INFO:pypsa.pf:Slack bus for sub-network 1 is South WARNING:pypsa.pf:No generators in sub-network 2, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 2 is North H2 WARNING:pypsa.pf:No generators in sub-network 3, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 3 is North Battery WARNING:pypsa.pf:No generators in sub-network 4, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 4 is South H2 WARNING:pypsa.pf:No generators in sub-network 5, better hope power is already balanced INFO:pypsa.pf:Slack bus for sub-network 5 is South Battery INFO:pypsa.opf:Performed preliminary steps INFO:pypsa.opf:Building pyomo model using angles formulation /home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/components.py:758: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version of pandas will change to not sort by default. To accept the future behavior, pass 'sort=False'. To retain the current behavior and silence the warning, pass 'sort=True'. keys=self.passive_branch_components) INFO:pypsa.opf:Solving model using gurobi ERROR:pyomo.opt:Solver (gurobi) returned non-zero return code (1) ERROR:pyomo.opt:Solver log: Traceback (most recent call last): File "", line 5, in File "/home/ws/sp2668/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pyomo/solvers/plugins/solvers/GUROBI_RUN.py", line 61, in gurobi_run model = read(model_file) File "gurobi.pxi", line 2652, in gurobipy.read (../../src/python/gurobipy.c:127968) File "gurobi.pxi", line 65, in gurobipy.gurobi.read (../../src/python/gurobipy.c:125608) File "gurobi.pxi", line 17, in gurobipy.gurobi._getdefaultenv (../../src/python/gurobipy.c:124705) File "env.pxi", line 45, in gurobipy.Env.__init__ (../../src/python/gurobipy.c:7673) gurobipy.GurobiError: No Gurobi license found (user sp2668, host iai-esm002, hostid 452b2088, cores 1) ERROR: Solver (gurobi) returned non-zero return code (1) ERROR: Solver log: Traceback (most recent call last): File "", line 5, in File "/home/ws/sp2668/software/anaconda3/envs/esm- tutorials/lib/python3.6/site- packages/pyomo/solvers/plugins/solvers/GUROBI_RUN.py", line 61, in gurobi_run model = read(model_file) File "gurobi.pxi", line 2652, in gurobipy.read (../../src/python/gurobipy.c:127968) File "gurobi.pxi", line 65, in gurobipy.gurobi.read (../../src/python/gurobipy.c:125608) File "gurobi.pxi", line 17, in gurobipy.gurobi._getdefaultenv (../../src/python/gurobipy.c:124705) File "env.pxi", line 45, in gurobipy.Env.__init__ (../../src/python/gurobipy.c:7673) gurobipy.GurobiError: No Gurobi license found (user sp2668, host iai- esm002, hostid 452b2088, cores 1) --------------------------------------------------------------------------- ApplicationError Traceback (most recent call last) in () ----> 1 network.lopf(solver_name="gurobi") ~/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/opf.py in network_lopf(network, snapshots, solver_name, solver_io, skip_pre, extra_functionality, solver_options, keep_files, formulation, ptdf_tolerance, free_memory) 1546 return network_lopf_solve(network, snapshots, formulation=formulation, 1547 solver_options=solver_options, -> 1548 keep_files=keep_files, free_memory=free_memory) ~/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pypsa/opf.py in network_lopf_solve(network, snapshots, formulation, solver_options, keep_files, free_memory) 1463 network.results = network.opt.solve(*args, suffixes=["dual"], keepfiles=keep_files, options=solver_options) 1464 else: -> 1465 network.results = network.opt.solve(*args, suffixes=["dual"], keepfiles=keep_files, options=solver_options) 1466 1467 if logger.isEnabledFor(logging.INFO): ~/software/anaconda3/envs/esm-tutorials/lib/python3.6/site-packages/pyomo/opt/base/solvers.py in solve(self, *args, **kwds) 624 logger.error("Solver log:\n" + str(_status.log)) 625 raise pyutilib.common.ApplicationError( --> 626 "Solver (%s) did not exit normally" % self.name) 627 solve_completion_time = time.time() 628 if self._report_timing: ApplicationError: Solver (gurobi) did not exit normally %% Cell type:markdown id: tags: Get the results objective and {generators,stores,links}.p_nom_opt with real availability: %% Cell type:code id: tags:  python obj_v3 = network.objective / 1e9 # Mio. Euro obj_v3  %% Cell type:code id: tags:  python # (a) Capacities for wind and solar. res_cap_v3 = network.generators.p_nom_opt / 1e3 res_cap_v3  %% Cell type:code id: tags:  python # (b) Store and dispatch power capacity. sto_cap_v3 = network.links.p_nom_opt / 1e3 sto_cap_v3  %% Cell type:code id: tags:  python # (c) Energy capacities sto_engy_v3 = network.stores.e_nom_opt / 1e6 sto_engy_v3  %% Cell type:code id: tags:  python network.stores_t.e.plot()  %% Cell type:code id: tags:  python np.cumsum(availability.loc["2012-7"] - availability.loc["2012-7"].mean()).plot()  %% Cell type:markdown id: tags: *** **(f) Compare all results for all three scenarios in terms of total system cost, renewable generation capacity, storage power capacity and storage energy capacity!** %% Cell type:code id: tags:  python scens = ["without transmission", "with transmission", "with real data and transmission"] attrs = ["storage power capacity", "storage energy capacity", "renewable capacity"]  %% Cell type:code id: tags:  python sto_cap_v1.name = attrs[0] + " " + scens[0] sto_cap_v2.name = attrs[0] + " " + scens[1] sto_cap_v3.name = attrs[0] + " " + scens[2] res_cap_v1.name = attrs[1] + " " + scens[0] res_cap_v2.name = attrs[1] + " " + scens[1] res_cap_v3.name = attrs[1] + " " + scens[2] sto_engy_v1.name = attrs[2] + " " + scens[0] sto_engy_v2.name = attrs[2] + " " + scens[1] sto_engy_v3.name = attrs[2] + " " + scens[2]  %% Cell type:code id: tags:  python values = [obj_v1, obj_v2, obj_v3] plt.bar(scens,values) plt.ylabel('Mio. Euro') plt.show()  %% Cell type:code id: tags:  python sto_caps = pd.concat([sto_cap_v1,sto_cap_v2,sto_cap_v3], axis=1, sort=False) sto_caps.plot.bar()  %% Cell type:code id: tags:  python res_caps = pd.concat([res_cap_v1,res_cap_v2,res_cap_v3], axis=1, sort=False) res_caps.plot.bar()  %% Cell type:code id: tags:  python sto_engy = pd.concat([sto_engy_v1,sto_engy_v2,sto_engy_v3], axis=1, sort=False) sto_engy.plot.bar()  ... ...
 %% Cell type:markdown id: tags: # Energy System Modelling - Tutorial III %% Cell type:markdown id: tags: **Settings** %% Cell type:code id: tags:  python import pypsa import numpy as np import pandas as pd import matplotlib.pyplot as plt  %% Cell type:code id: tags:  python %matplotlib inline  %% Cell type:code id: tags:  python solver = "glpk"  %% Cell type:markdown id: tags: *** **(a) Build a network in PyPSA with the two buses North and South and attach the load at each bus and attach the wind and solar generators with availability according to $G_{N,w}(t) = Cf_w(1+A_w\sin \omega_w t)$ and $G_{S,s}(t) = Cf_s(1+A_s\sin \omega_s t)$ for a year (you have to call set_snapshots for the year) and with p_nom_extendable set to True. As help you should have a look at the [minimal lopf example](https://www.pypsa.org/examples/minimal_example_lopf.html), understand what the [components documentation](https://pypsa.org/doc/components.html) of PyPSA gives you and that you can find the underlying objective function and constraints in the [LOPF documentation](https://pypsa.org/doc/optimal_power_flow.html#linear-optimal-power-flow).** > **Remarks:** For time reasons, you do not have to build the network from scratch. However, to get you acquainted with PyPSA we have omitted a few elements or some of their parameters of the network marked by three question marks ???. Either, you have to add an element similar to the one in the box above or add a few parameters. %% Cell type:markdown id: tags: Initialize network %% Cell type:code id: tags:  python network = pypsa.Network()  %% Cell type:markdown id: tags: Add North and South bus %% Cell type:code id: tags:  python network.add("Bus", "North", carrier="AC")  %% Cell type:code id: tags:  python ???  %% Cell type:markdown id: tags: Attach constant load %% Cell type:code id: tags:  python network.add("Load", "North Load", bus="North", p_set=20e3)  %% Cell type:code id: tags:  python ???  %% Cell type:markdown id: tags: Attach renewable generators according to given parameters %% Cell type:code id: tags:  python network.set_snapshots(np.arange(0, 4*7*24))  %% Cell type:code id: tags:  python Cfw = 0.3 Aw = 0.9 omegaw = 2*np.pi/(7*24) Cfs = 0.12 As = 1. omegas = 2*np.pi/24 GNwt = Cfw * (1+Aw*np.sin(omegaw*network.snapshots.to_series())) GSst = Cfs * (1+As*np.sin(omegas*network.snapshots.to_series()))  %% Cell type:code id: tags:  python pd.concat([GNwt, GSst], keys=['wind', 'solar'], axis=1).loc[:4*7*24].plot()  %% Output %% Cell type:code id: tags:  python network.add("Generator", "Wind", bus="North", p_nom_extendable=True, capital_cost=1.2e6, p_max_pu=GNwt)  %% Cell type:code id: tags:  python ???  %% Cell type:markdown id: tags: *** **(b) Attach extendable storages at the North and the South! The storages have to be modelled as an H2-bus (a bus with carrier='H2') linked to the AC-bus North with a Link where p_nom_extendable=True with the capital_cost of the power capacity and an also extendable Store with the capital_cost of the energy capacity, for instance. The losses can be set on the links as efficiency.** **(b) Attach extendable storage units at the North and the South! The storages have to be modelled as an H2-bus (a bus with carrier='H2') linked to the AC-bus North with a Link where p_nom_extendable=True with the capital_cost of the power capacity and an also extendable Store with the capital_cost of the energy capacity, for instance. The losses can be set on the links as efficiency.** %% Cell type:code id: tags:  python for bus in ["North", "South"]: # H2 storage network.add("Bus", bus + " H2", ??? ) network.add("Store", bus + " H2 St.", bus=bus + " H2", ??? ) network.add("Link", bus + "->H2", bus0=bus, bus1=bus + " H2", ??? ) network.add("Link", "H2->" + bus, bus0=bus + " H2", bus1=bus, ??? ) # Battery storage network.add("Bus", bus + " Battery", ??? ) network.add("Store", bus + " Battery St.", bus=bus + " Battery", ??? ) network.add("Link", bus + "<->Battery", bus0=bus, bus1=bus + " Battery", ??? )  %% Cell type:markdown id: tags: *** **(c) Run an investment optimization by calling the lopf function.** %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: *** **(d) How do your results objective and {generators,stores,links}.p_nom_opt compare with the results of III.1(d)?** %% Cell type:markdown id: tags: Objective value %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Capacities for wind and solar. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Store and dispatch power capacity. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Energy capacities. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Plot the storage energy states over time %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: *** **(e) Now we lift the restriction against transmission and allow North and South to bridge their 500 km separation with a transmission line. How does the cost optimal technology mix change?** %% Cell type:markdown id: tags: Add extendable link between North and South: %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Run LOPF: %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Get the results objective and {generators,stores,links}.p_nom_opt: %% Cell type:markdown id: tags: Objective value %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Capacities for wind and solar. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Store and dispatch power capacity. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Energy capacities. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Plot the storage energy states over time %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: *** **(e) Replace the approximated availability time-series of the wind and the solar generators with the ones from availability.csv computed from reanalysis weather data available on the [course website](https://nworbmot.org/courses/complex_renewable_energy_networks/) and re-run the LOPF. Compare the results! Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series!** **(e) Replace the approximated availability time-series of the wind and the solar generators with the ones from availability.csv computed from reanalysis weather data and re-run the LOPF. Compare the results! Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series!** %% Cell type:markdown id: tags: Adapt the network to new availabiltiy data: %% Cell type:code id: tags:  python network.remove("Generator", "Wind") network.remove("Generator", "Solar")  %% Cell type:code id: tags:  python availability = pd.read_csv("availability.csv", index_col=0, parse_dates=True) availability.head()  %% Output solar wind name 2012-01-01 00:00:00 0.0 0.402412 2012-01-01 01:00:00 0.0 0.480648 2012-01-01 02:00:00 0.0 0.542354 2012-01-01 03:00:00 0.0 0.586046 2012-01-01 04:00:00 0.0 0.641201 %% Cell type:markdown id: tags: Set snapshots of the network using the availability time series for July 2012. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Add wind generator with availability time series %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Add solar generator with availability time series %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Run LOPF: %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Get the results objective and {generators,stores,links}.p_nom_opt with real availability: %% Cell type:markdown id: tags: Objective value %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Capacities for wind and solar. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Store and dispatch power capacity. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Energy capacities. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Plot the storage energy states over time %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series. %% Cell type:code id: tags:  python  %% Cell type:markdown id: tags: *** **(f) Compare all results for all three scenarios in terms of total system cost, renewable generation capacity, storage power capacity and storage energy capacity!** > **Remark:** For example, you can use bar charts plt.bar(...) to visualize the differences. %% Cell type:code id: tags:  python  ... ...