区分不正确的、小的部分和由于有限差分步长不匹配的正确部分
Distinguishing between incorrect, small partials and correct partials not matching due to finite difference step size
有问题的代码:
class SecondPanelCoordinateInPanelReferenceFrame(om.ExplicitComponent):
def initialize(self):
self.options.declare('n', types=int)
def setup(self):
n = self.options['n']
self.add_input('panel_angles', shape=(n,))
self.add_input('second_panel_coordinate_relative_positions', shape=(2, n))
self.add_output('second_panel_coordinate_transformed_positions', shape=(2, n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'panel_angles',
rows=np.arange(n),
cols=np.arange(n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'second_panel_coordinate_relative_positions',
rows=np.tile(np.arange(n), 2),
cols=np.arange(2*n))
def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
self.second_panel_coordinate_relative_positions = inputs['second_panel_coordinate_relative_positions']
self.panel_angles = inputs['panel_angles']
self.x2r = self.second_panel_coordinate_relative_positions[0, :] # x2r = x coordinate number 2, relative
self.y2r = self.second_panel_coordinate_relative_positions[1, :]
self.cos_angles = np.cos(self.panel_angles)
self.sin_angles = np.sin(self.panel_angles)
second_panel_coordinate_transformed_positions = np.zeros_like(self.second_panel_coordinate_relative_positions)
second_panel_coordinate_transformed_positions[0, :] = self.x2r*self.cos_angles + self.y2r*self.sin_angles
outputs['second_panel_coordinate_transformed_positions'] = second_panel_coordinate_transformed_positions
def compute_partials(self, inputs, partials, discrete_inputs=None):
partials['second_panel_coordinate_transformed_positions',
'panel_angles'] = self.y2r*self.cos_angles - self.x2r*self.sin_angles
partials['second_panel_coordinate_transformed_positions',
'second_panel_coordinate_relative_positions'] = np.concatenate([self.cos_angles, self.sin_angles])
我非常有信心我已经正确地编写了 second_panel_coordinate_transformed_positions w.r.t panel_angles 的部分。但是,当 运行 check_partials() 时,它在数量级上标记出相当大的差异。
InfluenceCoefficientMatrixGroup.SecondPanelCoordinateInPanelReferenceFrame: 'second_panel_coordinate_transformed_positions' wrt 'panel_angles'
Forward Magnitude : 8.659561e-17
Fd Magnitude : 7.071696e-07 (fd:forward)
Absolute Error (Jfor - Jfd) : 7.071696e-07
Relative Error (Jfor - Jfd) : 1.000000e+00 *
Raw Forward Derivative (Jfor)
[[6.123234e-17 0.000000e+00]
[0.000000e+00 6.123234e-17]
[0.000000e+00 0.000000e+00]
[0.000000e+00 0.000000e+00]]
Raw FD Derivative (Jfd)
[[-5.0004445e-07 0.0000000e+00]
[ 0.0000000e+00 -5.0004445e-07]
[ 0.0000000e+00 0.0000000e+00]
[ 0.0000000e+00 0.0000000e+00]]
正向和有限差分部分都非常接近于 0,我不确定我的部分部分是否正确,或者由于有限步导致的错误是否比我在这里预期的更强烈。我怎样才能找出问题所在?
当一个导数的绝对值很小的时候,一般可以忽略相对误差。
在这种情况下,由于您的计算函数是复数安全的,我们可以使用复数步骤来获得更准确的分部近似值。
import openmdao.api as om
import numpy as np
class SecondPanelCoordinateInPanelReferenceFrame(om.ExplicitComponent):
def initialize(self):
self.options.declare('n', types=int)
def setup(self):
n = self.options['n']
self.add_input('panel_angles', shape=(n,))
self.add_input('second_panel_coordinate_relative_positions', shape=(2, n))
self.add_output('second_panel_coordinate_transformed_positions', shape=(2, n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'panel_angles',
rows=np.arange(n),
cols=np.arange(n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'second_panel_coordinate_relative_positions',
rows=np.tile(np.arange(n), 2),
cols=np.arange(2*n))
def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
self.second_panel_coordinate_relative_positions = inputs['second_panel_coordinate_relative_positions']
self.panel_angles = inputs['panel_angles']
self.x2r = self.second_panel_coordinate_relative_positions[0, :] # x2r = x coordinate number 2, relative
self.y2r = self.second_panel_coordinate_relative_positions[1, :]
self.cos_angles = np.cos(self.panel_angles)
self.sin_angles = np.sin(self.panel_angles)
second_panel_coordinate_transformed_positions = np.zeros_like(self.second_panel_coordinate_relative_positions)
second_panel_coordinate_transformed_positions[0, :] = self.x2r*self.cos_angles + self.y2r*self.sin_angles
outputs['second_panel_coordinate_transformed_positions'] = second_panel_coordinate_transformed_positions
def compute_partials(self, inputs, partials, discrete_inputs=None):
self.second_panel_coordinate_relative_positions = inputs['second_panel_coordinate_relative_positions']
self.panel_angles = inputs['panel_angles']
self.x2r = self.second_panel_coordinate_relative_positions[0, :] # x2r = x coordinate number 2, relative
self.y2r = self.second_panel_coordinate_relative_positions[1, :]
self.cos_angles = np.cos(self.panel_angles)
self.sin_angles = np.sin(self.panel_angles)
partials['second_panel_coordinate_transformed_positions',
'panel_angles'] = self.y2r*self.cos_angles - self.x2r*self.sin_angles
partials['second_panel_coordinate_transformed_positions',
'second_panel_coordinate_relative_positions'] = np.concatenate([self.cos_angles, self.sin_angles])
if __name__ == '__main__':
n = 5
p = om.Problem(model=om.Group())
ivc = p.model.add_subsystem('ivc', om.IndepVarComp(), promotes_outputs=['*'])
ivc.add_output('panel_angles', shape=(n,))
ivc.add_output('second_panel_coordinate_relative_positions', shape=(2, n))
p.model.add_subsystem('panel_comp', SecondPanelCoordinateInPanelReferenceFrame(n=n), promotes_inputs=['*'])
p.setup(force_alloc_complex=True)
p.set_val('panel_angles', np.random.rand(n))
p.set_val('second_panel_coordinate_relative_positions', np.random.rand(2, n))
with np.printoptions(linewidth=1024, edgeitems=1000):
p.check_partials(method='cs')
这给了我们:
------------------------------------------------------------------
Component: SecondPanelCoordinateInPanelReferenceFrame 'panel_comp'
------------------------------------------------------------------
panel_comp: 'second_panel_coordinate_transformed_positions' wrt 'panel_angles'
Forward Magnitude : 9.957115e-01
Fd Magnitude : 9.957115e-01 (cs:None)
Absolute Error (Jfor - Jfd) : 3.695246e-16
Relative Error (Jfor - Jfd) : 3.711162e-16
Raw Forward Derivative (Jfor)
[[ 0.18045286 0. 0. 0. 0. ]
[ 0. -0.54661688 0. 0. 0. ]
[ 0. 0. -0.07489634 0. 0. ]
[ 0. 0. 0. -0.15068612 0. ]
[ 0. 0. 0. 0. 0.79484104]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]]
Raw FD Derivative (Jfd)
[[ 0.18045286 0. 0. 0. 0. ]
[ 0. -0.54661688 0. 0. 0. ]
[ 0. 0. -0.07489634 0. 0. ]
[ 0. 0. 0. -0.15068612 0. ]
[ 0. 0. 0. 0. 0.79484104]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
panel_comp: 'second_panel_coordinate_transformed_positions' wrt 'second_panel_coordinate_relative_positions'
Forward Magnitude : 2.236068e+00
Fd Magnitude : 2.236068e+00 (cs:None)
Absolute Error (Jfor - Jfd) : 1.922963e-16
Relative Error (Jfor - Jfd) : 8.599751e-17
Raw Forward Derivative (Jfor)
[[0.86465361 0. 0. 0. 0. 0.50236852 0. 0. 0. 0. ]
[0. 0.54817618 0. 0. 0. 0. 0.83636288 0. 0. 0. ]
[0. 0. 0.8643305 0. 0. 0. 0. 0.50292423 0. 0. ]
[0. 0. 0. 0.82015556 0. 0. 0. 0. 0.57214059 0. ]
[0. 0. 0. 0. 0.98318242 0. 0. 0. 0. 0.18262619]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]]
Raw FD Derivative (Jfd)
[[0.86465361 0. 0. 0. 0. 0.50236852 0. 0. 0. 0. ]
[0. 0.54817618 0. 0. 0. 0. 0.83636288 0. 0. 0. ]
[0. 0. 0.8643305 0. 0. 0. 0. 0.50292423 0. 0. ]
[0. 0. 0. 0.82015556 0. 0. 0. 0. 0.57214059 0. ]
[0. 0. 0. 0. 0.98318242 0. 0. 0. 0. 0.18262619]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
关于您的计算的一个注意事项...在一些不常见的情况下,在使用相同的输入调用计算之前调用 compute_partials。因此,通常不建议您缓存计算。
有问题的代码:
class SecondPanelCoordinateInPanelReferenceFrame(om.ExplicitComponent):
def initialize(self):
self.options.declare('n', types=int)
def setup(self):
n = self.options['n']
self.add_input('panel_angles', shape=(n,))
self.add_input('second_panel_coordinate_relative_positions', shape=(2, n))
self.add_output('second_panel_coordinate_transformed_positions', shape=(2, n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'panel_angles',
rows=np.arange(n),
cols=np.arange(n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'second_panel_coordinate_relative_positions',
rows=np.tile(np.arange(n), 2),
cols=np.arange(2*n))
def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
self.second_panel_coordinate_relative_positions = inputs['second_panel_coordinate_relative_positions']
self.panel_angles = inputs['panel_angles']
self.x2r = self.second_panel_coordinate_relative_positions[0, :] # x2r = x coordinate number 2, relative
self.y2r = self.second_panel_coordinate_relative_positions[1, :]
self.cos_angles = np.cos(self.panel_angles)
self.sin_angles = np.sin(self.panel_angles)
second_panel_coordinate_transformed_positions = np.zeros_like(self.second_panel_coordinate_relative_positions)
second_panel_coordinate_transformed_positions[0, :] = self.x2r*self.cos_angles + self.y2r*self.sin_angles
outputs['second_panel_coordinate_transformed_positions'] = second_panel_coordinate_transformed_positions
def compute_partials(self, inputs, partials, discrete_inputs=None):
partials['second_panel_coordinate_transformed_positions',
'panel_angles'] = self.y2r*self.cos_angles - self.x2r*self.sin_angles
partials['second_panel_coordinate_transformed_positions',
'second_panel_coordinate_relative_positions'] = np.concatenate([self.cos_angles, self.sin_angles])
我非常有信心我已经正确地编写了 second_panel_coordinate_transformed_positions w.r.t panel_angles 的部分。但是,当 运行 check_partials() 时,它在数量级上标记出相当大的差异。
InfluenceCoefficientMatrixGroup.SecondPanelCoordinateInPanelReferenceFrame: 'second_panel_coordinate_transformed_positions' wrt 'panel_angles'
Forward Magnitude : 8.659561e-17
Fd Magnitude : 7.071696e-07 (fd:forward)
Absolute Error (Jfor - Jfd) : 7.071696e-07
Relative Error (Jfor - Jfd) : 1.000000e+00 *
Raw Forward Derivative (Jfor)
[[6.123234e-17 0.000000e+00]
[0.000000e+00 6.123234e-17]
[0.000000e+00 0.000000e+00]
[0.000000e+00 0.000000e+00]]
Raw FD Derivative (Jfd)
[[-5.0004445e-07 0.0000000e+00]
[ 0.0000000e+00 -5.0004445e-07]
[ 0.0000000e+00 0.0000000e+00]
[ 0.0000000e+00 0.0000000e+00]]
正向和有限差分部分都非常接近于 0,我不确定我的部分部分是否正确,或者由于有限步导致的错误是否比我在这里预期的更强烈。我怎样才能找出问题所在?
当一个导数的绝对值很小的时候,一般可以忽略相对误差。
在这种情况下,由于您的计算函数是复数安全的,我们可以使用复数步骤来获得更准确的分部近似值。
import openmdao.api as om
import numpy as np
class SecondPanelCoordinateInPanelReferenceFrame(om.ExplicitComponent):
def initialize(self):
self.options.declare('n', types=int)
def setup(self):
n = self.options['n']
self.add_input('panel_angles', shape=(n,))
self.add_input('second_panel_coordinate_relative_positions', shape=(2, n))
self.add_output('second_panel_coordinate_transformed_positions', shape=(2, n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'panel_angles',
rows=np.arange(n),
cols=np.arange(n))
self.declare_partials('second_panel_coordinate_transformed_positions', 'second_panel_coordinate_relative_positions',
rows=np.tile(np.arange(n), 2),
cols=np.arange(2*n))
def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
self.second_panel_coordinate_relative_positions = inputs['second_panel_coordinate_relative_positions']
self.panel_angles = inputs['panel_angles']
self.x2r = self.second_panel_coordinate_relative_positions[0, :] # x2r = x coordinate number 2, relative
self.y2r = self.second_panel_coordinate_relative_positions[1, :]
self.cos_angles = np.cos(self.panel_angles)
self.sin_angles = np.sin(self.panel_angles)
second_panel_coordinate_transformed_positions = np.zeros_like(self.second_panel_coordinate_relative_positions)
second_panel_coordinate_transformed_positions[0, :] = self.x2r*self.cos_angles + self.y2r*self.sin_angles
outputs['second_panel_coordinate_transformed_positions'] = second_panel_coordinate_transformed_positions
def compute_partials(self, inputs, partials, discrete_inputs=None):
self.second_panel_coordinate_relative_positions = inputs['second_panel_coordinate_relative_positions']
self.panel_angles = inputs['panel_angles']
self.x2r = self.second_panel_coordinate_relative_positions[0, :] # x2r = x coordinate number 2, relative
self.y2r = self.second_panel_coordinate_relative_positions[1, :]
self.cos_angles = np.cos(self.panel_angles)
self.sin_angles = np.sin(self.panel_angles)
partials['second_panel_coordinate_transformed_positions',
'panel_angles'] = self.y2r*self.cos_angles - self.x2r*self.sin_angles
partials['second_panel_coordinate_transformed_positions',
'second_panel_coordinate_relative_positions'] = np.concatenate([self.cos_angles, self.sin_angles])
if __name__ == '__main__':
n = 5
p = om.Problem(model=om.Group())
ivc = p.model.add_subsystem('ivc', om.IndepVarComp(), promotes_outputs=['*'])
ivc.add_output('panel_angles', shape=(n,))
ivc.add_output('second_panel_coordinate_relative_positions', shape=(2, n))
p.model.add_subsystem('panel_comp', SecondPanelCoordinateInPanelReferenceFrame(n=n), promotes_inputs=['*'])
p.setup(force_alloc_complex=True)
p.set_val('panel_angles', np.random.rand(n))
p.set_val('second_panel_coordinate_relative_positions', np.random.rand(2, n))
with np.printoptions(linewidth=1024, edgeitems=1000):
p.check_partials(method='cs')
这给了我们:
------------------------------------------------------------------
Component: SecondPanelCoordinateInPanelReferenceFrame 'panel_comp'
------------------------------------------------------------------
panel_comp: 'second_panel_coordinate_transformed_positions' wrt 'panel_angles'
Forward Magnitude : 9.957115e-01
Fd Magnitude : 9.957115e-01 (cs:None)
Absolute Error (Jfor - Jfd) : 3.695246e-16
Relative Error (Jfor - Jfd) : 3.711162e-16
Raw Forward Derivative (Jfor)
[[ 0.18045286 0. 0. 0. 0. ]
[ 0. -0.54661688 0. 0. 0. ]
[ 0. 0. -0.07489634 0. 0. ]
[ 0. 0. 0. -0.15068612 0. ]
[ 0. 0. 0. 0. 0.79484104]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]]
Raw FD Derivative (Jfd)
[[ 0.18045286 0. 0. 0. 0. ]
[ 0. -0.54661688 0. 0. 0. ]
[ 0. 0. -0.07489634 0. 0. ]
[ 0. 0. 0. -0.15068612 0. ]
[ 0. 0. 0. 0. 0.79484104]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
panel_comp: 'second_panel_coordinate_transformed_positions' wrt 'second_panel_coordinate_relative_positions'
Forward Magnitude : 2.236068e+00
Fd Magnitude : 2.236068e+00 (cs:None)
Absolute Error (Jfor - Jfd) : 1.922963e-16
Relative Error (Jfor - Jfd) : 8.599751e-17
Raw Forward Derivative (Jfor)
[[0.86465361 0. 0. 0. 0. 0.50236852 0. 0. 0. 0. ]
[0. 0.54817618 0. 0. 0. 0. 0.83636288 0. 0. 0. ]
[0. 0. 0.8643305 0. 0. 0. 0. 0.50292423 0. 0. ]
[0. 0. 0. 0.82015556 0. 0. 0. 0. 0.57214059 0. ]
[0. 0. 0. 0. 0.98318242 0. 0. 0. 0. 0.18262619]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]]
Raw FD Derivative (Jfd)
[[0.86465361 0. 0. 0. 0. 0.50236852 0. 0. 0. 0. ]
[0. 0.54817618 0. 0. 0. 0. 0.83636288 0. 0. 0. ]
[0. 0. 0.8643305 0. 0. 0. 0. 0.50292423 0. 0. ]
[0. 0. 0. 0.82015556 0. 0. 0. 0. 0.57214059 0. ]
[0. 0. 0. 0. 0.98318242 0. 0. 0. 0. 0.18262619]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. ]]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
关于您的计算的一个注意事项...在一些不常见的情况下,在使用相同的输入调用计算之前调用 compute_partials。因此,通常不建议您缓存计算。