Оптимизация openmdao с суррогатом в качестве одной из нескольких моделей связанных дисциплин

Я думал, что понял январскую дискуссию об использовании метамоделей в оптимизации. Но моя попытка пока не удалась. У меня есть немного поворота. Я хочу использовать метамодель одной из нескольких дисциплин, где пример, рассмотренный в январе, оптимизирован только на результатах метамодели. Я построил пример задачи на основе учебного примера по оптимизации параболоидов. Я добавил второй компонент, соединил два компонента в группе и оптимизировал его. Затем я попытался заменить один из компонентов метамоделью этого компонента. Ниже приводится версия с реальной моделью.

from __future__ import print_function

from openmdao.api import IndepVarComp, Component, Problem, Group, ExecComp, NLGaussSeidel, ScipyOptimizer, UniformDriver, DumpRecorder, InMemoryRecorder

import math
import numpy as np

class Paraboloid(Component):
""" Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3 """

def __init__(self):
    super(Paraboloid, self).__init__()

    self.add_param('z', val=0.0)
    self.add_param('y', val=0.0)

    self.add_output('f_xy', val=0.0)

def solve_nonlinear(self, params, unknowns, resids):
    """f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3
    """

    x = params['z']
    y = params['y']

    f_xy = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
    unknowns['f_xy'] = f_xy

def linearize(self, params, unknowns, resids):
    """ Jacobian for our paraboloid."""

    x = params['z']
    y = params['y']
    J = {}

    J['f_xy', 'z'] = 2.0*x - 6.0 + y
    J['f_xy', 'y'] = 2.0*y + 8.0 + x
    return J

class Sinx(Component):
""" Evaluates the equation f(x) = sin(x) """

def __init__(self):
    super(Sinx, self).__init__()
self.C = 50.

    self.add_param('x', val=0.0)

    self.add_output('z', val=0.0)

def solve_nonlinear(self, params, unknowns, resids):
    """f(x) = 10.* sin(x/C)
    """

    x = params['x']

    sinx = math.sin(x/self.C) *10.
    unknowns['z'] = sinx

def linearize(self, params, unknowns, resids):
    """ Jacobian for our paraboloid."""

    x = params['x']
    J = {}

    J['z', 'x'] = math.cos(x/self.C)/self.C *10.
    return J

class Mda(Group):
def __init__(self):
    super(Mda, self).__init__()

self.f1in=['x']
self.f1out=['z']
self.f2in=['z', 'y']
self.f2out=['f_xy']

self.add('x', IndepVarComp('x', 10.), promotes=['*'])
self.add('y', IndepVarComp('y', 0.), promotes=['*'])

self.add('f1', Sinx(), promotes=self.f1in+self.f1out)
self.add('f2', Paraboloid(), promotes=self.f2in+self.f2out)
self.add('obj_cmp', ExecComp('obj = f_xy'), promotes=['f_xy', 'obj'])
self.nl_solver = NLGaussSeidel()


if __name__ == "__main__":

top = Problem()

root = top.root = Mda()

top.driver = ScipyOptimizer()
top.driver.options['optimizer'] = 'SLSQP'

top.driver.add_desvar('x', lower=-50, upper=50)
top.driver.add_desvar('y', lower=-50, upper=50)
top.driver.add_objective('obj')

top.setup()
top.run()

print('obj =%f at (%f,%f)'%(top['obj'],top['x'],top['y']))

Ниже приведен класс, который, как я думал, будет работать как метамодель.

class SinxSurr(MetaModel):
''' Evaluate surrogate of Sinx '''
def __init__(self):
super(SinxSurr, self).__init__()

    self.add_param('x', val=0.)
    self.add_output('z', val=0., surrogate=FloatKrigingSurrogate())

И вот часть, чтобы запустить его:

if __name__ == "__main__":
# build training data by sampling
top = Problem()
root = top.root = Group()

root.add('sinx', Sinx())
root.add('p1', IndepVarComp('x', 50.0))
root.connect('p1.x', 'sinx.x')

top.driver = UniformDriver(num_samples=500)
top.driver.add_desvar('p1.x', lower=-50, upper=50)
top.driver.add_objective('sinx.z')
recorder = InMemoryRecorder()
top.driver.add_recorder(recorder)

top.setup()
top.run()
top.cleanup()

# retrieve sampling results from recorder
xlist=[]
slist=[]
for line in recorder.iters:
xlist.append(line['unknowns']['p1.x'])
slist.append(line['unknowns']['sinx.z'])
recorder.close()

if len(xlist) != len(slist):
print('Recorder parse failure')
sys.exit(1)
x=10.

top = Problem()
root = top.root = Mda()

top.driver = ScipyOptimizer()
top.driver.options['optimizer'] = 'SLSQP'

top.driver.add_desvar('x', lower=-50, upper=50)
top.driver.add_desvar('y', lower=-50, upper=50)
top.driver.add_objective('obj')

top.setup()
top.root['f1.train:x'] = xlist
top.root['f1.train:z'] = slist
top.run()

print('obj =%f at (%f,%f)'%(top['obj'],top['x'],top['y']))

Когда я запускаю его, я получаю сообщение об ошибке:

Setup: Checking for potential issues...

No recorders have been specified, so no data will be saved.

The following parameters have no associated unknowns:
f1.train:x
f1.train:z

Setup: Check complete.
##############################################

Traceback (most recent call last):
  File "surrDisc.py", line 164, in <module>
top.root['f1.train:x'] = xlist
TypeError: 'Mda' object does not support item assignment

Я не понимаю, как взаимодействовать данные из метамодели с группой (по крайней мере).

1 ответ

Вы хотели переименовать переменную "z" в "z:float", когда сделали суррогат?

self.add_output('z:float', val=0., surrogate=FloatKrigingSurrogate())

Если вы хотите переименовать его, вам придется явно подключить "f1.z:float" к "f2.z", а также не включать "z" в рекламные акции, которые вы перечисляете в self.f1out а также self.f2in,

Другие вопросы по тегам