OpenMDAO1.x:难以访问通过多个组隐式链接的变量

时间:2015-11-11 22:01:23

标签: openmdao

我无法访问通过多个组层隐式链接的变量。根据{{​​3}}:

  

在新的OpenMDAO中,组不是组件,没有自己的组件   变量。通过传递变量,可以将变量提升到组级别   将arg提升为添加调用,例如,

group = Group()
group.add('comp1', Times2(), promotes=['x'])
     

这将允许访问属于comp1的变量x   通过group.params ['x']。

但是,当我尝试访问子子组的变量时,我遇到了错误。请参阅下面的示例,其中显示了一个有效且无法运行的示例:

from openmdao.api import Component, Group, Problem
import numpy as np


class Times2(Component):
    def __init__(self):
        super(Times2, self).__init__()
        self.add_param('x', 1.0, desc='my var x')
        self.add_output('y', 2.0, desc='my var y')

    def solve_nonlinear(self, params, unknowns, resids):
        unknowns['y'] = params['x'] * 2.0

    def linearize(self, params, unknowns, resids):
        J = {}
        J[('y', 'x')] = np.array([2.0])
        return J


class PassGroup1(Group):

    def __init__(self):
        super(PassGroup1, self).__init__()

        self.add('t1', Times2(), promotes=['*'])


class PassGroup2(Group):

    def __init__(self):
        super(PassGroup2, self).__init__()

        self.add('g1', PassGroup1(), promotes=['*'])


prob = Problem(root=Group())
prob.root.add('comp', PassGroup2(), promotes=['*'])
prob.setup()
prob.run()

# this works
print prob.root.comp.g1.t1.params['x']

# this does not
print prob.root.params['x']

你能解释为什么这不起作用,以及如何在不了解较低级别组的情况下将变量提供给顶层?

1 个答案:

答案 0 :(得分:2)

您的问题有几个答案。首先,我要指出你有我们称之为"悬挂参数"。我的意思是,组件上的参数(或通过提升和/或连接链接到多个组件)没有与之关联的最终src变量。因此,仅仅为了完全理解,需要说明的是,就OpenMDAO而言,悬挂参数并不是它的问题。作为对用户的一种控制,我们提供了一种在问题实例中设置其值的简单方法,但我们从不在运行时使用它或任何内容传递任何数据。

x是优化器的设计变量的常见情况下,您将创建IndepVarComp以为此值提供src。但是,由于您的示例中没有优化器,因此忽略IndepVarComp在技术上并不是错误的。

为了更直接地回答你的问题,你不应该真正深入到任何一个子级别的params词典。作为一个用户,我无法想到这样做的理由。如果你坚持problem['x'],你永远不会出错。

但是,既然你问过,这里有一些细节,我们会对一个稍微修改过的案例进行实际的参数调整。

from openmdao.api import Component, Group, Problem
import numpy as np


class Plus1(Component): 
    def __init__(self): 
        super(Plus1, self).__init__()
        self.add_param('w', 4.0)
        self.add_output('x', 5.0)

    def solve_nonlinear(self, params, unknowns, resids): 
        unknowns['x'] = params['w'] + 1

    def linearize(self, params, unknowns, resids): 
        J = {}
        J['x', 'w'] = 1
        return J


class Times2(Component):
    def __init__(self):
        super(Times2, self).__init__()
        self.add_param('x', 1.0, desc='my var x')
        self.add_output('y', 2.0, desc='my var y')

    def solve_nonlinear(self, params, unknowns, resids):
        unknowns['y'] = params['x'] * 2.0

    def linearize(self, params, unknowns, resids):
        J = {}
        J[('y', 'x')] = np.array([2.0])
        return J


class PassGroup1(Group):

    def __init__(self):
        super(PassGroup1, self).__init__()

        self.add('t1', Times2(), promotes=['x','y'])


class PassGroup2(Group):

    def __init__(self):
        super(PassGroup2, self).__init__()

        self.add('g1', PassGroup1(), promotes=['x','y'])
        self.add('p1', Plus1(), promotes=['w','x'])


prob = Problem(root=Group())
prob.root.add('comp', PassGroup2(), promotes=['w','x','y'])
prob.setup()
prob.run()

# this works
print prob.root.comp.g1.t1.params['x']

# this does not
print prob.root.comp.params.keys()

请注意,在我的示例中,' x'用户不再可以自由设置。它现在由' p1'计算。相反,' w'现在是用户设置参数。这是必要的,以说明params如何工作。

现在实际上正在进行一些数据传递,OpenMDAO负责您可以更清楚地看到实际模式。在根部,根本没有参数(不包括任何悬挂参数)。从根的角度来看,一切都是未知的,因为在这个层面上,每个人都有一个src负责它。向下有p1g1的一个级别,现在g1上有一个参数,p1是src,所以一些数据传递必须在那里发生层级的层次结构。因此g1在其参数字典g1.t1.x中有一个条目。为什么它是一条完整的道路?由于本答案范围之外的各种原因,所有参数的簿记都是使用完整路径名完成的。但这也是在problem中使用快捷方式的另一个动机,因为它可以与相对(或提升)名称一起使用。