import sys
import openmdao.api as om
class ParaboloidExternalCodeCompFD(om.ExternalCodeComp):
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('f_xy', val=0.0)
self.input_file = 'paraboloid_input.dat'
self.output_file = 'paraboloid_output.dat'
# providing these is optional; the component will verify that any input
# files exist before execution and that the output files exist after.
self.options['external_input_files'] = [self.input_file]
self.options['external_output_files'] = [self.output_file]
self.options['command'] = [
sys.executable, 'extcode_paraboloid.py', self.input_file, self.output_file
]
def setup_partials(self):
# this external code does not provide derivatives, use finite difference
self.declare_partials(of='*', wrt='*', method='fd')
def compute(self, inputs, outputs):
x = inputs['x']
y = inputs['y']
# generate the input file for the paraboloid external code
with open(self.input_file, 'w') as input_file:
input_file.write('%.16f\n%.16f\n' % (x, y))
# the parent compute function actually runs the external code
super().compute(inputs, outputs)
# parse the output file from the external code and set the value of f_xy
with open(self.output_file, 'r') as output_file:
f_xy = float(output_file.read())
outputs['f_xy'] = f_xy
prob = om.Problem()
model = prob.model
model.add_subsystem('p', ParaboloidExternalCodeCompFD())
# find optimal solution with SciPy optimize
# solution (minimum): x = 6.6667; y = -7.3333
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.model.add_design_var('p.x', lower=-50, upper=50)
prob.model.add_design_var('p.y', lower=-50, upper=50)
prob.model.add_objective('p.f_xy')
prob.driver.options['tol'] = 1e-9
prob.driver.options['disp'] = True
prob.setup()
# Set input values
prob.set_val('p.x', 3.0)
prob.set_val('p.y', -4.0)
prob.run_driver()
print('p.x =', prob.get_val('p.x'), " expected:", [6.66666667])
print('p.x =', prob.get_val('p.y'), " expected:", [-7.3333333])
下面是名为extcode_paraboloid.py的外部代码脚本:
#!/usr/bin/env python
#
# usage: extcode_paraboloid.py input_filename output_filename
#
# Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3.
#
# Read the values of `x` and `y` from input file
# and write the value of `f_xy` to output file.
if __name__ == '__main__':
import sys
input_filename = sys.argv[1]
output_filename = sys.argv[2]
with open(input_filename, 'r') as input_file:
file_contents = input_file.readlines()
x, y = [float(f) for f in file_contents]
f_xy = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
with open(output_filename, 'w') as output_file:
output_file.write('%.16f\n' % f_xy)
作为OpenMDAO测试套件的一部分,我们运行了一个与此非常类似的测试用例。您的
declare_partials
调用不太正确,因为您将前两个参数列为“”和“”,这两个参数与任何变量名都不匹配。我怀疑这只是你文章中的一个输入错误,因为如果你在使用这些参数时实际运行OpenMDAO,你会得到一个异常,告诉你声明的部分与任何变量都不匹配。在下面的示例中,我将部分声明为self.declare_partials(of='*', wrt='*', method='fd')
。假设您的部分实际上声明正确,我的猜测是,出于某种原因,您的外部代码生成的输出文件要么根本没有得到更新,要么您总是将相同的值写入输出文件。下面是计算抛物面的外部代码的工作示例。希望这能帮助你找到问题所在。如果没有,你可以尝试在这里发布你的代码,我们可以从那里开始以下是OpenMDAO脚本:
下面是名为
extcode_paraboloid.py
的外部代码脚本:如果将它们放在同一个目录中并运行OpenMDAO脚本,则应得到如下结果:
相关问题 更多 >
编程相关推荐