{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Wind rose data" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Here we demonstrate how mean results over wind rose data are calculated in `foxes`. We need the following imports:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "\n", "import foxes\n", "import foxes.variables as FV\n", "import foxes.constants as FC" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "First, we setup the model book and the wind farm. We choose 6 x 5 turbines on a regular grid:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "mbook = foxes.ModelBook()\n", "\n", "farm = foxes.WindFarm()\n", "foxes.input.farm_layout.add_grid(\n", " farm=farm,\n", " xy_base=[0.0, 0.0],\n", " step_vectors=[[900.0, 50.0], [-80., 500.0]],\n", " steps=[6, 5],\n", " turbine_models=[\"NREL5MW\", \"kTI_05\"],\n", " verbosity=0\n", ")\n", "\n", "ax = foxes.output.FarmLayoutOutput(farm).get_figure(figsize=(4, 3))\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Next, we create the states based on the static data file `wind_rose_bremen.csv.gz`. The data represents a (coarse) wind rose with 216 states. Each of them consists of the wind direction and wind speed bin centres, and the respective statistical weight of the bin (normalized such that 1 represents 100%):\n", "```\n", "state,wd,ws,weight\n", "0,0.0,3.5,0.00158\n", "1,0.0,6.0,0.00244\n", "2,0.0,8.5,0.00319\n", "3,0.0,12.5,0.0036700002\n", "4,0.0,17.5,0.00042\n", "...\n", "```\n", "Let's create the states object and have a look at the wind rose:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "states = foxes.input.states.StatesTable(\n", " data_source=\"wind_rose_bremen.csv\",\n", " output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],\n", " var2col={FV.WS: \"ws\", FV.WD: \"wd\", FV.WEIGHT: \"weight\"},\n", " fixed_vars={FV.RHO: 1.225, FV.TI: 0.05},\n", ")\n", "\n", "o = foxes.output.StatesRosePlotOutput(states, point=[0., 0., 100.])\n", "fig = o.get_figure(16, FV.AMB_WS, [0, 3.5, 6, 10, 15, 20], figsize=(6, 6))\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can now setup our algorithm. In this example, we invoke one wake model for the wind deficit, `Bastankhah_linear` (with linear wake superposition), and another for the turbulence intensity wake effect, `CrespoHernandez_max` (with maximum wake superposition). Both obtain the wake growth parameter `k` by a relation `k = 0.5 * TI`, see `turbine_models` choice in the wind farm setup." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "algo = foxes.algorithms.Downwind(\n", " mbook,\n", " farm,\n", " states=states,\n", " rotor_model=\"centre\",\n", " wake_models=[\"Bastankhah2014_linear\", \"CrespoHernandez_max\"],\n", " wake_frame=\"rotor_wd\",\n", " partial_wakes_model=\"auto\",\n", " chunks={FC.STATE: 500, FC.POINT: 4000},\n", " verbosity=0,\n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We can now calculate the results:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with foxes.utils.runners.DaskRunner() as runner:\n", " farm_results = runner.run(algo.calc_farm)\n", "\n", "o = foxes.output.FarmResultsEval(farm_results)\n", "o.add_efficiency()\n", "\n", "fig, axs = plt.subplots(2,1,figsize=(6, 7))\n", "o = foxes.output.FarmLayoutOutput(farm, farm_results)\n", "o.get_figure(fig=fig, ax=axs[0], color_by=\"mean_REWS\", title=\"Mean REWS [m/s]\", s=150, annotate=0)\n", "o.get_figure(fig=fig, ax=axs[1], color_by=\"mean_EFF\", title=\"Mean efficiency [%]\", s=150, annotate=0)\n", "plt.show()\n", "\n", "o = foxes.output.FarmResultsEval(farm_results)\n", "P0 = o.calc_mean_farm_power(ambient=True)\n", "P = o.calc_mean_farm_power()\n", "print(f\"\\nFarm power : {P/1000:.1f} MW\")\n", "print(f\"Farm ambient power: {P0/1000:.1f} MW\")\n", "print(f\"Farm efficiency : {o.calc_farm_efficiency()*100:.2f} %\")\n", "print(f\"Annual farm yield : {o.calc_farm_yield(algo=algo):.2f} GWh\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we display the mean wind speed field as a 2D plot, including wake effects. We could simply do this by\n", "\n", "```python\n", "o = foxes.output.FlowPlots2D(algo, farm_results)\n", "o.get_mean_fig_xy(FV.WS, resolution=30)\n", "plt.show()\n", "```\n", "\n", "This is perfectly fine, but if we wish to see a progress bar and have additional options for the parallel run on a cluster (which we are not using here), the output function should instead be passed to a `DaskRunner` object:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with foxes.utils.runners.DaskRunner() as runner:\n", " o = foxes.output.FlowPlots2D(algo, farm_results, runner=runner)\n", " o.get_mean_fig_xy(FV.WS, resolution=30)\n", " plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Note that for the vectorization/parallelization to work we need to set the `chunks` arguments in the creation of the `Algorithm` object. Here chunks of 4000 points were calculated at a time (for all states)." ] } ], "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 }