计算雅可比向量积时出错

Error when computing jacobian vector product

我有一个包含耦合学科的小组,该小组嵌套在一个所有其他组件都未耦合的模型中。我已将非线性牛顿和线性直接求解器分配给耦合组。

当我尝试 运行 具有默认 "RunOnce" 求解器的模型时,一切正常,但是一旦我尝试 运行 优化,我就会收到 [=34] 引发的以下错误=]:

File "...\openmdao\core\group.py", line 1790, in _apply_linear scope_out, scope_in)
File "...\openmdao\core\explicitcomponent.py", line 339, in _apply_linear self.compute_jacvec_product(*args)
File "...\Thermal_Cycle.py", line 51, in compute_jacvec_product d_inputs['T'] = slope * deff_dT / alp_sc File "...\openmdao\vectors\vector.py", line 363, in setitem raise KeyError(msg.format(name)) KeyError: 'Variable name "T" not found.'

下面是模型的N2图。错误中提到的变量 "T" 来自隐式 "temp" 组件,并作为输入反馈给 "sc" 组件(错误消息中的文件 Thermal_Cycle.py)。

N2 diagram

当我在整个模型之上分配 DirectSolver 时,错误消失了。我的印象是 "RunOnce" 只要具有隐式组件的组按照建议 here 对它们应用适当的求解器就可以工作,并且在我的例子中已经完成。为什么在尝试计算模型的全导数时它不起作用,即为什么 compute_jacvec_product 找不到耦合变量 "T"?

我想使用 "RunOnce" 求解器的原因是,随着我的变量向量 "T" 的增加,在顶部使用 DirecSolver 的优化变得非常长。我怀疑线性 "RunOnce"?

应该快得多

基于 N2,我 认为 我同意您将直接求解器仅放在耦合周围的策略。那应该可以正常工作,但是看起来您正在组件中实现线性运算符,基于:

File "...\Thermal_Cycle.py", line 51, in compute_jacvec_product d_inputs['T'] = slope * deff_dT / alp_sc 

您不应将直接求解器与无矩阵分音一起使用。直接求解器计算逆矩阵,这需要矩阵的完整组装。它起作用的唯一原因是 OM 具有一些后备功能,可以通过 compute_jacvec_product 方法传递单位矩阵的列来手动 assemble 雅可比矩阵。 这种回退机制可以使事情正常进行,但速度非常慢(您最终会调用 compute_jacvec_product 很多)。

你得到的错误,以及为什么当你把直接求解器放在模型中更高的位置时它会起作用,可能是因为你的 compute_jacvec_product 实现中缺少必要的 if 条件. 请参阅 docs on explicit component for some examples,但关键的见解是要认识到在执行 jacvec 乘积时并非每个变量都会出现(这取决于正在执行的求解类型——即一个用于牛顿,一个用于总计整个模型的导数)。 所以需要那些 if-checks 来检查变量是否相关。这样做是因为对于昂贵的代码(即 CFD),其中一些操作非常昂贵,除非需要,否则您不想执行它们。

是不是你的组件大到无法使用compute_partials功能?你试过specifying the sparsity in your jacobian了吗?通常,在您开始使用具有 1e6 或更多隐式输出变量的真正大型 PDE 求解器之前,不需要矩阵自由偏导数方法。

没有看到一些代码,很难评论更多细节,但总而言之: 您不应将 compute_jacvec_product 与直接求解器结合使用。如果你真的需要无矩阵部分,那么你需要切换到像 PetscKrylov 这样的迭代线性求解器。

如果你可以 post Thermal_Cycle.py 中具有 compute_jacvec_product 的组件的代码,我可以就如何处理这种情况下的偏导数给出更详细的建议.

我认为 compute_jacvec_product 方法的这个示例可能会有所帮助。

问题是,根据求解器配置或模型结构,OpenMDAO 可能只需要您在此方法中提供的部分部分。例如,你的无矩阵组件可能有两个输入,但只有一个是连接的,所以 OpenMDAO 不需要关于未连接输入的导数,事实上,在 d_inputs 或 d_outputs 向量。

所以,要解决这个问题,你只需要在赋值之前加上一个 if 语句,就像在例子中一样。