首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenMDAO不想脱离默认设置

OpenMDAO不想脱离默认设置
EN

Stack Overflow用户
提问于 2021-07-08 05:04:47
回答 2查看 35关注 0票数 0

我有一些几何图形,我已经将其参数化到网格预处理器中,该处理器为我运行的外部代码生成输入。它的输出是由其输入定义的几何图形,调用我的外部求解器,然后从CSV文件中摄取输出。我已经让它运行了,但在优化方面肯定没有最小化函数的价值。事实上,它尝试过的值都稍微偏离了起始点。

我有5个影响几何形状的设计变量,它们被设置为不同的范围,让我们称它们为a,b,c,d和e。每个变量的标称起始值是0.1。从我保存的文件的历史记录中可以清楚地看到,例如,它已经尝试过

代码语言:javascript
复制
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的值,我已经做了一些比较,现在我得到了以下结果

代码语言:javascript
复制
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]

有没有人尝试过类似的东西,并能提供反馈/提示?

我的完整代码如下所示。

代码语言:javascript
复制
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()
EN

回答 2

Stack Overflow用户

发布于 2021-07-08 21:58:36

是否在每次执行时正确地重新生成了您的输出文件(‘输入-热_csv.csv’)?我这样问是因为看起来你打算在你的计算机中删除它,但条件似乎不正确,所以它永远不会被删除:

代码语言:javascript
复制
        if os.path.isfile('mdao.e'): 
            os.remove('mdao.e')
        if os.path.isfile('mdao.e'):             
            os.remove('input-thermal_csv.csv')
票数 0
EN

Stack Overflow用户

发布于 2021-07-09 19:56:10

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68292961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档