【问题标题】:OpenMDAO doesnt want to move away from the defaultsOpenMDAO 不想摆脱默认设置
【发布时间】:2021-07-07 21:04:47
【问题描述】:

我有一些几何图形,我已在上游参数化到网格预处理器中,该预处理器为我运行的外部代码生成输入。其输出是由其输入定义的几何图形,调用我的外部求解器,然后从 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()

【问题讨论】:

    标签: openmdao


    【解决方案1】:

    您的输出文件('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')
    

    【讨论】:

    • 这是一个很好的呐喊!很好发现,它实际上每次都重新生成。我最终所做的是缩放返回值,使其更接近 1,最终在代码中进行了大约 37 次尝试,并且离我的开始很远,这很棒。我不确定我应该这样做,但这是一个开始
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-08-26
      • 2016-09-05
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      相关资源
      最近更新 更多