我无法访问通过多个组层隐式链接的变量。根据{{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']
你能解释为什么这不起作用,以及如何在不了解较低级别组的情况下将变量提供给顶层?
答案 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负责它。向下有p1
和g1
的一个级别,现在g1
上有一个参数,p1
是src,所以一些数据传递必须在那里发生层级的层次结构。因此g1
在其参数字典g1.t1.x
中有一个条目。为什么它是一条完整的道路?由于本答案范围之外的各种原因,所有参数的簿记都是使用完整路径名完成的。但这也是在problem
中使用快捷方式的另一个动机,因为它可以与相对(或提升)名称一起使用。