我有问题,我已经实现了一些成分的分析导数,我使用复杂的步骤,其余的。它们之间有一个循环依赖关系,所以我也使用一个求解器来收敛它们。当我使用NonlinearBlockGS时,它会收敛。但是,当我将NewtonSolver与线性求解器结合使用时,即使迭代次数很高,优化也会失败(迭代限制超过了)。但是我发现,当我使用prob.model.approx_totals()时,它很容易收敛并且工作得很好。我读到approx_totals使用fd或cs来查找模型梯度。所以我有两个问题。
approx_totals()时,我会失去混合分析方法的好处吗?有没有办法用混合分析策略找出整个模型(或群)的导数?(无论如何,在我的例子中,耦合的explicitcomponents使用“复杂步骤”。但我只是好奇。)我也会感激的,如果你能告诉我一些例子,其中使用混合导数。我自己找不到他们。
编辑:添加示例。我无法在示例代码中再现这个问题。另外,我也不想浪费你的时间在我的代码(有超过30个ExplicitComponents和7个组)。所以我在下面做了一个简单的结构来更好地解释它。其中有7个成分是A to G,只有F and G没有分析衍生物,使用FD。
import openmdao.api as om
import numpy as np
class ComponentA_withDerivatives(om.ExplicitComponent):
def setup(self):
#setup inputs and outputs
def setup_partials(self):
#partial declaration
def compute(self, inputs, outputs):
def compute_partials(self, inputs, J):
#Partial definition
class ComponentB_withDerivatives(om.ExplicitComponent):
.....
class ComponentC_withDerivatives(om.ExplicitComponent):
......
class ComponentD_withDerivatives(om.ExplicitComponent):
......
class ComponentE_withDerivatives(om.ExplicitComponent):
......
class ComponentF(om.ExplicitComponent):
def setup(self):
#setup inputs and outputs
self.declare_partials(of='*', wrt='*', method='fd')
def compute(self,inputs,outputs):
# Computation
class ComponentG(om.ExplicitComponent):
def setup(self):
#setup inputs and outputs
self.declare_partials(of='*', wrt='*', method='fd')
def compute(self,inputs,outputs):
# Computation
class GroupAB(om.Group):
def setup(self):
self.add_subsystem('A', ComponentA_withDerivatives(), promotes_inputs=['x','y'], promotes_outputs=['z'])
self.add_subsystem('B', ComponentB_withDerivatives(), promotes_inputs=['x','y','w','u'], promotes_outputs=['k'])
class GroupCD(om.Group):
def setup(self):
self.add_subsystem('C', ComponentC_withDerivatives(), .....)
self.add_subsystem('D', ComponentD_withDerivatives(), ...)
class Final(om.Group):
def setup(self):
cycle1 = self.add_subsystem('cycle1', om.Group(), promotes=['*'])
cycle1.add_subsystem('GroupAB', GroupAB())
cycle1.add_subsystem('ComponentF', ComponentF())
cycle1.linear_solver = om.DirectSolver()
cycle1.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)
cycle2 = self.add_subsystem('cycle2', om.Group(), promotes=['*'])
cycle2.add_subsystem('GroupCD', GroupCD())
cycle2.add_subsystem('ComponentE_withDerivatives', ComponentE_withDerivatives())
cycle2.linear_solver = om.DirectSolver()
cycle2.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)
self.add_subsystem('ComponentG', ComponentG(), promotes_inputs=['a1','a2','a3'], promotes_outputs=['b1'])
prob = om.Problem()
prob.model = Final()
prob.driver = om.pyOptSparseDriver()
prob.driver.options['optimizer'] = 'SNOPT'
prob.driver.options['print_results']= True
## Design Variables
## Costraints
## Objectives
# Setup
prob.setup()
##prob.model.approx_totals(method='fd')
prob.run_model()
prob.run_driver()这不管用。cycle1不收敛。当我完全删除cycle1或使用NonlinearBlockGS而不是Newton或取消注释prob.model.approx_total(method='FD')时,代码就能工作。( cycle2没有问题。(与牛顿合作)
因此,如果我不使用approx_totals(),我假设Openm道使用混合策略。或者我应该以某种方式手动提及它?当我使用approx_totals()的时候,我会失去我所拥有的分析导数的好处吗?
发布于 2021-06-17 01:47:31
您提供的代码示例是不可运行的,因此我不得不做一些猜测。你叫run_model()和run_driver()。但是,您需要在示例代码中包含一个优化器,并且您已经在模型层次结构的顶部显示了要调用approx_totals。因此,当您说它不工作时,我假设您的意思是优化器不收敛。
您正确地理解了approx_totals的行为。当您将其设置在模型的顶部时,OpenMDAO将从组级别对相关变量进行FD。在这种情况下,这意味着你也将FD-跨越求解本身。你说这似乎是可行的,但混合分析方法不起作用。
一般来说,当我使用approx_totals()时,我会失去混合分析方法的好处吗?
是。你不再使用混合的方法了。你只是一次又一次的穿越模型。
有没有办法用混合分析策略找出整个模型(或群)的导数?
OpenMDAO是指在不使用approx_totals的情况下,使用混合策略计算总衍生品。问题是,对于你的模型,它似乎不起作用。
通常(在这个场景中不是这样),Openm道会自动检测混合策略吗?
它将“检测”它(它实际上没有检测到任何东西,但是底层的算法将使用混合策略,除非您告诉它不要使用approx_totals。同样,问题不是没有采用混合战略,而是不起作用。
,那么为什么混合策略不起作用呢?
我只能猜测,因为我不能运行密码.所以YMMV。您提到您正在为显式组件的部分使用复杂步骤。复杂步长是一种比FD精确得多的近似方案,但也有其自身的缺陷。并不是所有的计算都是复杂的--安全的。有些可以重写为复杂安全,而另一些则不能。所谓“复杂-安全”,我的意思是,计算正确地处理复杂部分,给出一个导数。
两种常用的复杂安全方法是np.linalg.norm和np.abs。双方都乐于接受复数,并给出答案,但这不是正确的答案,当你需要导数。正因为如此,OpenMDAO附带了一个一组安全的自定义函数 --自定义norm和abs。
非cs安全方法通常发生的情况是,复杂的部分以某种方式被抛出,得到0偏导数。错误的部分,错误的总数。
要检查这一点,请确保使用有限差分检查对正在执行复杂步骤的组件调用check_partials。你可能会发现一些不符之处。
您可以使用的修补程序是:
https://stackoverflow.com/questions/67942714
复制相似问题