{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Heterogeneous flow" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The best way to run `foxes` calculations on heterogeneous background flow fields is by providing them in `netCDF` format. The following coordinates are supported (can be `None` if not present):\n", "\n", "- A state coordinate, e.g. `Time` (expected by default) or `state`, or similar\n", "- A height coordinate, e.g. `height` (expected by default) or `h`, or similar\n", "- A `y` coordinate, e.g. `UTMY` (expected by default) or `y`, or similar\n", "- A `x` coordinate, e.g. `UTMX` (expected by default) or `x`, or similar\n", "\n", "The file may contain any kind of `foxes` variables as data fields, e.g.:\n", "\n", "- Wind speed data, e.g. `WS` (expected by default, if claimed as output variable), `ws` or similar\n", "- Wind direction data, e.g. `WD` (expected by default, if claimed as output variable), `wd` or similar\n", "- Turbulence intensity data, e.g. `TI` (expected by default, if claimed as output variable), `ti` or similar\n", "- Air density data, e.g. `RHO` (expected by default, if claimed as output variable), `rho` or similar\n", "\n", "All data must depend on the state coordinate, and may depend on the others." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "These are the required imports for this example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "import foxes\n", "import foxes.variables as FV" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "One very simple example for `netCDF` type data is provided in the static data, under the name `wind_rotation.nc`. It contains two states, two heights, and simple 2 x 2 horizontal data that describes identical wind speeds at all four corner points associated with different wind direction values. It can be loaded as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "states = foxes.input.states.FieldDataNC(\n", " data_source=\"wind_rotation.nc\",\n", " states_coord=\"state\",\n", " x_coord=\"x\",\n", " y_coord=\"y\",\n", " h_coord=\"h\",\n", " time_format=None,\n", " output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],\n", " var2ncvar={FV.WS: \"ws\", FV.WD: \"wd\"},\n", " fixed_vars={FV.RHO: 1.225, FV.TI: 0.1},\n", " load_mode=\"preload\",\n", " bounds_error=False,\n", " bounds_extra_space=1000,\n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The `bounds_extra_space` parameter is here set to 1000 meters. Alternatively, distances can be specified as multiples of the rotor diameter as string, e.g., `2D`. If not `None` this cuts the input data spatially to the specified extension of the wind farm boundary area.\n", "\n", "Note that it is recommended that the `states` object should be created outside the `Engine` context when working with NetCFD input." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Now back to our example. Let's place a simple 3 x 3 grid wind farm inside the data domain, which is a rectangle between `(0, 0)` and `(2500, 2500)`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "farm = foxes.WindFarm()\n", "foxes.input.farm_layout.add_grid(\n", " farm,\n", " xy_base=np.array([500.0, 500.0]),\n", " step_vectors=np.array([[500.0, 0], [0, 500.0]]),\n", " steps=(3, 3),\n", " turbine_models=[\"NREL5MW\"],\n", " verbosity=0,\n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The streamline following wakes are realized by selecting a `wake frame` that is an instance of `foxes.models.wake_frames.Streamlines`, e.g. the model `streamlines_100` in the model book. This model has a streamline step size of 100 m:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "algo = foxes.algorithms.Downwind(\n", " farm,\n", " states,\n", " rotor_model=\"grid16\",\n", " wake_models=[\"Jensen_linear_k007\"],\n", " wake_frame=\"streamlines_100\",\n", " verbosity=0,\n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We run the algorithm, once explicitely for calculating the wind farm data, and once implicitely when creating horizontal flow plots:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "farm_results = algo.calc_farm()\n", "\n", "fr = farm_results.to_dataframe()\n", "print(fr[[FV.WD, FV.AMB_REWS, FV.REWS, FV.AMB_P, FV.P]])\n", "\n", "o = foxes.output.FlowPlots2D(algo, farm_results)\n", "for fig in o.gen_states_fig_xy(\n", " FV.WS,\n", " resolution=10,\n", " figsize=(8, 8),\n", " quiver_pars=dict(angles=\"xy\", scale_units=\"xy\", scale=0.07),\n", " quiver_n=15,\n", " xmin=0,\n", " xmax=2500,\n", " ymin=0,\n", " ymax=2500,\n", "):\n", " plt.show()\n", " plt.close(fig)" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 4 }