0

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

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

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

这将允许通过 group.params['x'] 访问属于 comp1 的变量 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']

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

4

1 回答 1

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。p1在有and的地方往下一层g1,现在有一个参数g1p1src ,因此必须在该层次结构的那个级别上进行一些数据传递。所以g1在它的参数字典中有一个条目,g1.t1.x. 为什么它是一个完整的路径?出于此答案范围之外的各种原因,所有参数的簿记都是使用完整路径名完成的。但这也是通过捷径工作的另一个动机problem因为这将适用于相对(或提升)名称。

于 2015-11-12T00:05:08.403 回答