diff --git a/.gitignore b/.gitignore index 14c5a9ac64d55f7181966bff6cb3a83db67cd4d7..4529688adbfc84bf8e59c8d4c045cc972a0576f0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /.pydevproject /cost_models/fuga/pascal_test snopt +*.png # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/docs/source/conf.py b/docs/source/conf.py index 7399b447073caf7c9546ac16b03e710b87d19f98..a88631be76c9fa73ab4cea52408f66a5478bd050 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,9 +17,6 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ @@ -180,3 +177,5 @@ intersphinx_mapping = { 'pandas': ('http://pandas-docs.github.io/pandas-docs-travis', None), 'numpy': ('http://docs.scipy.org/doc/numpy-1.13.0', None) } + +figure_language_filename = 'examples/{basename}{ext}' diff --git a/docs/source/dev_guide/quick_guide.rst b/docs/source/dev_guide/quick_guide.rst deleted file mode 100644 index 09203e2a8a7f38fe177a7f752514f259c8fa5e57..0000000000000000000000000000000000000000 --- a/docs/source/dev_guide/quick_guide.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _quick_guide: - -======================= -Quick Reference -======================= - -1. Do this first. -2. Then do this. -3. Lastly, this. diff --git a/docs/source/examples.rst b/docs/source/examples.rst deleted file mode 100644 index 7cdd42fe9368f68ba23a1e99bf770ef7d997c2b8..0000000000000000000000000000000000000000 --- a/docs/source/examples.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _examples: - -=========================== -Examples -=========================== - -Eventually we would like to have several TOPFARM examples here to demonstrate -how you can use the code. diff --git a/docs/source/examples/example_1_constrained_layout_optimization.rst b/docs/source/examples/example_1_constrained_layout_optimization.rst new file mode 100644 index 0000000000000000000000000000000000000000..149f9e11802c7c59fb7c7b52613bbd0d955c8843 --- /dev/null +++ b/docs/source/examples/example_1_constrained_layout_optimization.rst @@ -0,0 +1,36 @@ +.. Example 1 + +Example 1: Constrained Layout Optimization +=========================================== + +This example demonstrates the optimization of a wind turbine layout that is +subject to boundary constraints. + +Specifications +-------------- + +- The cost function is a dummy function that penalizes the turbines when they + are far away from pre-specified, desired positions. +- There is a boundary beyond which the turbines cannot go. +- The turbines cannot be closer than 2D. + +Results +------- + +The optimization results are visualized in the figure below. The turbines' +trajectories during the optimizations are shown by the colored lines. + +- All turbines that begin outside the boundary immediately jump inside the + boundary. +- Turbines 1 and 3 rotate around each other as they try to reach their + specified final locations but stay at least 2D away from each other. +- Turbine 2 remains on the boundary but tries to minimize its distance to + its specified final location. +- Turbine 4 converges to its specified location. + +.. figure:: /../../examples/example_1_constrained_layout_optimization.png + +Code +---- + +.. literalinclude:: /../../examples/example_1_constrained_layout_optimization.py diff --git a/docs/source/index.rst b/docs/source/index.rst index 6f30b010d65e79bd8c7a1b520d5a9f466957703f..7757c90e4a5f4f9838493c86e5294421d2aa4080 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,13 +10,9 @@ Welcome to TOPFARM, the wind-farm optimizer :maxdepth: 2 installation - examples +.. toctree:: + :caption: Examples + :maxdepth: 2 - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + examples/example_1_constrained_layout_optimization diff --git a/examples/example_1_constrained_layout_optimization.py b/examples/example_1_constrained_layout_optimization.py new file mode 100644 index 0000000000000000000000000000000000000000..99c761d6a65491336a977492b072fcdb54722bbd --- /dev/null +++ b/examples/example_1_constrained_layout_optimization.py @@ -0,0 +1,74 @@ +"""Example: optimizing a layout with constraints + +This example uses a dummy cost function to optimize a simple wind turbine +layout that is subject to constraints. The optimization pushes the wind turbine +locations to specified locations in the farm. +""" +import os + +from matplotlib.patches import Polygon +import matplotlib.pyplot as plt +import numpy as np + +from topfarm import TopFarm +from topfarm.cost_models.dummy import DummyCost + + +# ------------------------ INPUTS ------------------------ + +# define the conditions for the wind farm +boundary = [(0, 0), (6, 0), (6, -10), (0, -10)] # turbine boundaries +initial = np.array([[6, 0], [6, -8], [1, 1], [-1, -8]]) # initial turbine pos +desired = np.array([[3, -3], [7, -7], [4, -3], [3, -7]]) # desired turbine pos +optimal = np.array([[2.5, -3], [6, -7], [4.5, -3], [3, -7]]) # optimal layout +min_spacing = 2 # min distance between turbines + +# ------------------------ OPTIMIZATION ------------------------ + +# create the wind farm and run the optimization +tf = TopFarm(initial, DummyCost(desired, ['turbineX', 'turbineY']), + min_spacing, boundary=boundary, record_id=None) +cost, state, recorder = tf.optimize() + +# get the positions tried during optimization from the recorder +rec_x, rec_y = recorder.get('turbineX'), recorder.get('turbineY') + +# get the final, optimal positions +optimized = tf.turbine_positions + +# ------------------------ PLOT (if possible) ------------------------ + +try: + + # initialize the figure and axes + fig = plt.figure(1, figsize=(7, 5)) + plt.clf() + ax = plt.axes() + + # plot the boundary and desired locations + ax.add_patch(Polygon(boundary, closed=True, fill=False, + label='Boundary')) # boundary + plt.plot(desired[:, 0], desired[:, 1], 'ok', mfc='None', ms=10, + label='Desired') # desired positions + + # plot the history of each turbine + for i_turb in range(rec_x.shape[1]): + l, = plt.plot(rec_x[0, i_turb], rec_y[0, i_turb], + 'x', ms=8, label=f'Turbine {i_turb+1}') # initial + plt.plot(rec_x[:, i_turb], rec_y[:, i_turb], + c=l.get_color()) # tested values + plt.plot(rec_x[-1, i_turb], rec_y[-1, i_turb], + 'o', ms=8, c=l.get_color()) # final + + # make a few adjustments to the plot + ax.autoscale_view() # autoscale the boundary + plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, + ncol=4, mode='expand', borderaxespad=0.) # add a legend + plt.tight_layout() # zoom the plot in + plt.axis('off') # remove the axis + + # save the png + fig.savefig(os.path.basename(__file__).replace('.py', '.png')) + +except RuntimeError: + pass diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000000000000000000000000000000000000..cdc9c412e7180d995e18cbde71ee3cb400e1a316 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +# add example_*.py files to those that pytest should test +[tool:pytest] +python_files = test_*.py *_test.py testing/*/*.py example_*.py \ No newline at end of file