Есть несколько ответов на ваш вопрос. Во-первых, я укажу, что у вас есть то, что мы называем "зависающим параметром". Под этим я подразумеваю параметр компонента (или связанный с несколькими компонентами через продвижение и/или соединение), который не имеет связанной с ним конечной переменной 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» теперь является параметром, устанавливаемым пользователем. Это было необходимо, чтобы проиллюстрировать, как работают параметры.
Теперь, когда на самом деле происходит некоторая передача данных, за которую отвечает OpenMDAO, вы можете более четко увидеть фактический шаблон. В корне вообще нет параметров (не считая всяких висящих params). Все, с точки зрения корней, неизвестно, потому что на этом уровне за все отвечает src. Спуститесь на один уровень вниз, где есть p1
и g1
, и теперь есть параметр g1
, для которого p1
является источником, поэтому передача некоторых данных должна происходить на этом уровне иерархии. Таким образом, g1
имеет запись в своем словаре параметров, g1.t1.x
. Почему полный путь? Весь учет параметров ведется с полными путями по разным причинам, выходящим за рамки этого ответа. Но это также еще одна мотивация для работы с ярлыком в problem
, потому что он будет работать с относительными (или продвинутыми) именами.
person
Justin Gray
schedule
12.11.2015