OpenMDAO v0.13:将一个nxm数组的片段连接到一个在n个独立组件中的1xm数组。

时间:2022-10-02 20:38:31

I am trying to connect either the rows of an nxm array to 1xm arrays in n individual components or connect slices of an 1xn*m array to 1xm arrays in n individual components. The original nxm or 1xn*m array would then be used as an optimization parameter. The problem is that the assembly seems to have some serious problems when I do this. I either get obviously wrong answers or a size mismatch error.

我尝试将nxm数组的行连接到n个单独的组件中的1xm数组,或者将1xn*m数组的片段连接到n个独立组件中的1xm数组。最初的nxm或1xn*m数组将被用作优化参数。问题是,当我这样做时,大会似乎有一些严重的问题。我要么得到明显错误的答案,要么是大小不匹配的错误。

I have been able to get the assembly to work by passing in n 1xm arrays using exec(), but I would much prefer the method explained previously. If anyone can tell me how to make this work in a proper way I would really appreciate it.

通过使用exec(),我可以通过传入n 1xm数组来让程序集工作,但是我更喜欢前面解释的方法。如果有人能告诉我如何以合适的方式进行这项工作,我将非常感激。

I have provided a simplified example of code for what works and what I want to do. The method I would like to use is shown first, followed by the method I have gotten to work, but seriously dislike.

我提供了一个简化的代码示例,说明了什么是可行的,什么是我想要做的。我想使用的方法首先显示,然后是我开始工作的方法,但是非常不喜欢。


What I want to do

    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')
        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')
        q = Array(np.zeros(2), iotype='in', dtype='float')

        def execute(self):

            y = self.y + self.q[0]
            x = self.x + self.q[1]
            term1 = self.term1
            f = term1 + x + y**2
            print 'q = %s' % self.q
            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')

        def __init__(self, size):

            super(assembly, self).__init__()

            self.size = size

            self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
            self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
            self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))

            print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)


        def configure(self):

            self.add('driver', SLSQPdriver())
            # self.add('driver', pyOptDriver())
            # self.driver.optimizer = 'SNOPT'
            # 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 in range(0, self.size):
                c1 = self.add('comp1_%d' % i, component1())
                c1.missing_deriv_policy = 'assume_zero'

                c2 = self.add('comp2_%d'%i, component2())
                self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
                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('q[%d, :]' % i, 'comp2_%d.q' % i)
                self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)

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

            # self.connect('summer.fs[:]', 'fs[:]')
            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_parameter('q', low=0., 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
        a_vals = np.array([1., 1., 1., 1.])
        test = set_as_top(assembly(size=len(a_vals)))
        test.a_vals = a_vals
        print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
        test.x = 2.
        test.y = -5
        test.q = np.tile(np.arange(0., 2.), (4, 1))
        print test.q

        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)
        print 'fs = %s' % test.fs
        print test.fs

----------

What works

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')
    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')
    q = Array(np.zeros(2), iotype='in', dtype='float')

    def execute(self):

        y = self.y + self.q[0]
        x = self.x + self.q[1]
        term1 = self.term1
        f = term1 + x + y**2
        print 'in comp2 q = %s' % self.q
        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')

    def __init__(self, size):

        super(assembly, self).__init__()

        self.size = size

        self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))

        self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))

        for i in range(0, size):
            self.add('q_%d' % i, Array(np.zeros(2), iotype='in', dtype='float'))

        print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)

    def configure(self):

        # self.add('driver', SLSQPdriver())
        self.add('driver', pyOptDriver())
        self.driver.optimizer = 'SNOPT'
        # 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
        # print 'in configure q = %s' % self.q


        # create instances of components
        for i in range(0, self.size):
            c1 = self.add('comp1_%d' % i, component1())
            c1.missing_deriv_policy = 'assume_zero'

            c2 = self.add('comp2_%d'%i, component2())
            self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
            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('q_%d' % i, 'comp2_%d.q' % i)

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

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

        # self.connect('summer.fs[:]', 'fs[:]')
        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=0., high=5.)
        for i in range(0, self.size):
            self.driver.add_parameter('q_%d' % i, low=0., 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
    a_vals = np.array([1., 1., 1., 1.])
    test = set_as_top(assembly(size=len(a_vals)))
    test.a_vals = a_vals
    print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
    test.x = 2.
    test.y = -5
    q = np.tile(np.arange(1., 3.), (4, 1))
    for i in range(0, len(a_vals)):
        exec('test.q_%d = q[%d]' % (i, i))
        exec('print test.q_%d' % i)
        print test.q_0, test.q_1, test.q_2, test.q_3

    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)
    print 'fs = %s' % test.fs
    print test.fs
    for i in range(0, len(a_vals)):
        exec('print test.q_%d' % i)

