我在 openMDAO 中使用 SLSQP 算法,但我无法理解它的实际工作原理。我只是看常见的抛物面示例,它有 2 个设计变量,旨在最小化 f,没有任何限制。通过打印每次迭代的 x、y 和 f 的值(迭代可能不是正确的词),我可以看到有时使用每个设计变量(x,y)的前向有限差分来评估一阶导数。然后使用这些导数来查找下一个 x 和 y 值,但是我看不到该模式。
另外,当我读到 SLSQP 方法时,还需要二阶导数。但是,我没有看到它被计算出来。让我举一个我的输出的例子:
iteration 1:
x = 0
y = 0
f = 22
iteration 2:
x = 0.01
y = 0
f = 21.9401
iteration 3:
x = 0
y = 0.01
f = 22.0801
Run Code Online (Sandbox Code Playgroud)
从最后 2 次迭代中,我们可以计算出 df/dx = 5.99 , df/dy = -8.01
下一次迭代恰好是:
x = 5.99
y = -8.01
f = -25.9597
Run Code Online (Sandbox Code Playgroud)
然后从这一点再次进行两次有限差分计算找到: df/dx = 2.02 , df/dy = 2.02 …
optimization mathematical-optimization scipy openmdao scipy-optimize
我正在尝试编写代码来计算机翼上的边界层发展。
我从一组点S开始,它们描述了机翼的形状。
我在这些点上运行无粘解算器并提取驻点,这将是S的一个元素。
点集S现在被驻点分为两组s u和s l,它们描述了上边界层和下边界层下方的机翼形状。
这是我的第一个问题。假设我编写了一个组件 BoundaryLayerSolve,它采用边界层中的点向量s和该边界层的边缘速度向量u e 。s和u e的长度相同。如果我想使用这个组件两次,机翼的每一侧一次,我需要先验地知道驻点的位置,直到模型已经设置并运行无粘解算器时才能找到该位置。我该如何设置它才能处理这些未知的输入数组大小?
现在已知上下边界层的输入s和u e数组,可以计算边界层。我将使用两种模型,一种用于边界层的层流区域,另一种用于湍流区域。假设这两个模型使用完全不同的计算,并且这些计算足够复杂,为了找到它们的解析偏导数,必须将它们分解为子组件。
层流计算从驻点开始并沿s进行。在每一步,都会计算动量厚度的值。如果达到转变阈值,则层流计算必须停止,并且必须对s的其余部分使用湍流计算。我应该强调的是,不能选择对所有s进行层流,对所有s进行湍流,然后简单地切掉层流输出的后部和湍流输出的前部。湍流计算必须从过渡点层流计算的值开始。
在伪代码中,这将类似于:
transition_point = 0
for index, point in enumerate(s):
transition_point += 1
momentum_thickness = laminar(point)
if momentum_thickness > transition_threshold:
break
for point in s[transition_point+1:]:
turbulent(s)
Run Code Online (Sandbox Code Playgroud)
这是我的第二个问题。直到层流计算期间才知道转变点,因此层流计算的输出动量_厚度数组的长度是先验未知的。因此,用于湍流计算的输入点阵列的长度也是先验未知的。我该如何解决这个问题?
这是我的第三个问题。如何让一个组件在满足条件后终止其计算,并传递给另一个组件以完成数组其余部分的计算?
收集我的问题:
我知道这是一个很长的问题,也许可以分解。感谢您提前阅读。
我正在尝试熟悉 OpenMDAO。我发现难以理解的一件事是集成/状态变量如何在 OpenMDAO 的单独组件中工作。我认为这非常重要,我想了解基础知识。
假设我有一个具有恒定推力和变化质量的火箭,我想用离散时间和 0.1 秒的时间步长模拟飞行的前 10 秒。假设质量的变化也是时间的函数,但也假设它是一个依赖于许多事物的困难变量,因此我们希望在不同的组件中计算它并简单地作为该组件的输入。
- 如何确保质量在速度的离散时间步计算中更新,同时在不同的组件中?
下面的代码是我尝试解决这个示例问题的一个平庸的尝试,但我现在相当确定 Mass 是一个简单的静态输入,而它应该随时间发生某种任意的变化。(假设推力是常数)
from openmdao.api import ExplicitComponent
class VelocityComponent(ExplicitComponent):
def setup(self):
self.add_input('T', desc='Propulsion Thrust')
self.add_input('M', desc='Instanteneous Mass')\
self.add_output('v', desc='Satellite Velocity')
self.declare_partials('*','*')
def compute(self, inputs, outputs)
v = 10 #some initial velocity value
t = 0 #initial time value
tstep = 0.1
tend = 10
for i in range(0,tend/tstep):
a = inputs['T']/inputs['M'] #calculate acceleration
v += a #update velocity
t += tstep #next time step
outputs['v'] = v
Run Code Online (Sandbox Code Playgroud)
速度 v …
我使用 OpenMDAO 半结构化元模型作为 Dymos 优化的一部分。有两个输入值,因此范围是二维的。通常,这工作得很好。然而,我最近注意到,对于一组特定的训练数据,它无法正确插值。
我使用元模型 html 可视化工具来查看发生的情况,可以看到拟合是错误的。将鼠标悬停在某些数据点上,我可以看到它们正确显示输入数据值。然而,将光标向任意方向稍微远离该点,插值结果就会大不相同。这意味着元模型“拟合”不会经过训练数据点,甚至在某些区域接近它。
使用“线性”方法时出现此问题。我将其改为使用“lagrange2”,现在看起来拟合得好多了。不过,这种方法的计算量似乎非常大,因为我的优化尚未完成,而且它已经是使用“线性”所需时间的 3 倍以上。因此,我希望能够回到“线性”。
有谁知道为什么会发生这种情况以及如何解决该问题?非常感谢所有帮助。谢谢。
我有一个2D阵列的参数.它可以正常输出正确但当我尝试使用渐变(例如优化或check_total_derivatives)做任何事情时,我得到一个大小调整错误.我想知道处理2D大小的params最好的方法是什么.这是一个示例代码:
import numpy as np
from openmdao.api import Group, Problem, Component, IndepVarComp, ExecComp
class C1(Component):
def __init__(self, n):
super(C1, self).__init__()
self.add_param('grid', val=np.zeros((n, n)))
self.add_output('x', shape=1)
self.n = n
def solve_nonlinear(self, params, unknowns, resids):
x = 0
for i in range(self.n):
for j in range(self.n):
x += params['grid'][i][j]
unknowns['x'] = x
def linearize(self, params, unknowns, resids):
J = {}
J['x', 'grid'] = np.ones((self.n, self.n))
return J
class Group1(Group):
def __init__(self, n):
super(Group1, self).__init__()
self.add('grid', IndepVarComp('grid', np.zeros((n, n))), promotes=['*'])
self.add('c1', C1(n), promotes=['*']) …Run Code Online (Sandbox Code Playgroud) 我遇到了一个问题,Group其中包括OpenMDAO中子系统之间的反馈.我正在使用NonlinearBlockBS求解器.我希望Gauss-Seidel求解器能够顺序运行子系统,将早期块的输出传递给其他输入.但是,当我在OpenMDAO中实现它时,似乎不会发生这种情况.
我已经制作了一个示例脚本来演示此问题:
class A(ExplicitComponent):
def setup(self):
self.add_input('x', shape=1)
self.add_input('b', shape=1)
self.add_output('a', shape=1)
def compute(self, inputs, outputs):
outputs['a'] = inputs['x'] + 2 * inputs['b']
print('A: x = {:1.0f}, b = {:1.0f}, a = {:1.0f}'.format(inputs['x'][0], inputs['b'][0], outputs['a'][0]))
class B(ExplicitComponent):
def setup(self):
self.add_input('x', shape=1)
self.add_input('a', shape=1)
self.add_output('b', shape=1)
def compute(self, inputs, outputs):
outputs['b'] = inputs['x'] - 0.5 * inputs['a']
print('B: x = {:1.0f}, a = {:1.0}, b = {:1.0f}'.format(inputs['x'][0], inputs['a'][0], outputs['b'][0]))
if __name__ == '__main__':
ivc = IndepVarComp()
ivc.add_output('x', …Run Code Online (Sandbox Code Playgroud) 我刚刚完成了阅读器和记录器的教程。我想知道是否有一种方法可以计算每个学科被调用的次数。下面我在 Sellar 问题中使用全局变量来计算这个。更好的方法是什么?另外,如果问题没有解决者,建议的方式会改变吗?
import numpy as np
import time
import openmdao.api as om
tic = time.perf_counter()
dc1 = 0
dc2 = 0
class SellarDis1(om.ExplicitComponent):
def setup(self):
self.add_input('z', val=np.zeros(2))
self.add_input('x', val=0.)
self.add_input('y2', val=1.0)
self.add_output('y1', val=1.0)
self.declare_partials('*', '*', method='fd')
def compute(self, inputs, outputs):
global dc1
dc1+=1
z1 = inputs['z'][0]
z2 = inputs['z'][1]
x1 = inputs['x']
y2 = inputs['y2']
outputs['y1'] = z1**2 + z2 + x1 - 0.2*y2
class SellarDis2(om.ExplicitComponent):
def setup(self):
self.add_input('z', val=np.zeros(2))
self.add_input('y1', val=1.0)
self.add_output('y2', val=1.0)
self.declare_partials('*', '*',method='fd')
def compute(self, inputs, …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 SLSQP 来优化机翼的迎角,以将驻点放置在所需的位置。这纯粹是作为一个测试用例,以检查我计算停滞位置的部分的方法是否有效。
当使用 COBYLA 运行时,优化在 47 次迭代后收敛到正确的 alpha (6.04144912)。当使用 SLSQP 运行时,它完成一次迭代,然后挂起很长时间(10、20 分钟或更长时间,我没有准确计时),并以错误值退出。输出是:
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|0
--------------------------------------------------------------
Design Vars
{'alpha': array([0.5])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'obj_cmp.obj': array([0.00023868])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|1
--------------------------------------------------------------
Design Vars
{'alpha': array([0.5])}
Nonlinear constraints
None
Linear constraints
None
Objectives
{'obj_cmp.obj': array([0.00023868])}
Optimization terminated successfully. (Exit mode 0)
Current function value: 0.0002386835700364719
Iterations: 1
Function evaluations: 1
Gradient evaluations: 1
Optimization Complete
-----------------------------------
Finished optimisation …Run Code Online (Sandbox Code Playgroud) 我刚刚在超级计算机上安装了OpenMDAOv1.3.安装成功,所有测试都通过或跳过.但是,当我运行测试时,我得到以下警告:
*path/OpenMDAO/openmdao/core/driver.py:228: UserWarning: parallel derivs %s specified but not running under MPI
warnings.warn("parallel derivs %s specified but not running under MPI")
Run Code Online (Sandbox Code Playgroud)
我不知道该怎么做(如果有的话),所以我正在寻找有关警告信息含义的信息.我们计划与OpenMDAO的内置MPI功能并行运行.我目前在系统上加载了openmpi-1.8.4.
我正在学习第一个Paraboloid教程的 OpenMDAO .但是,在我使用约束情况(add_constraint(...))运行代码时,我得到错误:AttributeError:'float'对象没有属性'size'.我只是复制粘贴了教程中的代码,但我无法解决错误.这是代码:
from __future__ import print_function
from openmdao.api import IndepVarComp, Component, Problem, Group
from openmdao.api import ScipyOptimizer
from openmdao.api import ExecComp
class Paraboloid(Component):
def __init__(self):
super(Paraboloid, self).__init__()
self.add_param('x', val=0.0)
self.add_param('y', val=0.0)
self.add_output('f_xy', shape=1)
def solve_nonlinear(self, params, unknowns, resids):
"""f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3
"""
x = params['x']
y = params['y']
unknowns['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
def linearize(self, params, unknowns, resids):
""" Jacobian for our paraboloid."""
x = params['x']
y = …Run Code Online (Sandbox Code Playgroud) 我一般是 OpenMDAO 和 MDO 的新手。我喜欢使用 OpenMDAO,并想了解更多。目前我正在阅读有关 MDO 架构的信息。当我在 Openmdao 中“正常”运行问题时,MDO 架构是什么。如果我假设它是整体 AAO(因为它计算总导数并从那里解决问题),我是否正确?我问这个是因为我读到了 MAUD 架构(在本文中描述),这让我感到困惑。这是否可以被视为 MDO 架构的一种分类(因为它确实提供了数学和算法框架)还是只是一种纯粹的计算架构?
最后,通过在 OpenMDAO 中实现大规模设计问题来比较不同的 MDO 架构(如 MDF、CO、ATC 等)是否有意义?我知道 OpenMDAO 专注于单体架构。那么在 OpenMDAO 中比较单体架构和分布式架构是否公平?来自 OpenMDAO V1的 MDO 架构基准测试结果(在本文中)是否仍然适用于当前版本的 OpenMDAO V2(即在合并来自 MAUD 架构的想法之后)?
谢谢你。
我正在使用 SLSQP 优化器。我记得在某处读到过,有一个目标函数或设计变量的最佳大小(或者可能是两者之间的比率?)来搜索设计空间。例如,如果我的目标函数大一个数量级,那么设计空间的跳跃似乎也大一个数量级。
如果这个跳跃太小,它可能会限制它搜索的设计空间的数量,或者可能需要很长时间才能到达某个点。然而,太大的跳跃也不好。
任何帮助,将不胜感激。如果有不清楚的地方,请告诉我。谢谢!