首页 > 解决方案 > 因子的含义正是在组中找到的单数/单数条目

问题描述

我正在努力解决由隐式组件引起的关于组中单个条目的错误,但我不知道如何解决它。

我们基于有效性-NTU 方法创建了一个百叶式翅片换热器模型。它使用 ImplicitComponent 以这样一种方式求解系统,即“猜测的”出口温度(用于计算流体特性)等于根据实际传热计算的实际出口温度。该组件似乎运行良好,可以在此处找到该基础热交换器的 N2 图。

其中,两个输入是冷侧和热侧的质量流量(参见原始 N2 中的独立性)。然而,验证数据使用冷侧流速和热侧体积流速而不是质量流速。虽然不是直接的组输入,但这些属性是在热交换器组内计算的。手动更改质量流量,直到流速和体积流量满足验证数据的要求。但我想我可以在热交换器组周围添加一个额外的隐式组件来为我完成这项工作。可以在此处找到生成的 N2 图。但是,此隐式组件会导致错误:

Traceback (most recent call last):
  File "...\openmdao\solvers\linear\direct.py", line 275, in _linearize
    self._lu = scipy.sparse.linalg.splu(matrix)
  File "...\scipy\sparse\linalg\dsolve\linsolve.py", line 326, in splu
    ilu=False, options=_options)
RuntimeError: Factor is exactly singular

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "louveredfin3.py", line 91, in <module>
    p.run_model()
  File "...\openmdao\core\problem.py", line 527, in run_model
    self.model.run_solve_nonlinear()
  File "...\openmdao\core\system.py", line 3734, in run_solve_nonlinear
    self._solve_nonlinear()
  File "...\openmdao\core\group.py", line 1886, in _solve_nonlinear
    self._nonlinear_solver.solve()
  File "...\openmdao\solvers\solver.py", line 597, in solve
    raise err
  File "...\openmdao\solvers\solver.py", line 593, in solve
    self._solve()
  File "...\openmdao\solvers\solver.py", line 384, in _solve
    self._single_iteration()
  File "...\openmdao\solvers\nonlinear\newton.py", line 230, in _single_iteration
    self._linearize()
  File "...\openmdao\solvers\nonlinear\newton.py", line 161, in _linearize
    self.linear_solver._linearize()
  File "...\openmdao\solvers\linear\direct.py", line 278, in _linearize
    raise RuntimeError(format_singular_error(system, matrix))
RuntimeError: Singular entry found in Group (<model>) for column associated with state/residual 'ConvertInputs.m_dot_hot' index 0.

这个错误在实际中意味着什么?求解器是否无法通过更改输出(在这种情况下为 m_dot_hot 和 m_dot_cold)来减少残差?但是,如果是这种情况,我无法理解为什么,因为手动更改质量流量确实会导致“V_cold”和“flowrate_hot”发生变化。

作为替代方案,我尝试对同一级别的所有组件(此处为 N2 )仅使用一个求解器,但这会导致相同的错误。同样去除原始温度隐含分量(即只有一个隐含分量,它会改变质量流量)也不能解决问题。

如果有帮助,隐式组件看起来像这样(暂时使用单个值而不是长度为 n 的数组):

class ConvertInputs(om.ImplicitComponent):

    def initialize(self):
        self.options.declare('n', default=1, desc='length of the array')

    def setup(self):
        self.add_input('flowrate_hot_required', val=1.33, desc='required flowrate', units='L/s')
        self.add_input('flowrate_hot', val=1.33, desc='actual flowrate', units='L/s')
        self.add_input('V_cold_required', val=8., desc='required air velocity', units='m/s')
        self.add_input('V_cold', val=8., desc='actual air velocity', units='m/s')
        self.add_output('m_dot_hot', val=1.296, desc='hot side mass flow rate', units='kg/s')
        self.add_output('m_dot_cold', val=1.655, desc='cold side mass flow rate', units='kg/s')

        self.declare_partials('*', '*', method='fd')

    def apply_nonlinear(self, inputs, outputs, residuals):
        residuals['m_dot_hot'] = inputs['flowrate_hot'] - inputs['flowrate_hot_required']
        residuals['m_dot_cold'] = inputs['V_cold'] - inputs['V_cold_required']

和 FluidProperties 中的相关行如下:

        outputs['flowrate_hot'] = inputs['m_dot_hot'] / (outputs['rho_hot_in']*1e-3)
        outputs['V_cold'] = inputs['m_dot_cold'] / (outputs['rho_cold_in'] * inputs['A_flow_cold'])

