Optimising storage locations#
Functions to optimise hydrogen storage locations.
References#
- h2ss.optimisation.ref_power_curve(v)[source]#
Power curve for the reference wind turbine.
Parameters#
- vfloat
Wind speed [m s⁻¹]
Returns#
- float
Wind turbine power output at a given wind speed from the power curve [MW]
Notes#
The NREL 15 MW reference wind turbine is used; see [1], Appendix D, p. 84, for the data used to generate the power curve.
- h2ss.optimisation.weibull_probability_distribution(v, k, c)[source]#
Weibull probability distribution function.
Parameters#
- vfloat
Wind speed [m s⁻¹]
- kfloat
Shape (Weibull distribution parameter, k)
- cfloat
Scale (Weibull distribution parameter, C) [m s⁻¹]
Returns#
- float
Weibull probability distribution function [s m⁻¹]
Notes#
The Weibull probability distribution function, \(f(v)\) [s m⁻¹] is based on Eqn. (1) of [2], where \(k\) and \(C\) [m s⁻¹] are the shape and scale Weibull distribution parameters, respectively, and \(v\) is the wind speed.
\[f(v) = \frac{k}{C} \, \left( \frac{v}{C} \right)^{k - 1} \, \exp \left( -\left( \frac{v}{C} \right)^k \right)\]See also [3], Eqn. (2).
- h2ss.optimisation.weibull_distribution(weibull_wf_data)[source]#
Generate a power curve and Weibull distribution.
Parameters#
- weibull_wf_datapandas.DataFrame
Dataframe of the Weibull distribution parameters for the wind farms
Returns#
- pandas.DataFrame
Dataframe of the Weibull distribution for each wind farm for wind speeds of 0 to 30 m s⁻¹ at an interval of 0.01
- h2ss.optimisation.weibull_power_curve(v, k, c)[source]#
Weibull probability distribution function multiplied by the power curve.
Parameters#
- vfloat
Wind speed between cut-in and cut-out [m s⁻¹]
- kfloat
Shape (Weibull distribution parameter, k)
- cfloat
Scale (Weibull distribution parameter, C) [m s⁻¹]
Returns#
- float
Weibull probability distribution multiplied by the power curve [MW s m⁻¹]
- h2ss.optimisation.number_of_turbines(owf_cap, wt_power=15)[source]#
Number of reference wind turbines in the offshore wind farm.
Parameters#
- owf_capfloat
Maximum nameplate capacity of the proposed offshore wind farm [MW]
- wt_powerfloat
Rated power of the reference wind turbine [MW]
Returns#
- int
Number of wind turbines in the offshore wind farm comprising of reference wind turbines
Notes#
The number of turbines, \(n\) of an offshore wind farm was determined using the floor division of the wind farm’s maximum nameplate capacity, \(P_{owf}\) [MW] by the reference wind turbine’s rated power, \(P_{rated}\) [MW].
\[n = \left\lfloor \frac{P_{owf}}{P_{rated}} \right\rfloor\]
- h2ss.optimisation.annual_energy_production_function(n_turbines, k, c, w_loss=0.1, acdc_loss=0.982)[source]#
Annual energy production of the wind farm.
Parameters#
- n_turbinesint
Number of wind turbines in wind farm
- kfloat
Shape (Weibull distribution parameter)
- cfloat
Scale (Weibull distribution parameter) [m s⁻¹]
- w_lossfloat
Wake loss
- acdc_lossfloat
AC-DC conversion losses
Returns#
- tuple[float, float, float]
Annual energy production of wind farm [MWh], integral [MW], and absolute error [MW]
Notes#
The annual energy production, \(E_{annual}\) [MWh], is based on Eqn. (3) of [2], where \(n\) is the number of turbines in the wind farm, \(w\) is the wake loss, which is assumed to be a constant value of 0.1, \(v_i\) and \(v_o\) [m s⁻¹] are the cut-in and cut-out speeds of the wind turbine, respectively, \(P(v)\) [MW] is the wind turbine power output, \(f(v)\) [s m⁻¹] is the Weibull probability distribution function, and \(\varepsilon\) is the AC-DC conversion loss.
\[E_{annual} = 365 \times 24 \times n \, \left( 1 - w \right) \, \varepsilon \, \int\limits_{v_i}^{v_o} P(v) \, f(v) \,\mathrm{d}v\]In the function’s implementation, both the limit and absolute error tolerance for the integration have been increased.
- h2ss.optimisation.annual_energy_production(weibull_wf_data)[source]#
Annual energy production of the wind farms.
Parameters#
- weibull_wf_datapandas.DataFrame
Dataframe of the Weibull distribution parameters for the wind farms
Returns#
- pandas.DataFrame
Dataframe with the annual energy production for each wind farm
- h2ss.optimisation.annual_hydrogen_production(aep, eta_conv=0.7, e_pcl=0.003053)[source]#
Annual hydrogen production from the wind farm’s energy generation.
Parameters#
- aepfloat
Annual energy production of wind farm [MWh]
- eta_convfloat
Conversion efficiency of the electrolyser
- e_pclfloat
Electricity consumed by other parts of the hydrogen plant [MWh kg⁻¹]
Returns#
- float
Annual hydrogen production [kg]
Notes#
Eqn. (4) of [2], Eqn. (9) of [4], and [6]. The value for the electricity consumed by other parts of the hydrogen plant is from Table 3 of [4] for proton exchange membrane (PEM) electrolysers predicted for the year 2030. This includes energy for water purification, hydrogen compression, and losses. The electrolyser conversion efficiency is based on [6]. See [5] for the heating values.
\[m_{annual} = \dfrac{E_{annual}}{\dfrac{LHV}{3,600 \, \eta} + E_{plant}}\]where \(m_{annual}\) is the annual hydrogen production [kg], \(E_{annual}\) is the annual energy production of the wind farm [MWh], \(LHV\) is the lower heating value of hydrogen [MJ kg⁻¹], \(\eta\) is the conversion efficiency of the electrolyser, and \(E_{plant}\) is the electricity consumed by other parts of the hydrogen plant [MWh kg⁻¹].
- h2ss.optimisation.transmission_distance(cavern_df, wf_data, injection_point_coords=(-6, -12, 53, 21))[source]#
Calculate the transmission distance to the injection point.
Parameters#
- cavern_dfgeopandas.GeoDataFrame
Dataframe of potential caverns
- wf_datageopandas.GeoDataFrame
Geodataframe of the offshore wind farm data
- injection_point_coordstuple[float, float, float, float]
Injection point coordinates (lon-deg, lon-min, lat-deg, lat-min)
Returns#
- tuple[geopandas.GeoDataFrame, geopandas.GeoSeries]
The cavern dataframe and injection point
Notes#
A hacky workaround was used to prevent “DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)” during the transformation of the injection point from a single-row series, i.e. assigning a duplicate row and dropping it after reprojecting.
- h2ss.optimisation.electrolyser_capacity(n_turbines, wt_power=15, cap_ratio=0.83)[source]#
Calculate the electrolyser capacity for an offshore wind farm.
Parameters#
- n_turbinesint
Number of wind turbines in wind farm
- wt_powerfloat
Rated power of the reference wind turbine [MW]
- cap_ratiofloat
Ratio of electrolyser capacity to the wind farm capacity
Returns#
- int
Electrolyser capacity [MW]
Notes#
In the offshore electrolyser concept of [6], the electricity from an offshore wind farm “is supplied to the electrolyser by medium voltage alternating current (AC) cable. The electrolyser requires direct current (DC) electricity input so this concept includes an AC-DC converter. The hydrogen obtained is compressed and delivered onshore by hydrogen pipelines”.
The “energy from the offshore wind farm is only subjected to wake losses and a small amount of electricity loss in the site network and the AC-DC converter before being supplied to the electrolyser. The hydrogen obtained will then be transported to onshore infrastructure by pipeline. The losses incurred by pipeline transmission are very low” [6].
The electrolyser capacity, \(P_{electrolyser}\) [MW] is rounded down to an integer and is the product of the number of reference wind turbines of the offshore wind farm, \(n\), the rated power of the reference wind turbine, \(P_{rated}\), and the ratio of the electrolyser capacity to the offshore wind farm capacity, \(F_{electrolyser}\).
\[P_{electrolyser} = \left\lfloor n \, P_{rated} \, F_{electrolyser} \right\rfloor\]
- h2ss.optimisation.hydrogen_pipeline_density(pressure, temperature)[source]#
Calculate the density of hydrogen in the pipelines.
Parameters#
- pressurefloat
Pressure of hydrogen in the pipeline [Pa]
- temperaturefloat
Temperature of hydrogen in the pipeline [°C]
Returns#
- float
Pipeline hydrogen density [kg m⁻³]
Notes#
According to [8], the envisaged future hydrogen pipeline system is assumed to be operated at pressure levels up to 10 MPa. They used an average operating pressure of 6.5 MPa for transmission pipelines and calculated the density using the average soil temperature, which was assumed to be the operating temperature of the hydrogen [8].
- h2ss.optimisation.capex_pipeline(e_cap, p_rate=0.0055, pressure=10000000.0, temperature=10, u=15)[source]#
Capital expenditure (CAPEX) for the pipeline.
Parameters#
- e_capfloat
Electrolyser capacity [MW]
- p_ratefloat
Electrolyser production rate [kg s⁻¹ MW⁻¹]
- pressurefloat
Pressure of hydrogen in the pipeline [Pa]
- temperaturefloat
Temperature of hydrogen in the pipeline [°C]
- ufloat
Average fluid velocity [m s⁻¹]
Returns#
- float
CAPEX of the pipeline per km of pipeline [€ km⁻¹]
Notes#
See Eqn. (18) of [2] and Section 3.1 of [7], from which the following text has been taken.
The estimation of offshore pipeline costs is based on the onshore pipeline calculations of [8], multiplied by a factor of two to reflect the estimated cost scaling of onshore to expected offshore costs, as suggested by [9].
In the reference case, the resulting capital expenditure for transmission pipelines and associated recompression stations was represented by a second order polynomial function.
The electrolyser production rate was based on the Siemens - Silyzer 300 [10].
Because the electrolyser plant is assumed to be operating at full capacity at all times, the CAPEX was calculated considering a 75% utilisation rate, i.e. the pipeline capacity is 33% oversized [11].
\[CAPEX = 2,000 \, \left( 16,000 \, \frac{P_{electrolyser} \times EPR}{\rho_{H_2} \, v_{H_2} \, \pi} + 1,197.2 \, \sqrt{\frac{P_{electrolyser} \times EPR}{\rho_{H_2} \, v_{H_2} \, \pi}} + 329 \right)\]where \(CAPEX\) is the CAPEX of the pipeline per km of pipeline [€ km⁻¹], \(P_{electrolyser}\) is the electrolyser capacity [MW], \(EPR\) is the electrolyser production rate [kg s⁻¹ MW⁻¹], \(\rho_{H_2}\) is the density of hydrogen [kg m⁻³], and \(v_{H_2}\) is the average fluid velocity [m s⁻¹].
- h2ss.optimisation.lcot_pipeline_function(capex, d_transmission, ahp, opex_ratio=0.02, discount_rate=0.08, lifetime=30)[source]#
Levelised cost of transmission (LCOT) of hydrogen in pipelines.
Parameters#
- capexfloat
Capital expenditure (CAPEX) of the pipeline [€ km⁻¹]
- d_transmissionfloat
Pipeline transmission distance [km]
- ahpfloat
Annual hydrogen production [kg]
- opex_ratiofloat
Ratio of the operational expenditure (OPEX) to the CAPEX
- discount_ratefloat
Discount rate
- lifetimeint
Lifetime of the pipeline [year]
Returns#
- float
LCOT of hydrogen in the pipeline [€ kg⁻¹]
Notes#
The OPEX is calculated as a percentage of the CAPEX. See the introduction of Section 3, Eqn. (1) and (2), and Section 3.5, Eqn. (22) of [7]; see Tables 2 and 3 for the assumptions and constants used.
\[LCOT = \frac{\mathrm{total\ lifecycle\ costs\ of\ all\ components}} {\mathrm{lifetime\ hydrogen\ transported}}\]\[OPEX = CAPEX \times F_{OPEX}\]\[LCOT = \frac{\left( CAPEX + \displaystyle\sum_{l=0}^{L} \frac{OPEX}{{(1 + DR)}^l} \right) \, d} {\displaystyle\sum_{l=0}^{L} \frac{AHP}{{(1 + DR)}^l}}\]where \(LCOT\) is the LCOT of hydrogen in pipelines [€ kg⁻¹], \(CAPEX\) is the CAPEX of the pipeline per km of pipeline [€ km⁻¹], \(d\) is the pipeline transmission distance [km], \(OPEX\) is the OPEX of the pipeline [€ km⁻¹], \(DR\) is the discount rate, \(AHP\) is the annual hydrogen production [kg], \(L\) is the lifetime of the pipeline [year], and \(F_{OPEX}\) is the ratio of the OPEX to the CAPEX.
- h2ss.optimisation.lcot_pipeline(weibull_wf_data, cavern_df)[source]#
Calculate the pipeline levelised cost of transmission.
Parameters#
- cavern_dfgeopandas.GeoDataFrame
Dataframe of potential caverns
- weibull_wf_datapandas.DataFrame
Dataframe of the Weibull distribution parameters for the wind farms
Returns#
- pandas.DataFrame
Dataframe of potential caverns
- h2ss.optimisation.rotor_area(diameter=248)[source]#
Wind turbine rotor swept area.
Parameters#
- diameterfloat
Wind turbine rotor diameter [m]
Returns#
- float
Wind turbine rotor swept area [m²]
Notes#
\[A = \frac{\pi \, D^2}{4}\]where \(A\) is the wind turbine rotor swept area [m²] and \(D\) is the rotor diameter [m].
- h2ss.optimisation.power_wind_resource(v, rho=1.225, diameter=248)[source]#
Total wind resource power passing through a wind turbine’s rotor.
Parameters#
- vfloat
Wind speed [m s⁻¹]
- rhofloat
Air density [kg m⁻³]
- diameterfloat
Wind turbine rotor diameter [m]
Returns#
- float
Power contained in the wind resource [MW]
Notes#
\[P_{wind} = \frac{\rho_{air} \, A \, v^3}{2 \times 10^6}\]where \(P_{wind}\) is the power contained in the wind resource [MW], \(\rho_{air}\) is the air density [kg m⁻³], \(A\) is the rotor swept area [m²], and \(v\) is the wind speed [m s⁻¹].
- h2ss.optimisation.power_coefficient(v)[source]#
Power coefficient of the reference wind turbine.
Parameters#
- vfloat
Wind speed [m s⁻¹]
Returns#
- float
Power coefficient
Notes#
This is specific to the power curve of the NREL 15 MW reference wind turbine [1].
\[C_p = \frac{P}{P_{wind}} = \frac{P \times 2 \times 10^6} {\rho_{air} \, A \, v^3}\]where \(P\) is the wind turbine power output [MW], \(P_{wind}\) is the power contained in the wind resource [MW], \(\rho_{air}\) is the air density [kg m⁻³], \(A\) is the rotor swept area [m²], \(v\) is the wind speed [m s⁻¹], and \(C_p\) is the power coefficient of the wind turbine.