Python 如何在OpenMDAO中使用两个隐式且可能耦合的系统进行优化?

Python 如何在OpenMDAO中使用两个隐式且可能耦合的系统进行优化?,python,openmdao,Python,Openmdao,我一直在参考Sellar MDA和BalanceComp教程,但我无法制定OpenMDAO体系结构来优化此类隐式方程耦合系统: 使用设计变量x、y最小化函数F,以同时满足以下非线性方程作为约束: Rx,y,z=fx,y,c-gx,y,d=0 Sx,y,z=fx,y,c-hx,y,d=e 用常数c,d,e 所以我的想法是让F,F,g,h是显式的组件类,让R,S是在每个类中使用BalanceComp 1的组类!确定各自的解决方案,因为系统可独立用于其他应用。我相信常数c,d,e可以通过IndepVa

我一直在参考Sellar MDA和BalanceComp教程,但我无法制定OpenMDAO体系结构来优化此类隐式方程耦合系统:

使用设计变量x、y最小化函数F,以同时满足以下非线性方程作为约束:

Rx,y,z=fx,y,c-gx,y,d=0

Sx,y,z=fx,y,c-hx,y,d=e

用常数c,d,e

所以我的想法是让F,F,g,h是显式的组件类,让R,S是在每个类中使用BalanceComp 1的组类!确定各自的解决方案,因为系统可独立用于其他应用。我相信常数c,d,e可以通过IndepVarComp输入

一起解决这个系统需要创建一个组组件,称之为ImpMDA,使用Sellar教程中类似于组的循环,其中包含R,S

我的主要问题是如何在周期中跨两个系统全局同步x,y。R的结果是否应该反馈给s,反之亦然?当它们同时被求解时,我假设它们是耦合的

请注意,x,y可能来自其他一些独立的组件,因此很难将它们作为向量馈送,除非创建一些明确的组件,如Lister,它接受输入并生成一个向量馈送给ImpMDA

如果可能的话,在一个更简单的玩具箱上实现一个特定的实现会非常有帮助,但如果我能从OpenMDAO中获得一些关于这个问题建模的一般性见解,我将非常感激

对于特定的使用情况,考虑飞行器翼面燃烧设计目标函数的最小化,同时在飞行中的所有操作点保持俯仰修正隐式系统1和俯仰稳定隐式系统2,从而确定水平尾部区域和机翼位置。与重心匹配的机翼面积相关的压力中心是俯仰配平的要求,同样,俯仰稳定性的中性点也是如此,因此设计变量在系统中起作用

编辑:

下面是我正在寻找的模块化方法的Python示例:

将numpy作为np导入 从scipy.optimize import fsolve,最小化 def fxs,c:return-xs[0]**2+xs[1]+c显式组件1 def gxs,d:return-xs[0]**3+xs[1]**2-d显式组件2 def hxs,d:返回xs[0]+xs[1]**2+d显式组件3 此函数用于快速生成问题中所示的剩余函数。 不同剩余函数的OpenMDAO实现也将完成 通过BalanceComp或ImplicitComponent,可能与此处不共享相同的方程式设置。 def剩余量F1、f2、a=6、b=4、常数=0: 返回lambda xs:f1xs,a-f2xs,b+const def Fxs:目标函数 返回xs[0]**2-xs[1]**2-5 x0=[-2,2]初始猜测 问题1 x1_opt=minimizeF,x0, 方法='trust-constr', 约束={'type':'eq','fun':residualerf,g,a=1,b=2}, 选项={'disp':False} 打印X1_opt,'\n\n' 问题2 m、 n=5,6 def coupledxs:耦合方程 return[residualerf,gxs,residualerf,h,a=4,b=3,const=m*nxs] x2_opt=minimizeF,x0, 方法='trust-constr', 约束={'type':'eq','fun':耦合}, 选项={'disp':False} printx2_opt 返回:

         cg_niter: 22
     cg_stop_cond: 2
           constr: [array([-8.8817842e-16])]
      constr_nfev: [102]
      constr_nhev: [0]
      constr_njev: [0]
   constr_penalty: 3.2410415627552283
 constr_violation: 8.881784197001252e-16
   execution_time: 0.028232574462890625
              fun: -10.302775637731996
             grad: array([ 1.19209290e-07, -4.60555129e+00])
              jac: [array([[-5.96046448e-08, -3.60555129e+00]])]
  lagrangian_grad: array([ 1.95345288e-07, -8.88178420e-16])
          message: '`xtol` termination condition is satisfied.'
           method: 'equality_constrained_sqp'
             nfev: 102
             nhev: 0
              nit: 23
            niter: 23
             njev: 0
       optimality: 1.9534528835387254e-07
           status: 2
          success: True
        tr_radius: 5.238777835236851e-09
                v: [array([-1.2773501])]
                x: array([1.17707733e-08, 2.30277564e+00]) 


         cg_niter: 0
     cg_stop_cond: 1
           constr: [array([4.4408921e-14, 0.0000000e+00])]
      constr_nfev: [36]
      constr_nhev: [0]
      constr_njev: [0]
   constr_penalty: 2.1867764273118655
 constr_violation: 4.440892098500626e-14
   execution_time: 0.012656688690185547
              fun: -24.59492687150548
             grad: array([  5.27636947, -10.30629829])
              jac: [array([[15.60368701, -9.30629829],
       [-6.27636948, -9.30629823]])]
  lagrangian_grad: array([1.77635684e-15, 0.00000000e+00])
          message: '`gtol` termination condition is satisfied.'
           method: 'equality_constrained_sqp'
             nfev: 36
             nhev: 0
              nit: 12
            niter: 12
             njev: 0
       optimality: 1.7763568394002505e-15
           status: 1
          success: True
        tr_radius: 4.9172480000000025
                v: [array([-0.55882674, -0.54862737])]
                x: array([2.63818474, 5.1531491 ])