2 个解决方案

#1


1  

So, I took a look at your model too, and you definitely aren't doing anything wrong. There is a bug in the model setup when it is assembling a network graph for the top optimization problem. It seems to lose the q variable from the inputs and never allocates space for it in the vector that is used to solve for the total derivatives. I think it is confused about q because it has no direct full connection to anything, just slice connections to the numbered comp2s.

所以,我也看了你的模型,你肯定没有做错什么。在为最优优化问题装配网络图时,模型设置中存在一个缺陷。它似乎从输入中丢失了q变量,而没有为它在用于求解总导数的向量中分配空间。我认为它对q很困惑,因为它与任何东西都没有直接的完全连接,只是将连接与编号的comp2s连接起来。

Your first workaround is probably the best one. However, I also found another one. I created a dummy component called fakefake; this component does nothing except allow you to directly connect the full q vector to something. Then, I took its output fakefake.out and used it in a constraint. Since that output never changes, the constraint is always satisfied. This workaround works because the full q connection prevents the input from being erroneously removed from the graph during pruning.

你的第一个工作可能是最好的。然而,我也找到了另一个。我创建了一个虚拟组件fakefake;这个组件不做任何事情,只允许您直接将完整的q向量连接到某个东西。然后,我选择了它的输出fakefake。在一个约束条件下使用它。由于输出从不改变,约束总是满足的。这种方法是有效的,因为完整的q连接可以防止在修剪过程中错误地从图形中删除输入。

With these changes, i was able to get it to run. I am not sure if the answers are correct though, since I don't know what they are supposed to be. I have included my code below. Note, I also added derivatives for component2 and summer.

有了这些变化,我就能让它运行起来。我不知道答案是否正确,因为我不知道它们应该是什么。我的代码如下。注意,我还为component2和summer添加了衍生工具。

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')
    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')
    q = Array(np.zeros(2), iotype='in', dtype='float')

    f = Float(iotype='out')

    def execute(self):

        y = self.y + self.q[0]
        x = self.x + self.q[1]
        term1 = self.term1
        f = term1 + x + y**2
        print 'q = %s' % self.q
        self.f = f
        print "In comp2", self.name, self.x, self.y, self.term1, self.f

    def list_deriv_vars(self):
        return ('x', 'y', 'term1', 'q'), ('f',)

    def provideJ(self):
        # f = (y+q0)**2 + x + q1 + term1

        df_dx = 1.0
        df_dy = 2.0*self.y + 2.0*self.q[0]
        df_dterm1 = 1.0
        df_dq = np.array([2.0*self.q[0] + 2.0*self.y, 1.0])

        J = np.array([[df_dx, df_dy, df_dterm1, df_dq[0], df_dq[1]]])
        return J

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)

    def list_deriv_vars(self):
        return ('fs',), ('total',)

    def provideJ(self):
        J = np.ones((1.0, len(self.fs)))
        return J

class fakefake(Component):

    out = Float(0.0, iotype='out')

    def __init__(self, size):
        super(fakefake, self).__init__()

        self.size = size
        self.add('q', Array(np.zeros(size), iotype='in', dtype='float'))

    def execute(self):
        pass

    def list_deriv_vars(self):
        return ('q',), ('out',)

    def provideJ(self):
        J = np.zeros((1.0, 2.0*len(self.q)))
        return J

