我尝试使用OpenMDAO解决下面显示的隐式等式。方程式如下所示,
x[i]*z[i] + z[i] - 4 = 0,
y[i] = x[i] + 2*z[i]
The solution is (for i=2) z = [2.666667, 2], y = [5.833333, 5] for x = [0.5, 1.0].
对于这种情况,我使用了下面显示的代码,
from __future__ import print_function
from openmdao.api import Component, Group, Problem, Newton, ScipyGMRES, IndepVarComp
class SimpleEquationSystem(Component):
"""Solve the Equation
x[i]*z[i] + z[i] - 4 = 0
y[i] = x[i] + 2*z[i]
Solution: z = [2.666667, 2], y = [5.833333, 5] for x = [0.5, 1.0]
"""
def __init__(self):
super(SimpleEquationSystem, self).__init__()
self.add_param('x', [0.5, 1.0])
self.add_state('y', [0.0,0.0])
self.add_state('z', [0.0,0.0])
self.iter=0
def solve_nonlinear(self, params, unknowns, resids):
"""This component does no calculation on its own. It mainly holds the
initial value of the state. An OpenMDAO solver outside of this
component varies it to drive the residual to zero."""
pass
def apply_nonlinear(self, params, unknowns, resids):
""" Report the residual """
self.iter+=1
for i in range(2):
x=params['x'][i]
y = unknowns['y'][i]
z = unknowns['z'][i]
resids['y'][i] = x*z + z - 4
resids['z'][i] = x + 2*z - y
print('y_%d' % self.iter,'=%s' %resids['y'], 'z_%d' % self.iter, '=%s' %resids['z'])
print('x' ,'=%s' %x, 'y', '=%s' %y, 'z', '=%s' %z)
top = Problem()
root = top.root = Group()
root.add('comp', SimpleEquationSystem())
root.add('p1', IndepVarComp('x', [0.5, 1.0]))
root.connect('p1.x', 'comp.x')
# Tell these components to finite difference
root.comp.deriv_options['type'] = 'fd'
root.comp.deriv_options['form'] = 'central'
root.comp.deriv_options['step_size'] = 1.0e-4
root.nl_solver = Newton()
root.nl_solver.options['maxiter']=int(200)
root.ln_solver = ScipyGMRES()
top.setup()
top.print_all_convergence(level=1, depth=2)
top.run()
print('Solution x=%s, y=%s, z=%s' % (top['comp.x'], top['comp.y'], top['comp.z']))
此代码错误消息“RuntimeWarning:double_scalars中遇到无效值”。在使用上面的代码片段时,应该能够在OpenMDAO中获得此错误。
当残差方程实现为标量而不是如下所示的向量时,它可以正常工作。
resids['z1']= params['x1'] + 2*unknowns['z1'] - unknowns['y1']
resids['z2']= params['x2'] + 2*unknowns['z2'] - unknowns['y2']
resids['y1']= params['x1']*unknowns['z1'] + unknowns['z1'] - 4
resids['y2']= params['x2']*unknowns['z2'] + unknowns['z2'] - 4
但我希望将残差作为向量,以便使用for循环更容易处理。你能帮我解决这个问题吗?
答案 0 :(得分:1)
声明变量时,它恰好是您声明的变量类型。你给它一个列表,OpenMDAO将其解释为列表,这不是支持区分的数据类型,因此牛顿不能对它做任何事情。您需要通过进行以下更改来使它们成为numpy数组:
import numpy as np
和
self.add_param('x', np.array([0.5, 1.0]))
self.add_state('y', np.array([0.0,0.0]))
self.add_state('z', np.array([0.0,0.0]))
也:
root.add('p1', IndepVarComp('x', np.array([0.5, 1.0])))