Turbine Models Library Pre-Processing Tools#
The turbine-models package hosts wind turbine data for a variety of wind turbines and has tools that can streamline the process to run new turbines with the PySAM Windpower model or FLORIS.
The full list of turbine models available in the turbine-models library can be found here
H2Integrate has preprocessing tools that leverage the functionality available in the turbine-models library. The function export_turbine_to_pysam_format() will save turbine model specifications formatted for the PySAM Windpower model. The PySAM Windpower model is wrapped in H2I and can be utilized with the “pysam_wind_plant_performance” model. Example usage of the export_turbine_to_pysam_format() function is demonstrated in the following section using Example 8.
Turbine Model Pre-Processing with PySAM Windpower Model#
Example 8 (08_wind_electrolyzer) currently uses an 8.3 MW turbine. In the following sections we will demonstrate how to:
Save turbine model specifications for the NREL 5 MW turbine in the PySAM Windpower format using
export_turbine_to_pysam_format()Load the turbine model specifications for the NREL 5 MW turbine and update performance parameters for the wind technology in the
tech_configdictionary for the NREL 5 MW turbine.Run H2I with the updated tech_config dictionary, showcasing two different methods to run H2I with the NREL 5 MW turbine:
initializing H2I with a dictionary input
saving the updated tech_config dictionary to a new file and initializing H2I by specifying the filepath to the top-level config file.
We’ll start off by importing the required modules and packages:
import os
import numpy as np
from h2integrate import EXAMPLE_DIR
from h2integrate.core.utilities import load_yaml
from h2integrate.core.inputs.validation import load_tech_yaml
from h2integrate.preprocess.wind_turbine_file_tools import export_turbine_to_pysam_format
from h2integrate.core.h2integrate_model import H2IntegrateModel
Load the tech config file that we want to update the turbine model for:
# Load the tech config file
tech_config_path = EXAMPLE_DIR / "08_wind_electrolyzer" / "tech_config.yaml"
tech_config = load_tech_yaml(tech_config_path)
This example uses the “pysam_wind_plant_performance” performance model for the wind plant. Currently, the performance model is using an 8.3MW wind turbine with a rotor diameter of 196 meters and a hub-height of 130 meters. This information is defined in the tech_config file:
4technologies:
5 wind:
6 performance_model:
7 model: "PYSAMWindPlantPerformanceModel"
8 cost_model:
9 model: "ATBWindPlantCostModel"
10 model_inputs:
11 performance_parameters:
12 num_turbines: 100
13 turbine_rating_kw: 8300
14 rotor_diameter: 196.
15 hub_height: 130.
16 create_model_from: "default"
17 config_name: "WindPowerSingleOwner"
18 pysam_options: !include "pysam_options_8.3MW.yaml"
19 run_recalculate_power_curve: False
20 layout:
21 layout_mode: "basicgrid"
22 layout_options:
23 row_D_spacing: 10.0
24 turbine_D_spacing: 10.0
25 rotation_angle_deg: 0.0
26 row_phase_offset: 0.0
27 layout_shape: "square"
28 cost_parameters:
29 capex_per_kW: 1500.0
30 opex_per_kW_per_year: 45
31 cost_year: 2019
If we want to replace the 8.3 MW turbine with the NREL 5 MW turbine, we can do so using the export_turbine_to_pysam_format() function:
turbine_name = "NREL_5MW"
turbine_model_fpath = export_turbine_to_pysam_format(turbine_name)
print(turbine_model_fpath)
/home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/library/pysam_options_NREL_5MW.yaml
# Load the turbine model file formatted for the PySAM Windpower module
pysam_options = load_yaml(turbine_model_fpath)
pysam_options
{'Turbine': {'wind_turbine_max_cp': 0.481305875,
'wind_turbine_ct_curve': [0.0,
0.0,
0.0,
1.132034888,
0.999470963,
0.917697381,
0.860849503,
0.815371198,
0.811614904,
0.807939328,
0.80443352,
0.800993851,
0.79768116,
0.794529244,
0.791495834,
0.788560434,
0.787217182,
0.787127977,
0.785839257,
0.783812219,
0.783568108,
0.783328285,
0.781194418,
0.777292539,
0.773464375,
0.769690236,
0.766001924,
0.762348072,
0.758760824,
0.755242872,
0.751792927,
0.748434131,
0.745113997,
0.717806682,
0.672204789,
0.63831272,
0.610176496,
0.585456847,
0.563222111,
0.542912273,
0.399312061,
0.310517829,
0.248633226,
0.203543725,
0.169616419,
0.143478955,
0.122938861,
0.106515296,
0.093026095,
0.081648606,
0.072197368,
0.064388275,
0.057782745,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0],
'wind_turbine_powercurve_windspeeds': [0.0,
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
7.1,
7.2,
7.3,
7.4,
7.5,
7.6,
7.7,
7.8,
7.9,
8.0,
9.0,
10.0,
10.1,
10.2,
10.3,
10.4,
10.5,
10.6,
10.7,
10.8,
10.9,
11.0,
11.1,
11.2,
11.3,
11.4,
11.5,
11.6,
11.7,
11.8,
11.9,
12.0,
13.0,
14.0,
15.0,
16.0,
17.0,
18.0,
19.0,
20.0,
21.0,
22.0,
23.0,
24.0,
25.0,
26.0,
27.0,
28.0,
29.0,
30.0,
31.0,
32.0,
33.0,
34.0,
35.0,
36.0,
37.0,
38.0,
39.0,
40.0,
41.0,
42.0,
43.0,
44.0,
45.0,
46.0,
47.0,
48.0,
49.0],
'wind_turbine_powercurve_powerout': [0.0,
0.0,
0.0,
40.52,
177.67,
403.9,
737.59,
1187.18,
1239.25,
1292.52,
1347.32,
1403.26,
1460.7,
1519.64,
1580.17,
1642.11,
1705.76,
1771.17,
2518.55,
3448.38,
3552.14,
3657.95,
3765.12,
3873.93,
3984.48,
4096.58,
4210.72,
4326.15,
4443.4,
4562.5,
4683.42,
4806.16,
4929.93,
5000.0,
5000.0,
4999.98,
4999.96,
4999.98,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0],
'wind_turbine_rotor_diameter': 126,
'wind_turbine_hub_ht': 90}}
# Create dictionary of updated inputs for the new turbine formatted for
# the "pysam_wind_plant_performance" model
updated_parameters = {
"turbine_rating_kw": np.max(pysam_options["Turbine"].get("wind_turbine_powercurve_powerout")),
"rotor_diameter": pysam_options["Turbine"].pop("wind_turbine_rotor_diameter"),
"hub_height": pysam_options["Turbine"].pop("wind_turbine_hub_ht"),
"pysam_options": pysam_options,
}
# Update wind performance parameters with model from PySAM
tech_config["technologies"]["wind"]["model_inputs"]["performance_parameters"].update(
updated_parameters
)
# The technology input for the updated wind turbine model
tech_config["technologies"]["wind"]["model_inputs"]["performance_parameters"]
{'num_turbines': 100,
'turbine_rating_kw': np.float64(5000.0),
'rotor_diameter': 126,
'hub_height': 90,
'create_model_from': 'default',
'config_name': 'WindPowerSingleOwner',
'pysam_options': {'Turbine': {'wind_turbine_max_cp': 0.481305875,
'wind_turbine_ct_curve': [0.0,
0.0,
0.0,
1.132034888,
0.999470963,
0.917697381,
0.860849503,
0.815371198,
0.811614904,
0.807939328,
0.80443352,
0.800993851,
0.79768116,
0.794529244,
0.791495834,
0.788560434,
0.787217182,
0.787127977,
0.785839257,
0.783812219,
0.783568108,
0.783328285,
0.781194418,
0.777292539,
0.773464375,
0.769690236,
0.766001924,
0.762348072,
0.758760824,
0.755242872,
0.751792927,
0.748434131,
0.745113997,
0.717806682,
0.672204789,
0.63831272,
0.610176496,
0.585456847,
0.563222111,
0.542912273,
0.399312061,
0.310517829,
0.248633226,
0.203543725,
0.169616419,
0.143478955,
0.122938861,
0.106515296,
0.093026095,
0.081648606,
0.072197368,
0.064388275,
0.057782745,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0],
'wind_turbine_powercurve_windspeeds': [0.0,
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
7.1,
7.2,
7.3,
7.4,
7.5,
7.6,
7.7,
7.8,
7.9,
8.0,
9.0,
10.0,
10.1,
10.2,
10.3,
10.4,
10.5,
10.6,
10.7,
10.8,
10.9,
11.0,
11.1,
11.2,
11.3,
11.4,
11.5,
11.6,
11.7,
11.8,
11.9,
12.0,
13.0,
14.0,
15.0,
16.0,
17.0,
18.0,
19.0,
20.0,
21.0,
22.0,
23.0,
24.0,
25.0,
26.0,
27.0,
28.0,
29.0,
30.0,
31.0,
32.0,
33.0,
34.0,
35.0,
36.0,
37.0,
38.0,
39.0,
40.0,
41.0,
42.0,
43.0,
44.0,
45.0,
46.0,
47.0,
48.0,
49.0],
'wind_turbine_powercurve_powerout': [0.0,
0.0,
0.0,
40.52,
177.67,
403.9,
737.59,
1187.18,
1239.25,
1292.52,
1347.32,
1403.26,
1460.7,
1519.64,
1580.17,
1642.11,
1705.76,
1771.17,
2518.55,
3448.38,
3552.14,
3657.95,
3765.12,
3873.93,
3984.48,
4096.58,
4210.72,
4326.15,
4443.4,
4562.5,
4683.42,
4806.16,
4929.93,
5000.0,
5000.0,
4999.98,
4999.96,
4999.98,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0]}},
'run_recalculate_power_curve': False,
'layout': {'layout_mode': 'basicgrid',
'layout_options': {'row_D_spacing': 10.0,
'turbine_D_spacing': 10.0,
'rotation_angle_deg': 0.0,
'row_phase_offset': 0.0,
'layout_shape': 'square'}}}
Option 1: Run H2I with dictionary input#
# Create the top-level config input dictionary for H2I
h2i_config = {
# "name": "H2Integrate Config",
# "system_summary": f"Updated hybrid plant using {turbine_name} turbine",
"driver_config": EXAMPLE_DIR / "08_wind_electrolyzer" / "driver_config.yaml",
"technology_config": tech_config,
"plant_config": EXAMPLE_DIR / "08_wind_electrolyzer" / "plant_config.yaml",
}
# Create a H2Integrate model with the updated tech config
h2i = H2IntegrateModel(h2i_config)
# Run the model
h2i.run()
# Get LCOE of wind plant
wind_lcoe = h2i.model.get_val("finance_subgroup_electricity_profast.LCOE", units="USD/MW/h")
print(f"Wind LCOE is ${wind_lcoe[0]:.2f}/MWh")
# Get LCOH of wind/electrolyzer plant
lcoh = h2i.model.get_val("finance_subgroup_hydrogen.LCOH_produced_profast_model", units="USD/kg")
print(f"LCOH is ${lcoh[0]:.2f}/kg")
Wind LCOE is $68.18/MWh
LCOH is $6.82/kg
Option 2: Save new tech_config to file and run H2I from file#
from h2integrate.core.utilities import write_readable_yaml
# Define a new filepath for the updated tech config
tech_config_path_new = EXAMPLE_DIR / "08_wind_electrolyzer" / f"tech_config_{turbine_name}.yaml"
# Save the updated tech config to the new filepath
write_readable_yaml(tech_config, tech_config_path_new)
# Load in the top-level H2I config file
h2i_config_path = EXAMPLE_DIR / "08_wind_electrolyzer" / "wind_plant_electrolyzer.yaml"
h2i_config_dict = load_yaml(h2i_config_path)
# Define a new filepath for the updated top-level config
h2i_config_path_new = (
EXAMPLE_DIR / "08_wind_electrolyzer" / f"wind_plant_electrolyzer_{turbine_name}.yaml"
)
# Update the technology config filepath in the top-level config with the updated
# tech config filename
h2i_config_dict["technology_config"] = tech_config_path_new.name
# Save the updated top-level H2I config to the new filepath
write_readable_yaml(h2i_config_dict, h2i_config_path_new)
# Change the CWD to the example folder since filepaths in h2i_config_dict are relative
# to the "08_wind_electrolyzer" folder
os.chdir(EXAMPLE_DIR / "08_wind_electrolyzer")
# Create a H2Integrate model with the updated tech config
h2i = H2IntegrateModel(h2i_config_path_new.name)
# Run the model
h2i.run()
# Get LCOE of wind plant
wind_lcoe = h2i.model.get_val("finance_subgroup_electricity_profast.LCOE", units="USD/MW/h")
print(f"Wind LCOE is ${wind_lcoe[0]:.2f}/MWh")
# Get LCOH of wind/electrolyzer plant
lcoh = h2i.model.get_val("finance_subgroup_hydrogen.LCOH_produced_profast_model", units="USD/kg")
print(f"LCOH is ${lcoh[0]:.2f}/kg")
Wind LCOE is $68.18/MWh
LCOH is $6.82/kg
Turbine Model Pre-Processing with FLORIS#
Example 26 (26_floris) currently uses an 660 kW turbine. This example uses the “floris_wind_plant_performance” performance model for the wind plant. Currently, the performance model is using an 660 kW wind turbine with a rotor diameter of 47.0 meters and a hub-height of 65 meters. In the following sections we will demonstrate how to:
Save turbine model specifications for the Vestas 1.65 MW turbine in the FLORIS format using
export_turbine_to_floris_format()Load the turbine model specifications for the Vestas 1.65 MW turbine and update performance parameters for the wind technology in the
tech_configdictionary for the Vestas 1.65 MW turbine.Run H2I with the updated tech_config dictionary for the Vestas 1.65 MW turbine
We’ll start off with Step 1 and importing the function export_turbine_to_floris_format(), which will save turbine model specifications of the Vestas 1.65 MW turbine formatted for FLORIS.
from h2integrate.preprocess.wind_turbine_file_tools import export_turbine_to_floris_format
turbine_name = "Vestas_1.65MW"
turbine_model_fpath = export_turbine_to_floris_format(turbine_name)
print(turbine_model_fpath)
/home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/library/floris_turbine_Vestas_1.65MW.yaml
Step 2: Load the turbine model specifications for the Vestas 1.65 MW turbine and update performance parameters for the wind technology in the tech_config dictionary for the Vestas 1.65 MW turbine.
# Load the tech config file
tech_config_path = EXAMPLE_DIR / "26_floris" / "tech_config.yaml"
tech_config = load_tech_yaml(tech_config_path)
# Load the turbine model file formatted for FLORIS
floris_options = load_yaml(turbine_model_fpath)
# Create dictionary of updated inputs for the new turbine formatted for
# the "floris_wind_plant_performance" model
updated_parameters = {
"hub_height": -1, # -1 indicates to use the hub-height in the floris_turbine_config
"floris_turbine_config": floris_options,
}
# Update distributed wind+ performance parameters in the tech config
tech_config["technologies"]["distributed_wind_plant"]["model_inputs"]["performance_parameters"].update(
updated_parameters
)
# The technology input for the updated wind turbine model
tech_config["technologies"]["distributed_wind_plant"]["model_inputs"]["performance_parameters"]
{'num_turbines': 100,
'hub_height': -1,
'operational_losses': 12.83,
'floris_wake_config': {'name': 'Gauss',
'description': 'Onshore template',
'floris_version': 'v4.0.0',
'logging': {'console': {'enable': False, 'level': 'WARNING'},
'file': {'enable': False, 'level': 'WARNING'}},
'solver': {'type': 'turbine_grid', 'turbine_grid_points': 1},
'flow_field': {'air_density': 1.225,
'reference_wind_height': -1,
'wind_directions': [],
'wind_shear': 0.33,
'wind_speeds': [],
'wind_veer': 0.0},
'wake': {'model_strings': {'combination_model': 'sosfs',
'deflection_model': 'gauss',
'turbulence_model': 'crespo_hernandez',
'velocity_model': 'gauss'},
'enable_secondary_steering': False,
'enable_yaw_added_recovery': False,
'enable_transverse_velocities': False,
'wake_deflection_parameters': {'gauss': {'ad': 0.0,
'alpha': 0.58,
'bd': 0.0,
'beta': 0.077,
'dm': 1.0,
'ka': 0.38,
'kb': 0.004},
'jimenez': {'ad': 0.0, 'bd': 0.0, 'kd': 0.05}},
'wake_velocity_parameters': {'cc': {'a_s': 0.179367259,
'b_s': 0.0118889215,
'c_s1': 0.0563691592,
'c_s2': 0.13290157,
'a_f': 3.11,
'b_f': -0.68,
'c_f': 2.41,
'alpha_mod': 1.0},
'gauss': {'alpha': 0.58, 'beta': 0.077, 'ka': 0.38, 'kb': 0.004},
'jensen': {'we': 0.05}},
'wake_turbulence_parameters': {'crespo_hernandez': {'initial': 0.1,
'constant': 0.5,
'ai': 0.8,
'downstream': -0.32}},
'enable_active_wake_mixing': False},
'farm': {'layout_x': [], 'layout_y': []}},
'floris_turbine_config': {'turbine_type': 'Vestas_1.65MW',
'hub_height': 70.0,
'TSR': 8.0,
'rotor_diameter': 82,
'power_thrust_table': {'wind_speed': [0.0,
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
8.0,
9.0,
10.0,
11.0,
12.0,
13.0,
14.0,
15.0,
16.0,
17.0,
18.0,
19.0,
20.0,
21.0,
22.0,
23.0,
24.0,
25.0,
26.0,
27.0,
28.0,
29.0,
30.0,
31.0,
32.0,
33.0,
34.0,
35.0,
36.0,
37.0,
38.0,
39.0,
40.0,
41.0,
42.0,
43.0,
44.0,
45.0,
46.0,
47.0,
48.0,
49.0],
'power': [0.0,
0.0,
0.0,
0.0,
28.0,
144.0,
309.0,
511.0,
758.0,
1017.0,
1285.0,
1504.0,
1637.0,
1650.0,
1650.0,
1650.0,
1650.0,
1650.0,
1650.0,
1650.0,
1650.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0],
'thrust_coefficient': [0.0,
0.0,
0.0,
0.979,
1.111,
1.014,
0.925,
0.843,
0.768,
0.701,
0.642,
0.578,
0.509,
0.438,
0.379,
0.334,
0.299,
0.272,
0.249,
0.232,
0.218,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0],
'ref_air_density': 1.225,
'ref_tilt': 5.0,
'cosine_loss_exponent_yaw': 1.88,
'cosine_loss_exponent_tilt': 1.88}},
'resource_data_averaging_method': 'weighted_average',
'operation_model': 'cosine-loss',
'default_turbulence_intensity': 0.06,
'enable_caching': True,
'cache_dir': 'cache',
'layout': {'layout_mode': 'basicgrid',
'layout_options': {'row_D_spacing': 5.0,
'turbine_D_spacing': 5.0,
'rotation_angle_deg': 0.0,
'row_phase_offset': 0.0,
'layout_shape': 'square'}}}
Step 3: Run H2I with the updated tech_config dictionary for the Vestas 1.65 MW turbine
# Create the top-level config input dictionary for H2I
h2i_config = {
"driver_config": EXAMPLE_DIR / "26_floris" / "driver_config.yaml",
"technology_config": tech_config,
"plant_config": EXAMPLE_DIR / "26_floris" / "plant_config.yaml",
}
# Create a H2Integrate model with the updated tech config
h2i = H2IntegrateModel(h2i_config)
# Run the model
h2i.run()
# Get LCOE of wind plant
wind_lcoe = h2i.model.get_val("finance_subgroup_distributed.LCOE", units="USD/MW/h")
print(f"Wind LCOE is ${wind_lcoe[0]:.2f}/MWh")
Wind LCOE is $86.64/MWh
UserWarning: /home/docs/checkouts/readthedocs.org/user_builds/h2integrate/envs/531/lib/python3.11/site-packages/floris/core/flow_field.py:156
'where' used without 'out', expect unitialized memory in output. If this is intentional, use out=None.