Skip to content
Snippets Groups Projects
Commit b3a266cd authored by Mads M. Pedersen's avatar Mads M. Pedersen
Browse files

implemented easy_drivers.py

parent 9555a926
No related branches found
No related tags found
1 merge request!30Easy drivers
'''
Created on 17. maj 2018
@author: mmpe
'''
from topfarm import TopFarm
import numpy as np
import pytest
from topfarm.cost_models.dummy import DummyCost, DummyCostPlotComp
from topfarm.plotting import NoPlot
from topfarm.easy_drivers import EasyScipyOptimizeDriver, EasySimpleGADriver
initial = [[6, 0], [6, -8], [1, 1]] # initial turbine layouts
optimal = np.array([[2.5, -3], [6, -7], [4.5, -3]]) # desired turbine layouts
boundary = [(0, 0), (6, 0), (6, -10), (0, -10)] # turbine boundaries
desired = [[3, -3], [7, -7], [4, -3]] # desired turbine layouts
@pytest.fixture
def topfarm_generator():
def _topfarm_obj(driver):
plot_comp = DummyCostPlotComp(desired)
#plot_comp = NoPlot()
return TopFarm(initial, DummyCost(desired), 2, plot_comp=plot_comp, boundary=boundary, driver=driver)
return _topfarm_obj
# # CONMIN-specific Settings
# self.driver.itmax = 30
# self.driver.fdch = 0.00001
# self.driver.fdchm = 0.000001
# self.driver.ctlmin = 0.01
# self.driver.delfun = 0.001
#
# # NEWSUMT-specific Settings
# #self.driver.itmax = 10
#
# # COBYLA-specific Settings
# #self.driver.rhobeg = 1.0
# #self.driver.rhoend = 1.0e-4
# #self.driver.maxfun = 1000
#
# # SLSQP-specific Settings
# #self.driver.accuracy = 1.0e-6
# #self.driver.maxiter = 50
#
# # Genetic-specific Settings
# #self.driver.population_size = 90
# #self.driver.crossover_rate = 0.9
# #self.driver.mutation_rate = 0.02
# #self.selection_method = 'rank'
@pytest.mark.parametrize('driver,tol',[(EasyScipyOptimizeDriver(), 1e-4),
(EasyScipyOptimizeDriver(tol=1e-3), 1e-2),
(EasyScipyOptimizeDriver(maxiter=13), 1e-1),
(EasyScipyOptimizeDriver(optimizer='COBYLA', tol=1e-3), 1e-2),
#(EasyPyOptSparseSLSQP(),??),
(EasySimpleGADriver(), 1e-4)][-1:])
def test_optimizers(driver, tol, topfarm_generator):
tf = topfarm_generator(driver)
tf.optimize()
tb_pos = tf.turbine_positions
#tf.plot_comp.show()
assert sum((tb_pos[2] - tb_pos[0])**2) > 2**2 - tol # check min spacing
assert tb_pos[1][0]< 6 + tol # check within border
np.testing.assert_array_almost_equal(tb_pos, optimal, -int(np.log10(tol)))
#print (tb_pos - optimal)
File moved
......@@ -19,7 +19,7 @@ class TopFarm(object):
"""
def __init__(self, turbines, cost_comp, min_spacing, boundary, boundary_type='convex_hull', plot_comp=None,
driver_options={'optimizer': 'SLSQP'}):
driver=ScipyOptimizeDriver()):
self.initial_positions = turbines = np.array(turbines)
......@@ -32,19 +32,18 @@ class TopFarm(object):
indeps = prob.model.add_subsystem('indeps', IndepVarComp(), promotes=['*'])
min_x, min_y = self.boundary_comp.vertices.min(0)
mean_x, mean_y = self.boundary_comp.vertices.mean(0)
if driver_options['optimizer'] == 'SLSQP':
design_var_kwargs = {}
if 'optimizer' in driver.options and driver.options['optimizer'] == 'SLSQP':
min_x, min_y, mean_x, mean_y = 0, 0, 1, 1 # scaling disturbs SLSQP
# Default +/- sys.float_info.max does not work for SLSQP
design_var_kwargs = {'lower': np.nan, 'upper': np.nan}
indeps.add_output('turbineX', turbines[:, 0], units='m', ref0=min_x, ref=mean_x)
indeps.add_output('turbineY', turbines[:, 1], units='m', ref0=min_y, ref=mean_y)
indeps.add_output('boundary', self.boundary_comp.vertices, units='m')
prob.model.add_subsystem('cost_comp', cost_comp, promotes=['*'])
prob.driver = ScipyOptimizeDriver()
prob.driver.options.update(driver_options)
design_var_kwargs = {}
if driver_options['optimizer'] == 'SLSQP':
# Default +/- sys.float_info.max does not work for SLSQP
design_var_kwargs = {'lower': np.nan, 'upper': np.nan}
prob.driver = driver
prob.model.add_design_var('turbineX', **design_var_kwargs)
prob.model.add_design_var('turbineY', **design_var_kwargs)
prob.model.add_objective('cost')
......
......@@ -19,9 +19,6 @@ class DummyCost(ExplicitComponent):
self.optimal = np.array(optimal_positions)
self.N = self.optimal.shape[0]
def cost(self, x, y):
"""Evaluate cost function"""
def setup(self):
self.add_input('turbineX', val=np.zeros(self.N), units='m')
self.add_input('turbineY', val=np.zeros(self.N), units='m')
......
from openmdao.drivers.scipy_optimizer import ScipyOptimizeDriver
#from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
from openmdao.drivers.genetic_algorithm_driver import SimpleGADriver
class EasyScipyOptimizeDriver(ScipyOptimizeDriver):
def __init__(self, optimizer='SLSQP', maxiter=200, tol=1e-6, disp=True):
"""
Parameters
----------
optimizer : {'Nelder-Mead', 'Powell', 'CG', 'BFGS', 'Newton-CG', 'L-BFGS-B',
'TNC', 'COBYLA', 'SLSQP'}
Inequality constraints are supported by COBYLA and SLSQP,
but equality constraints are only supported by SLSQP. None of the other
optimizers support constraints.
maxiter : int
Maximum number of iterations.
tol : float
Tolerance for termination. For detailed control, use solver-specific options.
disp : bool
Set to False to prevent printing of Scipy convergence messages
"""
ScipyOptimizeDriver.__init__(self)
self.options.update({'optimizer': optimizer, 'maxiter': maxiter, 'tol': tol, 'disp': disp})
# class EasyPyOptSparseSLSQP(pyOptSparseDriver):
# def __init__(self, maxit=200, acc=1e-6):
# pyOptSparseDriver.__init__(self)
# raise NotImplementedError
class EasySimpleGADriver(SimpleGADriver):
def __init__(self, elitism=True, max_gen=100):
"""Simple Genetic Algorithm Driver with argument
Parameters
----------
bits : dict
Number of bits of resolution. Default is an empty dict, where every unspecified variable is assumed to be integer, and the number of bits is calculated automatically. If you have a continuous var, you should set a bits value as a key in this dictionary.
NotImplemented
debug_print : list
List of what type of Driver variables to print at each iteration. Valid items in list are ‘desvars’, ‘ln_cons’, ‘nl_cons’, ‘objs’, ‘totals’
NotImplemented
elitism : bool
If True, replace worst performing point with best from previous generation each iteration.
max_gen : int
Number of generations before termination.
pop_size :
Number of points in the GA. Set to 0 and it will be computed as four times the number of bits.
NotImplemented
procs_per_model : int
Number of processors to give each model under MPI.
NotImplemented
run_parallel : bool
Set to True to execute the points in a generation in parallel.
NotImplemented
"""
SimpleGADriver.__init__(self)
self.options.update({'elitism': elitism, 'max_gen': max_gen})
#
# class COBYLADriverWrapper(CONMINdriver):
# # CONMIN-specific Settings
# self.driver.itmax = 30
# self.driver.fdch = 0.00001
# self.driver.fdchm = 0.000001
# self.driver.ctlmin = 0.01
# self.driver.delfun = 0.001
#
# # NEWSUMT-specific Settings
# #self.driver.itmax = 10
#
# # COBYLA-specific Settings
# #self.driver.rhobeg = 1.0
# #self.driver.rhoend = 1.0e-4
# #self.driver.maxfun = 1000
#
# # SLSQP-specific Settings
# #self.driver.accuracy = 1.0e-6
# #self.driver.maxiter = 50
#
# # Genetic-specific Settings
# #self.driver.population_size = 90
# #self.driver.crossover_rate = 0.9
# #self.driver.mutation_rate = 0.02
# #self.selection_method = 'rank'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment