def adaptation ( config , kind='' ): # local copy konfig = copy.deepcopy(config) # check kind if kind: konfig['KIND_ADAPT'] = kind kind = konfig.get('KIND_ADAPT','NONE') if kind == 'NONE': return {} # check adapted? # decompose su2decomp(konfig) # get adaptation function adapt_function = su2mesh.adapt.name_map[kind] # setup problem suffix = 'adapt' meshname_orig = konfig['MESH_FILENAME'] meshname_new = su2io.add_suffix( konfig['MESH_FILENAME'], suffix ) konfig['MESH_OUT_FILENAME'] = meshname_new # Run Adaptation info = adapt_function(konfig) # update super config config['MESH_FILENAME'] = meshname_new config['KIND_ADAPT'] = kind # files out files = { 'MESH' : meshname_new } # info out append_nestdict( info, { 'FILES' : files } ) return info
def adaptation(config, kind=''): # local copy konfig = copy.deepcopy(config) # check kind if kind: konfig['KIND_ADAPT'] = kind kind = konfig.get('KIND_ADAPT', 'NONE') if kind == 'NONE': return {} # check adapted? # decompose su2decomp(konfig) # get adaptation function adapt_function = su2mesh.adapt.name_map[kind] # setup problem suffix = 'adapt' meshname_orig = konfig['MESH_FILENAME'] meshname_new = su2io.add_suffix(konfig['MESH_FILENAME'], suffix) konfig['MESH_OUT_FILENAME'] = meshname_new # Run Adaptation info = adapt_function(konfig) # update super config config['MESH_FILENAME'] = meshname_new config['KIND_ADAPT'] = kind # files out files = {'MESH': meshname_new} # info out append_nestdict(info, {'FILES': files}) return info
def projection( config, step = 1e-3 ): """ info = SU2.run.projection(config,step=1e-3) Runs an gradient projection with: SU2.run.decomp() SU2.run.GPC() Assumptions: Redundant decomposition if config.DECOMPOSED == True Writes tecplot file of gradients Adds objective suffix to gradient plot filename Inputs: config - an SU2 config step - a float or list of floats for geometry sensitivity finite difference step Outputs: info - SU2 State with keys: GRADIENTS.<config.OBJECTIVE_FUNCTION> Updates: config.DECOMPOSED config.MATH_PROBLEM Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # choose dv values Definition_DV = konfig['DEFINITION_DV'] n_DV = len(Definition_DV['KIND']) if isinstance(step,list): assert len(step) == n_DV , 'unexpected step vector length' else: step = [step]*n_DV dv_old = [0.0]*n_DV # SU2_GPC input requirement, assumes linear superposition of design variables dv_new = step konfig.unpack_dvs(dv_new,dv_old) # filenames objective = konfig['OBJECTIVE_FUNCTION'] grad_filename = konfig['GRAD_OBJFUNC_FILENAME'] output_format = konfig['OUTPUT_FORMAT'] plot_extension = su2io.get_extension(output_format) adj_suffix = su2io.get_adjointSuffix(objective) grad_plotname = os.path.splitext(grad_filename)[0] + '_' + adj_suffix + plot_extension # Run Projection SU2_GPC(konfig) # read raw gradients raw_gradients = su2io.read_gradients(grad_filename) os.remove(grad_filename) # Write Gradients data_plot = su2util.ordered_bunch() data_plot['VARIABLE'] = range(len(raw_gradients)) data_plot['GRADIENT'] = raw_gradients data_plot['FINDIFF_STEP'] = step su2util.write_plot(grad_plotname,output_format,data_plot) # gradient output dictionary gradients = { objective : raw_gradients } # info out info = su2io.State() info.GRADIENTS.update( gradients ) return info
def direct ( config ): """ info = SU2.run.direct(config) Runs an adjoint analysis with: SU2.run.decomp() SU2.run.CFD() SU2.run.merge() Assumptions: Redundant decomposition if config.DECOMPOSED == True Does not rename restart filename to solution filename Adds 'direct' suffix to convergence filename Outputs: info - SU2 State with keys: FUNCTIONS HISTORY.DIRECT FILES.DIRECT Updates: config.DECOMPOSED config.MATH_PROBLEM Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # setup direct problem konfig['MATH_PROBLEM'] = 'DIRECT' konfig['CONV_FILENAME'] = konfig['CONV_FILENAME'] + '_direct' # Run Solution SU2_CFD(konfig) # merge konfig['SOLUTION_FLOW_FILENAME'] = konfig['RESTART_FLOW_FILENAME'] su2merge(konfig) # filenames plot_format = konfig['OUTPUT_FORMAT'] plot_extension = su2io.get_extension(plot_format) history_filename = konfig['CONV_FILENAME'] + plot_extension special_cases = su2io.get_specialCases(konfig) # get history and objectives history = su2io.read_history( history_filename ) aerodynamics = su2io.read_aerodynamics( history_filename , special_cases ) # update super config config.update({ 'DECOMPOSED' : konfig['DECOMPOSED'] , 'MATH_PROBLEM' : konfig['MATH_PROBLEM'] }) # info out info = su2io.State() info.FUNCTIONS.update( aerodynamics ) info.FILES.DIRECT = konfig['RESTART_FLOW_FILENAME'] if 'EQUIV_AREA' in special_cases: info.FILES.WEIGHT_NF = 'WeightNF.dat' info.HISTORY.DIRECT = history return info
def adjoint( config ): """ info = SU2.run.adjoint(config) Runs an adjoint analysis with: SU2.run.decomp() SU2.run.CFD() SU2.run.merge() Assumptions: Redundant decomposition if config.DECOMPOSED == True Does not run Gradient Projection Does not rename restart filename to solution filename Adds 'adjoint' suffix to convergence filename Outputs: info - SU2 State with keys: HISTORY.ADJOINT_NAME FILES.ADJOINT_NAME Updates: config.DECOMPOSED config.MATH_PROBLEM Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # setup problem konfig['MATH_PROBLEM'] = 'ADJOINT' konfig['CONV_FILENAME'] = konfig['CONV_FILENAME'] + '_adjoint' # Run Solution SU2_CFD(konfig) # merge konfig['SOLUTION_ADJ_FILENAME'] = konfig['RESTART_ADJ_FILENAME'] su2merge(konfig) # filenames plot_format = konfig['OUTPUT_FORMAT'] plot_extension = su2io.get_extension(plot_format) history_filename = konfig['CONV_FILENAME'] + plot_extension special_cases = su2io.get_specialCases(konfig) # get history history = su2io.read_history( history_filename ) # update super config config.update({ 'DECOMPOSED' : konfig['DECOMPOSED'] , 'MATH_PROBLEM' : konfig['MATH_PROBLEM'] , 'OBJECTIVE_FUNCTION' : konfig['OBJECTIVE_FUNCTION'] }) # files out objective = konfig['OBJECTIVE_FUNCTION'] adj_title = 'ADJOINT_' + objective suffix = su2io.get_adjointSuffix(objective) restart_name = konfig['RESTART_FLOW_FILENAME'] restart_name = su2io.add_suffix(restart_name,suffix) # info out info = su2io.State() info.FILES[adj_title] = restart_name info.HISTORY[adj_title] = history return info
def direct(config): """ info = SU2.run.direct(config) Runs an adjoint analysis with: SU2.run.decomp() SU2.run.CFD() SU2.run.merge() Assumptions: Redundant decomposition if config.DECOMPOSED == True Does not rename restart filename to solution filename Adds 'direct' suffix to convergence filename Outputs: info - SU2 State with keys: FUNCTIONS HISTORY.DIRECT FILES.DIRECT Updates: config.DECOMPOSED config.MATH_PROBLEM Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # setup direct problem konfig['MATH_PROBLEM'] = 'DIRECT' konfig['CONV_FILENAME'] = konfig['CONV_FILENAME'] + '_direct' # Run Solution SU2_CFD(konfig) # merge konfig['SOLUTION_FLOW_FILENAME'] = konfig['RESTART_FLOW_FILENAME'] su2merge(konfig) # filenames plot_format = konfig['OUTPUT_FORMAT'] plot_extension = su2io.get_extension(plot_format) history_filename = konfig['CONV_FILENAME'] + plot_extension special_cases = su2io.get_specialCases(konfig) # averaging final iterations final_avg = config.get('ITER_AVERAGE_OBJ', 0) # get history and objectives history = su2io.read_history(history_filename) aerodynamics = su2io.read_aerodynamics(history_filename, special_cases, final_avg) # update super config config.update({ 'DECOMPOSED': konfig['DECOMPOSED'], 'MATH_PROBLEM': konfig['MATH_PROBLEM'] }) # info out info = su2io.State() info.FUNCTIONS.update(aerodynamics) info.FILES.DIRECT = konfig['RESTART_FLOW_FILENAME'] if 'EQUIV_AREA' in special_cases: info.FILES.WEIGHT_NF = 'WeightNF.dat' if 'INV_DESIGN_CP' in special_cases: info.FILES.TARGET_CP = 'TargetCp.dat' if 'INV_DESIGN_HEATFLUX' in special_cases: info.FILES.TARGET_HEATFLUX = 'TargetHeatFlux.dat' info.HISTORY.DIRECT = history return info
def deform ( config, dv_new=None, dv_old=None ): """ info = SU2.run.deform(config,dv_new=[],dv_old=[]) Deforms mesh with: SU2.run.decomp() SU2.run.DEF() Assumptions: Redundant decomposition if config.DECOMPOSED == True If optional dv_new ommitted, config is setup for deformation If using dv_old, must provide dv_new Adds 'deform' suffix to mesh output name Outputs: info - SU2 State with keys: HISTORY.ADJOINT_NAME FILES.ADJOINT_NAME Updates: config.DECOMPOSED config.MESH_FILENAME config.DV_VALUE_OLD = config.DV_VALUE_NEW Executes in: ./ """ if dv_new is None: dv_new = [] if dv_old is None: dv_old = [] # error check if dv_old and not dv_new: raise Exception, 'must provide dv_old with dv_new' # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # unpack design variables if dv_new: konfig.unpack_dvs(dv_new,dv_old) # redundancy check if konfig['DV_VALUE_NEW'] == konfig['DV_VALUE_OLD']: info = su2io.State() info.FILES.MESH = konfig.MESH_FILENAME info.VARIABLES.DV_VALUE_NEW = konfig.DV_VALUE_NEW return info # setup mesh name suffix = 'deform' mesh_name = konfig['MESH_FILENAME'] meshname_suffixed = su2io.add_suffix( mesh_name , suffix ) konfig['MESH_OUT_FILENAME'] = meshname_suffixed # Run Deformation SU2_DEF(konfig) # update super config config.update({ 'DECOMPOSED' : konfig['DECOMPOSED'] , 'MESH_FILENAME' : konfig['MESH_OUT_FILENAME'] , 'DV_KIND' : konfig['DV_KIND'] , 'DV_MARKER' : konfig['DV_MARKER'] , 'DV_PARAM' : konfig['DV_PARAM'] , 'DV_VALUE_OLD' : konfig['DV_VALUE_NEW'] , 'DV_VALUE_NEW' : konfig['DV_VALUE_NEW'] }) # not modified: config['MESH_OUT_FILENAME'] # info out info = su2io.State() info.FILES.MESH = meshname_suffixed info.VARIABLES.DV_VALUE_NEW = konfig.DV_VALUE_NEW return info #: def deform()
def deform(config, dv_new=None, dv_old=None): """ info = SU2.run.deform(config,dv_new=[],dv_old=[]) Deforms mesh with: SU2.run.decomp() SU2.run.DEF() Assumptions: Redundant decomposition if config.DECOMPOSED == True If optional dv_new ommitted, config is setup for deformation If using dv_old, must provide dv_new Adds 'deform' suffix to mesh output name Outputs: info - SU2 State with keys: HISTORY.ADJOINT_NAME FILES.ADJOINT_NAME Updates: config.DECOMPOSED config.MESH_FILENAME config.DV_VALUE_OLD = config.DV_VALUE_NEW Executes in: ./ """ if dv_new is None: dv_new = [] if dv_old is None: dv_old = [] # error check if dv_old and not dv_new: raise Exception, 'must provide dv_old with dv_new' # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # unpack design variables if dv_new: konfig.unpack_dvs(dv_new, dv_old) # redundancy check if konfig['DV_VALUE_NEW'] == konfig['DV_VALUE_OLD']: info = su2io.State() info.FILES.MESH = konfig.MESH_FILENAME info.VARIABLES.DV_VALUE_NEW = konfig.DV_VALUE_NEW return info # setup mesh name suffix = 'deform' mesh_name = konfig['MESH_FILENAME'] meshname_suffixed = su2io.add_suffix(mesh_name, suffix) konfig['MESH_OUT_FILENAME'] = meshname_suffixed # Run Deformation SU2_DEF(konfig) # update super config config.update({ 'DECOMPOSED': konfig['DECOMPOSED'], 'MESH_FILENAME': konfig['MESH_OUT_FILENAME'], 'DV_KIND': konfig['DV_KIND'], 'DV_MARKER': konfig['DV_MARKER'], 'DV_PARAM': konfig['DV_PARAM'], 'DV_VALUE_OLD': konfig['DV_VALUE_NEW'], 'DV_VALUE_NEW': konfig['DV_VALUE_NEW'] }) # not modified: config['MESH_OUT_FILENAME'] # info out info = su2io.State() info.FILES.MESH = meshname_suffixed info.VARIABLES.DV_VALUE_NEW = konfig.DV_VALUE_NEW return info #: def deform()
def geometry ( config , step = 1e-3 ): """ info = SU2.run.geometry(config) Runs an geometry analysis with: SU2.run.decomp() SU2.run.GEO() Assumptions: Redundant decomposition if config.DECOMPOSED == True Performs both function and gradient analysis Inputs: config - an SU2 configuration step - gradient finite difference step if config.GEO_MODE=GRADIENT Outputs: info - SU2 State with keys: FUNCTIONS GRADIENTS Updates: config.DECOMPOSED Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # unpack function_name = konfig['GEO_PARAM'] func_filename = 'of_func.dat' grad_filename = 'of_grad.dat' # choose dv values Definition_DV = konfig['DEFINITION_DV'] n_DV = len(Definition_DV['KIND']) if isinstance(step,list): assert len(step) == n_DV , 'unexpected step vector length' else: step = [step]*n_DV dv_old = [0.0]*n_DV # SU2_DOT input requirement, assumes linear superposition of design variables dv_new = step konfig.unpack_dvs(dv_new,dv_old) # decompose su2decomp(konfig) # Run Solution SU2_GEO(konfig) # info out info = su2io.State() # get function values if konfig.GEO_MODE == 'FUNCTION': functions = su2io.tools.read_plot(func_filename) for key,value in functions.items(): functions[key] = value[0] info.FUNCTIONS.update( functions ) # get gradient_values if konfig.GEO_MODE == 'GRADIENT': gradients = su2io.tools.read_plot(grad_filename) info.GRADIENTS.update( gradients ) # update super config config.update({ 'DECOMPOSED' : konfig['DECOMPOSED'] }) return info
def adjoint(config): """ info = SU2.run.adjoint(config) Runs an adjoint analysis with: SU2.run.decomp() SU2.run.CFD() SU2.run.merge() Assumptions: Redundant decomposition if config.DECOMPOSED == True Does not run Gradient Projection Does not rename restart filename to solution filename Adds 'adjoint' suffix to convergence filename Outputs: info - SU2 State with keys: HISTORY.ADJOINT_NAME FILES.ADJOINT_NAME Updates: config.DECOMPOSED config.MATH_PROBLEM Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # setup problem konfig['MATH_PROBLEM'] = 'ADJOINT' konfig['CONV_FILENAME'] = konfig['CONV_FILENAME'] + '_adjoint' # Run Solution SU2_CFD(konfig) # merge konfig['SOLUTION_ADJ_FILENAME'] = konfig['RESTART_ADJ_FILENAME'] su2merge(konfig) # filenames plot_format = konfig['OUTPUT_FORMAT'] plot_extension = su2io.get_extension(plot_format) history_filename = konfig['CONV_FILENAME'] + plot_extension special_cases = su2io.get_specialCases(konfig) # get history history = su2io.read_history(history_filename) # update super config config.update({ 'DECOMPOSED': konfig['DECOMPOSED'], 'MATH_PROBLEM': konfig['MATH_PROBLEM'], 'ADJ_OBJFUNC': konfig['ADJ_OBJFUNC'] }) # files out objective = konfig['ADJ_OBJFUNC'] adj_title = 'ADJOINT_' + objective suffix = su2io.get_adjointSuffix(objective) restart_name = konfig['RESTART_FLOW_FILENAME'] restart_name = su2io.add_suffix(restart_name, suffix) # info out info = su2io.State() info.FILES[adj_title] = restart_name info.HISTORY[adj_title] = history return info
def projection(config, step=1e-3): """ info = SU2.run.projection(config,step=1e-3) Runs an gradient projection with: SU2.run.decomp() SU2.run.DOT() Assumptions: Redundant decomposition if config.DECOMPOSED == True Writes tecplot file of gradients Adds objective suffix to gradient plot filename Inputs: config - an SU2 config step - a float or list of floats for geometry sensitivity finite difference step Outputs: info - SU2 State with keys: GRADIENTS.<config.OBJECTIVE_FUNCTION> Updates: config.DECOMPOSED config.MATH_PROBLEM Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # decompose su2decomp(konfig) # choose dv values Definition_DV = konfig['DEFINITION_DV'] n_DV = len(Definition_DV['KIND']) if isinstance(step, list): assert len(step) == n_DV, 'unexpected step vector length' else: step = [step] * n_DV dv_old = [ 0.0 ] * n_DV # SU2_DOT input requirement, assumes linear superposition of design variables dv_new = step konfig.unpack_dvs(dv_new, dv_old) # filenames objective = konfig['OBJECTIVE_FUNCTION'] grad_filename = konfig['GRAD_OBJFUNC_FILENAME'] output_format = konfig['OUTPUT_FORMAT'] plot_extension = su2io.get_extension(output_format) adj_suffix = su2io.get_adjointSuffix(objective) grad_plotname = os.path.splitext( grad_filename)[0] + '_' + adj_suffix + plot_extension # Run Projection SU2_DOT(konfig) # read raw gradients raw_gradients = su2io.read_gradients(grad_filename) os.remove(grad_filename) # Write Gradients data_plot = su2util.ordered_bunch() data_plot['VARIABLE'] = range(len(raw_gradients)) data_plot['GRADIENT'] = raw_gradients data_plot['FINDIFF_STEP'] = step su2util.write_plot(grad_plotname, output_format, data_plot) # gradient output dictionary gradients = {objective: raw_gradients} # info out info = su2io.State() info.GRADIENTS.update(gradients) return info
def geometry ( config , step = 1e-3 ): """ info = SU2.run.geometry(config) Runs an geometry analysis with: SU2.run.decomp() SU2.run.GDC() Assumptions: Redundant decomposition if config.DECOMPOSED == True Performs both function and gradient analysis Inputs: config - an SU2 configuration step - gradient finite difference step if config.GEO_MODE=GRADIENT Outputs: info - SU2 State with keys: FUNCTIONS GRADIENTS Updates: config.DECOMPOSED Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # unpack function_name = konfig['GEO_PARAM'] func_filename = 'of_func.dat' grad_filename = 'of_grad.dat' # choose dv values Definition_DV = konfig['DEFINITION_DV'] n_DV = len(Definition_DV['KIND']) if isinstance(step,list): assert len(step) == n_DV , 'unexpected step vector length' else: step = [step]*n_DV dv_old = [0.0]*n_DV # SU2_GPC input requirement, assumes linear superposition of design variables dv_new = step konfig.unpack_dvs(dv_new,dv_old) # decompose su2decomp(konfig) # Run Solution SU2_GDC(konfig) # info out info = su2io.State() # get function values if konfig.GEO_MODE == 'FUNCTION': functions = su2io.tools.read_plot(func_filename) for key,value in functions.items(): functions[key] = value[0] info.FUNCTIONS.update( functions ) # get gradient_values if konfig.GEO_MODE == 'GRADIENT': gradients = su2io.tools.read_plot(grad_filename) info.GRADIENTS.update( gradients ) # update super config config.update({ 'DECOMPOSED' : konfig['DECOMPOSED'] }) return info
def geometry(config, step=1e-3): """ info = SU2.run.geometry(config) Runs an geometry analysis with: SU2.run.decomp() SU2.run.GDC() Assumptions: Redundant decomposition if config.DECOMPOSED == True Performs both function and gradient analysis Outputs: info - SU2 State with keys: FUNCTIONS GRADIENTS Updates: config.DECOMPOSED Executes in: ./ """ # local copy konfig = copy.deepcopy(config) # unpack function_name = konfig['GEO_PARAM'] func_filename = 'of_eval.dat' grad_filename = 'of_grad.dat' # does both direct and gradient, very cheap konfig.GEO_MODE = 'GRADIENT' # choose dv values Definition_DV = konfig['DEFINITION_DV'] n_DV = len(Definition_DV['KIND']) if isinstance(step, list): assert len(step) == n_DV, 'unexpected step vector length' else: step = [step] * n_DV dv_old = [ 0.0 ] * n_DV # SU2_GPC input requirement, assumes linear superposition of design variables dv_new = step konfig.unpack_dvs(dv_new, dv_old) # decompose su2decomp(konfig) # Run Solution SU2_GDC(konfig) # get function values func_file = open(func_filename) funcs = float(func_file.readline().strip()) func_file.close() functions = ordered_bunch({function_name: funcs}) # get gradient_values grads = su2io.read_gradients(grad_filename) gradients = ordered_bunch({function_name: grads}) # update super config config.update({'DECOMPOSED': konfig['DECOMPOSED']}) # info out info = su2io.State() info.FUNCTIONS.update(functions) info.GRADIENTS.update(gradients) return info