我有一些几何图形,我已经将其参数化到网格预处理器中,该处理器为我运行的外部代码生成输入。它的输出是由其输入定义的几何图形,调用我的外部求解器,然后从CSV文件中摄取输出。我已经让它运行了,但在优化方面肯定没有最小化函数的价值。事实上,它尝试过的值都稍微偏离了起始点。
我有5个影响几何形状的设计变量,它们被设置为不同的范围,让我们称它们为a,b,c,d和e。每个变量的标称起始值是0.1。从我保存的文件的历史记录中可以清楚地看到,例如,它已经尝试过
a | b | c | d | e
------------------
0.100001 0.1 0.1 0.1 0.1
0.1 0.100001 0.1 0.1 0.1
0.1 0.1 0.100001 0.1 0.1
0.1 0.1 0.1 0.100001 0.1
0.1 0.1 0.1 0.1 0.100001
0.1 0.1 0.1 0.1 0.1然后,它以某种方式确定原始的起始值是最优的,这非常奇怪,因为在我的例子中,我们可以依次查看每个值的返回值(fout)。然后我意识到我需要将返回值调整到更接近于1的值,我已经做了一些比较,现在我得到了以下结果
Inequality constraints incompatible (Exit mode 4)
Current function value: [0.90320516]
Iterations: 3
Function evaluations: 2
Gradient evaluations: 2
Optimization FAILED.
Inequality constraints incompatible
-----------------------------------
Optimal pfc_thickness: [0.1]
Optimal conductor radius: [0.10000001]
Optimal conductor thickness: [0.1]
Optimal cut height: [0.1]
Optimal cut width: [0.3745392]
Objective value: [0.90320516]有没有人尝试过类似的东西,并能提供反馈/提示?
我的完整代码如下所示。
from openmdao.api import Problem, Group, ExternalCodeComp, IndepVarComp, ScipyOptimizeDriver
import sys
import os
from make_geometry import *
file = open("data.txt", "w")
class ExternalCode(ExternalCodeComp):
def setup(self):
self.iteration = 0
self.add_input('pfc_thickness', val = 0.0)
self.add_input('conductor_radius', val = 0.0)
self.add_input('conductor_thickness', val = 0.0)
self.add_input('conductor_origin_x', val = 0.0)
self.add_input('conductor_origin_y', val = 0.0)
self.add_input('cut_height', val = 0.0)
self.add_input('cut_width', val = 0.0)
self.add_output('fout', val=0.0)
problem_name = "mdao"
self.geometry_instance = build_geometry(problem_name)
self.input_file = 'input-thermal.i'
self.output_file = 'input-thermal_csv.csv'
self.options['external_input_files'] = [self.input_file]
self.options['external_output_files'] = [self.output_file]
#os.environ['LD_LIBRARY_PATH'] = '/usr/lib64/mpich/lib:/usr/lib64'
self.options['command'] = ['/home/adavis/opt/moose/modules/combined/combined-opt','-i','input-thermal.i']
def setup_partials(self):
# this external code does not provide derivatives, use finite difference
self.declare_partials(of='*', wrt='*', method='fd')
def __read_csv(self,filename):
import csv
with open(filename) as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
line_count = 0
for row in csv_reader:
data = row
return data[1] # this is the maxtemp
def compute(self, inputs, outputs):
self.iteration = self.iteration + 1
# set the variables
print(inputs)
pfc_thickness = inputs['pfc_thickness'][0]
conductor_radius = inputs['conductor_radius'][0]
conductor_thickness = inputs['conductor_thickness'][0]
#conductor_origin_x = inputs['conductor_origin_x']
#conductor_origin_y = inputs['conductor_origin_y']
cut_height = inputs['cut_height'][0]
cut_width = inputs['cut_width'][0]
# set the geometry instance
self.geometry_instance.pfc_thickness = pfc_thickness
self.geometry_instance.conductor_radius = conductor_radius
self.geometry_instance.conductor_thickness = conductor_thickness
self.geometry_instance.conductor_origin_x = 5.0
self.geometry_instance.conductor_origin_y = 5.0
self.geometry_instance.cut_height = cut_height
self.geometry_instance.cut_width = cut_width
if os.path.isfile('mdao.e'):
os.remove('mdao.e')
if os.path.isfile('mdao.e'):
os.remove('input-thermal_csv.csv')
# build the file
self.geometry_instance.build_all()
# test to make sure mesh exists
if not os.path.isfile('mdao.e'):
print('meshing failed')
sys.exit(1)
filename = '%s_%s_%s_%s_%s.cub' % (pfc_thickness,conductor_radius,conductor_thickness,cut_height,cut_width)
os.system('cp mdao.cub %s' % (filename))
# the parent compute function actually runs the external code
super().compute(inputs, outputs)
# get the output
f_xy = self.__read_csv(self.output_file)
file.write('%s %s\n' % (self.iteration, f_xy))
# set the output data in f_out
outputs['fout'] = f_xy
if __name__ == "__main__":
prob = Problem()
# Create and connect inputs
prob.model.add_subsystem('p', ExternalCode())
prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.model.add_design_var('p.pfc_thickness', lower=0.1, upper = 2)
prob.model.add_design_var('p.conductor_radius', lower=0.1, upper = 3.5)
prob.model.add_design_var('p.conductor_thickness', lower=0.1, upper = 1.0)
prob.model.add_design_var('p.cut_height', lower=0.1, upper = 1.5)
prob.model.add_design_var('p.cut_width', lower=0.1, upper = 3.0)
prob.model.add_objective('p.fout')
prob.driver.options['tol'] = 1e-9
prob.driver.options['disp'] = True
prob.model.approx_totals()
# run the ExternalCodeComp Component
prob.setup()
prob.set_solver_print(level=2)
# Set input values
prob.set_val('p.pfc_thickness', 0.1)
prob.set_val('p.conductor_radius', 0.1)
prob.set_val('p.conductor_thickness', 0.1)
prob.set_val('p.cut_height', 0.1)
prob.set_val('p.cut_width', 0.1)
prob.run_driver()
print('Optimal pfc_thickness: ', prob.get_val('p.pfc_thickness'))
print('Optimal conductor radius: ', prob.get_val('p.conductor_radius'))
print('Optimal conductor thickness: ', prob.get_val('p.conductor_thickness'))
print('Optimal cut height: ', prob.get_val('p.cut_height'))
print('Optimal cut width: ', prob.get_val('p.cut_width'))
print('Objective value: ', prob.get_val('p.fout'))
file.close()发布于 2021-07-08 21:58:36
是否在每次执行时正确地重新生成了您的输出文件(‘输入-热_csv.csv’)?我这样问是因为看起来你打算在你的计算机中删除它,但条件似乎不正确,所以它永远不会被删除:
if os.path.isfile('mdao.e'):
os.remove('mdao.e')
if os.path.isfile('mdao.e'):
os.remove('input-thermal_csv.csv')发布于 2021-07-09 19:56:10
当你使用有限差分时,你需要非常小心的步长和方法。您可以考虑切换到相对步长而不是绝对步长,或者使用不同的步长( OpenMDAO V3.9中的默认值是1e-6,绝对步长)。如果您正在使用文件i/o,那么请确保您的输出也具有足够的位数。如果您将输出截断为8或9位,那么您可能会在非常小的步骤中得到有效的0更改(因为更改是在您没有打印到文件的数字中进行的)。
您可以查看declare_partials和check_partials方法中的选项,以了解如何调整这些设置。
https://stackoverflow.com/questions/68292961
复制相似问题