Heat Software Config

本文介绍了OpenStack Heat中软件配置钩子的工作原理及其在实例启动过程中的作用。包括从元数据服务器下载数据、处理多部分数据、执行用户的脚本等步骤,并提供了故障排除和示例模板。

This article describes Software Configuration Hooks new in Icehouse.

All the following topics depend on https://github.com/openstack/heat-templates/tree/master/hot/software-config.

Pre-requisites

Images with cloud-init,  heat-config, os-collect-config, os-refresh-config, os-apply-config, heat-config-cfn-init, heat-config-puppet, heat-config-salt and heat-config-script  packages installed
Nova metadata server up and running
Heat CFN API service up and running

How hook works

1. When the instance boots up, it runs the cloud-init script. Cloud-init creates the directories under /var/lib/cloud:

root@web-server:/var/lib/cloud# ls
data  handlers  instance  instances  scripts  seed  sem


2. Download the data from the metadata server

root@web-server:/var/lib/cloud/instance# ll
-rw-r--r-- 1 root root    52 Aug  7 08:21 boot-finished
drwxr-xr-x 2 root root  4096 Aug  7 08:16 boothooks/
-rw------- 1 root root   128 Aug  7 08:16 cloud-config.txt
-rw-r--r-- 1 root root    29 Aug  7 08:16 datasource
drwxr-xr-x 2 root root  4096 Aug  7 08:16 handlers/
-r-------- 1 root root 10500 Aug  7 08:16 obj.pkl
drwxr-xr-x 2 root root  4096 Aug  7 08:16 scripts/
drwxr-xr-x 2 root root  4096 Aug  7 08:21 sem/
-rw------- 1 root root  3894 Aug  7 08:16 user-data.txt
-rw------- 1 root root  3954 Aug  7 08:16 user-data.txt.i
-rw------- 1 root root     4 Aug  7 08:16 vendor-data.txt
-rw------- 1 root root   345 Aug  7 08:16 vendor-data.txt.i
user-data.txt vs user-data.txt.i: Thecontent of user-data.txt is raw data from http://169.254.169.254/latest/user-data. It maybe contains gzip compressed user data. But user-data.txt.i contains the post-processed user data (uncompressed, with includes resolved).


3. Splits the multiple parts into the /var/lib/cloud/instance directory

3.1 Content-Type: text/part-handler & Content-Type: text/x-cfninitdata

Then content of this part-handers will be written to /var/lib/cloud/instance/handlers. The “part” handled here is subpart of user data. 

Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="part-handler.py"

#part-handler

def list_types():
    return(["text/x-cfninitdata"])

def handle_part(data, ctype, filename, payload):
    if ctype == "__begin__":
        try:
            os.makedirs('/var/lib/heat-cfntools', 0o700)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise
        return

    if ctype == "__end__":
        return

    with open('/var/log/part-handler.log', 'a') as log:
        timestamp = datetime.datetime.now()
        log.write('%s filename:%s, ctype:%s\n' % (timestamp, filename, ctype))

    if ctype == 'text/x-cfninitdata':
        with open('/var/lib/heat-cfntools/%s' % filename, 'w') as f:
            f.write(payload)

        # TODO(sdake) hopefully temporary until users move to heat-cfntools-1.3
        with open('/var/lib/cloud/data/%s' % filename, 'w') as f:
            f.write(payload)

For example, the following code process "text/x-cfninitdata" sections by writing them to /var/lib/heat-cfntools/ and /var/lib/cloud/data/. The payload is like this:

{"deployments": [], "os-collect-config": {"cfn": {"stack_name": "stackname", "metadata_url": "http://heat-server:8000/v1/", "path": "web_server.Metadata", "secret_access_key": "ba455502219c41a58757a62c5425d7ce", "access_key_id": "8776148cc65a4f95b3c4a0b390f87625"}}}

3.2  /var/lib/heat-cfntools

When part-handler executes , the directory looks like:

root@web-server:/var/lib/heat-cfntools# ls
cfn-init-data  cfn-watch-server


4. Execute user's script

4.1 The first loop of os-collect-config

os-collect-config is a daemon process. It collects data from defined configuration sources and runs a defined hook whenever the metadata has been changed.

root@web-server:~# ps aux  | grep os-collect-config
root      1229  2.5  1.2  99192 25816 ?        Ss   Aug07  33:39 /opt/stack/venvs/os-collect-config/bin/python /usr/local/bin/os-collect-config

Firstly, the default configuration of /etc/ os-collect-config.confjust contains default command options, like this:

[DEFAULT]
command = os-refresh-config

Afterone loop of os-collect-config execution, the directory of/var/lib/os-collect-config and /var/run/os-collect-config are like this:

