{ "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. They should contain the following coordinates:\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\n", "import foxes.constants as FC" ] }, { "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", " pre_load=True,\n", " bounds_error=False,\n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Note that it is recommended that the `states` object should be created outside the `DaskRunner` 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": [ "mbook = foxes.ModelBook()\n", "\n", "algo = foxes.algorithms.Downwind(\n", " mbook,\n", " farm,\n", " states=states,\n", " rotor_model=\"grid16\",\n", " wake_models=[\"Jensen_linear_k007\"],\n", " wake_frame=\"streamlines_100\",\n", " partial_wakes_model=\"auto\",\n", " chunks={FC.STATE: 1000, FC.POINT: 4000},\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": "foxes", "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.8.10" }, "vscode": { "interpreter": { "hash": "4fb778166dae186e4d4cfa777e9f30c32eb0bc447af40b9aef55a0c1baf561be" } } }, "nbformat": 4, "nbformat_minor": 2 }