问题描述
"d_sq = x**2 + y**2"
其中 x
、y
和 d_sq
始终是一维 np.array
。我希望能够在不分配大型密集矩阵的情况下将其与大型数组一起使用。我还希望根据连接的形状配置阵列的长度。
但是,如果我指定 x={"shape_by_conn": True}
而不是 x={"shape":100000}
,即使我也有 has_diag_partials=True
,它也会尝试分配一个 100000^2 的数组。有没有办法让这两个选项兼容?
解决方法
首先,我会注意到您使用 ExecComp
有点超出其设计预期用途。这并不是说你完全无效,但一般来说 ExecComp 是为小型、廉价的计算而设计的。将巨型数组传递给它不是我们测试的内容。
话虽如此,我认为你想要的会奏效。当您在此使用 shape_by_conn
时,您需要确保调整输入和输出的大小。我已经提供了一个例子,以及一个手动定义的组件,它可以做同样的事情。由于您的方程式非常简单,因此总体上会快一些。
import numpy as np
import openmdao.api as om
class SparseCalc(om.ExplicitComponent):
def setup(self):
self.add_input('x',shape_by_conn=True)
self.add_input('y',shape_by_conn=True)
self.add_output('d_sq',shape_by_conn=True,copy_shape='x')
def setup_partials(self):
# when using shape_by_conn,you need to delcare partials
# in this secondary method
md = self.get_io_metadata(iotypes='input')
# everything should be the same shape,so just need this one
x_shape = md['x']['shape']
row_col = np.arange(x_shape[0])
self.declare_partials('d_sq','x',rows=row_col,cols=row_col)
self.declare_partials('d_sq','y',cols=row_col)
def compute(self,inputs,outputs):
outputs['d_sq'] = inputs['x']**2 + inputs['y']**2
def compute_partials(self,J):
J['d_sq','x'] = 2*inputs['x']
J['d_sq','y'] = 2*inputs['y']
if __name__ == "__main__":
p = om.Problem()
# use IVC here,because you have to have something connected to
# in order to use shape_by_conn. Normally IVC is not needed
ivc = p.model.add_subsystem('ivc',om.IndepVarComp(),promotes=['*'])
ivc.add_output('x',3*np.ones(10))
ivc.add_output('y',2*np.ones(10))
# p.model.add_subsystem('sparse_calc',SparseCalc(),promotes=['*'])
p.model.add_subsystem('sparse_exec_calc',om.ExecComp('d_sq = x**2 + y**2',x={'shape_by_conn':True},y={'shape_by_conn':True},d_sq={'shape_by_conn':True,'copy_shape':'x'},has_diag_partials=True),promotes=['*'])
p.setup(force_alloc_complex=True)
p.run_model()
如果您仍然发现这没有按预期工作,请随时submit a bug report 使用一个测试用例来清楚地显示问题(即会引发您看到的错误)。在这种情况下,提供的手动组件可以作为一种解决方法。