我尝试了一种模块化的方式。由于脚本相当大,因此它基于github的要点

这里的Residualer是一个组,用于实现Residualer功能。在initialize方法中,我定义了特定于每个实例化的选项

每个实例化为f、g和h创建自己的子系统。实际上,我可能会制作一个输出f、g和h的组件,因为它们是简单的方程,彼此独立

problem1\u优化器和problem2\u优化器使用对残差具有相等约束的scipy优化器,正如您的示例所做的那样

problem2_优化器的N2为:

problem2_solver使用residualer上的use_solver选项包括平衡组件和Newton solver。该平衡分量为x中的每个元素添加一个隐式变量,该元素具有相应的残差R或S。这两个标量值x1和x2被多路复用到x变量中,然后通过提升传递到相应的分量。如编码所示,这要求每个标量隐式变量都有一个残差,因此它只适用于第二个示例。请注意,以下未连接的输入是由于我们的平衡公司只接受一个变量B le,并对方程的另一侧使用假设值0.0。第二种情况下没有优化,因为只有两个变量和两个未知数,因此没有更多的优化自由度


使用外部代码comps对于解决这个问题中的任何细节都不是真正必要的。另外,你关于在所有飞行条件下匹配俯仰和稳定性的陈述意味着你实际上有很大的耦合方程向量。请尝试将其归结为一个更紧凑的代表性示例,即使您无法在OpenMDAO中对其进行表述,也请提供基本方程或独立的python脚本,以实现您所寻求的收敛。正如所提出的,这个问题太宽泛了,不能给出一个好的答案。对不起,我的意思是明确地编辑了这个问题。我将试着准备一个Python脚本,并相应地编辑问题。@JustinGray添加了Python示例。这很好,也很有启发性。非常感谢您抽出时间来写这篇文章!不过,我对重新设计这个有一些疑问。假设我想把一个平衡comp作为一个组放在每个方程R和S中,所以它们是隐式分量而不是显式分量;在这种情况下,R和S都有各自的x_0和x_1,它们需要相互同步以求解耦合系统。这是可行的还是设计设置不可行?隐式组件定义隐式变量x_i及其相关残差。OpenMDAO中的解算器通过改变组内或组下的所有隐式变量来满足组内或组下的所有残差。所以,是的,一个包含R和S的组中的单个牛顿解算器在收敛时将同时满足这两个条件。有时这会变得很难思考:x_1应该与R或S相关联吗?通常,您可以将它们视为一个由两个变量和两个残差组成的系统,解算器将为您处理。如果我们将x_1和x_2作为单独的输入传递给f、g和h,那么这个代码可能会更容易处理,这样我们就可以去掉mux。