0

グループの複数のレイヤーを介して暗黙的にリンクされている変数へのアクセスに問題があります。ドキュメントによると:

新しい OpenMDAO では、グループはコンポーネントではなく、独自の変数を持ちません。変数は、promotes 引数を add 呼び出しに渡すことでグループ レベルに昇格できます。

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']

これが機能しない理由と、下位レベルのグループの知識がなくても変数をトップレベルで使用できるようにする方法を説明していただけますか?

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' がユーザー設定パラメーターになりました。これは、パラメーターがどのように機能するかを説明するために必要でした。

OpenMDAO が担当するデータの受け渡しが実際に行われているので、実際のパターンをより明確に見ることができます。ルートには、パラメーターはまったくありません (ぶら下がっているパラメーターを除く)。ルーツの観点からは、すべてが未知です。なぜなら、すべてがそのレベルでそれを担当する src を持っているからです。p1とが存在する 1 レベル下に移動すると、srcg1のパラメータが存在するg1ためp1、階層のそのレベルでデータの受け渡しが発生する必要があります。したがってg1、そのパラメータ ディクショナリに エントリがありますg1.t1.x。なぜフルパスなのですか?この回答の範囲外のさまざまな理由により、パラメーターのすべてのブックキーピングはフルパス名で行われます。しかし、それはまた、ショートカットを介して作業するもう1つの動機ですproblemそれは相対(または昇格)名で機能するためです。

于 2015-11-12T00:05:08.403 に答える