有没有办法缓存 OpenMDAO 组件输出以避免重复执行?

It there a way to cache OpenMDAO component outputs to avoid duplicate executions?

我正在编写一个由五个子系统组成的模型。第一个子系统使用它不迭代解决任何问题的输入为其他子系统生成数据,因此它的输出在计算过程中没有改变。我希望它像初始化一样调用一次计算方法。我如何编写一个在 run_model 中调用一次并在 run_driver 中每次调用一次的模型?

如果没有更多细节,很难确定,但你提到了“迭代”,所以我猜你在模型的顶层有一个求解器,并且有一个组件不涉及该求解器循环,但是每次求解器迭代时都会被调用。

这个问题的解决方案是在您的模型中创建一个仅包含需要迭代的组件的子组。将 only-运行-once 组件与该组一起放在模型的顶部。将迭代求解器放在子组上。

另一种解决方案是向您的组件添加一些缓存,以便它检查其输入以查看它们是否已更改。如果有,重新运行。如果他们没有,请保留旧答案。

这是一个包含这两个特征的示例(注意:此示例中的求解器不收敛,因为它是一个玩具问题,没有有效的物理解决方案。我只是将它们放在一起来说明模型结构和缓存)

import openmdao.api as om
# from openmdao.utils.assert_utils import assert_check_totals


class StingyComp(om.ExplicitComponent): 

    def setup(self): 

        self.add_input('x1', val=2.)
        self.add_input('x2', val=3.)

        self.add_output('x')

        self._input_hash = None


    def compute(self, inputs, outputs):

        x1 = inputs['x1'][0] # pull the scalar out so you can hash it
        x2 = inputs['x2'][0]

        print("running StingyComp")
        current_input_hash = hash((x1, x2))
        if self._input_hash != current_input_hash : 
            print('    ran compute')
            outputs['x'] = 2*x1 + x2**2
            self._input_hash = current_input_hash
        else: 
            print('    skipped compute')


class NormalComp(om.ExplicitComponent): 

    def setup(self): 

        self.add_input('x1', val=2.)
        self.add_input('x2', val=3.)

        self.add_output('y')

    def compute(self, inputs, outputs):

        x1 = inputs['x1']
        x2 = inputs['x2']

        print("running normal Comp")
        outputs['y'] = x1 + x2


p = om.Problem()



p.model.add_subsystem('run_once1', NormalComp(), promotes=['*'])
p.model.add_subsystem('run_once2', StingyComp(), promotes=['*'])

sub_group = p.model.add_subsystem('sub_group', om.Group(), promotes=['*']) # transparent group that could hold sub-solver
sub_group.add_subsystem('C1', om.ExecComp('f1 = f2**2 + 1.5 * x - y**2.5'), promotes=['*'])
sub_group.add_subsystem('C2', om.ExecComp('f2 = f1**2 + x**1.5 - 2.5*y'), promotes=['*'])
sub_group.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
sub_group.linear_solver = om.DirectSolver()


p.setup()


print('first run')
p.run_model()

print('second run, same inputs')
p.run_model()

p['x1'] = 10
p['x2'] = 27.5

print('third run, new inputs')
p.run_model()