Skip to content

Commit

Permalink
Support initializing FLORIS with default values (#1040)
Browse files Browse the repository at this point in the history
* Support initializing with defaults

* Add docs for using FLORIS as a library

* Fix defaults data types

* Require setting the atmospheric conditions

* Store defaults in a YAML file

Allows for using this file in other areas of the software

* Add a function to display the input configs

* Add back print_dict as a wrapper for show_config to avoid breaking user interface changes.

---------

Co-authored-by: misi9170 <[email protected]>
  • Loading branch information
rafmudaf and misi9170 authored Feb 5, 2025
1 parent e6bbd6e commit 47cbb29
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 19 deletions.
136 changes: 134 additions & 2 deletions docs/advanced_concepts.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,148 @@
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## FLORIS as a library\n",
"\n",
"FLORIS is commonly used as a library in other software packages.\n",
"In cases where the calling-code will create inputs for FLORIS rather than require them from the\n",
"user, it can be helpful to initialize the FLORIS model with default inputs and then\n",
"change them in code.\n",
"In this case, the following workflow is recommended."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": []
"source": [
"import floris\n",
"\n",
"# Initialize FLORIS with defaults\n",
"fmodel = floris.FlorisModel(\"defaults\")\n",
"\n",
"# Within the calling-code's setup step, update FLORIS as needed\n",
"fmodel.set(\n",
" wind_directions=[i for i in range(10)],\n",
" wind_speeds=[5 + i for i in range(10)],\n",
" turbulence_intensities=[i for i in range(10)],\n",
" # turbine_library_path=\"path/to/turbine_library\", # Shown here for reference\n",
" # turbine_type=[\"my_turbine\"]\n",
")\n",
"\n",
"# Within the calling code's computation, run FLORIS\n",
"fmodel.run()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Alternatively, the calling-code can import the FLORIS default inputs as a Python dictionary\n",
"and modify them directly before initializing the FLORIS model.\n",
"This is especially helpful when the calling-code will modify a parameter that isn't\n",
"supported by the `FlorisModel.set(...)` command.\n",
"In particular, the wake model parameters are not directly accessible, so these can be updated\n",
"externally, as shown below.\n",
"Note that the `FlorisModel.get_defaults()` function returns a deep copy of the default inputs,\n",
"so these can be modified directly without side effects."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"solver\n",
" type\n",
" turbine_grid\n",
" turbine_grid_points\n",
" 3\n",
"wake\n",
" model_strings\n",
" combination_model\n",
" sosfs\n",
" deflection_model\n",
" gauss\n",
" turbulence_model\n",
" crespo_hernandez\n",
" velocity_model\n",
" jensen\n",
"farm\n",
" layout_x\n",
" [0.0]\n",
" layout_y\n",
" [0.0]\n",
" turbine_type\n",
" ['nrel_5MW']\n",
" turbine_library_path\n",
" /Users/rmudafor/Development/floris/floris/turbine_library\n",
"flow_field\n",
" wind_speeds\n",
" [5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0]\n",
" wind_directions\n",
" [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]\n",
" wind_veer\n",
" 0.0\n",
" wind_shear\n",
" 0.12\n",
" air_density\n",
" 1.225\n",
" turbulence_intensities\n",
" [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]\n",
" reference_wind_height\n",
" 90.0\n",
"name\n",
" GCH\n",
"description\n",
" Default initialization: Gauss-Curl hybrid model (GCH)\n",
"floris_version\n",
" v4\n"
]
}
],
"source": [
"import floris\n",
"\n",
"# Retrieve the default parameters\n",
"fdefaults = floris.FlorisModel.get_defaults()\n",
"\n",
"# Update wake model parameters\n",
"fdefaults[\"wake\"][\"model_strings\"][\"velocity_model\"] = \"jensen\"\n",
"fdefaults[\"wake\"][\"wake_velocity_parameters\"][\"jensen\"][\"we\"] = 0.05\n",
"\n",
"# Initialize FLORIS with modified parameters\n",
"fmodel = floris.FlorisModel(configuration=fdefaults)\n",
"\n",
"# Within the calling-code's setup step, update FLORIS as needed\n",
"fmodel.set(\n",
" wind_directions=[i for i in range(10)],\n",
" wind_speeds=[5 + i for i in range(10)],\n",
" turbulence_intensities=[i for i in range(10)],\n",
" # turbine_library_path=\"path/to/turbine_library\", # Shown here for reference\n",
" # turbine_type=[\"my_turbine\"]\n",
")\n",
"\n",
"# Verify settings are correct\n",
"fmodel.show_config() # Shows truncated set of inputs; show all with fmodel.show_config(full=True)\n",
"\n",
"# Within the calling code's computation, run FLORIS\n",
"fmodel.run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
Expand Down
106 changes: 106 additions & 0 deletions floris/default_inputs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

name: GCH
description: "Default initialization: Gauss-Curl hybrid model (GCH)"
floris_version: v4

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

solver:
type: turbine_grid
turbine_grid_points: 3

farm:
layout_x:
- 0.0
layout_y:
- 0.0
turbine_type:
- nrel_5MW

flow_field:
air_density: 1.225
reference_wind_height: -1
turbulence_intensities: []
wind_directions: []
wind_shear: 0.12
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: true
enable_yaw_added_recovery: true
enable_transverse_velocities: true
enable_active_wake_mixing: 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
empirical_gauss:
horizontal_deflection_gain_D: 3.0
vertical_deflection_gain_D: -1
deflection_rate: 22
mixing_gain_deflection: 0.0
yaw_added_mixing_gain: 0.0

wake_velocity_parameters:
gauss:
alpha: 0.58
beta: 0.077
ka: 0.38
kb: 0.004
jensen:
we: 0.05
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
turbopark:
A: 0.04
sigma_max_rel: 4.0
turboparkgauss:
A: 0.04
include_mirror_wake: True
empirical_gauss:
wake_expansion_rates: [0.023, 0.008]
breakpoints_D: [10]
sigma_0_D: 0.28
smoothing_length_D: 2.0
mixing_gain_velocity: 2.0
awc_wake_exp: 1.2
awc_wake_denominator: 400

wake_turbulence_parameters:
crespo_hernandez:
initial: 0.1
constant: 0.5
ai: 0.8
downstream: -0.32
wake_induced_mixing:
atmospheric_ti_gain: 0.0
31 changes: 29 additions & 2 deletions floris/floris_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
NDArrayStr,
)
from floris.utilities import (
load_yaml,
nested_get,
nested_set,
print_nested_dict,
Expand Down Expand Up @@ -63,7 +64,15 @@ class FlorisModel(LoggingManager):
- **logging**: See `floris.simulation.core.Core` for more details.
"""

@staticmethod
def get_defaults() -> dict:
return copy.deepcopy(load_yaml(Path(__file__).parent / "default_inputs.yaml"))

def __init__(self, configuration: dict | str | Path):

if configuration == "defaults":
configuration = FlorisModel.get_defaults()

self.configuration = configuration

if isinstance(self.configuration, (str, Path)):
Expand Down Expand Up @@ -1627,11 +1636,29 @@ def get_turbine_layout(self, z=False):
else:
return xcoords, ycoords

def print_dict(self) -> None:
def show_config(self, full=False) -> None:
"""Print the FlorisModel dictionary.
"""
print_nested_dict(self.core.as_dict())
config_dict = self.core.as_dict()
if not full:
del config_dict["logging"]
del config_dict["wake"]["enable_secondary_steering"]
del config_dict["wake"]["enable_yaw_added_recovery"]
del config_dict["wake"]["enable_transverse_velocities"]
del config_dict["wake"]["enable_active_wake_mixing"]
del config_dict["wake"]["wake_deflection_parameters"]
del config_dict["wake"]["wake_velocity_parameters"]
del config_dict["wake"]["wake_turbulence_parameters"]
print_nested_dict(config_dict)

def print_dict(self) -> None:
"""Print the FlorisModel dictionary.
"""
self.logger.warning(
"The print_dict() method has been deprecated."
" Please use the show_config() method instead."
)
self.show_config(full=True)

### Properties

Expand Down
28 changes: 14 additions & 14 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ description = "A controls-oriented engineering wake model."
readme = "README.md"
requires-python = ">=3.9"
authors = [
{ name = "Rafael Mudafort", email = "rafael.mudafort@nrel.gov" },
{ name = "Paul Fleming", email = "paul.fleming@nrel.gov" },
{ name = "Rafael Mudafort", email = "Rafael.Mudafort@nrel.gov" },
{ name = "Paul Fleming", email = "Paul.Fleming@nrel.gov" },
{ name = "Michael (Misha) Sinner", email = "[email protected]" },
{ name = "Eric Simley", email = "[email protected]" },
{ name = "Christopher Bay", email = "[email protected]" },
]
license = { file = "LICENSE.txt" }
keywords = ["floris"]
classifiers = [
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy"
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy"
]
dependencies = [
"attrs",
Expand Down Expand Up @@ -63,7 +63,8 @@ include = ["floris*"]
[tool.setuptools.package-data]
floris = [
"turbine_library/*.yaml",
"core/wake_velocity/turbopark_lookup_table.mat"
"core/wake_velocity/turbopark_lookup_table.mat",
"default_inputs.yaml"
]

[project.urls]
Expand All @@ -76,7 +77,6 @@ Documentation = "https://nrel.github.io/floris/"
branch = true
source = "floris/*"
omit = [
"setup.py",
"tests/*"
]

Expand Down
Loading

0 comments on commit 47cbb29

Please sign in to comment.