OpenMDAO 不想摆脱默认设置

问题描述

我有一些几何图形,我已将其参数化到网格预处理器中,该预处理器为我运行的外部代码生成输入。它的输出是由其输入定义的几何图形,调用我的外部求解器,然后从 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',upper = 3.5)
  prob.model.add_design_var('p.conductor_thickness',upper = 1.0)
  prob.model.add_design_var('p.cut_height',upper = 1.5)
  prob.model.add_design_var('p.cut_width',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()

解决方法

您的输出文件 ('input-thermal_csv.csv') 是否在每次执行时正确重新生成?我问是因为您似乎打算在您的计算中删除它,但条件似乎不正确,因此它永远不会被删除:

        if os.path.isfile('mdao.e'): 
            os.remove('mdao.e')
        if os.path.isfile('mdao.e'):             
            os.remove('input-thermal_csv.csv')
,

当你使用有限差分时,你需要非常小心步长和方法。您可以考虑切换到相对步长而不是绝对步长,或使用不同的步长(OpenMDAO V3.9 中的默认值为 1e-6,绝对)。如果您正在使用文件 i/o,那么请确保您也在编写具有足够位数的输出。如果您将输出截断为 8 位或 9 位数字,那么您可能会在非常小的步骤中获得有效的 0 更改(因为更改在您未打印到文件的数字中有所下降)。

您可以查看 declare_partialscheck_partials 方法中的选项,了解如何调整这些设置。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...