In setting up an optimization with multiple components I am getting a gradient not provided error despite having set ignore_deriv=True or missing_deriv_policy='assume_zero. I have recreated the problem in the example below. The error from this example is KeyError: 'comp1_0 (2-comp1_0): does not provide analytical derivatives fory'. Can you give me any direction on what this error may be stemming from and how to fix it?

I am working in OpenMDAO v0.13.

Example:

from openmdao.main.api import Assembly, Component
from openmdao.lib.datatypes.api import Float, Array, List
from openmdao.lib.drivers.api import DOEdriver, SLSQPdriver, COBYLAdriver, CaseIteratorDriver
from pyopt_driver.pyopt_driver import pyOptDriver

import numpy as np

class component1(Component):

    x = Float(iotype='in')
    # y = Float(iotype='in', missing_deriv_policy='assume_zero')
    y = Float(iotype='in', deriv_ignore=True)
    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

        print "In comp1", self.name, self.a, self.x, self.term1

    def list_deriv_vars(self):
        return ('x',), ('term1',)

    def provideJ(self):

        x = self.x
        a = self.a
        dterm1_dx = 2.*a*x

        J = np.array([[dterm1_dx]])
        print 'In comp1, J = %s' % J

        return J

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
        print "In comp2", self.name, self.x, self.y, self.term1, self.f

class summer(Component):

    total = Float(iotype='out', desc='sum of all f values')

    def __init__(self, size):
        super(summer, self).__init__()
        self.size = size

        self.add('fs', Array(np.zeros(size), iotype='in', desc='f values from all cases'))

    def execute(self):
        self.total = sum(self.fs)
        print 'In summer, fs = %s and total = %s' % (self.fs, self.total)

class assembly(Assembly):

    x = Float(iotype='in')
    y = Float(iotype='in')
    total = Float(iotype='out', default_value=100)

    def __init__(self, a_vals=[1, 1, 1, 1]):

        self.a_vals = a_vals

        super(assembly, self).__init__()

        print 'in init a_vals = %s' % self.a_vals

    def configure(self):

        self.add('driver', SLSQPdriver())
        # self.add('driver', pyOptDriver())
        # self.driver.optimizer = 'SLSQP'
        # self.driver.pyopt_diff = True

        #create this first, so we can connect to it
        self.add('summer', summer(size=len(self.a_vals)))
        self.connect('summer.total', 'total')

        print 'in configure a_vals = %s' % self.a_vals

        # create instances of components
        for i, a in enumerate(self.a_vals):
            c1 = self.add('comp1_%d'%i, component1())
            c1.a = a
            c2 = self.add('comp2_%d'%i, component2())

            self.connect('x', ['comp1_%d.x'%i, 'comp2_%d.x'%i])
            self.connect('y', ['comp1_%d.y'%i, 'comp2_%d.y'%i])
            self.connect( 'comp1_%d.term1'%i, 'comp2_%d.term1'%i)

            self.connect('comp2_%d.f'%i, 'summer.fs[%d]'%i)

            self.driver.workflow.add(['comp1_%d'%i, 'comp2_%d'%i])

        self.driver.workflow.add(['summer'])

        # set up main driver (optimizer)
        self.driver.iprint = 1
        self.driver.maxiter = 100
        self.driver.accuracy = 1.0e-6
        self.driver.add_parameter('x', low=-5., high=5.)
        self.driver.add_parameter('y', low=-5., high=5.)
        self.driver.add_objective('summer.total')

if __name__ == "__main__":
    """ the result should be -1 at (x, y) = (-0.5, 0) """

    import time
    from openmdao.main.api import set_as_top

    test = set_as_top(assembly([1, 1, 1, 1]))

    test.x = 2
    test.y = 4

    tt = time.time()
    test.run()

    print "Elapsed time: ", time.time()-tt, "seconds"

    print 'result = ', test.summer.total
    print '(x, y) = (%s, %s)' % (test.x, test.y)

asked 22 Jul '15, 18:08

jthomas's gravatar image

jthomas
372210

edited 22 Jul '15, 18:08


Hey, Jthomas

I got your code sample to run by setting the missing_deriv_policy on c1 right after instantiating it:

c1 = self.add('comp1_%d'%i, component1())
c1.missing_deriv_policy = 'assume_zero'

It's a component attribute rather than a trait metadata, and means that all derivatives found in that component will be assumed zero whenever they aren't provided.

link

answered 22 Jul '15, 21:10

Kenneth%20T%20Moore's gravatar image

Kenneth T Moore ♦
1.1k1212

Thank you for correcting my misunderstanding, that helps a lot.

(23 Jul '15, 09:48) jthomas jthomas's gravatar image

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×43
×39
×22
×9

Asked: 22 Jul '15, 18:08

Seen: 1,203 times

Last updated: 23 Jul '15, 09:48

powered by OSQA