class assembly(Assembly):

    x = Float(iotype='in')
    y = Float(iotype='in')
    total = Float(iotype='out')

    def __init__(self, size):

        super(assembly, self).__init__()

        self.size = size

        self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
        self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
        self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))

        print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)


    def configure(self):

        self.add('driver', SLSQPdriver())
        # self.add('driver', pyOptDriver())
        # self.driver.optimizer = 'SNOPT'
        # 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')

        # Trying something...
        self.add('fakefake', fakefake(self.size))
        self.connect('q', 'fakefake.q')

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

        # create instances of components

        for i in range(0, self.size):
            c1 = self.add('comp1_%d' % i, component1())
            c1.missing_deriv_policy = 'assume_zero'

            c2 = self.add('comp2_%d'%i, component2())
            self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
            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('q[%d, :]' % i, 'comp2_%d.q' % i)
            #self.connect('q[%d]' % i, 'comp2_%d.q' % i)
            self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)

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

        # self.connect('summer.fs[:]', 'fs[:]')
        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_parameter('q', low=0., high=5.)
        #for i in range(0, self.size):
        #    self.driver.add_parameter('comp2_%d.q' % i, low=0., high=5.)
        self.driver.add_objective('summer.total')
        self.driver.add_constraint('fakefake.out < 1000')


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

    import time
    from openmdao.main.api import set_as_top
    a_vals = np.array([1., 1., 1., 1.])
    test = set_as_top(assembly(size=len(a_vals)))
    test.a_vals = a_vals
    print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
    test.x = 2.
    test.y = -5
    test.q = np.tile(np.arange(0., 2.), (4, 1))
    print test.q

    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)
    print 'fs = %s' % test.fs
    print test.fs

#2


1  

I can get past the setup error by making a small change in the connection of q, to comp2_.q.

我可以通过在q和comp2_q .q的连接上做一个小小的改变来克服设置错误。

I go from:

我从:

self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)

to:

:

self.connect('q[%d]' % i, 'comp2_%d.q' % i)

and then the problem runs through its first evaluation. Unfortunately it then does somewhere in the derivatives calculations. This happens even if I turn on SNOPT and use pyopt_diff=True. So something else in this toy problem is amiss. But removing the extra : gets you past the connection error.

然后这个问题通过它的第一个评估。不幸的是,它会在衍生品计算中出现。即使我打开SNOPT并使用pyopt_diff=True,也会发生这种情况。所以在这个玩具问题上还有其他问题。但是删除额外的:使您通过连接错误。

#1


1  

So, I took a look at your model too, and you definitely aren't doing anything wrong. There is a bug in the model setup when it is assembling a network graph for the top optimization problem. It seems to lose the q variable from the inputs and never allocates space for it in the vector that is used to solve for the total derivatives. I think it is confused about q because it has no direct full connection to anything, just slice connections to the numbered comp2s.

所以,我也看了你的模型,你肯定没有做错什么。在为最优优化问题装配网络图时,模型设置中存在一个缺陷。它似乎从输入中丢失了q变量,而没有为它在用于求解总导数的向量中分配空间。我认为它对q很困惑,因为它与任何东西都没有直接的完全连接,只是将连接与编号的comp2s连接起来。

Your first workaround is probably the best one. However, I also found another one. I created a dummy component called fakefake; this component does nothing except allow you to directly connect the full q vector to something. Then, I took its output fakefake.out and used it in a constraint. Since that output never changes, the constraint is always satisfied. This workaround works because the full q connection prevents the input from being erroneously removed from the graph during pruning.

你的第一个工作可能是最好的。然而,我也找到了另一个。我创建了一个虚拟组件fakefake;这个组件不做任何事情,只允许您直接将完整的q向量连接到某个东西。然后,我选择了它的输出fakefake。在一个约束条件下使用它。由于输出从不改变,约束总是满足的。这种方法是有效的,因为完整的q连接可以防止在修剪过程中错误地从图形中删除输入。

With these changes, i was able to get it to run. I am not sure if the answers are correct though, since I don't know what they are supposed to be. I have included my code below. Note, I also added derivatives for component2 and summer.

