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

OpenMDAO1.x: Difficulty accessing variables implicitly linked through multiple Groups

我无法访问通过多层组隐式链接的变量。根据 documentation:

In new OpenMDAO, Groups are NOT Components and do not have their own variables. Variables can be promoted to the Group level by passing the promotes arg to the add call, e.g.,

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

This will allow the variable x that belongs to comp1 to be accessed via 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']

您能否解释一下为什么这不起作用,以及我如何在不了解较低级别组的情况下使变量对顶层可用?

您的问题有几个答案。首先,我要指出,您拥有我们所说的 "hanging parameter"。我的意思是,组件上的参数(或通过提升 and/or 连接链接到多个组件)没有与之关联的最终 src 变量。因此,为了完整理解,需要说明的是,就 OpenMDAO 而言,挂起参数不是问题。为了方便用户,我们提供了一种简单的方法让您在问题实例中设置它的值,但我们从不在 运行 时间内进行任何数据传递或任何事情。

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

为了更直接地回答您的问题,您实际上不应该深入研究任何子级别的参数字典。作为用户,我想不出这样做的充分理由。如果你坚持使用 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' 现在是用户设置的参数。为了说明参数如何工作,这是必要的。

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