3

いくつかの異なるコンポーネントを制御するモデル パラメーターの大規模なセットがあります。モデルは並行して実行されています。実行中、モデル パラメーターは一定に保たれます。IndepVarComp()問題は、すべてをオブジェクトで渡したいのに、並行して実行するときにすべてのモデル パラメーターを追加する必要があることです。モデルを実行する前 (セットアップと実行の間) に、実行スクリプトの値を編集できるようにする必要があります。これを行う良い方法はありますか?パラメータの「ソース」なしで MPI の下で実行することによるデータの受け渡しの問題を認識しています。

IndepVarComp()オブジェクトを渡さない限り、各モデル パラメータを追加すると機能します。これは理にかなっています。値を変更してモデルの変更を追跡できるようにすることを OpenMDAO に伝えると、オブジェクトによる受け渡しは矛盾します。ただし、セットアップ後にパラメーター値を渡すことができるようにする必要があり、IndepVarComp()各モデル パラメーターを作成せずに MPI でそれを行うことはできません。

私がやりたいことのOpenMDAOドキュメントからのセラーの問題に基づいた例を添付しました。の行 28 のコメントを外し、行 27 のコメントを外し、行 139 のコメントを外すことによりsrc.py、この例は正常に並列に機能します。

で実行$ mpirun -np 4 python call.py

call.py

from __future__ import print_function

from openmdao.api import Problem, ScipyOptimizer

from src import SellarDerivativesSuperGroup

import numpy as np

if __name__ == "__main__":

    ######################### for MPI functionality #########################
    from openmdao.core.mpi_wrap import MPI

    # if MPI: # pragma: no cover
    #     if you called this script with 'mpirun', then use the petsc data passing

    if MPI:
        from openmdao.core.petsc_impl import PetscImpl as impl
    else:
        from openmdao.api import BasicImpl as impl
    # else:
    #     if you didn't use 'mpirun', then use the numpy data passing
        # from openmdao.api import BasicImpl as impl

    def mpi_print(prob, *args):
        """ helper function to only print on rank 0 """
        if prob.root.comm.rank == 0:
            print(*args)

    ##################
    nProblems = 4
    datasize = 10
    top = Problem(impl=impl)
    top.root = SellarDerivativesSuperGroup(nProblems=nProblems, datasize=datasize)

    top.driver = ScipyOptimizer()
    top.driver.options['optimizer'] = 'SLSQP'
    top.driver.options['tol'] = 1.0e-8



    top.driver.add_desvar('z', lower=np.array([-10.0, 0.0]),
                         upper=np.array([10.0, 10.0]))
    top.driver.add_desvar('x', lower=0.0, upper=10.0)

    top.driver.add_objective('obj')
    top.driver.add_constraint('con1', upper=0.0)
    top.driver.add_constraint('con2', upper=0.0)

    top.setup(check=True)

    # Setting initial values for design variables
    top['x'] = 1.0
    top['z'] = np.array([5.0, 2.0])
    top['varTree:leaf1'] = np.ones(datasize)

    top.run()

    if top.root.comm.rank == 0:
        print("\n")
        print("Minimum found at (%f, %f, %f)" % (top['z'][0],
                                                 top['z'][1],
                                                 top['x']))
        print("Coupling vars: %f, %f" % (top['y1_0'], top['y2_0']))
        print("Minimum objective: ", top['obj']/nProblems)

src.py

from __future__ import print_function

from openmdao.api import ExecComp, IndepVarComp, Group, NLGaussSeidel, \
                         Component, ParallelGroup, ScipyGMRES

import numpy as np


class SellarDis1(Component):
    """Component containing Discipline 1."""

    def __init__(self, problem_id=0, datasize=0):
        super(SellarDis1, self).__init__()

        self.problem_id = problem_id

        # Global Design Variable
        self.add_param('z', val=np.zeros(2))

        # Local Design Variable
        self.add_param('x', val=0.)

        # Coupling parameter
        self.add_param('y2_%i' % problem_id, val=1.0)

        # Dummy variable tree element
        self.add_param('varTree:leaf1', val=np.zeros(datasize), pass_by_obj=True)
        # self.add_param('varTree:leaf1', val=np.zeros(datasize), pass_by_obj=False)

        # Coupling output
        self.add_output('y1_%i' % problem_id, val=1.0)

    def solve_nonlinear(self, params, unknowns, resids):
        """Evaluates the equation
        y1 = z1**2 + z2 + x1 - 0.2*y2"""

        problem_id = self.problem_id

        z1 = params['z'][0]
        z2 = params['z'][1]
        x1 = params['x']
        y2 = params['y2_%i' % problem_id]

        unknowns['y1_%i' % problem_id] = z1**2 + z2 + x1 - 0.2*y2

    def linearize(self, params, unknowns, resids):
        """ Jacobian for Sellar discipline 1."""

        problem_id = self.problem_id

        J = {}

        J['y1_%i' % problem_id, 'y2_%i' % problem_id] = -0.2
        J['y1_%i' % problem_id, 'z'] = np.array([[2*params['z'][0], 1.0]])
        J['y1_%i' % problem_id, 'x'] = 1.0

        return J


