factor 的含义完全是在组中找到的单数/单数条目
Meaning of factor is exactly singular / singular entry found in group
我正在努力解决由隐式组件引起的关于组中单个条目的错误,我无法弄清楚如何解决它。
我们基于有效性-NTU 方法创建了百叶窗翅片换热器模型。它使用 ImplicitComponent 以“猜测的”出口温度(用于计算流体属性)等于根据实际热传递计算的实际出口温度的方式求解系统。这个组件似乎 运行 很好,可以找到这个基础热交换器的 N2 图 here。
其中,两个输入是冷侧和热侧的质量流量(参见原始 N2 中的 indeps)。然而,验证数据使用冷侧流速和热侧体积流量而不是质量流量。虽然不是直接组输入,但这些属性是在热交换器组内计算的。手动更改质量流量,直到流速和体积流量满足验证数据的要求即可。但我想我可以在热交换器组周围添加一个额外的隐式组件来为我完成这项工作。可以找到生成的 N2 图 here。但是,此隐式组件会导致错误:
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 here) 上的所有组件仅使用一个求解器,但这会导致相同的错误。同样删除原始温度隐式分量(即只有一个隐式分量,它会改变质量流量)也没有解决问题。
如果有帮助,隐式组件如下所示(暂时使用单个值而不是长度为 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 子系统并手动更改步长为 1e-6 的独立函数“m_dot_hot”和“m_dot_cold”:
Diff. flowrate_hot = -1.0271477852707989e-06
Diff. V_cold = -4.6808071525461514e-06
我还没有意识到您实际上可以为隐式组件添加边界,这非常有用,我为两个隐式组件都添加了边界。不幸的是,错误也没有得到改善。将顶层隐式组件和 FluidProperties 的部分设置为复杂步骤也没有改善这种情况。应该对所有组件还是只对此处涉及的组件执行此操作?
但是,我在隐式组件中打印“m_dot_*”输出时注意到以下内容,而在 apply_nonlinear( ) 和计算 () 分别。它表明,在热交换器子系统求解后,顶层隐式分量“m_dot_*”输出以 1e-6 的步长变化,正如我预期的那样用于梯度计算。但是,在此之后根本不再打印 FluidProperties 中的输入,并且很快就会出现奇异错误。因此,对我来说,似乎不再调用较低级别的 FluidProperties 计算方法。由于没有给出分析导数或设置值(即仅 FD 用于所有输出 w.r.t。所有输入),在我看来,FluidProperties 组件永远不会以“m_dot_*”步长执行并且没有(成功或正确地)计算梯度。尽管如此,N2 图显示顶层到子系统的 inputs/outputs 已正确连接。这可能是指向具体问题的指针吗?
您的错误(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。该组件专为您要实现的目标而设计,但已经定义了衍生产品。这是一个很小的机会,这将解决您的问题,但可能不会。
我推荐的是:
将顶级牛顿求解器的 max_iter
选项设置为 0(子求解仍将 运行)。然后你可以 运行 你的模型并手动更改你对 m_dot_hot
的猜测,看看你是否真的可以在内置耦合的模型中手动收敛它。也许你做的方式有错误此模型中导致问题的连接。你说你可以手动收敛原始模型,这一步将确保你耦合模型也有解决方案
我注意到您没有为设计变量定义任何界限。也许求解器在其迭代中将 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 及更高版本,牛顿求解器的默认设置是使用边界强制线搜索,这将在尝试收敛时遵守这些限制
考虑为您的偏导数切换到 cs
方法。 FD 值可能不是很好(至少在默认步长下是这样,你得到的是数字而不是物理的 0。
我正在努力解决由隐式组件引起的关于组中单个条目的错误,我无法弄清楚如何解决它。
我们基于有效性-NTU 方法创建了百叶窗翅片换热器模型。它使用 ImplicitComponent 以“猜测的”出口温度(用于计算流体属性)等于根据实际热传递计算的实际出口温度的方式求解系统。这个组件似乎 运行 很好,可以找到这个基础热交换器的 N2 图 here。
其中,两个输入是冷侧和热侧的质量流量(参见原始 N2 中的 indeps)。然而,验证数据使用冷侧流速和热侧体积流量而不是质量流量。虽然不是直接组输入,但这些属性是在热交换器组内计算的。手动更改质量流量,直到流速和体积流量满足验证数据的要求即可。但我想我可以在热交换器组周围添加一个额外的隐式组件来为我完成这项工作。可以找到生成的 N2 图 here。但是,此隐式组件会导致错误:
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 here) 上的所有组件仅使用一个求解器,但这会导致相同的错误。同样删除原始温度隐式分量(即只有一个隐式分量,它会改变质量流量)也没有解决问题。
如果有帮助,隐式组件如下所示(暂时使用单个值而不是长度为 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 子系统并手动更改步长为 1e-6 的独立函数“m_dot_hot”和“m_dot_cold”:
Diff. flowrate_hot = -1.0271477852707989e-06
Diff. V_cold = -4.6808071525461514e-06
我还没有意识到您实际上可以为隐式组件添加边界,这非常有用,我为两个隐式组件都添加了边界。不幸的是,错误也没有得到改善。将顶层隐式组件和 FluidProperties 的部分设置为复杂步骤也没有改善这种情况。应该对所有组件还是只对此处涉及的组件执行此操作?
但是,我在隐式组件中打印“m_dot_*”输出时注意到以下内容,而在 apply_nonlinear( ) 和计算 () 分别。它表明,在热交换器子系统求解后,顶层隐式分量“m_dot_*”输出以 1e-6 的步长变化,正如我预期的那样用于梯度计算。但是,在此之后根本不再打印 FluidProperties 中的输入,并且很快就会出现奇异错误。因此,对我来说,似乎不再调用较低级别的 FluidProperties 计算方法。由于没有给出分析导数或设置值(即仅 FD 用于所有输出 w.r.t。所有输入),在我看来,FluidProperties 组件永远不会以“m_dot_*”步长执行并且没有(成功或正确地)计算梯度。尽管如此,N2 图显示顶层到子系统的 inputs/outputs 已正确连接。这可能是指向具体问题的指针吗?
您的错误(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。该组件专为您要实现的目标而设计,但已经定义了衍生产品。这是一个很小的机会,这将解决您的问题,但可能不会。
我推荐的是:
将顶级牛顿求解器的
max_iter
选项设置为 0(子求解仍将 运行)。然后你可以 运行 你的模型并手动更改你对m_dot_hot
的猜测,看看你是否真的可以在内置耦合的模型中手动收敛它。也许你做的方式有错误此模型中导致问题的连接。你说你可以手动收敛原始模型,这一步将确保你耦合模型也有解决方案我注意到您没有为设计变量定义任何界限。也许求解器在其迭代中将 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 及更高版本,牛顿求解器的默认设置是使用边界强制线搜索,这将在尝试收敛时遵守这些限制
考虑为您的偏导数切换到
cs
方法。 FD 值可能不是很好(至少在默认步长下是这样,你得到的是数字而不是物理的 0。