いくつかの異なるコンポーネントを制御するモデル パラメーターの大規模なセットがあります。モデルは並行して実行されています。実行中、モデル パラメーターは一定に保たれます。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=['*'])