Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate turbine libraries #345

Open
rafmudaf opened this issue Feb 27, 2022 · 22 comments
Open

Consolidate turbine libraries #345

rafmudaf opened this issue Feb 27, 2022 · 22 comments
Assignees
Labels
bug Something isn't working documentation v3 Label to denote focus on v3
Milestone

Comments

@rafmudaf
Copy link
Collaborator

rafmudaf commented Feb 27, 2022

For simplicity in the setuptools configuration, I created a new turbine library in floris/turbine_library so there is now two instances with the other one in examples/inputs/turbine_definitions. @bayc Let's think about how to resolve this via setup.py and the package_data keyword.

See #325

@rafmudaf rafmudaf added the bug Something isn't working label Feb 27, 2022
@rafmudaf rafmudaf added this to the v3.1.0 milestone Feb 27, 2022
@bayc
Copy link
Collaborator

bayc commented Mar 1, 2022

Sounds good! For now (to prevent confusion), I removed the examples/inputs/turbine_definitions folder so the users only have one place to look for the v3 release.

@ElieKadoche
Copy link

Hello! First, thank you for the amazing work done on the v3. From my understanding, if a user wants to add another turbine type, the new associated YAML file should be placed in the turbine_library folder, located in the FLORIS source code.

Modifying the content of the source code does not seem appropriate. Wouldn't it be better to allow an additional (external) turbine library? For example, there could be an additional_turbine_library variable in the YAML configuration.

_floris_dir = Path(__file__).parent.parent
fname = _floris_dir / "turbine_library" / f"{val}.yaml"

@bayc
Copy link
Collaborator

bayc commented Mar 1, 2022

Hello! First, thank you for the amazing work done on the v3. From my understanding, if a user wants to add another turbine type, the new associated YAML file should be placed in the turbine_library folder, located in the FLORIS source code.

Modifying the content of the source code does not seem appropriate. Wouldn't it be better to allow an additional (external) turbine library? For example, there could be an additional_turbine_library variable in the YAML configuration.

_floris_dir = Path(__file__).parent.parent
fname = _floris_dir / "turbine_library" / f"{val}.yaml"

Thank you for the feedback! This is something we have been discussing internally and agree that there should be a better solution to allow for user-defined turbine types. We will update here with any changes addressing this.

@bayc bayc added the v3 Label to denote focus on v3 label Mar 1, 2022
@econdon16
Copy link

Even when creating a new turbine in the turbine_library (the iea_15MW turbine) using the iea_10MW.yaml file as a template, I'm getting the following error:
ValueError: User-selected turbine definition "iea_15MW" does not exist in pre-defined turbine library.

Is there a way to bypass this for now until the external library is created?

@Bartdoekemeijer
Copy link
Collaborator

Hi @econdon16 . I have had success placing new turbine files in floris/floris/turbine_library and importing them in a similar manner as for the NREL 5MW and IEA 10MW turbine in the input YAML file. Can you share where you placed your files and how you modified your input YAML file?

@econdon16
Copy link

econdon16 commented Mar 7, 2022

@Bartdoekemeijer I duplicated the iea_10MW.yaml file within the same turbine_library folder and edited it to include the following:

turbine_type: 'iea_15MW'
generator_efficiency: 1.0
hub_height: 150.0
pP: 1.88
pT: 1.88
rotor_diameter: 240.0
TSR: 8.0
power_thrust_table:
power: ...
thrust: ...
wind_speed: ...

