在 OpenMDAO 的 ExecComp 中,shape_by_conn 与 has_diag_partials 兼容吗?

In OpenMDAO's ExecComp, is shape_by_conn compatible with has_diag_partials?

我有一个执行简单操作的 om.ExecComp

"d_sq = x**2 + y**2"

其中 xyd_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', rows=row_col, cols=row_col)

    def compute(self, inputs, outputs): 

        outputs['d_sq'] = inputs['x']**2 + inputs['y']**2

    def compute_partials(self, inputs, 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 使用一个可以清楚地显示问题的测试用例(即会引发您看到的错误)。在这种情况下,提供的手动组件可以作为解决方法。