Skip to content

Commit

Permalink
Documentation improvements and fixes (#853)
Browse files Browse the repository at this point in the history
* Increase contour levels

* Rename the introductory notebook

* Add a documentation page for advanced concepts

* Update the architecture diagrams

Some details were out of date

* Add guidance for extending the wake models

This came from this discussion thread: #547

* Remove custom templates for api docs

* Unpin the docs dependencies

* Remove napoleon and sphinx_book_theme config
  • Loading branch information
rafmudaf authored Mar 26, 2024
1 parent 4b33139 commit faba989
Show file tree
Hide file tree
Showing 14 changed files with 1,255 additions and 1,139 deletions.
5 changes: 1 addition & 4 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,8 @@ sphinx:
- 'sphinx.ext.viewcode'
- 'sphinx_autodoc_typehints'
- 'sphinxcontrib.autoyaml'
- 'sphinx.ext.napoleon' # Formats google and numpy docstring styles
- 'sphinxcontrib.mermaid'
config:
html_theme: sphinx_book_theme
templates_path:
- '_templates'
language: 'python'
nb_execution_show_tb: true # Shows the stack trace in stdout; its suppressed otherwise.
nb_execution_raise_on_error: true # Stops the Sphinx build if there is an error in a notebook. See https://github.com/executablebooks/jupyter-book/issues/2011
Expand All @@ -74,3 +70,4 @@ sphinx:
# class-doc-from
# no-value
autodoc_typehints: both
mermaid_version: "10.8"
34 changes: 0 additions & 34 deletions docs/_templates/custom-class-template.rst

This file was deleted.

66 changes: 0 additions & 66 deletions docs/_templates/custom-module-template.rst

This file was deleted.

3 changes: 2 additions & 1 deletion docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ parts:

- caption: User Reference
chapters:
- file: floris_101
- file: intro_concepts
- file: advanced_concepts
- file: floating_wind_turbine
- file: turbine_interaction
- file: input_reference_main
Expand Down
132 changes: 132 additions & 0 deletions docs/advanced_concepts.ipynb

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions docs/api_docs.rst → docs/api_docs.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
API Documentation
=================
# API Documentation

FLORIS is divided into two primary packages.
:py:mod:`floris.simulation` is the core code that models the wind turbines
and wind farms. It is low-level code that generally is nto accessed
by typical users. :py:mod:`floris.tools` is the set of analysis routines
{py:mod}`floris.simulation` is the core code that models the wind turbines
and wind farms. It is low-level code that generally is not accessed
by typical users. {py:mod}`floris.tools` is the set of analysis routines
that define, drive, and post process a simulation. This is where
more users will interface with the software.

```{eval-rst}
.. autosummary::
:toctree: _autosummary
:template: custom-module-template.rst
:recursive:
floris.logging_manager
Expand All @@ -19,3 +18,4 @@ more users will interface with the software.
floris.type_dec
floris.turbine_library
floris.utilities
```
58 changes: 32 additions & 26 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ be violated, and ongoing work should strive to meet these ideas and expand on th
as possible.

- Modularity in wake model formulation:
- New mathematical formulation should be straightforward to incorporate.
- Requisite solver and grid data structures should not conflict with other existing
wake models.
- New mathematical formulation should be straightforward to incorporate by non-expert
software developers.
- Solver and grid data structures for one wake model should not conflict with the data
structures for other wake models.
- Any new feature or work should not affect an existing feature:
- Low level code should be reused as much as possible, but high level code should rarely
be repurposed.
Expand All @@ -31,12 +32,12 @@ packages. The internal structure and hierarchy is described below.
```{mermaid}
classDiagram
class tools {
+FlorisInterface
class simulation["floris.simulation"] {
+Floris
}
class simulation {
+Floris
class tools["floris.tools"] {
+FlorisInterface
}
class logging_manager
Expand All @@ -45,9 +46,7 @@ classDiagram
tools <-- logging_manager
simulation <-- logging_manager
tools <-- type_dec
simulation <-- type_dec
tools <-- utilities
simulation <-- utilities
tools <-- simulation
```
Expand Down Expand Up @@ -75,54 +74,61 @@ classDiagram
class Farm
class FlowField {
array u
array v
array w
u: NDArrayFloat
v: NDArrayFloat
w: NDArrayFloat
}
class Grid {
<<interface>>
x: NDArrayFloat
y: NDArrayFloat
z: NDArrayFloat
}
class TurbineGrid
class TurbineCubatureGrid
class FlowFieldPlanarGrid
class PointsGrid
class WakeModelManager {
<<interface>>
}
class WakeCombination {
dict parameters
parameters: dict
function()
}
class WakeDeflection {
dict parameters
parameters: dict
function()
}
class WakeTurbulence {
dict parameters
parameters: dict
function()
}
class WakeVelocity {
dict parameters
parameters: dict
function()
}
class Solver {
<<interface>>
dict parameters
parameters: dict
}
Floris o-- Farm
Floris o-- FlowField
Floris o-- Grid
Floris o-- WakeModelManager
Floris *-- Solver
WakeModelManager o-- WakeCombination
WakeModelManager o-- WakeDeflection
WakeModelManager o-- WakeTurbulence
WakeModelManager o-- WakeVelocity
Floris *-- Farm
Floris *-- FlowField
Floris *-- Grid
Floris *-- WakeModelManager
Floris --> Solver
WakeModelManager *-- WakeCombination
WakeModelManager *-- WakeDeflection
WakeModelManager *-- WakeTurbulence
WakeModelManager *-- WakeVelocity
Grid <|-- TurbineGrid
Grid <|-- TurbineCubatureGrid
Grid <|-- FlowFieldPlanarGrid
Grid <|-- PointsGrid
Solver --> Farm
Solver --> FlowField
Expand Down
116 changes: 116 additions & 0 deletions docs/dev_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,119 @@ Be sure to complete each step in the sequence as described.
Generally, only NREL developers will have appropriate permissions to deploy
FLORIS updates. When the time comes, here is a great reference on doing it
is available [here](https://medium.freecodecamp.org/how-to-publish-a-pyton-package-on-pypi-a89e9522ce24).
## Extending the models
The FLORIS architecture is designed to support adding new wake models relatively easily.
Each of the following components have a general API that support plugging in to the rest of the
FLORIS framework:
- Velocity deficit
- Wake deflection
- Added turbulence due to the turbine wake
- Wake combination
- Solver algorithm
- Grid-points
Initially, it's recommended to copy an existing model as a starting point, and the
[Jensen](https://github.com/NREL/floris/blob/main/floris/simulation/wake_velocity/jensen.py) and
[Jimenez](https://github.com/NREL/floris/blob/main/floris/simulation/wake_deflection/jimenez.py)
models are good choices due to their simplicity.
New models must be registered in
[Wake.model_map](https://github.com/NREL/floris/blob/main/floris/simulation/wake.py#L45)
so that they can be enabled via the input dictionary.

```{mermaid}
classDiagram
class Floris
class Farm
class FlowField {
u: NDArrayFloat
v: NDArrayFloat
w: NDArrayFloat
}
class Grid {
<<interface>>
x: NDArrayFloat
y: NDArrayFloat
z: NDArrayFloat
}
class WakeModelManager {
<<interface>>
combination_model: BaseModel
deflection_model: BaseModel
velocity_model: BaseModel
turbulence_model: BaseModel
}
class Solver {
<<interface>>
parameters: dict
}
class BaseModel {
prepare_function() dict
function() None
}
Floris *-- Farm
Floris *-- FlowField
Floris *-- Grid
Floris *-- WakeModelManager
Floris --> Solver
Solver --> Farm
Solver --> FlowField
Solver --> Grid
Solver --> WakeModelManager
WakeModelManager -- BaseModel
style Grid stroke:#FF496B, stroke-width:2px
style WakeModelManager stroke:#FF496B, stroke-width:2px
style Solver stroke:#FF496B, stroke-width:2px
```
All of the models have a `prepare_function` and a `function` method.
The `prepare_function` allows the model classes to extract any information from the `Grid` and
`FlowField` data structures, and this is generally used for sizing the data arrays.
The `prepare_function` should return a dictionary that will ultimately be passed to the
`function`.
The `function` method is where the actual calculation is performed.
The API is dependent on the type of model, but generally it requires some indicationg of
the location of the current turbine in the solve step and some other information about the
atmospheric conditions and operation of the turbine.
Note the `*` in the function signature, which is a Python feature that allows
any number of arguments to be passed to the function after the `*` as keyword arguments.
Typically, these arguments are the ones returned from the `prepare_function`.
```python
def prepare_function(self, grid: Grid, flow_field: FlowField) -> Dict[str, Any]
def function(
self,
x_i: np.ndarray,
y_i: np.ndarray,
z_i: np.ndarray,
axial_induction_i: np.ndarray,
deflection_field_i: np.ndarray,
yaw_angle_i: np.ndarray,
turbulence_intensity_i: np.ndarray,
ct_i: np.ndarray,
hub_height_i: np.ndarray,
rotor_diameter_i: np.ndarray,
*,
variables_from_prepare_function: dict
) -> None:
```
Some models require a special grid and/or solver, and that mapping happens in
[floris.simulation.Floris](https://github.com/NREL/floris/blob/main/floris/simulation/floris.py#L145).
Generally, a specific kind of solver requires one or a number of specific grid-types.
For example, `full_flow_sequential_solver` requires either `FlowFieldGrid` or
`FlowFieldPlanarGrid`.
So, it is often the case that adding a new solver will require adding a new grid type, as well.
Loading

0 comments on commit faba989

Please sign in to comment.