使用的求解器是 NewtonSolver (solve_subsystems=True) 和 DirectSolver。此外,我仔细检查了是否在任何地方都声明了派生类(例如,现在所有组件中的 self.declare_partials(' * ', ' * ', method='fd') ),但到目前为止没有成功。

编辑——基于贾斯汀的回答: 谢谢你的回答和提示!我实现了 BalanceComp 替换顶级隐式组件,但不幸的是它没有任何区别。为顶级求解器设置 maxiter=0 仍然会引发错误,但较低的求解器似乎可以毫无问题地求解:

+  
+  ========
+  original
+  ========
+  NL: Newton 0 ; 14.3235199 1
+  NL: Newton 1 ; 0.0668341831 0.00466604463
+  NL: Newton 2 ; 0.000273898972 1.91223229e-05
+  NL: Newton 3 ; 1.17390481e-06 8.1956448e-08
+  NL: Newton 4 ; 5.0212449e-09 3.50559425e-10
+  NL: Newton 5 ; 2.14662005e-11 1.49866797e-12
+  NL: Newton Converged
NL: Newton 0 ; 0.252556049 1
Traceback (most recent call last):
[…]
RuntimeError: Factor is exactly singular

感受一下大小:仅使用 HX 子系统并手动更改独立的“m_dot_hot”和“m_dot_cold”,步长为 1e-6:

Diff. flowrate_hot = -1.0271477852707989e-06
Diff. V_cold = -4.6808071525461514e-06

我还没有意识到您实际上可以为隐式组件添加边界,这非常有用,我为两个隐式组件都添加了它们。不幸的是,这个错误也没有改善。将顶级隐式组件和 FluidProperties 的部分设置为复杂步骤也没有改善这种情况。应该对所有组件执行此操作,还是仅对此处涉及的组件执行此操作?

但是,当我在隐式组件中打印“m_dot_*”输出时,我注意到以下内容,以及分别在 apply_nonlinear() 和 compute() 中的 FluidProperties 组件中打印“m_dot_*”输入。它表明,在换热器子系统求解后,顶层隐式组件“m_dot_*”输出随着 1e-6 的步长变化,正如我期望的梯度计算那样。但是,在此之后,FluidProperties 中的输入根本不再打印,并且很快就会出现奇异错误。因此,对我来说,似乎不再调用较低级别的 FluidProperties 计算方法。由于没有给出分析导数或设置值(即,所有输入只使用 FD),在我看来,FluidProperties 组件永远不会使用“m_dot_*”步长执行,并且没有(成功或正确)计算梯度。尽管如此,N2 图表显示顶层到子系统的输入/输出已正确连接。这可能是指向特定问题的指针吗?

标签: openmdao

解决方案


您的错误 ( RuntimeError: Singular entry found in Group (<model>) for column associated with state/residual 'ConvertInputs.m_dot_hot' index 0.) 表明,该列中的所有偏导数均为 0。

实际上,这意味着就 OpenMDAO 而言,更改'ConvertInputs.m_dot_hot'不会影响模型中的任何残差。

您可以尝试的一件事是使用 OpenMDAO 标准库中的BalanceComp。该组件专为您要完成的任务而设计,但已经定义了衍生产品。这将解决您的问题的可能性很小,但可能不会。

我推荐的是以下内容:

  1. max_iter顶级牛顿求解器上的选项设置为 0(子求解仍将运行)。然后您可以运行您的模型并手动更改您的猜测,m_dot_hot看看您是否真的可以手动将其收敛到内置耦合的模型中。也许您在此模型中进行连接的方式存在错误导致问题. 您说您可以手动收敛原始模型,这一步将确保您的耦合模型也有解决方案

  2. 我注意到您没有对设计变量定义任何界限。也许求解器在其迭代中将 m_dot_hot 驱动为 0 或负数。我建议将下限和上限设置为合理的值,如下所示

     self.add_output('m_dot_hot', val=1.296, desc='hot side mass flow rate', units='kg/s', lower=1e-4, upper=10)
     self.add_output('m_dot_cold', val=1.655, desc='cold side mass flow rate', units='kg/s', lower=1e-4, upper=10)
    

    对于 OpenMDAO V3.0 及更高版本,牛顿求解器的默认设置是使用边界强制线搜索,这将在尝试收敛时遵守这些限制

  3. 考虑切换到cs偏导数的方法。FD 值可能不是很好(至少在默认步长下,你得到的是数字而不是物理的 0。


推荐阅读