root@web-server:/var/run/os-collect-config# ll
-rw-------  1 root root 111667 Aug  7 08:21 cfn.json
-rw-------  1 root root 111667 Aug  7 08:21 cfn.json.orig
-rw-------  1 root root   1061 Aug  7 08:21 ec2.json
-rw-------  1 root root   1061 Aug  7 08:20 ec2.json.last
-rw-------  1 root root   1061 Aug  7 08:19 ec2.json.orig
-rw-------  1 root root    300 Aug  7 08:21 heat_local.json
-rw-------  1 root root    300 Aug  7 08:20 heat_local.json.last
-rw-------  1 root root    300 Aug  7 08:19 heat_local.json.orig
-rw-------  1 root root    124 Aug  7 08:21 os_config_files.json

The content of /etc/heat_local.conf sources from/var/lib/heat-cfntools/cfn-init-data by heat_local::Collector. And ec2.json sources from metadata service by ec2::Collector.

But now, there are no cfn.json and cfn.json.orig because/etc/os-collect-config.conf is not configured fully yet.


Secondly, when os-refresh-config is called, the scripts of PHASES('pre-configure', 'configure',  'post-configure','migration') under /opt/stack/os-config-refresh will be executed. “os-apply-config”is among these scripts.

 

Thirdly, os-apply-config will create/etc/os-collect-collect.conf and /var/run/heat-config/heat-config by rendering templates predefined under /usr/libexec/os-apply-config/templates. But now/var/run/heat-config/heat-config is still empty.

root@web-server:~# cat /etc/os-collect-config.conf 
[DEFAULT]
command = os-refresh-config

[cfn]
metadata_url = http://heat-server:8000/v1/
stack_name = stack43
secret_access_key = ba455502219c41a58757a62c5425d7ce
access_key_id = 8776148cc65a4f95b3c4a0b390f87625
path = web_server.Metadata

4.2  The second loop of os-collect-config

Now, cfn.json and cfn.json.orig will be created by cfn::Collector in “os-collect-config” because now /etc/os-collect-config is configured correctly.

root@web-server:/var/run/os-collect-config# ll
-rw-------  1 root root 111667 Aug  7 08:21 cfn.json
-rw-------  1 root root 111667 Aug  7 08:21 cfn.json.orig

And /var/run/heat-config/heat-config will be filled with meaningful contents by “os-apply-config”.

root@web-server:/var/run/heat-config# ll
-rw-r--r--  1 root root 110761 Aug  8 09:09 heat-config

Now /opt/stack/os-config-refresh/configure.d/55-heat-config run, not only it will invoke proper hook under /var/lib/heat-config/hooks, but also it will signal heat with output.


Troubleshooting

/var/log/cloud-init.log
/var/log/cloud-init-output.log
/var/log/part-handler.log
/var/log/upstart/os-collect-config.log
/var/log/os-apply-config.log


References

https://help.ubuntu.com/community/CloudInit

http://cloudinit.readthedocs.org/en/latest/topics/examples.html

http://foss-boss.blogspot.com/2011/01/advanced-cloud-init-custom-handlers.html

https://github.com/openstack/heat-templates/tree/master/hot/software-config


Appendix

1. A Limit of Cloud-init

The first limit is osapi_max_request_body_size of nova-api service, and its default value is 114688. Define it in nova/api/sizelimit.py as following:

#default request size is 112k
max_request_body_size_opt = cfg.IntOpt('osapi_max_request_body_size',
                                       default=114688,
                                       help='The maximum body size '
                                           'per each osapi request(bytes)')
If your request body size is larger than osapi_max_request_body_size, it will complain like this “OverLimit: Over limit (HTTP 413)”.


The second limit is MAX_USERDATA_SIZE, and its default value is 65535. Define it in nova/compute/api.py:

MAX_USERDATA_SIZE = 65535

If your user-data size is larger than MAX_USERDATA_SIZE, it will complain directly like this “Instance User Data Too Large: User data too large. User data must be no larger than 65535 bytes once base64 encoded.”


2. One Template Sample

heat_template_version: 2013-05-23

description: Web Server Template

parameters:
  image:
    default: CentOS
    type: string
    description: Image use to boot a server
  
  flavor:
    default: m1.small
    type: string
    description: Flavor use to boot a server
    
  key_name:
    default: demo-key 
    type: string
    description: keypair name use to boot a server

resources:
  web_config:
    type: OS::Heat::SoftwareConfig
    properties:
      group: script
      config:
        get_file: scripts/web.sh

  web_deployment:
    type: OS::Heat::SoftwareDeployment
    properties:
      config:
        get_resource: web_config
      server:
        get_resource: web_server
        
  web_server:
    type: OS::Nova::Server
    properties:
      name: "Web Server"
      image: { get_param: image }
      flavor: { get_param: flavor } 
      key_name: { get_param: key_name } 
      user_data_format: SOFTWARE_CONFIG 

