External Drivers
OpenMDAO supports multiple external optimization libraries like Scipy, pyOptSparse, modOpt and pymoo. These are also available in Topfarm if the underlying libraries have heen installed. In this notebook we look at how drivers from external libraries are coupled to your Topfarm Problem.
Install TOPFARM if needed
[1]:
# Install TopFarm if needed
import importlib
if not importlib.util.find_spec("pyoptsparse"):
%pip install git+https://github.com/mdolab/pyoptsparse
import pyoptsparse
pyoptsparse.__version__ = "999"
if not importlib.util.find_spec("topfarm"):
%pip install git+https://gitlab.windenergy.dtu.dk/TOPFARM/TopFarm2.git
if not importlib.util.find_spec("modopt"):
%pip install "modopt[open_source_optimizers] @ git+https://github.com/lsdolab/modopt.git@65c7e272b8d75b39c9360c15a95deb3d70753958"
if not importlib.util.find_spec("pymoo"):
%pip install pymoo
%pip install openmdao>=3.44
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
Note: you may need to restart the kernel to use updated packages.
[2]:
import matplotlib
try: get_ipython().run_line_magic("matplotlib", "widget")
except: matplotlib.use("Agg")
[3]:
from topfarm.cost_models.dummy import DummyCost, DummyCostPlotComp
from topfarm.constraint_components.spacing import SpacingConstraint
from topfarm.constraint_components.boundary import XYBoundaryConstraint
from topfarm.easy_drivers import EasyScipyOptimizeDriver, EasySimpleGADriver, EasyDriverBase, EasySGDDriver, EasyRandomSearchDriver
from topfarm import TopFarmProblem
from topfarm.drivers.random_search_driver import RandomizeTurbinePosition_Circle
from topfarm.plotting import NoPlot
from topfarm.utils import plot_list_recorder
import numpy as np
import openmdao.api as om
Problem definition
First we set up the Topfarm Problem, and then we see how each optimization driver is configured.
[4]:
initial = np.array([[6, 0], [6, -8], [1, 1]]) # initial turbine layouts
optimal = np.array([[2.5, -3], [6, -7], [4.5, -3]]) # optimal turbine layouts
boundary = np.array([(0, 0), (6, 0), (6, -10), (0, -10)]) # turbine boundaries
desired = np.array([[3, -3], [7, -7], [4, -3]]) # desired turbine layouts
plot_comp = DummyCostPlotComp(optimal)
tf = TopFarmProblem(
design_vars=dict(zip('xy', initial.T)),
cost_comp=DummyCost(optimal_state=desired, inputs=['x', 'y']),
constraints=[XYBoundaryConstraint(boundary),
SpacingConstraint(2)
],
plot_comp=plot_comp
)
Scipy
[5]:
tf.driver = om.ScipyOptimizeDriver()
tf.driver.options['optimizer'] = 'SLSQP'
tf.driver.options['tol'] = 1e-9
tf.driver.options['disp'] = True
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
<Figure size 640x480 with 1 Axes>
Optimization terminated successfully (Exit mode 0)
Current function value: 1.500000000116204
Iterations: 16
Function evaluations: 21
Gradient evaluations: 16
Optimization Complete
-----------------------------------
[5]:
np.float64(1.500000000116204)
pyOptSparse
[6]:
tf.driver = om.pyOptSparseDriver(optimizer='SLSQP')
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
<Figure size 640x480 with 1 Axes>
Optimization Problem -- Optimization using pyOpt_sparse
================================================================================
Objective Function: _objfunc
Solution:
--------------------------------------------------------------------------------
Total Time: 1.5470
User Objective Time : 1.3985
User Sensitivity Time : 0.0313
Interface Time : 0.0135
Opt Solver Time: 0.1036
Calls to Objective Function : 19
Calls to Sens Function : 14
Objectives
Index Name Value
0 final_cost 1.500000E+00
Variables (c - continuous, i - integer, d - discrete)
Index Name Type Lower Bound Value Upper Bound Status
0 x_0 c 0.000000E+00 2.500026E+00 6.000000E+00
1 x_1 c 0.000000E+00 6.000000E+00 6.000000E+00 u
2 x_2 c 0.000000E+00 4.500026E+00 6.000000E+00
3 y_0 c -1.000000E+01 -3.000045E+00 0.000000E+00
4 y_1 c -1.000000E+01 -7.000441E+00 0.000000E+00
5 y_2 c -1.000000E+01 -2.999987E+00 0.000000E+00
Constraints (i - inequality, e - equality)
Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)
0 boundaryDistances i 0.000000E+00 3.000045E+00 1.000000E+30 9.00000E+100
1 boundaryDistances i 0.000000E+00 2.500026E+00 1.000000E+30 9.00000E+100
2 boundaryDistances i 0.000000E+00 6.999955E+00 1.000000E+30 9.00000E+100
3 boundaryDistances i 0.000000E+00 3.499974E+00 1.000000E+30 9.00000E+100
4 boundaryDistances i 0.000000E+00 7.000441E+00 1.000000E+30 9.00000E+100
5 boundaryDistances i 0.000000E+00 6.000000E+00 1.000000E+30 9.00000E+100
6 boundaryDistances i 0.000000E+00 2.999559E+00 1.000000E+30 9.00000E+100
7 boundaryDistances i 0.000000E+00 0.000000E+00 1.000000E+30 l 9.00000E+100
8 boundaryDistances i 0.000000E+00 2.999987E+00 1.000000E+30 9.00000E+100
9 boundaryDistances i 0.000000E+00 4.500026E+00 1.000000E+30 9.00000E+100
10 boundaryDistances i 0.000000E+00 7.000013E+00 1.000000E+30 9.00000E+100
11 boundaryDistances i 0.000000E+00 1.499974E+00 1.000000E+30 9.00000E+100
12 wtSeparationSquared i 4.000000E+00 2.825299E+01 1.000000E+30 9.00000E+100
13 wtSeparationSquared i 4.000000E+00 4.000000E+00 1.000000E+30 l 9.00000E+100
14 wtSeparationSquared i 4.000000E+00 1.825355E+01 1.000000E+30 9.00000E+100
Exit Status
Inform Description
0 Optimization terminated successfully.
--------------------------------------------------------------------------------
[6]:
np.float64(1.500000198978579)
modOpt
[7]:
tf.driver = om.modOptDriver()
tf.driver.options['optimizer'] = 'SLSQP'
tf.driver.options['maxiter'] = 200
tf.driver.options['disp'] = True
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[7], line 1
----> 1 tf.driver = om.modOptDriver()
2 tf.driver.options['optimizer'] = 'SLSQP'
3 tf.driver.options['maxiter'] = 200
4 tf.driver.options['disp'] = True
AttributeError: module 'openmdao.api' has no attribute 'modOptDriver'
pymoo
[8]:
tf.driver = om.pymooDriver()
tf.driver.options['optimizer'] = 'DE'
tf.driver.options['disp'] = False
tf.driver.run_settings['seed'] = 11
tf.driver.run_settings['termination'] = ('n_gen', 100)
tf.plot_comp.plot_improvements_only = True
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[8], line 1
----> 1 tf.driver = om.pymooDriver()
2 tf.driver.options['optimizer'] = 'DE'
3 tf.driver.options['disp'] = False
4 tf.driver.run_settings['seed'] = 11
AttributeError: module 'openmdao.api' has no attribute 'pymooDriver'
Simple Genetic Algorithm
[9]:
tf.driver = om.SimpleGADriver()
tf.driver.options['bits'] = {'x': 5, 'y': 5}
tf.driver.options['max_gen'] = 10
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
<Figure size 640x480 with 1 Axes>
[9]:
np.float64(2.5483870967741935)
Differential Evolution
[10]:
tf.driver = om.DifferentialEvolutionDriver()
tf.driver.options['max_gen'] = 10
tf.driver.options['Pc'] = 0.5
tf.driver.options['F'] = 0.5
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
<Figure size 640x480 with 1 Axes>
[10]:
np.float64(3.922034059487765)
Drivers that do not support constraints
In topfarm the problem is configured during instantiation for constraint handling. This means that for drivers that do not support constraints, these are being converted to penalties. In this case we it is important to indicate the driver already at the problem instantiation
[11]:
tf = TopFarmProblem(
design_vars=dict(zip('xy', initial.T)),
cost_comp=DummyCost(optimal_state=desired, inputs=['x', 'y']),
constraints=[XYBoundaryConstraint(boundary),
SpacingConstraint(2)
],
plot_comp = DummyCostPlotComp(optimal, plot_improvements_only=True),
driver=EasyRandomSearchDriver(RandomizeTurbinePosition_Circle(max_step=10), max_iter=1000, max_time=30)
)
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
<Figure size 640x480 with 1 Axes>
[11]:
np.float64(1.8106061127112252)
External drivers can also be given during instantiation of the problem
[12]:
tf = TopFarmProblem(
design_vars=dict(zip('xy', initial.T)),
cost_comp=DummyCost(optimal_state=desired, inputs=['x', 'y']),
constraints=[XYBoundaryConstraint(boundary),
SpacingConstraint(2)
],
plot_comp=plot_comp,
driver=om.modOptDriver(**{'optimizer': 'SLSQP',
'maxiter': 200,
'disp': True}),
)
cost, _, recorder = tf.optimize(state=dict(zip('xy', initial.T)))
cost
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[12], line 8
4 constraints=[XYBoundaryConstraint(boundary),
5 SpacingConstraint(2)
6 ],
7 plot_comp=plot_comp,
----> 8 driver=om.modOptDriver(**{'optimizer': 'SLSQP',
9 'maxiter': 200,
10 'disp': True}),
11 )
AttributeError: module 'openmdao.api' has no attribute 'modOptDriver'
[ ]: