【问题标题】:i can not manage to record/access derivatives我无法记录/访问衍生品
【发布时间】:2019-02-21 07:08:41
【问题描述】:

如果我只是复制粘贴代码,this link 中记录/访问衍生品的示例案例对我来说效果很好。 我试图弄清楚为什么类似的方法对我自己的问题不起作用。我将录制选项设置为相同。我试图列出一些差异,但不确定它们是否是造成这种情况的原因:

  • 我有一个额外的 maxiter 选项,因此优化器在 3 次迭代后“失败”。
  • 我可以访问所有其他记录的变量(目标、约束、列表输出)
  • 我无法访问 list_inputs,尽管前面提到的链接中的示例代码也是这种情况。
  • 我也添加了 N2,认为单个组件包裹/“卡”在一组中可能是原因;然后我更改了卖方问题结构,我仍然可以在卖方问题中访问衍生品,但不能在我的问题中访问。

我不确定我还能提供什么更多见解。我可能缺少一个明显的东西。 任何的想法?

这是我的问题和示例问题的 N^2 图表。

这里是代码sn-p。

prob = Problem()
probname = prob.model = Group()
recordername='recorder.sql'
GLOBAL_DESIGN_VAR = IndepVarComp()
#"The design variables Indepvar - Promotes none of the variables"
probname.add_subsystem('GLOBAL_DESIGN_VAR', GLOBAL_DESIGN_VAR)

listofloadcases=[inp.fatiguename]
AERO_GroupName='AERO%s' %''.join(listofloadcases)
probname.add_subsystem(AERO_GroupName, AERO(loadcase=listofloadcases))       

for key,val in infodict['sysdes']['desvar'].items():
    GLOBAL_DESIGN_VAR.add_output(key, val['init'])   
    probname.add_design_var('GLOBAL_DESIGN_VAR.{}'.format(key),lower=val['min'], upper=val['max'])     
    probname.connect('GLOBAL_DESIGN_VAR.{}'.format(key), '{}.{}'.format(AERO_GroupName,key))
probname.add_objective('{}.cumPSDerror'.format(AERO_GroupName))
probname.add_constraint('{}.cumDELerror'.format(AERO_GroupName),upper=0.1)

prob.driver=ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.driver.options['disp'] = True
prob.driver.options['tol'] = 1e-9

recorder = SqliteRecorder(recordername)
prob.driver.add_recorder(recorder)
prob.driver.recording_options['includes'] = []
prob.driver.recording_options['record_inputs'] = True
#        prob.driver.recording_options['record_outputs'] = True
prob.driver.recording_options['record_objectives'] = True
prob.driver.recording_options['record_constraints'] = True
prob.driver.recording_options['record_desvars'] = True
prob.driver.recording_options['record_derivatives'] = True

prob.setup(check=True)

prob.run_driver()

prob.cleanup()

cr = CaseReader('recorder.sql')

# Get derivatives associated with the last iteration.
derivs = cr.get_case(0).jacobian

# check that derivatives have been recorded.
print(set(derivs.keys()))

这就是我运行它时得到的结果

case = cr.get_case(-1)
print(case)
print(case.jacobian.keys())

所以 print(case) 有效,但 jacobian 是空的

driver rank0:SLSQP|20 {'GLOBAL_DESIGN_VAR.d2100': array([1.29472574]), 'GLOBAL_DESIGN_VAR.Factor_c': array([1.29491178]), 'GLOBAL_DESIGN_VAR.lus': array([1.28847898]), 
'GLOBAL_DESIGN_VAR.ng': array([1.29981202]), 'GLOBAL_DESIGN_VAR.bl': array([1.2948257]), 'GLOBAL_DESIGN_VAR.d1700': array([1.29472449]),
 'GLOBAL_DESIGN_VAR.sFactor_c': array([1.29981202]), 'GoldflexFLS12.error': array([3.04801276]), 'GoldflexFLS12.Lerror': array([0.73301603])}

 Traceback (most recent call last):

  File "<ipython-input-6-9a0bfa8ec35f>", line 5, in <module>
    print(case.jacobian.keys())

AttributeError: 'NoneType' object has no attribute 'keys'

可以运行的新代码;

from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, SqliteRecorder, CaseReader
from openmdao.api import Group
from openmdao.api import ExplicitComponent

class Exp(ExplicitComponent):    

    def setup(self):          
        self.add_input('des1',val=1)  
        self.add_input('des2',val=1)  
        self.add_output('out',val=1)                                          
        self.add_output('con',val=1)                                          
        self.declare_partials('*', '*',method='fd',step=0.001)

    def compute(self, inputs, outputs):
        outputs['out']=inputs['des1']**2+inputs['des2']
        outputs['con']=inputs['des1']

class AERO(Group):
    def setup(self):        
        self.add_subsystem('Exp',Exp(),promotes=['*'])


infodict={'desvar':{'des1':{"fdstep": 0.1,"init": 1.0,"max": 1.3,"min": 0.8},'des2':{"fdstep": 0.1,"init": 2.0,"max": 1.3,"min": 0.8}}}

prob = Problem()
probname = prob.model = Group()
recordername='recorder.sql'
GLOBAL_DESIGN_VAR = IndepVarComp()
probname.add_subsystem('GLOBAL_DESIGN_VAR', GLOBAL_DESIGN_VAR,promotes=['*'])
probname.add_subsystem('AERO', AERO(),promotes=['*']) 
for key,val in infodict['desvar'].items():
    GLOBAL_DESIGN_VAR.add_output(key, val['init'])   
    probname.add_design_var(key,lower=val['min'], upper=val['max'])     
probname.add_objective('out')
probname.add_constraint('con',upper=0.1)

prob.driver=ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.driver.options['disp'] = True
prob.driver.options['tol'] = 1e-9

recorder = SqliteRecorder(recordername)
prob.driver.add_recorder(recorder)
prob.driver.recording_options['includes'] = []
prob.driver.recording_options['record_inputs'] = True
#        prob.driver.recording_options['record_outputs'] = True
prob.driver.recording_options['record_objectives'] = True
prob.driver.recording_options['record_constraints'] = True
prob.driver.recording_options['record_desvars'] = True
prob.driver.recording_options['record_derivatives'] = True

prob.setup(check=True)

prob.run_driver()

prob.cleanup()

cr = CaseReader(recordername)

# Get derivatives associated with the last iteration.
derivs = cr.get_case(0).jacobian

# check that derivatives have been recorded.
print(set(derivs.keys()))

【问题讨论】:

  • 我们确实需要一些示例代码才能在这里使用。我在提供的链接中没有看到任何 list_inputs 电话。我的猜测是您将记录器连接到系统,可能是顶级系统,然后调用run_model。如果你有一个 NonlinearBlockGaussSeidel Solver,它不需要导数,那么 non 将被记录,你将无法访问它们。
  • @JustinGray 这是一个单组件问题,因为上面的 N2 与 IndepVarComp 不同。它是默认的求解器 LinearRunOnce(我假设)。我将记录器附加到问题.driver.add_recorder(etc) 所以我认为这应该给出每次迭代的总导数。我弄错了吗?
  • @JustinGray 我在问题结束时添加了一个可以由您运行的新代码。我希望您收到有关此评论的通知。我看到的唯一区别是“组”内的显式组件必须导致问题。但你能解释一下为什么以及如何解决它吗?

标签: openmdao


【解决方案1】:

假设您正在使用默认驱动程序 (RunOnceDriver) 并调用 run_driver(),那么您看不到任何派生的原因是默认驱动程序从不要求它们,因此从不计算它们。

所以你需要选择一个基于渐变的驱动,然后你还需要确保设置

prob.driver.recording_options['record_derivatives'] = True

这是一个最小的工作示例:

from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, SqliteRecorder, CaseReader

# build the model 
prob = Problem() 
indeps = prob.model.add_subsystem('indeps', IndepVarComp()) 
indeps.add_output('x', 3.0) 
indeps.add_output('y', -4.0) 

prob.model.add_subsystem('paraboloid', ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3')) 

prob.model.connect('indeps.x', 'paraboloid.x') 
prob.model.connect('indeps.y', 'paraboloid.y') 

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

recorder = SqliteRecorder("cases.sql")
prob.driver.add_recorder(recorder)
prob.driver.recording_options['record_derivatives'] = True


prob.model.add_design_var('indeps.x', lower=-50, upper=50) 
prob.model.add_design_var('indeps.y', lower=-50, upper=50) 
prob.model.add_objective('paraboloid.f') 

prob.setup() 
prob.run_driver() 


# minimum value 
print(prob['paraboloid.f']) 
# location of the minimum 
print(prob['indeps.x']) 
print(prob['indeps.y'])

prob.cleanup()

cr = CaseReader("cases.sql")

# driver_cases = cr.list_cases('driver')

# Get derivatives associated with the last iteration.
case = cr.get_case(-1)
print(case)

# check that derivatives have been recorded.
print(case.jacobian.keys())

【讨论】:

  • 我可能用“LinearRunOnce 驱动程序”的措辞误导了您。我想我的意思是 LinearRunOnce 求解器。正如手册中所述,这是默认设置,我不会更改它。但驱动程序是带有 SLSQ 的 ScipyOptimizer。我认为总导数仍有一个线性系统需要解决。请使用最少的代码查看更新后的问题,我仍然无法获得衍生输出。
  • 首先,如果您运行我在回答中提供的文件,它会为您提供衍生产品吗?我在我的机器上看到了它们,所以如果没有……你可能只是没有最新的 openmdao。我们最近发布了 V2.6。尝试更新到那个。其次,你给出的例子没有通过。它需要导入并依赖于一些未定义的变量:listofloadcases=[inp.fatiguename]
  • 我从您的示例和手册中的示例中都得到了派生词。但不知何故,我无法在我的代码示例中访问。是的,我粘贴到我的问题的代码 sn-p 不可运行,因为添加到问题的组包含一个显式组件,该组件调用机密的“外部 python 代码”。我把代码放在那里是为了检查我在添加模型和记录器等的方式上是否犯了明显的错误。我的问题也有这个问题的 N2 图。与您的相比,我无法区分我将记录器添加到问题中的方式。
  • 但是当我运行最后一部分时,我添加了我得到的问题的结尾
  • 如果没有可以测试的示例,我无法提供更多指导。如果您可以使用玩具组件而不是外部组件来修改您的示例,那么我可以再看看
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多