有了这些变化,我就能让它运行起来。我不知道答案是否正确,因为我不知道它们应该是什么。我的代码如下。注意,我还为component2和summer添加了衍生工具。

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')
    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')
    q = Array(np.zeros(2), iotype='in', dtype='float')

    f = Float(iotype='out')

    def execute(self):

        y = self.y + self.q[0]
        x = self.x + self.q[1]
        term1 = self.term1
        f = term1 + x + y**2
        print 'q = %s' % self.q
        self.f = f
        print "In comp2", self.name, self.x, self.y, self.term1, self.f

    def list_deriv_vars(self):
        return ('x', 'y', 'term1', 'q'), ('f',)

    def provideJ(self):
        # f = (y+q0)**2 + x + q1 + term1

        df_dx = 1.0
        df_dy = 2.0*self.y + 2.0*self.q[0]
        df_dterm1 = 1.0
        df_dq = np.array([2.0*self.q[0] + 2.0*self.y, 1.0])

        J = np.array([[df_dx, df_dy, df_dterm1, df_dq[0], df_dq[1]]])
        return J

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)

    def list_deriv_vars(self):
        return ('fs',), ('total',)

    def provideJ(self):
        J = np.ones((1.0, len(self.fs)))
        return J

class fakefake(Component):

    out = Float(0.0, iotype='out')

    def __init__(self, size):
        super(fakefake, self).__init__()

        self.size = size
        self.add('q', Array(np.zeros(size), iotype='in', dtype='float'))

    def execute(self):
        pass

    def list_deriv_vars(self):
        return ('q',), ('out',)

    def provideJ(self):
        J = np.zeros((1.0, 2.0*len(self.q)))
        return J

class assembly(Assembly):

    x = Float(iotype='in')
    y = Float(iotype='in')
    total = Float(iotype='out')

    def __init__(self, size):

        super(assembly, self).__init__()

        self.size = size

        self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
        self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
        self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))

        print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)


    def configure(self):

        self.add('driver', SLSQPdriver())
        # self.add('driver', pyOptDriver())
        # self.driver.optimizer = 'SNOPT'
        # 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')

        # Trying something...
        self.add('fakefake', fakefake(self.size))
        self.connect('q', 'fakefake.q')

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

        # create instances of components

        for i in range(0, self.size):
            c1 = self.add('comp1_%d' % i, component1())
            c1.missing_deriv_policy = 'assume_zero'

            c2 = self.add('comp2_%d'%i, component2())
            self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
            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('q[%d, :]' % i, 'comp2_%d.q' % i)
            #self.connect('q[%d]' % i, 'comp2_%d.q' % i)
            self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)

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

        # self.connect('summer.fs[:]', 'fs[:]')
        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_parameter('q', low=0., high=5.)
        #for i in range(0, self.size):
        #    self.driver.add_parameter('comp2_%d.q' % i, low=0., high=5.)
        self.driver.add_objective('summer.total')
        self.driver.add_constraint('fakefake.out < 1000')


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

    import time
    from openmdao.main.api import set_as_top
    a_vals = np.array([1., 1., 1., 1.])
    test = set_as_top(assembly(size=len(a_vals)))
    test.a_vals = a_vals
    print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
    test.x = 2.
    test.y = -5
    test.q = np.tile(np.arange(0., 2.), (4, 1))
    print test.q

    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)
    print 'fs = %s' % test.fs
    print test.fs

#2


1  

I can get past the setup error by making a small change in the connection of q, to comp2_.q.

我可以通过在q和comp2_q .q的连接上做一个小小的改变来克服设置错误。

I go from:

我从:

self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)

to:

:

self.connect('q[%d]' % i, 'comp2_%d.q' % i)

and then the problem runs through its first evaluation. Unfortunately it then does somewhere in the derivatives calculations. This happens even if I turn on SNOPT and use pyopt_diff=True. So something else in this toy problem is amiss. But removing the extra : gets you past the connection error.

然后这个问题通过它的第一个评估。不幸的是,它会在衍生品计算中出现。即使我打开SNOPT并使用pyopt_diff=True,也会发生这种情况。所以在这个玩具问题上还有其他问题。但是删除额外的:使您通过连接错误。