Полу-общий пример группы в группе не использует тот же вклад - PullRequest
0 голосов
/ 02 ноября 2018

Вот пример сокращенной диаграммы N2. У меня есть одна группа (gr1), подключенная к линейным и нелинейным решателям (DirectSolver и NonlinearBlockGS)

Если я использую настройку, показанную в версии 1, с оптимизатором на основе градиента для всей задачи, то конечная разница применяется к переменным D1 и D2 (которые являются числами с плавающей запятой).

Если я обертываю gr1 с gr2, с той же самой установкой (за исключением того, что теперь ок. _Totals находятся внутри gr2), конечная разность применяется к t и d, которые являются ndarrays, что приводит к оценке функции min n * 2.

Конечно, нет необходимости иметь gr2 в этой настройке, но моя цель - пометить версию, помеченную как желаемую в будущем, на изображении ниже.

enter image description here

Я не могу повторить ту же проблему с sellarmda, что странно, так как я пытался настроить ее идентично. Тем не менее я добавляю код sellarmda, который объясняет мою проблему. Переменная с именем "ver1", установленная в True или False, изменит настройки.

ver1 = False -> относится к группе с одним циклом. И в моей настройке fd применяется к глобальной переменной дизайна, что я и хочу.

ver2 = True -> случай с группой в группе. И FD применяется к большим массивам, которые являются параметрами связи.

from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, DirectSolver,ExplicitComponent,NonlinearBlockGS, Group
import numpy as np

class SellarDis1(ExplicitComponent):
    """
    Component containing Discipline 1 -- no derivatives version.
    """

    def setup(self):

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



        # Coupling parameter
        self.add_input('y2', val=1.0)

        # Coupling output
        self.add_output('y1', val=1.0)

        # Finite difference all partials.
        self.declare_partials('*', '*', method='fd')

    def compute(self, inputs, outputs):
        """
        Evaluates the equation
        y1 = z1**2 + z2 + x1 - 0.2*y2
        """
        z1 = inputs['z'][0]
        z2 = inputs['z'][1]
        y2 = inputs['y2']
        print(inputs['z'])

        outputs['y1'] = z1**2 + z2 -0.2*y2
class SellarDis2(ExplicitComponent):
    """
    Component containing Discipline 2 -- no derivatives version.
    """

    def setup(self):
        # Global Design Variable
        self.add_input('z', val=np.zeros(2))

        # Coupling parameter
        self.add_input('y1', val=1.0)

        # Coupling output
        self.add_output('y2', val=1.0)

        # Finite difference all partials.
        self.declare_partials('*', '*', method='fd')

    def compute(self, inputs, outputs):
        """
        Evaluates the equation
        y2 = y1**(.5) + z1 + z2
        """
        z1 = inputs['z'][0]
        z2 = inputs['z'][1]
        y1 = inputs['y1']

        # 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
        if y1.real < 0.0:
            y1 *= -1

        outputs['y2'] = y1**.5 + z1 + z2




class SellarMDA(Group):
    """
    Group containing the Sellar MDA.
    """

    def setup(self):
        ver1=False
        if ver1:
            cycle = self.add_subsystem('cycle', Group(), promotes=['*'])
            cycle.add_subsystem('d1', SellarDis1(), promotes_inputs=[ 'z', 'y2'], promotes_outputs=['y1'])
            cycle.add_subsystem('d2', SellarDis2(), promotes_inputs=['z', 'y1'], promotes_outputs=['y2'])
            # Nonlinear Block Gauss Seidel is a gradient free solver
            cycle.nonlinear_solver = NonlinearBlockGS()
        else:            
            self.add_subsystem('d1', SellarDis1(), promotes_inputs=[ 'z', 'y2'], promotes_outputs=['y1'])
            self.add_subsystem('d2', SellarDis2(), promotes_inputs=['z', 'y1'], promotes_outputs=['y2'])
            self.nonlinear_solver = NonlinearBlockGS()


        self.approx_totals()


prob = Problem()
indeps = prob.model.add_subsystem('indeps', IndepVarComp(), promotes=['*'])

indeps.add_output('z', np.array([5.0, 2.0]))  
SellarMDA11=SellarMDA()
prob.model.add_subsystem('SellarMDA', SellarMDA11, promotes=['*'])
#SellarMDA11.approx_totals()
prob.model.add_subsystem('obj_cmp', ExecComp('obj =  z[1] + y1 + exp(-y2)',
                   z=np.array([0.0, 0.0])),
                   promotes=[ 'z', 'y1', 'y2', 'obj'])
prob.model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])
prob.model.add_subsystem('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])

prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
# prob.driver.options['maxiter'] = 100
prob.driver.options['tol'] = 1e-8

prob.model.add_design_var('z', lower=0, upper=10)
prob.model.add_objective('obj')
prob.model.add_constraint('con1', upper=0)
prob.model.add_constraint('con2', upper=0)

prob.setup()
prob.set_solver_print(level=0)

# Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer
#prob.model.approx_totals()

prob.run_driver()

print('minimum found at')
print(prob['z'])

print('minumum objective')
print(prob['obj'][0])        

1 Ответ

0 голосов
/ 28 ноября 2018

мы внимательно изучили код и пример, который вы дали, и не смогли воспроизвести ни одну из описанных вами проблем. Без тестового примера мы не сможем добиться большего прогресса в этом.

...