计数功能评估

Ant*_*one 1 openmdao

我刚刚完成了阅读器和记录器的教程。我想知道是否有一种方法可以计算每个学科被调用的次数。下面我在 Sellar 问题中使用全局变量来计算这个。更好的方法是什么?另外,如果问题没有解决者,建议的方式会改变吗?

import numpy as np
import time
import openmdao.api as om

tic = time.perf_counter()
dc1 = 0
dc2 = 0

class SellarDis1(om.ExplicitComponent):
    def setup(self):
        self.add_input('z', val=np.zeros(2))
        self.add_input('x', val=0.)
        self.add_input('y2', val=1.0)
        self.add_output('y1', val=1.0)
        self.declare_partials('*', '*', method='fd')

    def compute(self, inputs, outputs):
        global dc1
        dc1+=1
        z1 = inputs['z'][0]
        z2 = inputs['z'][1]
        x1 = inputs['x']
        y2 = inputs['y2']
        outputs['y1'] = z1**2 + z2 + x1 - 0.2*y2

class SellarDis2(om.ExplicitComponent):

    def setup(self):
        self.add_input('z', val=np.zeros(2))
        self.add_input('y1', val=1.0)
        self.add_output('y2', val=1.0)
        self.declare_partials('*', '*',method='fd')

    def compute(self, inputs, outputs):
        global dc2
        dc2 +=1
        z1 = inputs['z'][0]
        z2 = inputs['z'][1]
        y1 = inputs['y1']
        if y1.real < 0.0:
            y1 *= -1
        outputs['y2'] = y1**.5 + z1 + z2

class SellarMDF(om.Group):
    def setup(self):
        indeps = self.add_subsystem('indeps', om.IndepVarComp(), promotes=['*'])
        indeps.add_output('x', 1.0)
        indeps.add_output('z', np.array([5.0, 2.0]))

        cycle = self.add_subsystem('cycle', om.Group(), promotes=['*'])
        cycle.add_subsystem('d1', SellarDis1(), promotes_inputs=['x', 'z', 'y2'],
                            promotes_outputs=['y1'])
        cycle.add_subsystem('d2', SellarDis2(), promotes_inputs=['z', 'y1'],
                            promotes_outputs=['y2'])

        cycle.linear_solver = om.ScipyKrylov()

        cycle.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
        

        self.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',
                                                  z=np.array([0.0, 0.0]), x=0.0, y1=0.0, y2=0.0),
                           promotes=['x', 'z', 'y1', 'y2', 'obj'])

        self.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1'])
        self.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2'])

prob = om.Problem()
prob.model = SellarMDF()

driver = prob.driver = om.ScipyOptimizer()
prob.driver.options['optimizer'] = 'SLSQP'

prob.model.add_design_var('x', lower=0, upper=10)
prob.model.add_design_var('z', lower=0, upper=10)

prob.model.add_objective('obj')
prob.model.add_constraint('con1', upper=0)
prob.model.add_constraint('con2', upper=0)
prob.setup()
prob.set_solver_print(level=0)

prob.run_driver()

print('minimum found at')
print(prob['x'][0])
print(prob['z'])

print('Coupling Variables')
print(prob['y1'][0])
print(prob['y2'][0])

print('minumum objective')
print(prob['obj'][0])

toc = time.perf_counter()
print(f"You waited {toc - tic:0.4f} seconds")
print("Function Calls")
print('SellarDis1 : ', dc1)
print('SellarDis2 : ', dc2)
Run Code Online (Sandbox Code Playgroud)

编辑:我所说的更好是指“openmdao”方式,例如使用录音机或其他东西。

Joh*_*asa 5

所有 OpenMDAO 系统(组件和组的总称)都具有该iter_count属性。这是 的文档页面System,所有组件和组都从中继承。iter_count是对每个方法的调用总数compute(),而iter_count_without_approx是对方法的调用次数compute(),不包括由于梯度近似而导致的调用次数。此方法适用于任何求解器层次结构或驱动程序设置。

因此,示例脚本的最后两行将是:

print('SellarDis1 : ', prob.model.cycle.d1.iter_count)
print('SellarDis2 : ', prob.model.cycle.d2.iter_count)
Run Code Online (Sandbox Code Playgroud)

正如您所建议的,这不使用录音机。如果您更喜欢使用记录器的解决方案,我们可以找到一个可行的方法。这里有很大的灵活性,要开始使用,您可以查看有关案例阅读的特定文档页面,这可以帮助对案例进行后处理以获得呼叫总数。

如果有任何不清楚的地方,请告诉我!

  • 我可以解决这个差异。iter_count 仅计算调用 `solve_nonlinear` 的次数。在 ExplicitComponent 上,“apply_nonlinear”也调用compute。这是因为,要计算当前输入和输出集的残差范数,您需要再次运行该组件,而残差是输出的变化。但这绝对令人困惑。为了弄清楚这一点,我们决定添加另一个计数器来跟踪调用“apply_nonlinear”的次数。要获得总执行次数,您需要将 iter_count 和 iter_count_apply 相加。(续) (2认同)
  • 这个新计数器将在 OpenMDAO 3.2.2 及更高版本中提供。 (2认同)