OpenMDAO:什么时候需要定义偏导数?

OpenMDAO: When is it needed to define the partial derivative?

我注意到定义不必要的偏导数会显着降低优化器的速度。因此我试图理解:我怎么知道我是否应该为某个 input/output 关系定义偏导数?

我认为如果它们与优化中的响应(约束或 objective)相关,或者作为组内非线性求解的一部分,则需要对其进行定义。我个人的做法是始终定义它们。如果我经常更改我的优化问题,我不想返回并确保我始终定义适当的导数。

OpenMDAO 的主分支包含一些雅可比着色技术,如果您的问题本质上特别稀疏,这些技术可以显着提高性能。通过在驱动程序上设置以下选项来启用此方法:

p.driver.options['dynamic_simul_derivs'] = True
p.driver.options['dynamic_simul_derivs_repeats'] = 5

此方法的工作原理是用随机数填充用户描述的稀疏模式(在 declare partials 中用 rowscols 指定)并计算总雅可比矩阵。重复选项可以提高对结果的信心,因为单次通过可能但不太可能导致雅可比矩阵中的 "incidental zero" 并不是真正的稀疏结构的一部分。

通过这种技术,通过计算向量化而不是使用嵌套 for 循环,我在很多情况下都获得了非常好的性能。当然,这些方法的有效性会因模型而异。

当您说 "unnecessary" 时,您是指始终为零的偏导数吗?

使用 declare_partials('*', '*'),当组件确实比这更稀疏时,会显着降低模型速度。在偏导数始终为零的任何地方,您都不应该声明它。

此外,如果你有向量化运算,那么你的雅可比实际上是一个对角矩阵。在这种情况下,您应该通过向 declare_partial 调用 1 提供 rowscols 参数来声明 [稀疏偏导数]。这通常会大大加快您的代码速度。

从技术上讲,如果您遵循从所有设计变量到每个组件的数据路径,再到 objective 和约束,那么您传递的任何变量都需要定义其部分。但实际上你应该声明并指定每个输出的所有部分 w.r.t。每个输入(除非它们为零),因此对模型连接的更改不会破坏您的导数。

更稀疏地声明你的部分需要多一点时间,但性能加速是值得的。