outputs:
  stdout:
    value:
      get_attr: [web_deployment, deploy_stdout]
  stderr:
    value:
      get_attr: [web_deployment, deploy_stderr]
  status_code:
    value:
      get_attr: [web_deployment, deploy_status_code]






i use this code to sweep and calculate at different angle of attack #!/usr/bin/env python ## \file Compute_polar.py # \brief Python script for performing polar sweep. # \author E Arad (based on T. Lukaczyk and F. Palacios script) # \version 6.2.0 "Falcon" # # The current SU2 release has been coordinated by the # SU2 International Developers Society <www.su2devsociety.org> # with selected contributions from the open-source community. # # The main research teams contributing to the current release are: # - Prof. Juan J. Alonso's group at Stanford University. # - Prof. Piero Colonna's group at Delft University of Technology. # - Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology. # - Prof. Alberto Guardone's group at Polytechnic University of Milan. # - Prof. Rafael Palacios' group at Imperial College London. # - Prof. Vincent Terrapon's group at the University of Liege. # - Prof. Edwin van der Weide's group at the University of Twente. # - Lab. of New Concepts in Aeronautics at Tech. Institute of Aeronautics. # # Copyright 2012-2019, Francisco D. Palacios, Thomas D. Economon, # Tim Albring, and the SU2 contributors. # # SU2 is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # SU2 is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with SU2. If not, see <http://www.gnu.org/licenses/>. # # # Several combinations of angles are possible: #------------------------------------------------ # 1. Polar-sweep in alpha per given phi ...... polarVar = aoa # 2. Polar-sweep in alpha per given beta (side slip angle) ...... polarVar = aoa # 3. Polar-sweep in phi per given alpha ...... polarVar = phi # 4. Mach ramp (single values for alpha, phi or both permitted) ... polarVar = MachRampNumbers # # Note: Seting a list of both phi and beta is impossible # For mach ramp you can specify alpha, phi (or both), but not a list of either of them # make print(*args) function available in PY2.6+, does'nt work on PY < 2.6 from __future__ import print_function # imports import os, sys from optparse import OptionParser sys.path.append(os.environ['SU2_RUN']) import SU2 import SU2.util.polarSweepLib as psl import copy import numpy as np def main(): # Command Line Options parser = OptionParser() parser.add_option("-c", "--ctrl", dest="ctrlFile", help="reads polar control parameters from FILE (default:polarCtrl.in) ", metavar="FILE", default="polarCtrl.in") parser.add_option("-n", "--partitions", dest="partitions", default=2, help="number of PARTITIONS", metavar="PARTITIONS") parser.add_option("-i", "--iterations", dest="iterations", default=-1, help="number of ITERATIONS", metavar="ITERATIONS") parser.add_option("-d", "--dimmension", dest="geomDim", default=2, help="Geometry dimension (2 or 3)", metavar="geomDim") parser.add_option("-w", "--Wind", action="store_true", dest="Wind", default=False, help=" Wind system (default is body system") parser.add_option("-v", "--Verbose", action="store_true", dest="verbose", default=False, help=" Verbose printout (if activated)") (options, args) = parser.parse_args() options.partitions = int(options.partitions) options.iterations = int(options.iterations) options.geomDim = int(options.geomDim) d2r = np.pi/180 # sweepOption = [] sweepOption.append(' Polar sweep type: 1. Sweep in AOA per given roll angle') sweepOption.append(' Polar sweep type: 2. Sweep in AOA per given sideslip-angle') sweepOption.append(' Polar sweep type: 3. Sweep in phi per given AOA') sweepOption.append(' Polar sweep type: 4. Mach ramp (single- value AOA and sideslip-angle') # #--------------- now read the parameters control file and parse it fc = open(options.ctrlFile, 'r') ctrl = fc.readlines() nc = np.size(ctrl) fc.close() print(str(nc)+" lines read from control file: "+options.ctrlFile) PA, polarSweepType, velDirOption, nAlpha, nBeta, nPhi, nMach, \ alpha, beta, phi, MachList, polarVar = \ psl.setPolaraType(ctrl, nc, options.verbose) if options.verbose: velDirOptionLegend = ['V(alpha,phi)', 'V(alpha,beta)'] print('>>> Control file details: Pitch axis is '+\ PA+'. Polar sweep type is '+str(polarSweepType)+\ '; polarVar = '+polarVar) print('>>> Velocity definiton: '+velDirOptionLegend[velDirOption-1]) print('>>> nAalpha = '+str(nAlpha)+'; nBeta = '+str(nBeta)+\ '; nPhi = '+str(nPhi)+'; nMach = '+str(nMach)) if polarSweepType < 4: nPolara = max(nAlpha, nPhi) else: nPolara = nMach #-------------Configuration base file ---------------------- inputbaseFileString = 'input base file' keyWordInputbaseFile = inputbaseFileString.lower() iBaseInputF = psl.parLocator(keyWordInputbaseFile, ctrl, nc, -1, options.verbose) bIFLine = ctrl[iBaseInputF] icol = bIFLine.index(':') sBIF = bIFLine[icol+1:] inputbaseFile = sBIF.strip(' ') inputbaseFile = inputbaseFile.strip('\n') print(' ') print('--------------------------------------------------------------------------------------') print(' ') print('Configuration file: ' + inputbaseFile) print('PolarSweepType = '+str(polarSweepType)+' Polar sweep in '+polarVar+' using '+\ str(nPolara)+' angles/Mach No ') print(' ') print('--------------------------------------------------------------------------------------') print(' ') if polarSweepType == 4: nPolara = 1 # prevent angles inner loop if options.geomDim not in [2, 3]: raise SystemExit('ERROR: dimension can be either 2 or 3 (-d parameter) ') if options.Wind: outSystem = 'Wind' else: outSystem = 'Body' print(" ") print("===============================================================================") print(" Polar sweep in "+str(options.geomDim)+"D ; output in "+outSystem+" system") print("===============================================================================") print(" ") # load config, start state config = SU2.io.Config(inputbaseFile) state = SU2.io.State() # Set SU2 defaults units, if definitions are not included in the cfg file if 'SYSTEM_MEASUREMENTS' not in config: config.SYSTEM_MEASUREMENTS = 'SI' if config.PHYSICAL_PROBLEM == 'NAVIER_STOKES': if 'REYNOLDS_LENGTH' not in config: config.REYNOLDS_LENGTH = 1.0 # prepare config config.NUMBER_PART = options.partitions if options.iterations > 0: config.EXT_ITER = options.iterations config.NZONES = 1 # find solution files if they exist state.find_files(config) # start results data results = SU2.util.bunch() if nMach == 0: if 'MACH_NUMBER' in config: MachList.append(config.MACH_NUMBER) else: MachList.append(0.5) nMach = 1 if nAlpha == 0: if 'AOA' in config: alpha.append(config.AOA) else: alpha.append(0.0) nAlpha = 1 if nPhi == 0: phi.append(0.0) nPhi = 1 noPhi_in_CTRL = True else: noPhi_in_CTRL = False if nBeta == 0: if noPhi_in_CTRL: if 'SIDESLIP_ANGLE' in config: beta.append(config.SIDESLIP_ANGLE) else: beta.append(0.0) nBeta = 1 else: if polarSweepType < 4: # alpha sweep with phi set tAlpha = [np.tan(d2r*x) for x in alpha] tPhi = [np.tan(d2r*x) for x in phi] tb = [x*y for y in tAlpha for x in tPhi] beta = [np.arctan(x)/d2r for x in tb] nBeta = np.size(beta) else: # Mach ramp if 'SIDESLIP_ANGLE' in config: beta.append(config.SIDESLIP_ANGLE) else: beta.append(0.0) nBeta = 1 if options.verbose: print('>>> alpha: '+str(alpha)) print('>>> beta: '+str(beta)) print('>>> phi: '+str(phi)) print('>>> Mach '+str(MachList)) results.AOA = alpha results.MACH = MachList results.SIDESLIP_ANGLE = beta if options.geomDim == 3: results.MOMENT_X = [] results.MOMENT_Y = [] if options.Wind: results.DRAG = [] results.LIFT = [] if options.geomDim == 3: results.SIDEFORCE = [] else: results.FORCE_X = [] results.FORCE_Y = [] if options.geomDim == 3: results.FORCE_Z = [] results.MOMENT_Z = [] if polarSweepType == 4: outFile = 'machRamp_aoa' + str(alpha[0]) + '.dat' else: outFile = 'Polar_M' + str(MachList[0]) + '.dat' bufsize = 12 # #----------- Prepare output header --------------- # if config.SYSTEM_MEASUREMENTS == 'SI': length_dimension = 'm' else: length_dimension = 'in' f = open(outFile, 'w', bufsize) if options.verbose: print('Opening polar sweep file: ' + outFile) f.write('% \n% Main coefficients for a polar sweep \n% \n% ') f.write(sweepOption[polarSweepType-1]) if polarSweepType == 1: satxt = ' ; Roll angle = %7.2f '%(phi[0]) elif polarSweepType == 2: satxt = ' ; Sideslip angle = %7.2f '%(beta[0]) elif polarSweepType == 3: satxt = ' ; AOA = %7.2f '%(alpha[0]) elif polarSweepType == 4: satxt = ' ; AOA = %7.2f Side slip angle = %7.2f ; '%(alpha[0], beta[0]) f.write(satxt) f.write('\n% \n') f.write('% ================== Reference parameteres ======================\n%\n') XR = config.REF_ORIGIN_MOMENT_X YR = config.REF_ORIGIN_MOMENT_Y ZR = config.REF_ORIGIN_MOMENT_Z f.write('% Reference point for moments : [ ') line_text = '%s , %s , %s ] [ %s ] '%(XR, YR, ZR, length_dimension) f.write(line_text) f.write('\n') f.write('% Reference area and length: ') line_text = 'Aref : %s Lref : %s [ %s ] '%(config.REF_AREA, config.REF_AREA, length_dimension) f.write(line_text) f.write('\n% ') line_text = 'Mach : %7.2f , '%(config.MACH_NUMBER) f.write(line_text) if config.PHYSICAL_PROBLEM == 'NAVIER_STOKES': line_text = 'Reynolds Number : %s '%(config.REYNOLDS_NUMBER) f.write(line_text) line_text = 'Reynolds length : %s [ %s ] '%(config.REYNOLDS_LENGTH, length_dimension) else: line_text = 'Physical problem : %s '%( config.PHYSICAL_PROBLEM) f.write(line_text) f.write('\n% ') rho = float(config.FREESTREAM_PRESSURE)/\ (float(config.GAS_CONSTANT)*float(config.FREESTREAM_TEMPERATURE)) line_text = 'Reference pressure : %s ,'%(config.FREESTREAM_PRESSURE) f.write(line_text) line_text = ' Reference density : %7.4f , '%(rho) f.write(line_text) line_text = ' Reference Temperature : %s '%(config.FREESTREAM_TEMPERATURE) f.write(line_text) f.write('\n% ') line_text = 'Constant specific heat ratio : %s , '%(config.GAMMA_VALUE) f.write(line_text) line_text = 'Gas constant : %s '%(config.GAS_CONSTANT) f.write(line_text) f.write('\n% ') line_text = 'Grid file : %s '%(config.MESH_FILENAME) f.write(line_text) f.write('\n% ') symmmetry_exists = False if 'MARKER_SYM' in config: if config.MARKER_SYM != 'NONE': symmmetry_exists = True if symmmetry_exists: line_text = 'Symmetry surface : yes' else: line_text = 'Symmetry surface : no' f.write(line_text) f.write('\n% \n') # ----------------- end reference parameter section -------------- if options.Wind: f.write('% AOA, Mach, CL, CD, ') if options.geomDim == 3: f.write('CY, ') else: if options.geomDim == 2: f.write('% AOA, Mach, CX, CY, ') else: f.write('% AOA, Mach, CX, CZ, CY, ') if options.geomDim == 3: f.write('Cmx, Cmz, Cmy \n') else: f.write(' Cmz \n') firstSweepPoint = True # iterate mach for MachNumber in MachList: # iterate angles for j in range(0, nPolara): if polarSweepType < 3: AngleAttack = alpha[j] SIDESLIP_ANGLE = beta[0] elif polarSweepType == 3: AngleAttack = alpha[0] SIDESLIP_ANGLE = beta[j] else: AngleAttack = alpha[0] SIDESLIP_ANGLE = beta[0] if options.verbose: print('Sweep step '+str(j)+': Mach = '+str(MachNumber)+\ ', aoa = ', str(AngleAttack)+', beta = '+str(SIDESLIP_ANGLE)) # local config and state konfig = copy.deepcopy(config) # enable restart in polar sweep konfig.DISCARD_INFILES = 'YES' ztate = copy.deepcopy(state) # # The eval functions below requires definition of various optimization # variables, though we are handling here only a direct solution. # So, if they are missing in the cfg file (and only then), some dummy values are # introduced here if 'OBJECTIVE_FUNCTION' not in konfig: konfig.OBJECTIVE_FUNCTION = 'DRAG' if 'DV_KIND' not in konfig: konfig.DV_KIND = ['FFD_SETTING'] if 'DV_PARAM' not in konfig: konfig.DV_PARAM = {'FFDTAG': ['1'], 'PARAM': [[0.0, 0.5]], 'SIZE': [1]} if 'DEFINITION_DV' not in konfig: konfig.DEFINITION_DV = {'FFDTAG': [[]], 'KIND': ['HICKS_HENNE'], 'MARKER': [['WING']], 'PARAM': [[0.0, 0.05]], 'SCALE': [1.0], 'SIZE': [1]} if 'OPT_OBJECTIVE' not in konfig: obj = {} obj['DRAG'] = {'SCALE':1.e-2, 'OBJTYPE':'DEFAULT', 'MARKER': 'None'} konfig.OPT_OBJECTIVE = obj # # --------- end of dummy optimization variables definition section --------- # # set angle of attack and side-slip angle konfig.AOA = AngleAttack konfig.SIDESLIP_ANGLE = SIDESLIP_ANGLE konfig.MACH_NUMBER = MachNumber caseName = 'DIRECT_M_' + str(MachNumber) + '_AOA_' + str(AngleAttack) print('Mach = ', konfig.MACH_NUMBER, 'AOA = ', konfig.AOA) print('case :' + caseName) if firstSweepPoint: # if caseName exists copy the restart file from it for run continuation # Continue from previous sweep point if this is not he first if os.path.isdir(caseName): command = 'cp '+caseName+'/'+config.SOLUTION_FLOW_FILENAME+' .' if options.verbose: print(command) os.system(command) konfig.RESTART_SOL = 'YES' else: konfig.RESTART_SOL = 'NO' firstSweepPoint = False else: konfig.RESTART_SOL = 'YES' if konfig.RESTART_SOL == 'YES': ztate.FILES.DIRECT = config.SOLUTION_FLOW_FILENAME # run su2 if options.Wind: drag = SU2.eval.func('DRAG', konfig, ztate) lift = SU2.eval.func('LIFT', konfig, ztate) if options.geomDim == 3: sideforce = SU2.eval.func('SIDEFORCE', konfig, ztate) else: force_x = SU2.eval.func('FORCE_X', konfig, ztate) force_y = SU2.eval.func('FORCE_Y', konfig, ztate) if options.geomDim == 3: force_z = SU2.eval.func('FORCE_Z', konfig, ztate) momentz = SU2.eval.func('MOMENT_Z', konfig, ztate) if options.geomDim == 3: momentx = SU2.eval.func('MOMENT_X', konfig, ztate) momenty = SU2.eval.func('MOMENT_Y', konfig, ztate) # append results if options.Wind: results.DRAG.append(drag) results.LIFT.append(lift) if options.geomDim == 3: results.SIDEFORCE.append(sideforce) else: results.FORCE_X.append(force_x) results.FORCE_Y.append(force_y) if options.geomDim == 3: results.FORCE_Z.append(force_z) results.MOMENT_Z.append(momentz) if options.geomDim == 3: results.MOMENT_X.append(momentx) results.MOMENT_Y.append(momenty) output = ' ' + str(AngleAttack) + ", "+str(MachNumber)+", " if options.Wind: output = output+ str(lift) + ", " + str(drag) if options.geomDim == 3: output = output+", "+str(sideforce) else: if options.geomDim == 2: output = output+ str(force_x) + ", " + str(force_y) else: output = output + str(force_x) + ", " + str(force_z) + ", " + str(force_y) if options.geomDim == 3: output = output + ", " + str(momentx) + ", " + str(momentz) + ", " output = output + str(momenty) + " \n" else: output = output+", "+str(momentz)+" \n" f.write(output) # save data SU2.io.save_data('results.pkl', results) os.system('cp results.pkl DIRECT/.') os.system('cp '+config.SOLUTION_FLOW_FILENAME+' DIRECT/.') if os.path.isdir(caseName): command = 'cat '+caseName+\ '/history_direct.dat DIRECT/history_direct.dat > tmp && mv tmp '+\ 'DIRECT/history_direct.dat' if options.verbose: print(command) os.system(command) os.system('rm -R '+caseName) command = 'cp -p -R DIRECT '+caseName if options.verbose: print(command) os.system(command) # Close open file f.close() if os.path.isdir('DIRECT'): os.system('rm -R DIRECT') if os.path.isfile(config.SOLUTION_FLOW_FILENAME): os.system('rm '+config.SOLUTION_FLOW_FILENAME) if os.path.isfile('results.pkl'): os.system('rm results.pkl') print('Post sweep cleanup completed') # sys.exit(0) #----------------------------------------------------------# #: for each angle # plotting #plt.figure() #plt.plot( results.MACH_NUMBER, results.AOA , results.LIFT , results.DRAG ) #plt.show() if __name__ == "__main__": main() explain how i can use this code to do analysis which the file polarCtrl.in as following # Control file for polar sweep run (default). # Note that this file is currently set for the QuickStart NACA 0012 case. Pitch axis : Z # One of the following lists of values (> 1) given at a time. angles of attack : 6.13779, 8.20698, 10.28034, 12.33281, 14.38945, 16.01136, 18.12235, 19.3137, 20.14555 # roll angles : 0.0, 45.0, 48.0, 50.0, 52.0, 55.0, 60.0, 90.0 # side slip angle : 3.0 # Mach ramp numbers : 0.3, 0.4, 0.6 input base file : SST_Incompressible.cfg the file SST_Incompressible.cfg as following %#############################################################################% % % % SU2 Configuration File % % Incompressible Airfoil Shape Optimization % % with SST Turbulence Model and Gamma-ReTheta Transition % % % %#############################################################################% % -------------------- MAIN SOLVER AND PHYSICS DEFINITION --------------------% % Solver for incompressible RANS equations SOLVER= INC_RANS % Use Menter's SST turbulence model KIND_TURB_MODEL= SST % Activate Langtry-Menter transition model %KIND_TRANS_MODEL= LM % Use the 2015 correlation for the LM model %LM_OPTIONS= LM2015 % [DIRECT, CONTINUOUS_ADJOINT, DISCRETE_ADJOINT] MATH_PROBLEM= DIRECT % Set to CONTINUOUS_ADJOINT for gradient computation RESTART_SOL= NO % -------------- COMPRESSIBLE AND INCOMPRESSIBLE FLUID CONSTANTS --------------% % GAMMA_VALUE= 1.4 GAS_CONSTANT= 287.87 % ------------------------- REFERENCE VALUES ---------------------------------% % Moment reference center (typically quarter-chord) REF_ORIGIN_MOMENT_X = 0.25 REF_ORIGIN_MOMENT_Y = 0.0 REF_ORIGIN_MOMENT_Z = 0.0 % Reference length (airfoil chord) [m] REF_LENGTH= 1.0 % Reference area [m^2] REF_AREA= 1.0 % Reference velocity [m/s] this for reynold number 1e7 REF_VELOCITY= 26.596 % Reference viscosity [kg/(m-s)] REF_VISCOSITY= 1.0 % ----------------------- INCOMPRESSIBLE CONDITIONS --------------------------% % Constant density model INC_DENSITY_MODEL= CONSTANT % Disable energy equation (isothermal flow) INC_ENERGY_EQUATION= NO % Non-dimensionalize using initial values INC_NONDIM= INITIAL_VALUES INC_DENSITY_INIT= 1.225 % Initial density (kg/m^3) - air at sea level INC_TEMPERATURE_INIT= 288.15 % Initial velocity vector 26.596 (m/s) at angle of AOA= 4.9004 INC_VELOCITY_INIT= ( 26.58650267 , 0.71069827, 0.0 ) % ---------------- TURBULENCE & TRANSITION INITIALIZATION --------------------% % Note: These are used even in incompressible flow for the turbulence model. % Reynolds number based on chord REYNOLDS_NUMBER= 1.8e6 % Freestream turbulence intensity (%) FREESTREAM_TURBULENCEINTENSITY= 0.0015 % Initial intermittency (1 = fully turbulent) FREESTREAM_INTERMITTENCY= 1.0 % Initial turb-to-lam viscosity ratio FREESTREAM_TURB2LAMVISCRATIO= 0.1 % Surface roughness height for transition model [m] HROUGHNESS= 1.0e-6 % ------------------------- BOUNDARY CONDITIONS ------------------------------% MARKER_HEATFLUX= ( AIRFOIL, 0.0 ) MARKER_FAR= ( FARFIELD ) % ------------------------- SURFACE IDENTIFICATION ---------------------------% % Surfaces to plot MARKER_PLOTTING= ( AIRFOIL ) % Surfaces to monitor forces MARKER_MONITORING= ( AIRFOIL ) % Surfaces to be modified during design MARKER_DESIGNING= ( AIRFOIL ) % Surfaces for detailed analysis MARKER_ANALYZE= ( AIRFOIL ) % ------------------------ NUMERICAL METHODS ---------------------------------% MUSCL_TURB= NO SLOPE_LIMITER_TURB= VENKATAKRISHNAN MUSCL_ADJFLOW= NO SLOPE_LIMITER_ADJFLOW= VENKATAKRISHNAN MUSCL_ADJTURB= NO SLOPE_LIMITER_ADJTURB= VENKATAKRISHNAN % Use higher-order reconstruction MUSCL_FLOW= NO ADJ_SHARP_LIMITER_COEFF= 3.0 LIMITER_ITER= 999999 LAX_SENSOR_COEFF= 0.15 JST_SENSOR_COEFF= ( 0.5, 0.02 ) ADJ_LAX_SENSOR_COEFF= 0.15 ADJ_JST_SENSOR_COEFF= ( 0.5, 0.02 ) % Spatial Discretization % Convective scheme for flow CONV_NUM_METHOD_FLOW= JST % Convective scheme for turbulence eqns CONV_NUM_METHOD_TURB= SCALAR_UPWIND % Gradient computation method NUM_METHOD_GRAD= WEIGHTED_LEAST_SQUARES % Slope limiter for flow SLOPE_LIMITER_FLOW= VENKATAKRISHNAN % Limiter coefficient VENKAT_LIMITER_COEFF= 0.05 % Temporal Discretization % Implicit Euler time integration TIME_DISCRE_FLOW= EULER_IMPLICIT % Implicit Euler for turbulence TIME_DISCRE_TURB= EULER_IMPLICIT % Linear Solver % Linear solver type LINEAR_SOLVER= FGMRES % Preconditioner type LINEAR_SOLVER_PREC= ILU % Linear solver tolerance LINEAR_SOLVER_ERROR= 1E-4 % Max linear solver iterations LINEAR_SOLVER_ITER= 10 % Multigrid % Number of multigrid levels MGLEVEL= 0 MGCYCLE= V_CYCLE % Match MG_PRE/POST lengths to MGLEVEL+1 (levels: 0..MGLEVEL) MG_PRE_SMOOTH= ( 1, 2, 3, 3 ) MG_POST_SMOOTH= ( 0, 0, 0, 0 ) MG_CORRECTION_SMOOTH= ( 0, 0, 0, 0 ) MG_DAMP_RESTRICTION= 0.8 MG_DAMP_PROLONGATION= 0.8 % ------------------------- CONVERGENCE PARAMETERS ---------------------------% % Initial CFL number CFL_NUMBER= 5.0 CFL_ADAPT= YES % CFL adaptation parameters % Reduce CFL for turbulence equations %CFL_ADAPT_PARAM= (0.1, 1.2, 0.5, 50.0, 0.001, 100) CFL_ADAPT_PARAM= (0.1, 1.2, 0.5, 50.0) CFL_REDUCTION_TURB= 1.0 % Max inner iterations per time step INNER_ITER= 20000 % Convergence criteria (log10 of residual) CONV_RESIDUAL_MINVAL= -10 % Field to monitor for convergence CONV_FIELD= DRAG ,LIFT % Window size for Cauchy criteria CONV_CAUCHY_ELEMS= 200 % Tolerance for Cauchy criteria CONV_CAUCHY_EPS= 1E-5 % Start convergence checking after N iterations CONV_STARTITER= 10 % ----------------------- TIME-DEPENDENT SIMULATION --------------------------% % Steady-state simulation TIME_DOMAIN= NO % No time marching TIME_MARCHING= NO % ------------------------- FLUID PROPERTIES ---------------------------------% % Fluid model for incompressible flow FLUID_MODEL= CONSTANT_DENSITY % Constant viscosity model VISCOSITY_MODEL= CONSTANT_VISCOSITY %# Dynamic viscosity (kg/m-s) for air at 15°C Dynamic viscosity of the fluid in kg/(m⋅s) MU_CONSTANT= 1.81e-05 % ----------------------- OUTPUT CONFIGURATION -------------------------------% SCREEN_OUTPUT= (INNER_ITER, WALL_TIME, RMS_RES, LIFT, DRAG, MOMENT_Z, SENS_GEO) HISTORY_OUTPUT= (ITER, LINSOL, RMS_RES, MAX_RES, AERO_COEFF, CFL_NUMBER) VOLUME_OUTPUT= (COORDINATES, SOLUTION, PRIMITIVE, RESIDUAL, FLOW_COEFFS) OUTPUT_FILES= (RESTART, PARAVIEW, SURFACE_PARAVIEW) % Output frequencies SCREEN_WRT_FREQ_INNER= 1 HISTORY_WRT_FREQ_INNER= 1 OUTPUT_WRT_FREQ= 100 WRT_FORCES_BREAKDOWN= YES % File names MESH_FILENAME= FFA-W3-211_StructMesh_RoundTE_RE1.8e6.su2 MESH_FORMAT= SU2 SOLUTION_FILENAME= solution_flow RESTART_FILENAME= restart_flow SOLUTION_ADJ_FILENAME= solution_adj RESTART_ADJ_FILENAME= restart_adj CONV_FILENAME= history TABULAR_FORMAT= CSV GRAD_OBJFUNC_FILENAME= of_grad MESH_OUT_FILENAME= mesh_out.su2 VOLUME_FILENAME= flow SURFACE_FILENAME= surface_flow READ_BINARY_RESTART= YES
最新发布
09-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值