Я использую OpenMDAO для оптимизации CFD. Вычислительная геометрия, построение сетки и выполнение решателя обрабатываются отдельным python скриптом, который принимает обновленный дизайн. За одно выполнение сценарий найдет силы, а также производные посредством сопряженного анализа. Моя проблема в том, что OpenMDAO, похоже, использует только производные, которые я указал, часть времени, а не для каждой итерации. Ниже приведен пример кода, который я использую:
import os
import argparse
import numpy as np
from matplotlib import pyplot as plt
import csv
import f90nml
import socket
import sys
import pickle
# Import OpenMDAO module - currently tested against version 2.8.0
from openmdao.api import Problem, Group, IndepVarComp, ExplicitComponent, ScipyOptimizeDriver
import openmdao.api as om
class FUN3DExternalCodeComp(om.ExternalCodeComp):
def setup(self):
# Design Variables
self.add_input('alpha', val=0.0)
self.add_input('TE1', val=0.0)
self.add_input('TE2', val=0.0)
self.add_input('TE3', val=0.0)
self.add_input('TE4', val=0.0)
self.add_input('TE5', val=0.0)
self.add_input('TE6', val=0.0)
self.add_output('CD', val=0.0)
self.add_output('CL', val=0.0)
self.add_output('CY', val=0.0)
self.add_output('CMx', val=0.0)
self.add_output('CMy', val=0.0)
self.add_output('CMz', val=0.0)
self.input_file = 'designVar.in'
self.output_file = 'fun3dResponse.out'
self.derivs_file = 'fun3dDerivs.out'
# 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.derivs_file]
self.options['command'] = [
# sys.executable, 'runFun3DsensPA_Euler.py',
sys.executable, 'function.py',
self.input_file, self.output_file, self.derivs_file]
# this external code does provide derivatives
self.declare_partials(of='*', wrt='*')
def compute(self, inputs, outputs):
alpha = inputs['alpha']
TE1 = inputs['TE1']
TE2 = inputs['TE2']
TE3 = inputs['TE3']
TE4 = inputs['TE4']
TE5 = inputs['TE5']
TE6 = inputs['TE6']
# 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%.16f\n%.16f\n%.16f\n%.16f\n%.16f\n' % (alpha, TE1, TE2, TE3, TE4, TE5, TE6))
# the parent compute function actually runs the external code
super(FUN3DExternalCodeComp, self).compute(inputs, outputs)
# parse the output file from the external code and set the value of f_xy
with open(os.path.join(self.output_file), 'r') as output_file:
outputs['CL'] = float(output_file.readline())
outputs['CD'] = float(output_file.readline())
outputs['CY'] = float(output_file.readline())
outputs['CMx'] = float(output_file.readline())
outputs['CMy'] = float(output_file.readline())
outputs['CMz'] = float(output_file.readline())
print('OUTPUTS', outputs)
def compute_partials(self, inputs, partials):
# parse the derivs file from the external code and set partials
with open(os.path.join(self.derivs_file), 'r') as derivs_file:
partials['CL', 'alpha'] = float(derivs_file.readline())
partials['CL', 'TE1'] = float(derivs_file.readline())
partials['CL', 'TE2'] = float(derivs_file.readline())
partials['CL', 'TE3'] = float(derivs_file.readline())
partials['CL', 'TE4'] = float(derivs_file.readline())
partials['CL', 'TE5'] = float(derivs_file.readline())
partials['CL', 'TE6'] = float(derivs_file.readline())
partials['CD', 'alpha'] = float(derivs_file.readline())
partials['CD', 'TE1'] = float(derivs_file.readline())
partials['CD', 'TE2'] = float(derivs_file.readline())
partials['CD', 'TE3'] = float(derivs_file.readline())
partials['CD', 'TE4'] = float(derivs_file.readline())
partials['CD', 'TE5'] = float(derivs_file.readline())
partials['CD', 'TE6'] = float(derivs_file.readline())
partials['CY', 'alpha'] = float(derivs_file.readline())
partials['CY', 'TE1'] = float(derivs_file.readline())
partials['CY', 'TE2'] = float(derivs_file.readline())
partials['CY', 'TE3'] = float(derivs_file.readline())
partials['CY', 'TE4'] = float(derivs_file.readline())
partials['CY', 'TE5'] = float(derivs_file.readline())
partials['CY', 'TE6'] = float(derivs_file.readline())
# Rolling moment partials
partials['CMx', 'alpha'] = float(derivs_file.readline())
partials['CMx', 'TE1'] = float(derivs_file.readline())
partials['CMx', 'TE2'] = float(derivs_file.readline())
partials['CMx', 'TE3'] = float(derivs_file.readline())
partials['CMx', 'TE4'] = float(derivs_file.readline())
partials['CMx', 'TE5'] = float(derivs_file.readline())
partials['CMx', 'TE6'] = float(derivs_file.readline())
# Pitching moment partials
partials['CMy', 'alpha'] = float(derivs_file.readline())
partials['CMy', 'TE1'] = float(derivs_file.readline())
partials['CMy', 'TE2'] = float(derivs_file.readline())
partials['CMy', 'TE3'] = float(derivs_file.readline())
partials['CMy', 'TE4'] = float(derivs_file.readline())
partials['CMy', 'TE5'] = float(derivs_file.readline())
partials['CMy', 'TE6'] = float(derivs_file.readline())
# Yaw moment partials
partials['CMz', 'alpha'] = float(derivs_file.readline())
partials['CMz', 'TE1'] = float(derivs_file.readline())
partials['CMz', 'TE2'] = float(derivs_file.readline())
partials['CMz', 'TE3'] = float(derivs_file.readline())
partials['CMz', 'TE4'] = float(derivs_file.readline())
partials['CMz', 'TE5'] = float(derivs_file.readline())
partials['CMz', 'TE6'] = float(derivs_file.readline())
print('PARTIALS', partials)
# Initialize OpenMDAO Problem
prob = om.Problem()
model = prob.model
# create and connect inputs
model.add_subsystem('p', FUN3DExternalCodeComp())
# Add Design variables
prob.model.add_design_var('p.alpha', lower = 1.0, upper = 10)
prob.model.add_design_var('p.TE1', lower = 1.0, upper = 10)
prob.model.add_design_var('p.TE2', lower = 1.0, upper = 10)
prob.model.add_design_var('p.TE3', lower = 1.0, upper = 10)
prob.model.add_design_var('p.TE4', lower = 1.0, upper = 10)
prob.model.add_design_var('p.TE5', lower = 1.0, upper = 10)
prob.model.add_design_var('p.TE6', lower = 1.0, upper = 10)
# Lift constraint
prob.model.add_constraint('p.CL', lower = 10, upper = 120)
prob.model.add_constraint('p.CY', lower = 20, upper = 250)
prob.model.add_constraint('p.CMx', lower = 20, upper = 250)
prob.model.add_constraint('p.CMy', lower = 20, upper = 250)
prob.model.add_constraint('p.CMz', lower = 20, upper = 250)
# Minimize Drag
prob.model.add_objective('p.CD')
prob.driver = om.pyOptSparseDriver(optimizer='SLSQP')
prob.driver.options['print_results'] = True
prob.driver.options['debug_print'] = ['desvars','ln_cons','nl_cons','objs','totals']
# prob.driver = om.ScipyOptimizeDriver()
# prob.driver.options['optimizer'] = 'SLSQP'
# prob.driver.options['tol'] = 1e-5
# prob.driver.options['disp'] = True
# prob.driver.options['maxiter'] = 20 # Maximum number of solver iterations
# prob.driver.options['debug_print'] = ['desvars','ln_cons','nl_cons','objs','totals']
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
recorder = om.SqliteRecorder('results.sql')
prob.driver.add_recorder(recorder)
prob.set_solver_print(level=0)
prob.setup()
# Set input values
prob.set_val('p.alpha', 3.0)
prob.set_val('p.TE1', 1.0)
prob.set_val('p.TE2', 2.0)
prob.set_val('p.TE3', 3.0)
prob.set_val('p.TE4', 4.0)
prob.set_val('p.TE5', 5.0)
prob.set_val('p.TE6', 6.0)
prob.run_driver()
Exception: '_auto_ivc.v0'
====================================================================== Traceback (most recent call last):
File "/Users/deslicjp/Documents/Software/OpenMDAO/openmdao/drivers/pyoptsparse_driver.py", line 593, in _gradfunc
sens_dict = self._compute_totals(of=self._quantities,
File "/Users/deslicjp/Documents/Software/OpenMDAO/openmdao/core/driver.py", line 849, in _compute_totals
totals = total_jac.compute_totals()
File "/Users/deslicjp/Documents/Software/OpenMDAO/openmdao/core/total_jac.py", line 1414, in compute_totals
self._print_derivatives()
File "/Users/deslicjp/Documents/Software/OpenMDAO/openmdao/core/total_jac.py", line 1629, in _print_derivatives
pprint.pprint({(of, wrt): J[of][wrt]})
KeyError: '_auto_ivc.v0'
======================================================================
capi_return is NULL
Call-back cb_slgrad_in_slsqp__user__routines failed.
Traceback (most recent call last):
ОБНОВЛЕНИЕ: 08-07-2020 15: 32
Любое понимание приветствуется!
Спасибо, Джо sh