-
Notifications
You must be signed in to change notification settings - Fork 156
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
Update to more flexible turbine operation model definitions #770
Conversation
…ain/floris/turbine_library/nrel_5MW.yaml with extension for before cut in and after cut out. Rename thrust field.
…hrust_coefficient key name.
… (tests need updating yet).
…MW turbine only, will remove prior to merge into v4 branch.
floris/simulation/farm.py
Outdated
self.turbine_map.append(TurbineMultiDimensional.from_dict(_turb)) | ||
else: | ||
self.turbine_map = [Turbine.from_dict(turb) for turb in self.turbine_definitions] | ||
self.turbine_map = [Turbine.from_dict(turb) for turb in self.turbine_definitions] | ||
|
||
def construct_turbine_fCts(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change function name to reflect that it isn't fCt
anymore
80e549f
to
d3f0084
Compare
8355471
to
b0f9c71
Compare
c20a84c
to
359cc9f
Compare
This was previously used for the multidimension turbine, but it has since been consolidated and flatten_dict isn't used
floris/simulation/farm.py
Outdated
@@ -81,8 +81,11 @@ class Farm(BaseClass): | |||
|
|||
turbine_definitions: list = field(init=False, validator=iter_validator(list, dict)) | |||
|
|||
turbine_fCts: Dict[str, interp1d] | List[interp1d] = field(init=False, factory=list) | |||
turbine_fCts_sorted: NDArrayFloat = field(init=False, factory=list) | |||
turbine_thrust_coefficient_functions: Dict[str, Callable] | List[Callable] = \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were previously either a dict or a list depending whether it was a multidimensional turbine. Now I believe they're only dict. Is that true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe I've fixed these in the last commit @misi9170 but I'll let you hit the resolve button
floris/simulation/farm.py
Outdated
turbine_thrust_coefficient_functions: Dict[str, Callable] | List[Callable] = \ | ||
field(init=False, factory=list) | ||
|
||
turbine_axial_induction_functions: Dict[str, Callable] | List[Callable] = \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were previously either a dict or a list depending whether it was a multidimensional turbine. Now I believe they're only dict. Is that true?
floris/simulation/farm.py
Outdated
|
||
turbine_type_map: NDArrayObject = field(init=False, factory=list) | ||
turbine_type_map_sorted: NDArrayObject = field(init=False, factory=list) | ||
|
||
turbine_power_interps: Dict[str, interp1d] | List[interp1d] = field(init=False, factory=list) | ||
turbine_power_interps_sorted: NDArrayFloat = field(init=False, factory=list) | ||
turbine_power_functions: Dict[str, Callable] | List[Callable] = field(init=False, factory=list) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were previously either a dict or a list depending whether it was a multidimensional turbine. Now I believe they're only dict. Is that true?
We decided to use the name "operation model" to describe these models. Now, "turbine model" refers to the turbine physical properties, such as rotor diameter and hub height, which are normally specified in the turbine yamls. We chose the name "operation model" to highlight that these models describe how the turbine performs in different operating modes. For example, intentional yaw misalignment is an operating mode, and the manifestation of how yaw misaligment affects the turbine's thrust and power is specified in an operation model. Similarly, the Helix wake mixing method is a "mode" that the turbine may operate in, and we plan to implement an operation model to represent the effects on thrust, axial induction, and power. |
Description
This pull request makes significant changes to the
Turbine()
class and surrounding code (most heavily located in turbine.py, but spread throughout the FLORIS source code) to enable specification of more advanced functionality for computing the thrust coefficient and power of a turbine off of "nominal" operation. In doing so, I've added two turbine operation models,CosineLossTurbine
(which is the default, and matches the previous behavior of FLORIS v3) andSimpleTurbine
, which is an actuator disk without handling for rotor misalignment with the flow.We envisage that other operation models will be added in FLORIS v4.1.
In doing so, I've also incorporated the multidimensional Cp/Ct turbine code. There are likely still some minor updates needed here to get all naming conventions aligned (e.g. dropping "cp" in favor of "power", see #765 ); however, the necessary functional changes have been made and multidimensional turbine tests pass.
Previous discussion
Modified from the FLORIS v4 project board
Currently, the turbine model is essentially implemented using interpolation functions, where each
turbine_type
has its own interpolation function and a mapping for which turbine is which type is created before the solver is run to mask the outputs of the interpolators to the correct turbine positions.Proposed changes for FLORIS v4 would not change this underlying structure, but the interpolators would be replaced by more general callable function definitions to implement different ways of computing power and thrust coefficient given turbine inputs. Now referred to as different "operation models"
A
turbine modeloperation model is then a set oftwothree functions:power()
, which returns the turbine power at the given atmospheric conditions and control settingsthrust_coefficient()
(or possiblyCt()
), which returns the turbine thrust coefficient at the given atmospheric conditions and control settings.axial_induction()
, returns the axial induction factorFor flexibility, there may also be a
prepare
function (similar to that of the wake models) that establishes a dictionary of keyword arguments needed for each turbine type; this will be unpacked in the call to the turbine functions.We imagine that
power()
,thrust_coefficient()
, may call from a library of lower level functions that implement, for example, sliding along the power curve for yaw angle or air density changes.We may represent a turbine model as a "static class", which has now memory but has various
@staticmethod
s for inheritance reasons and to enforce implementation of certain methods.The reason for not making them class objects is to save memory, but this could possibly be revisited if necessary as only one instantiated object would be needed for each
turbine_type
(not for each turbine).It is not yet clear exactly how the selection of different
subturbineoperation models will be configured in the inputs files. However, thesubturbineoperation models could be specified within the turbine yamls, as an option.How are we going to deal with multidimensional turbines? Should be able to be handled in this.
Steps
SimpleTurbine
implements main functionality,CosinePpTurbine
implements results of yaw misalignment. Check tests pass.Completion criteria
Still to do:
axial induction modelsHandling for rotor averaging methodArchitecture
Architecture of new turbine module within floris.simulation (and main connections to other parts of code). Arrows indicate where a function, method, or class is used by something upstream of it (i.e., if
b
points toa
, thena
calls/usesb
)Further discussion needed (not included in this PR)
To discuss further:
"multidim_cp_ct"
velocity model be removed to allow the user to use any velocity deficit model? Likely yes, but will be it's own PR