For compatibility reasons I am using OpenMDAO v0.10.3.2
I am trying to set up an optimization problem in OpenMDAO that requires the use of a case iterator driver within the workflow of an optimizer. To illustrate, I have created the simple example shown below. The code seems to run, but the optimizer does not appear to alter the parameters and exits after two runs of its workflow.
I am looking for suggestions in setting up this type of problem and insights into what may be going wrong with my current formulation.
from openmdao.main.api import Assembly, Component
from openmdao.lib.datatypes.api import Float, Array, List
from openmdao.lib.drivers.api import DOEdriver, SLSQPdriver, CaseIteratorDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
term1 = Float(iotype='out')
a = Float(iotype='in', default_value=1)
def execute(self):
x = self.x
a = self.a
term1 = a*x**2
self.term1 = term1
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
def execute(self):
y = self.y
x = self.x
term1 = self.term1
f = term1 + x + y**2
self.f = f
class summer(Component):
fs = Array(iotype='in', desc='f values from all cases')
total = Float(iotype='out', desc='sum of all f values')
def execute(self):
self.total = sum(self.fs)
print 'In summer, fs = %s and total = %s' % (self.fs, self.total)
class assembly(Assembly):
cases_a = Array(iotype='in', desc='list of cases')
x = Float(iotype='in')
y = Float(iotype='in')
f = Float(iotype='out')
total = Float(iotype='out', default_value=100)
def configure(self):
# create instances of components
self.add('component1', component1())
self.add('component2', component2())
self.add('summer', summer())
# set up main driver (optimizer)
self.add('driver', SLSQPdriver())
self.driver.iprint = 1
self.driver.maxiter = 100
self.driver.accuracy = 1.0e-6
self.driver.add('summer', summer())
self.driver.add_parameter('x', low=-5., high=5.)
self.driver.add_parameter('y', low=-5., high=5.)
self.driver.add_objective('summer.total')
# set up case iterator driver
self.add('case_driver', CaseIteratorDriver())
self.case_driver.workflow.add(['component1', 'component2'])
self.case_driver.add_parameter('component1.a')
self.case_driver.add_response('component2.f')
# Set up connections
self.connect('x', 'component1.x')
self.connect('y', 'component2.y')
self.connect('component1.x', 'component2.x')
self.connect('component1.term1', 'component2.term1')
self.connect('component2.f', 'f')
self.connect('cases_a', 'case_driver.case_inputs.component1.a')
self.connect('case_driver.case_outputs.component2.f', 'summer.fs')
self.connect('summer.total', 'total')
# establish main workflow
self.driver.workflow.add(['case_driver', 'summer'])
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
test = assembly()
values = [1, 1, 1, 1]
test.cases_a = np.array(values)
test.x = 4
test.y = 4
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.total
print '(x, y) = (%s, %s)' % (test.x, test.y)