class SellarDis2(Component):
    """Component containing Discipline 2."""

    def __init__(self, problem_id=0):
        super(SellarDis2, self).__init__()

        self.problem_id = problem_id

        # Global Design Variable
        self.add_param('z', val=np.zeros(2))

        # Coupling parameter
        self.add_param('y1_%i' % problem_id, val=1.0)

        # Coupling output
        self.add_output('y2_%i' % problem_id, val=1.0)

    def solve_nonlinear(self, params, unknowns, resids):
        """Evaluates the equation
        y2 = y1**(.5) + z1 + z2"""

        problem_id = self.problem_id

        z1 = params['z'][0]
        z2 = params['z'][1]
        y1 = params['y1_%i' % problem_id]

        # Note: this may cause some issues. However, y1 is constrained to be
        # above 3.16, so lets just let it converge, and the optimizer will
        # throw it out
        y1 = abs(y1)

        unknowns['y2_%i' % problem_id] = y1**.5 + z1 + z2

    def linearize(self, params, unknowns, resids):
        """ Jacobian for Sellar discipline 2."""

        problem_id = self.problem_id

        J = {}

        J['y2_%i' % problem_id, 'y1_%i' % problem_id] = .5*params['y1_%i' % problem_id]**-.5
        J['y2_%i' % problem_id, 'z'] = np.array([[1.0, 1.0]])

        return J


class SellarDerivativesSubGroup(Group):

    def __init__(self, problem_id=0, datasize=0):
        super(SellarDerivativesSubGroup, self).__init__()

        self.add('d1', SellarDis1(problem_id=problem_id, datasize=datasize), promotes=['*'])
        self.add('d2', SellarDis2(problem_id=problem_id), promotes=['*'])

        self.nl_solver = NLGaussSeidel()
        self.nl_solver.options['atol'] = 1.0e-12

        self.ln_solver = ScipyGMRES()


class SellarDerivatives(Group):
    """ Group containing the Sellar MDA. This version uses the disciplines
    with derivatives."""

    def __init__(self, problem_id=0, datasize=0):
        super(SellarDerivatives, self).__init__()

        self.add('d', SellarDerivativesSubGroup(problem_id=problem_id, datasize=datasize), promotes=['*'])


class SellarDerivativesSuperGroup(Group):

    def __init__(self, nProblems=0, datasize=0):

        super(SellarDerivativesSuperGroup, self).__init__()

        self.add('px', IndepVarComp('x', 1.0), promotes=['*'])
        self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['*'])
        # self.add('vt', IndepVarComp('varTree:leaf1', val=np.zeros(datasize)), promotes=['*'])

        pg = self.add('manySellars', ParallelGroup(), promotes=['*'])
        print(nProblems)
        for problem_id in np.arange(0, nProblems):
            pg.add('Sellar%i' % problem_id, SellarDerivatives(problem_id=problem_id, datasize=datasize), promotes=['*'])

        self.add('obj_cmp', ExecComp('obj = (x**2 + z[1] + y1_0 + exp(-y2_0)) + (x**2 + z[1] + y1_1 + exp(-y2_1)) + '
                                     '(x**2 + z[1] + y1_2 + exp(-y2_2)) + (x**2 + z[1] + y1_3 + exp(-y2_3))',
                                     z=np.array([0.0, 0.0]), x=0.0,
                                     y1_0=0.0, y2_0=0.0,
                                     y1_1=0.0, y2_1=0.0,
                                     y1_2=0.0, y2_2=0.0,
                                     y1_3=0.0, y2_3=0.0),
                 promotes=['*'])

        self.add('con_cmp1', ExecComp('con1 = 3.16 - y1_0'), promotes=['*'])
        self.add('con_cmp2', ExecComp('con2 = y2_0 - 24.0'), promotes=['*'])
4

2 に答える 2

1

これらのパラメーターが最適化設計変数として使用されることがない場合は、それらを OpenMDAO 変数として宣言する必要はありません。これらをinitメソッドで通常の python 属性として宣言するだけで、階層をループして属性値を任意の値に設定する小さなメソッドを作成できます。

IndepVarComps をオブジェクト渡しで追加するよりも少し簡単かもしれませんが、独自の提案されたソリューションも機能します。

于 2016-03-05T14:58:25.207 に答える