(My input file works with the iea_10MW.yaml file so I don't think the issue is there.)

@bayc
Copy link
Collaborator

bayc commented Mar 7, 2022

The code will look for the turbine file based on the file name. As such, do you have the file saved as iea_15MW.yaml?

@econdon16
Copy link

Yes I have named it that exactly @bayc

@bayc
Copy link
Collaborator

bayc commented Mar 7, 2022

In farm.py on line 77, you can see how the file path is constructed for loading the turbines (https://github.com/NREL/floris/blob/main/floris/simulation/farm.py#L77):

fname = _floris_dir / "turbine_library" / f"{val}.yaml"

You could try printing fname out before the if statement on line 78 and seeing if the file path exists/is correct. Perhaps the solution we have there doesn't work for all systems.

@econdon16
Copy link

I found my error to be in my environment organization. Though I thought I have floris v3.0.1 in it's own location, the turbine_library was being called from an installation of floris v3.0.1 in an anaconda environment i.e. I have floris/floris/turbine_library in two locations and it was favoring the one in a distant file. Adding my iea_15MW.yaml file to that location solved the issue, but any advice on editing that path?

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented Mar 8, 2022

If you're using conda, I think the Python interpreter will require that you add your new turbine to the floris in the anaconda installation. Like @ElieKadoche mentioned in #345 (comment), modifying the source code of an installed package is bad practice and we will resolve this in a future release. I'm not sure if I correctly understood so does this answer your question?

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented Mar 8, 2022

@econdon16 alternatively you can supply your turbine definition directly (as in, not in a turbine library directory) using the !include keyword in the input file...

farm:
  layout_x:
  - 0.0
  - 630.0
  - 1260.0
  layout_y:
  - 0.0
  - 0.0
  - 0.0
  turbine_type:
  - !include /your/path/to/raf_20MW.yaml

@rafmudaf rafmudaf modified the milestones: v3.1.0, v3.2.0 Apr 6, 2022
@rafmudaf rafmudaf modified the milestones: v3.2.0, v3.3 Sep 16, 2022
@spixap
Copy link

spixap commented Oct 23, 2022

Does anyone know how to create a yaml file that has a custom turbine type (!include /your/path/to/raf_20MW.yaml) not manually but directly from a python script? When I am trying to write the yaml file (using pyyalm and yalm.dump) the keyword !include is interpreted as a string and does not work. Thank you very much.

@rafmudaf
Copy link
Collaborator Author

Good question - I can't think of how to do this. Can you share a small example of what you've tried?

Are you automatically generating FLORIS input files? If so, you could also include the turbine definition directly under turbine_type rather than including the link to the turbine type yaml file.

@spixap
Copy link

spixap commented Oct 26, 2022

Thanks, @rafmudaf for your suggestion. Indeed this is what I also tried and it worked. All you need is to include the individual wind turbine content (i.e. the content that would normally be in the reference: !include /your/path/to/raf_20MW.yaml) per turbine, in the floris input file. Then you can overwrite the characteristics in the custom floris input file easily from the python script. In that way, you can even assign different Cp/Ct curves per wind turbine in the farm :)

Here follows an example with a custom input file: gch_new_input_32_turbines_Cp_Ct_rewritable.yaml

Loop to assign different curves to different turbines and write new input file

with open(r'inputs\gch_new_input_32_turbines_Cp_Ct_rewritable.yaml', 'r') as inputSpecsFile:
      farmSpecs = yaml.full_load(inputSpecsFile)

u_curves_list =  u_curves.tolist()
TSR_2_floris_list = TSR_2_floris.tolist()

for iturbine in range(N_TURBINES):
    
    Cp_2_floris_list = Cp_2_floris[iturbine,:].tolist()
    Ct_2_floris_list = Ct_2_floris[iturbine,:].tolist()

    farmSpecs['farm']['turbine_type'][iturbine]['power_thrust_table']['power']       = Cp_2_floris_list
    farmSpecs['farm']['turbine_type'][iturbine]['power_thrust_table']['thrust']      = Ct_2_floris_list
    farmSpecs['farm']['turbine_type'][iturbine]['power_thrust_table']['wind_speed']  = u_curves_list
    farmSpecs['farm']['turbine_type'][iturbine]['TSR']                               = TSR_2_floris_list[iturbine]
    
newFarmSpec = farmSpecs

with open(r'inputs\gch_new_input_32_turbines_Cp_Ct_rewritable.yaml', 'w') as file:
    documents = yaml.dump(newFarmSpec,file)

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented Feb 6, 2023

This should be added to the user documentation

@rafmudaf
Copy link
Collaborator Author

@RHammond2 mostly addressed this issue in #568, but I'm leaving this open since it is not yet in the documentation.

@rafmudaf rafmudaf modified the milestones: v3.4, v3.5 May 6, 2023
@pengyulu1112
Copy link

The error always show that nrel_5MW_custom.yaml is not defined when I am using external library, how can I solve it?

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented Jul 1, 2023

The error always show that nrel_5MW_custom.yaml is not defined when I am using external library, how can I solve it?

@pengyulu1112 could you share a simple script demonstrating the error? Also, please share the version of floris that you're using.

@pengyulu1112
Copy link

pengyulu1112 commented Jul 2, 2023

The version is 3.4.

I just modified the hub height of nrel_5MW, and I saved it as nrel_5MW100.yaml, I changed the hug height to 100m. But when I always meet the error shows that nrel_5MW100 does not exist in either the internal or external turbine library. So I wondering how to define an external turbine to my code. Thank you very much. Have a nice day!

This is the wind turbine I changed. Just vary the hub height of nrel_5MW. I renamed it as nrel_5MW100.yaml

turbine_type: 'nrel_5MW100'
generator_efficiency: 1.0
hub_height: 100.0
pP: 1.88
pT: 1.88
rotor_diameter: 126.0
TSR: 8.0
ref_density_cp_ct: 1.225
ref_tilt_cp_ct: 5.0
power_thrust_table:
  # Removed to save space

And this is the wind farm I set.

name: GCH
description: Three turbines using Gauss Curl Hybrid model
floris_version: v3.0.0

logging:
  console:
    enable: true
    level: WARNING
  file:
    enable: false
    level: WARNING

solver:
  type: turbine_grid
  turbine_grid_points: 3

farm:
  layout_x:
  - 0.0
  - 504.0
  - 1008

  layout_y:
  - 0.0
  - 0.0
  - 0.0

  turbine_type:
  - nrel_5MW
  - nrel_5MW
  - nrel_5MW100

flow_field:
  air_density: 1.225
  reference_wind_height: 90.0 # Since multiple defined turbines, must specify explicitly the reference wind height
  turbulence_intensity: 0.06
  wind_directions:
  - 270.0
  wind_shear: 0.12
  wind_speeds:
  - 8.0
  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

And this is the code I use.

import matplotlib.pyplot as plt
import floris.tools.visualization as wakeviz
from floris.tools import FlorisInterface
from floris.turbine_library import TurbineInterface, TurbineLibrary

fi = FlorisInterface("D:/python/floris/floris-main/examples/inputs/try/1x3mul.yaml")

horizontal_plane = fi.calculate_horizontal_plane(x_resolution=200, y_resolution=100, height=90)
y_plane = fi.calculate_y_plane(x_resolution=200, z_resolution=100, crossstream_dist=0.0)

# Create the plots
fig, ax_list = plt.subplots(2, 1, figsize=(9, 4))
ax_list = ax_list.flatten()

fig0 = wakeviz.visualize_cut_plane(horizontal_plane, ax=ax_list[0], title="Horizontal")
fig1 = wakeviz.visualize_cut_plane(y_plane, ax=ax_list[1], title="Streamwise profile")

ax_list[0].set_xlabel('x-coordinate of the wind turbine(m)')
ax_list[0].set_ylabel('wind turbine position(m)')

ax_list[1].set_xlabel('x-coordinate of the wind turbine(m)')
ax_list[1].set_ylabel('Height')

cbar = plt.colorbar(fig1, ax=ax_list)
cbar.set_label('Wind speed (m/s)')

wakeviz.show_plots()

Here is the error.

E:\python\FLoris\venv\Scripts\python.exe E:\python\FLoris\multiple_turbinetypes.py 
Traceback (most recent call last):
  File "E:\python\FLoris\multiple_turbinetypes.py", line 35, in <module>
    fi = FlorisInterface("D:/python/floris/floris-main/examples/inputs/try/1x3mul.yaml")
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\python\FLoris\venv\Lib\site-packages\floris\tools\floris_interface.py", line 57, in __init__
    self.floris = Floris.from_file(self.configuration)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\python\FLoris\venv\Lib\site-packages\floris\simulation\floris.py", line 338, in from_file
    return Floris.from_dict(input_dict)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\python\FLoris\venv\Lib\site-packages\floris\type_dec.py", line 160, in from_dict
    return cls(**kwargs)
           ^^^^^^^^^^^^^
  File "<attrs generated init floris.simulation.floris.Floris>", line 6, in __init__
  File "E:\python\FLoris\venv\Lib\site-packages\floris\type_dec.py", line 160, in from_dict
    return cls(**kwargs)
           ^^^^^^^^^^^^^
  File "<attrs generated init floris.simulation.farm.Farm>", line 26, in __init__
  File "E:\python\FLoris\venv\Lib\site-packages\floris\simulation\farm.py", line 136, in __attrs_post_init__
    raise FileNotFoundError(
FileNotFoundError: The turbine type: nrel_5MW100 does not exist in either the internal or external turbine library.

Process finished with exit code 1

@NREL NREL deleted a comment from pengyulu1112 Jul 3, 2023
@NREL NREL deleted a comment from pengyulu1112 Jul 3, 2023
@rafmudaf
Copy link
Collaborator Author

rafmudaf commented Jul 3, 2023

@pengyulu1112 Take a look at the description in #568. An additional field is required in your input file: turbine_library_path.

@pengyulu1112
Copy link

Thank you! I creat a new file which named nrel_5MW100.yaml in E:/ then it works!! Thank you very much!

@rafmudaf rafmudaf modified the milestones: v3.5, v4.0 Aug 2, 2023
@rafmudaf rafmudaf modified the milestones: v4.0, v3.6 Nov 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation v3 Label to denote focus on v3
Projects
None yet
Development

No branches or pull requests

7 participants