def process_surface_adjoint(config_filename, filter_type='LAPLACE', marker_name='airfoil', chord_length=1.0): print('') print( '-------------------------------------------------------------------------' ) print( '| SU2 Suite (Process Surface Adjoint) |' ) print( '-------------------------------------------------------------------------' ) print('') # some other defaults c_clip = 0.01 # percent chord to truncate fft_copy = 5 # number of times to copy the fft signal smth_len = 0.05 # percent chord smoothing window length lapl_len = 1e-4 # laplace smoothing parameter # read config file config_data = libSU2.Get_ConfigParams(config_filename) surface_filename = config_data['SURFACE_ADJ_FILENAME'] + '.csv' print surface_filename mesh_filename = config_data['MESH_FILENAME'] gradient = config_data['ADJ_OBJFUNC'] print('Config filename = %s' % config_filename) print('Surface filename = %s' % surface_filename) print('Filter Type = %s' % filter_type) # read adjoint data adj_data = np.genfromtxt(surface_filename, dtype=float, delimiter=',', skip_header=1) # read mesh data mesh_data = libSU2_mesh.Read_Mesh(mesh_filename) # proces adjoint data P = map(int, adj_data[:, 0]) X = adj_data[:, 6].copy() Y = adj_data[:, 7].copy() Sens = adj_data[:, 1].copy() PsiRho = adj_data[:, 2].copy() I = range(0, len(P)) # important - for unsorting durring write # store in dict by point index adj_data_dict = dict(zip(P, zip(X, Y, Sens, PsiRho, I))) # sort airfoil points iP_sorted, _ = libSU2_mesh.sort_Airfoil(mesh_data, marker_name) assert (len(iP_sorted) == len(P)) # rebuild airfoil loop i = 0 for this_P in iP_sorted: # the adjoint data entry this_adj_data = adj_data_dict[this_P] # re-sort P[i] = this_P X[i] = this_adj_data[0] Y[i] = this_adj_data[1] Sens[i] = this_adj_data[2] PsiRho[i] = this_adj_data[3] I[i] = this_adj_data[4] # next i = i + 1 #: for each point # calculate arc length S = np.sqrt(np.diff(X)**2 + np.diff(Y)**2) / chord_length S = np.cumsum(np.hstack([0, S])) # tail trucating, by arc length I_clip_lo = S < S[0] + c_clip I_clip_hi = S > S[-1] - c_clip S_clip = S.copy() Sens_clip = Sens.copy() Sens_clip[I_clip_hi] = Sens_clip[I_clip_hi][0] Sens_clip[I_clip_lo] = Sens_clip[I_clip_lo][-1] # some edge length statistics dS_clip = np.diff(S_clip) min_dS = np.min(dS_clip) mean_dS = np.mean(dS_clip) max_dS = np.max(dS_clip) #print 'min_dS = %.4e ; mean_dS = %.4e ; max_dS = %.4e' % ( min_dS , mean_dS , max_dS ) # -------------------------------------------- # APPLY FILTER if filter_type == 'FOURIER': Freq_notch = [1 / max_dS, np.inf] # the notch frequencies Sens_filter, Frequency, Power = fft_filter(S_clip, Sens_clip, Freq_notch, fft_copy) #Sens_filter = smooth(S_clip,Sens_filter, 0.03,'blackman') # post smoothing elif filter_type == 'WINDOW': Sens_filter = window(S_clip, Sens_clip, smth_len, 'blackman') elif filter_type == 'LAPLACE': Sens_filter = laplace(S_clip, Sens_clip, lapl_len) elif filter_type == 'SHARPEN': Sens_smooth = smooth(S_clip, Sens_clip, smth_len / 5, 'blackman') # pre smoothing Sens_smoother = smooth(S_clip, Sens_smooth, smth_len, 'blackman') Sens_filter = Sens_smooth + (Sens_smooth - Sens_smoother) # sharpener else: raise Exception, 'unknown filter type' # -------------------------------------------- # PLOTTING if pylab_imported: # start plot fig = plt.figure(gradient) plt.clf() #if not fig.axes: # for comparing two filter calls #plt.subplot(1,1,1) #ax = fig.axes[0] #if len(ax.lines) == 4: #ax.lines.pop(0) #ax.lines.pop(0) # SENSITIVITY plt.plot(S, Sens, color='b') # original plt.plot(S_clip, Sens_filter, color='r') # filtered plt.xlim(-0.1, 2.1) plt.ylim(-5, 5) plt.xlabel('Arc Length') plt.ylabel('Surface Sensitivity') #if len(ax.lines) == 4: #seq = [2, 2, 7, 2] #ax.lines[0].set_dashes(seq) #ax.lines[1].set_dashes(seq) plot_filename = os.path.splitext(surface_filename)[0] + '.png' plt.savefig('Sens_' + plot_filename, dpi=300) # zoom in plt.ylim(-0.4, 0.4) plt.savefig('Sens_zoom_' + plot_filename, dpi=300) # SPECTRAL if filter_type == 'FOURIER': plt.figure('SPECTRAL') plt.clf() plt.plot(Frequency, Power) #plt.xlim(0,Freq_notch[0]+10) plt.xlim(0, 200) plt.ylim(0, 0.15) plt.xlabel('Frequency (1/C)') plt.ylabel('Surface Sensitivity Spectal Power') plt.savefig('Spectral_' + plot_filename, dpi=300) #: if spectral plot #: if plot # -------------------------------------------- # SAVE SURFACE FILE # reorder back to input surface points Sens_out = np.zeros(len(S)) Sens_out[I] = Sens_filter # left over from sort adj_data[:, 1] = Sens_out # get surface header surface_orig = open(surface_filename, 'r') header = surface_orig.readline() surface_orig.close() # get list of prefix names prefix_names = libSU2.get_AdjointPrefix(None) prefix_names = prefix_names.values() # add filter prefix, before adjoint prefix surface_filename_split = surface_filename.rstrip('.csv').split('_') if surface_filename_split[-1] in prefix_names: surface_filename_split = surface_filename_split[0:-1] + [ 'filtered' ] + [surface_filename_split[-1]] else: surface_filename_split = surface_filename_split + ['filtered'] surface_filename_new = '_'.join(surface_filename_split) + '.csv' # write filtered surface file (only updates Sensitivity) surface_new = open(surface_filename_new, 'w') surface_new.write(header) for row in adj_data: for i, value in enumerate(row): if i > 0: surface_new.write(', ') if i == 0: surface_new.write('%i' % value) else: surface_new.write('%.16e' % value) surface_new.write('\n') surface_new.close() print('') print( '----------------- Exit Success (Process Surface Adjoint) ----------------' ) print('') return
def mesh_adaptation(filename, partitions=0, cycles=1, overwrite=False, save_all=False): # General and default parameters Config_INP_filename = filename Config_CFD_filename = "config_CFD_" + Config_INP_filename Config_MAC_filename = "config_MAC_" + Config_INP_filename #Mesh_MAC_filename = "mesh_MAC_" + filename.replace(".cfg",".su2") finest_mesh_filename = "mesh_finest.su2" finest_flow_filename = "restart_flow_finest.dat" finest_lin_filename = "restart_lin_finest.dat" finest_adj_filename = "restart_adj_finest.dat" # assumes serial with partitions = 1 if partitions == 1: partitions = 0 # Get parameters params_get = libSU2.Get_ConfigParams(Config_INP_filename) kind_adapt = params_get['KIND_ADAPT'] objfunc = params_get['ADJ_OBJFUNC'] restart_flow_file = params_get['RESTART_FLOW_FILENAME'] restart_adj_file = params_get['RESTART_ADJ_FILENAME'] original_mesh_file = params_get['MESH_FILENAME'] #output_mesh_file = params_get['MESH_OUT_FILENAME'] Mesh_MAC_filename = params_get['MESH_OUT_FILENAME'] cadj_prefix = libSU2.get_AdjointPrefix(objfunc) # Get solution file names volume_flow_file = params_get['VOLUME_FLOW_FILENAME'] volume_adj_file = params_get['VOLUME_ADJ_FILENAME'] surface_flow_file = params_get['SURFACE_FLOW_FILENAME'] surface_adj_file = params_get['SURFACE_ADJ_FILENAME'] history_file = params_get['CONV_FILENAME'] # Get mesh filenames and filetypes mesh_filetype = params_get['MESH_FORMAT'] if mesh_filetype == "CGNS": error_str = "Currently cannot support mesh adaptation with CGNS grid files. Please convert your CGNS mesh to SU2 format using the CGNS_TO_SU2 flag in the configuration file, re-specify the mesh file to the native .su2 file and set the MESH_FORMAT flag to SU2." print "\n*****\n" + error_str + "\n*****\n" return 1 elif mesh_filetype == "NETCDF_ASCII": error_str = "Currently cannot support mesh adaptation with NETCDF_ASCII grid files. Please convert your mesh to SU2 format, re-specify the mesh file to the native .su2 file and set the MESH_FORMAT flag to SU2." print "\n*****\n" + error_str + "\n*****\n" return 1 # Get output solution filetypes output_filetype = params_get['OUTPUT_FORMAT'] if output_filetype == "TECPLOT": vol_file_ext = ".plt" elif output_filetype == "PARAVIEW": vol_file_ext = ".vtk" if ((kind_adapt == "ROBUST") or (kind_adapt == "COMPUTABLE_ROBUST")): restart_lin_file = params_get['RESTART_LIN_FILENAME'] # Loop over number of adaptation cycles for iAdaptCycle in range(cycles): # Copy original input file to working files shutil.copy(Config_INP_filename, Config_MAC_filename) shutil.copy(Config_INP_filename, Config_CFD_filename) # Run direct flow simulation # For iAdaptCycle == 0, store restart file, objective function and original mesh file params_set = {'MATH_PROBLEM': 'DIRECT'} if iAdaptCycle > 0: params_set.update({ 'RESTART_SOL': 'YES', 'ADJ_OBJFUNC': objfunc, 'RESTART_FLOW_FILENAME': restart_flow_file, 'RESTART_ADJ_FILENAME': restart_adj_file, 'SOLUTION_FLOW_FILENAME': restart_flow_file, 'MESH_FILENAME': Mesh_MAC_filename }) if ((kind_adapt == "ROBUST") or kind_adapt == ("COMPUTABLE_ROBUST")): params_set.update({'RESTART_LIN_FILENAME': restart_lin_file}) # Load the new config file options and run the direct problem libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation(Config_CFD_filename, partitions) else: libSU2_run.SU2_CFD(Config_CFD_filename, partitions) # Copy flow solution & history file if save_all: print "Saving cycle " + str( iAdaptCycle) + " flow solution and history files..." print "Saving " + volume_flow_file + "_cycle" + str( iAdaptCycle) + vol_file_ext print "Saving " + surface_flow_file + "_cycle" + str( iAdaptCycle) + vol_file_ext print "Saving " + history_file + "_flow_cycle" + str( iAdaptCycle) + vol_file_ext shutil.move( volume_flow_file + vol_file_ext, volume_flow_file + "_cycle" + str(iAdaptCycle) + vol_file_ext) shutil.move( surface_flow_file + vol_file_ext, surface_flow_file + "_cycle" + str(iAdaptCycle) + vol_file_ext) shutil.move( surface_flow_file + ".csv", surface_flow_file + "_cycle" + str(iAdaptCycle) + ".csv") shutil.move( history_file + vol_file_ext, history_file + "_flow_cycle" + str(iAdaptCycle) + vol_file_ext) # If needed, run the adjoint simulation # For the first adaption cycle, use the filenames of the orignal .cfg file if (kind_adapt == "GRAD_ADJOINT" or kind_adapt == "GRAD_FLOW_ADJ" or kind_adapt == "ROBUST" or kind_adapt == "COMPUTABLE_ROBUST" or kind_adapt == "COMPUTABLE" or kind_adapt == "REMAINING"): params_set = { 'MATH_PROBLEM': 'ADJOINT', 'SOLUTION_FLOW_FILENAME': restart_flow_file } if iAdaptCycle > 0: params_set.update({ 'RESTART_SOL': 'YES', 'SOLUTION_ADJ_FILENAME': restart_adj_file, 'MESH_FILENAME': Mesh_MAC_filename }) # Load the new config file options and run the adjoint problem libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation(Config_CFD_filename, partitions) else: libSU2_run.SU2_CFD(Config_CFD_filename, partitions) # Copy adjoint solution & history file if save_all: print "Saving cycle " + str( iAdaptCycle) + " adjoint solution and history files..." print "Saving " + volume_adj_file + "_cycle" + str( iAdaptCycle) + vol_file_ext print "Saving " + surface_adj_file + "_adj_cycle" + str( iAdaptCycle) + vol_file_ext print "Saving " + history_file + "_flow_cycle" + str( iAdaptCycle) + vol_file_ext shutil.move( volume_adj_file + vol_file_ext, volume_adj_file + "_cycle" + str(iAdaptCycle) + vol_file_ext) shutil.move( surface_adj_file + vol_file_ext, surface_adj_file + "_cycle" + str(iAdaptCycle) + vol_file_ext) shutil.move( surface_adj_file + ".csv", surface_adj_file + "_cycle" + str(iAdaptCycle) + ".csv") shutil.move( history_file + vol_file_ext, history_file + "_adj_cycle" + str(iAdaptCycle) + vol_file_ext) # If needed, change the parameters to run the first linear simulation # For the first adaptation cycle, use the filenames from the original .cfg file if kind_adapt == "COMPUTABLE_ROBUST": params_set = { 'MATH_PROBLEM': 'LINEARIZED', 'SOLUTION_FLOW_FILENAME': restart_flow_file } if iAdaptCycle > 0: params_set.update({ 'RESTART_SOL': 'YES', 'RESTART_LIN_FILENAME': restart_lin_file, 'MESH_FILENAME': Mesh_MAC_filename }) # Load the new config file options and run the linearized problem libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation(Config_CFD_filename, partitions) else: libSU2_run.SU2_CFD(Config_CFD_filename, partitions) # Change the parameters to do a direct and adjoint iteration over a fine grid if ((kind_adapt == "ROBUST" or kind_adapt == "COMPUTABLE" or kind_adapt == "COMPUTABLE_ROBUST" or kind_adapt == "REMAINING") and (iAdaptCycle < cycles - 1 or cycles == 1)): # Create the fine grid and interpolate the flow solution from coarse to refined grid params_set = { 'KIND_ADAPT': "FULL_FLOW", 'SOLUTION_FLOW_FILENAME': restart_flow_file, 'RESTART_FLOW_FILENAME': finest_flow_filename, 'MESH_FILENAME': original_mesh_file, 'MESH_OUT_FILENAME': finest_mesh_filename } if iAdaptCycle > 0: params_set.update({'MESH_FILENAME': Mesh_MAC_filename}) # Run the mesh adaptation module libSU2.Set_ConfigParams(Config_MAC_filename, params_set) libSU2_run.SU2_MAC(Config_MAC_filename, partitions) # Create the fine grid and interpolate the adjoint solution from coarse to refined grid params_set = { 'KIND_ADAPT': "FULL_ADJOINT", 'SOLUTION_FLOW_FILENAME': restart_flow_file, 'SOLUTION_ADJ_FILENAME': restart_adj_file, 'RESTART_FLOW_FILENAME': finest_flow_filename, 'RESTART_ADJ_FILENAME': finest_adj_filename, 'MESH_FILENAME': original_mesh_file, 'MESH_OUT_FILENAME': finest_mesh_filename } if iAdaptCycle > 0: params_set.update({'MESH_FILENAME': Mesh_MAC_filename}) # Run the mesh adaptation module libSU2.Set_ConfigParams(Config_MAC_filename, params_set) libSU2_run.SU2_MAC(Config_MAC_filename, partitions) # Create the fine grid and interpolate the linear solution from coarse to refined grid if kind_adapt == "COMPUTABLE_ROBUST": params_set = { 'KIND_ADAPT': "FULL_LINEAR", 'SOLUTION_FLOW_FILENAME': restart_flow_file, 'SOLUTION_LIN_FILENAME': restart_lin_file, 'RESTART_FLOW_FILENAME': finest_flow_filename, 'RESTART_ADJ_FILENAME': finest_lin_filename, 'MESH_FILENAME': original_mesh_file, 'MESH_OUT_FILENAME': finest_mesh_filename } if iAdaptCycle > 0: params_set.update({'MESH_FILENAME': Mesh_MAC_filename}) # Run the mesh adaptation module libSU2.Set_ConfigParams(Config_MAC_filename, params_set) libSU2_run.SU2_MAC(Config_MAC_filename, partitions) # Change the parameters to do one iteration of the flow solver on the finest grid # Always start from the interpolated solution and store the residual in the solution file for finest grid # No multigrid or convergence acceleration params_set = { 'MATH_PROBLEM': 'DIRECT', 'EXT_ITER': 2, 'RESTART_SOL': 'YES', 'SOLUTION_FLOW_FILENAME': finest_flow_filename, 'STORE_RESIDUAL': 'YES', 'RESTART_FLOW_FILENAME': finest_flow_filename, 'MESH_FILENAME': finest_mesh_filename, 'FULLMG': 'NO', 'MGLEVEL': 0, 'MGCYCLE': 0, 'MG_PRE_SMOOTH': '( 0 )', 'MG_POST_SMOOTH': '( 0 )', 'MG_CORRECTION_SMOOTH': '( 0 )' } libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation(Config_CFD_filename, partitions) else: libSU2_run.SU2_CFD(Config_CFD_filename, partitions) # Change the parameters to do one iteration of the adjoint solver on the finest grid # Always start from the interpolated solution and store the residual in the solution file for finest grid # No multigrid or convergence acceleration params_set = { 'MATH_PROBLEM': 'ADJOINT', 'EXT_ITER': 2, 'RESTART_SOL': 'YES', 'SOLUTION_FLOW_FILENAME': finest_flow_filename, 'SOLUTION_ADJ_FILENAME': finest_adj_filename, 'MESH_FILENAME': finest_mesh_filename, 'FULLMG': 'NO', 'MGLEVEL': 0, 'MGCYCLE': 0, 'MG_PRE_SMOOTH': '( 0 )', 'MG_POST_SMOOTH': '( 0 )', 'MG_CORRECTION_SMOOTH': '( 0 )' } libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation(Config_CFD_filename, partitions) else: libSU2_run.SU2_CFD(Config_CFD_filename, partitions) # Change the parameters to do one iteration of the linear solver on the finest grid # Always start from the interpolated solution and store the residual in the solution file for finest grid # No multigrid or convergence acceleration if kind_adapt == "COMPUTABLE_ROBUST": params_set = { 'MATH_PROBLEM': 'LINEARIZED', 'EXT_ITER': 2, 'RESTART_SOL': 'YES', 'SOLUTION_FLOW_FILENAME': finest_flow_filename, 'SOLUTION_LIN_FILENAME': finest_lin_filename, 'RESTART_LIN_FILENAME': finest_lin_filename, 'MESH_FILENAME': finest_mesh_filename, 'FULLMG': 'NO', 'MGLEVEL': 0, 'MGCYCLE': 0, 'MG_PRE_SMOOTH': '( 0 )', 'MG_POST_SMOOTH': '( 0 )', 'MG_CORRECTION_SMOOTH': '( 0 )' } libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation(Config_CFD_filename, partitions) else: libSU2_run.SU2_CFD(Config_CFD_filename, partitions) # Perform adaptation using above solution files if ((kind_adapt == "GRAD_FLOW") or (kind_adapt == "GRAD_ADJOINT") or (kind_adapt == "GRAD_FLOW_ADJ")): params_set = { 'SOLUTION_FLOW_FILENAME': restart_flow_file, 'SOLUTION_ADJ_FILENAME': restart_adj_file } elif ((kind_adapt == "COMPUTABLE") or (kind_adapt == "REMAINING")): params_set = { 'SOLUTION_FLOW_FILENAME': finest_flow_filename, 'SOLUTION_ADJ_FILENAME': finest_adj_filename, 'RESTART_FLOW_FILENAME': restart_flow_file, 'RESTART_ADJ_FILENAME': restart_adj_file } elif ((kind_adapt == "ROBUST") or (kind_adapt == "COMPUTABLE_ROBUST")): params_set = { 'SOLUTION_FLOW_FILENAME': finest_flow_filename, 'SOLUTION_ADJ_FILENAME': finest_adj_filename, 'SOLUTION_LIN_FILENAME': finest_lin_filename, 'RESTART_FLOW_FILENAME': restart_flow_file, 'RESTART_ADJ_FILENAME': restart_adj_file, 'RESTART_LIN_FILENAME': restart_lin_file } params_set.update({ 'KIND_ADAPT': kind_adapt, 'MESH_OUT_FILENAME': Mesh_MAC_filename }) if iAdaptCycle > 0: params_set.update({'MESH_FILENAME': Mesh_MAC_filename}) # Run the mesh adaptation module libSU2.Set_ConfigParams(Config_MAC_filename, params_set) libSU2_run.SU2_MAC(Config_MAC_filename, partitions) # Copy cycle mesh file if save_all: print "Saving cycle " + str(iAdaptCycle) + " mesh file..." shutil.copy( Mesh_MAC_filename, Mesh_MAC_filename.replace(".su2", "_cycle" + str(iAdaptCycle) + ".su2")) # Clean up if overwrite: os.rename(Mesh_MAC_filename, original_mesh_file) if ((kind_adapt == "ROBUST") or (kind_adapt == "COMPUTABLE") or (kind_adapt == "COMPUTABLE_ROBUST") or (kind_adapt == "REMAINING")): os.remove(finest_mesh_filename) os.remove(finest_flow_filename) if kind_adapt == "COMPUTABLE_ROBUST": os.remove(finest_lin_filename) if save_all: os.remove(Mesh_MAC_filename) os.remove(Config_MAC_filename) os.remove(Config_CFD_filename)
def process_surface_adjoint( config_filename , filter_type='LAPLACE' , marker_name='airfoil' , chord_length=1.0 ): print('') print('-------------------------------------------------------------------------') print('| SU2 Suite (Process Surface Adjoint) |') print('-------------------------------------------------------------------------') print('') # some other defaults c_clip = 0.01 # percent chord to truncate fft_copy = 5 # number of times to copy the fft signal smth_len = 0.05 # percent chord smoothing window length lapl_len = 1e-4 # laplace smoothing parameter # read config file config_data = libSU2.Get_ConfigParams(config_filename) surface_filename = config_data['SURFACE_ADJ_FILENAME'] + '.csv' print surface_filename mesh_filename = config_data['MESH_FILENAME'] gradient = config_data['OBJECTIVE_FUNCTION'] print('Config filename = %s' % config_filename) print('Surface filename = %s' % surface_filename) print('Filter Type = %s' % filter_type) # read adjoint data adj_data = np.genfromtxt( surface_filename , dtype = float , delimiter = ',' , skip_header = 1 ) # read mesh data mesh_data = libSU2_mesh.Read_Mesh(mesh_filename) # proces adjoint data P = map(int, adj_data[:,0] ) X = adj_data[:,6].copy() Y = adj_data[:,7].copy() Sens = adj_data[:,1].copy() PsiRho = adj_data[:,2].copy() I = range(0,len(P)) # important - for unsorting durring write # store in dict by point index adj_data_dict = dict( zip( P , zip(X,Y,Sens,PsiRho,I) ) ) # sort airfoil points iP_sorted,_ = libSU2_mesh.sort_Airfoil(mesh_data,marker_name) assert(len(iP_sorted) == len(P)) # rebuild airfoil loop i = 0 for this_P in iP_sorted: # the adjoint data entry this_adj_data = adj_data_dict[this_P] # re-sort P[i] = this_P X[i] = this_adj_data[0] Y[i] = this_adj_data[1] Sens[i] = this_adj_data[2] PsiRho[i] = this_adj_data[3] I[i] = this_adj_data[4] # next i = i+1 #: for each point # calculate arc length S = np.sqrt( np.diff(X)**2 + np.diff(Y)**2 ) / chord_length S = np.cumsum( np.hstack([ 0 , S ]) ) # tail trucating, by arc length I_clip_lo = S < S[0] + c_clip I_clip_hi = S > S[-1] - c_clip S_clip = S.copy() Sens_clip = Sens.copy() Sens_clip[I_clip_hi] = Sens_clip[I_clip_hi][0] Sens_clip[I_clip_lo] = Sens_clip[I_clip_lo][-1] # some edge length statistics dS_clip = np.diff(S_clip) min_dS = np.min ( dS_clip ) mean_dS = np.mean( dS_clip ) max_dS = np.max ( dS_clip ) #print 'min_dS = %.4e ; mean_dS = %.4e ; max_dS = %.4e' % ( min_dS , mean_dS , max_dS ) # -------------------------------------------- # APPLY FILTER if filter_type == 'FOURIER': Freq_notch = [ 1/max_dS, np.inf ] # the notch frequencies Sens_filter,Frequency,Power = fft_filter( S_clip,Sens_clip, Freq_notch, fft_copy ) #Sens_filter = smooth(S_clip,Sens_filter, 0.03,'blackman') # post smoothing elif filter_type == 'WINDOW': Sens_filter = window( S_clip, Sens_clip, smth_len, 'blackman' ) elif filter_type == 'LAPLACE': Sens_filter = laplace( S_clip, Sens_clip, lapl_len ) elif filter_type == 'SHARPEN': Sens_smooth = smooth( S_clip, Sens_clip , smth_len/5, 'blackman' ) # pre smoothing Sens_smoother = smooth( S_clip, Sens_smooth, smth_len , 'blackman' ) Sens_filter = Sens_smooth + (Sens_smooth - Sens_smoother) # sharpener else: raise Exception, 'unknown filter type' # -------------------------------------------- # PLOTTING if pylab_imported: # start plot fig = plt.figure(gradient) plt.clf() #if not fig.axes: # for comparing two filter calls #plt.subplot(1,1,1) #ax = fig.axes[0] #if len(ax.lines) == 4: #ax.lines.pop(0) #ax.lines.pop(0) # SENSITIVITY plt.plot(S ,Sens ,color='b') # original plt.plot(S_clip,Sens_filter,color='r') # filtered plt.xlim(-0.1,2.1) plt.ylim(-5,5) plt.xlabel('Arc Length') plt.ylabel('Surface Sensitivity') #if len(ax.lines) == 4: #seq = [2, 2, 7, 2] #ax.lines[0].set_dashes(seq) #ax.lines[1].set_dashes(seq) plot_filename = os.path.splitext(surface_filename)[0] + '.png' plt.savefig('Sens_'+plot_filename,dpi=300) # zoom in plt.ylim(-0.4,0.4) plt.savefig('Sens_zoom_'+plot_filename,dpi=300) # SPECTRAL if filter_type == 'FOURIER': plt.figure('SPECTRAL') plt.clf() plt.plot(Frequency,Power) #plt.xlim(0,Freq_notch[0]+10) plt.xlim(0,200) plt.ylim(0,0.15) plt.xlabel('Frequency (1/C)') plt.ylabel('Surface Sensitivity Spectal Power') plt.savefig('Spectral_'+plot_filename,dpi=300) #: if spectral plot #: if plot # -------------------------------------------- # SAVE SURFACE FILE # reorder back to input surface points Sens_out = np.zeros(len(S)) Sens_out[I] = Sens_filter # left over from sort adj_data[:,1] = Sens_out # get surface header surface_orig = open(surface_filename,'r') header = surface_orig.readline() surface_orig.close() # get list of prefix names prefix_names = libSU2.get_AdjointPrefix(None) prefix_names = prefix_names.values() # add filter prefix, before adjoint prefix surface_filename_split = surface_filename.rstrip('.csv').split('_') if surface_filename_split[-1] in prefix_names: surface_filename_split = surface_filename_split[0:-1] + ['filtered'] + [surface_filename_split[-1]] else: surface_filename_split = surface_filename_split + ['filtered'] surface_filename_new = '_'.join(surface_filename_split) + '.csv' # write filtered surface file (only updates Sensitivity) surface_new = open(surface_filename_new,'w') surface_new.write(header) for row in adj_data: for i,value in enumerate(row): if i > 0: surface_new.write(', ') if i == 0: surface_new.write('%i' % value ) else: surface_new.write('%.16e' % value ) surface_new.write('\n') surface_new.close() print('') print('----------------- Exit Success (Process Surface Adjoint) ----------------') print('') return
def mesh_adaptation( filename , partitions = 0 , cycles = 1 , overwrite = False , save_all = False ): # General and default parameters Config_INP_filename = filename Config_CFD_filename = "config_CFD_" + Config_INP_filename Config_MAC_filename = "config_MAC_" + Config_INP_filename #Mesh_MAC_filename = "mesh_MAC_" + filename.replace(".cfg",".su2") finest_mesh_filename = "mesh_finest.su2" finest_flow_filename = "restart_flow_finest.dat" finest_lin_filename = "restart_lin_finest.dat" finest_adj_filename = "restart_adj_finest.dat" # assumes serial with partitions = 1 if partitions == 1: partitions = 0 # Get parameters params_get = libSU2.Get_ConfigParams( Config_INP_filename ) kind_adapt = params_get['KIND_ADAPT'] objfunc = params_get['ADJ_OBJFUNC'] restart_flow_file = params_get['RESTART_FLOW_FILENAME'] restart_adj_file = params_get['RESTART_ADJ_FILENAME'] original_mesh_file = params_get['MESH_FILENAME'] #output_mesh_file = params_get['MESH_OUT_FILENAME'] Mesh_MAC_filename = params_get['MESH_OUT_FILENAME'] cadj_prefix = libSU2.get_AdjointPrefix(objfunc) # Get solution file names volume_flow_file = params_get['VOLUME_FLOW_FILENAME'] volume_adj_file = params_get['VOLUME_ADJ_FILENAME'] surface_flow_file = params_get['SURFACE_FLOW_FILENAME'] surface_adj_file = params_get['SURFACE_ADJ_FILENAME'] history_file = params_get['CONV_FILENAME'] # Get mesh filenames and filetypes mesh_filetype = params_get['MESH_FORMAT'] if mesh_filetype == "CGNS": error_str = "Currently cannot support mesh adaptation with CGNS grid files. Please convert your CGNS mesh to SU2 format using the CGNS_TO_SU2 flag in the configuration file, re-specify the mesh file to the native .su2 file and set the MESH_FORMAT flag to SU2." print "\n*****\n" + error_str + "\n*****\n" return 1 elif mesh_filetype == "NETCDF_ASCII": error_str ="Currently cannot support mesh adaptation with NETCDF_ASCII grid files. Please convert your mesh to SU2 format, re-specify the mesh file to the native .su2 file and set the MESH_FORMAT flag to SU2." print "\n*****\n" + error_str + "\n*****\n" return 1 # Get output solution filetypes output_filetype = params_get['OUTPUT_FORMAT'] if output_filetype == "TECPLOT": vol_file_ext = ".plt" elif output_filetype == "PARAVIEW": vol_file_ext = ".vtk" if( (kind_adapt == "ROBUST") or (kind_adapt == "COMPUTABLE_ROBUST") ): restart_lin_file = params_get['RESTART_LIN_FILENAME'] # Loop over number of adaptation cycles for iAdaptCycle in range(cycles): # Copy original input file to working files shutil.copy( Config_INP_filename, Config_MAC_filename ) shutil.copy( Config_INP_filename, Config_CFD_filename ) # Run direct flow simulation # For iAdaptCycle == 0, store restart file, objective function and original mesh file params_set = { 'MATH_PROBLEM' : 'DIRECT'} if iAdaptCycle > 0: params_set.update({'RESTART_SOL' : 'YES' , 'ADJ_OBJFUNC' : objfunc, 'RESTART_FLOW_FILENAME' : restart_flow_file, 'RESTART_ADJ_FILENAME' : restart_adj_file, 'SOLUTION_FLOW_FILENAME' : restart_flow_file, 'MESH_FILENAME' : Mesh_MAC_filename }) if( (kind_adapt == "ROBUST") or kind_adapt == ("COMPUTABLE_ROBUST") ): params_set.update( {'RESTART_LIN_FILENAME' : restart_lin_file} ) # Load the new config file options and run the direct problem libSU2.Set_ConfigParams( Config_CFD_filename, params_set ) if partitions > 1: parallel_computation( Config_CFD_filename, partitions ) else: libSU2_run.SU2_CFD( Config_CFD_filename, partitions ) # Copy flow solution & history file if save_all: print "Saving cycle " + str(iAdaptCycle) + " flow solution and history files..." print "Saving " + volume_flow_file + "_cycle" + str(iAdaptCycle) + vol_file_ext print "Saving " + surface_flow_file + "_cycle" + str(iAdaptCycle) + vol_file_ext print "Saving " + history_file + "_flow_cycle" + str(iAdaptCycle) + vol_file_ext shutil.move( volume_flow_file + vol_file_ext , volume_flow_file + "_cycle"+str(iAdaptCycle)+vol_file_ext ) shutil.move( surface_flow_file + vol_file_ext , surface_flow_file + "_cycle"+str(iAdaptCycle)+vol_file_ext ) shutil.move( surface_flow_file + ".csv" , surface_flow_file + "_cycle"+str(iAdaptCycle)+".csv" ) shutil.move( history_file + vol_file_ext , history_file + "_flow_cycle"+str(iAdaptCycle)+vol_file_ext ) # If needed, run the adjoint simulation # For the first adaption cycle, use the filenames of the orignal .cfg file if ( kind_adapt == "GRAD_ADJOINT" or kind_adapt == "GRAD_FLOW_ADJ" or kind_adapt == "ROBUST" or kind_adapt == "COMPUTABLE_ROBUST" or kind_adapt == "COMPUTABLE" or kind_adapt == "REMAINING" ): params_set = { 'MATH_PROBLEM' : 'ADJOINT', 'SOLUTION_FLOW_FILENAME' : restart_flow_file } if iAdaptCycle > 0: params_set.update({ 'RESTART_SOL' : 'YES' , 'SOLUTION_ADJ_FILENAME' : restart_adj_file , 'MESH_FILENAME' : Mesh_MAC_filename }) # Load the new config file options and run the adjoint problem libSU2.Set_ConfigParams( Config_CFD_filename, params_set ) if partitions > 1: parallel_computation( Config_CFD_filename, partitions ) else: libSU2_run.SU2_CFD( Config_CFD_filename, partitions ) # Copy adjoint solution & history file if save_all: print "Saving cycle " + str(iAdaptCycle) + " adjoint solution and history files..." print "Saving " + volume_adj_file + "_cycle" + str(iAdaptCycle) + vol_file_ext print "Saving " + surface_adj_file + "_adj_cycle" + str(iAdaptCycle) + vol_file_ext print "Saving " + history_file + "_flow_cycle" + str(iAdaptCycle) + vol_file_ext shutil.move( volume_adj_file + vol_file_ext , volume_adj_file + "_cycle"+str(iAdaptCycle)+vol_file_ext ) shutil.move( surface_adj_file + vol_file_ext , surface_adj_file + "_cycle"+str(iAdaptCycle)+vol_file_ext ) shutil.move( surface_adj_file + ".csv" , surface_adj_file + "_cycle"+str(iAdaptCycle)+".csv" ) shutil.move( history_file + vol_file_ext , history_file + "_adj_cycle"+str(iAdaptCycle)+vol_file_ext ) # If needed, change the parameters to run the first linear simulation # For the first adaptation cycle, use the filenames from the original .cfg file if kind_adapt == "COMPUTABLE_ROBUST": params_set = {'MATH_PROBLEM' : 'LINEARIZED' , 'SOLUTION_FLOW_FILENAME' : restart_flow_file } if iAdaptCycle > 0: params_set.update({'RESTART_SOL' : 'YES' , 'RESTART_LIN_FILENAME' : restart_lin_file , 'MESH_FILENAME' : Mesh_MAC_filename }) # Load the new config file options and run the linearized problem libSU2.Set_ConfigParams(Config_CFD_filename, params_set) if partitions > 1: parallel_computation( Config_CFD_filename, partitions ) else: libSU2_run.SU2_CFD( Config_CFD_filename, partitions ) # Change the parameters to do a direct and adjoint iteration over a fine grid if ( (kind_adapt == "ROBUST" or kind_adapt == "COMPUTABLE" or kind_adapt == "COMPUTABLE_ROBUST" or kind_adapt == "REMAINING") and (iAdaptCycle < cycles-1 or cycles == 1) ): # Create the fine grid and interpolate the flow solution from coarse to refined grid params_set = { 'KIND_ADAPT' : "FULL_FLOW" , 'SOLUTION_FLOW_FILENAME' : restart_flow_file , 'RESTART_FLOW_FILENAME' : finest_flow_filename , 'MESH_FILENAME' : original_mesh_file , 'MESH_OUT_FILENAME' : finest_mesh_filename } if iAdaptCycle > 0: params_set.update( {'MESH_FILENAME' : Mesh_MAC_filename} ) # Run the mesh adaptation module libSU2.Set_ConfigParams( Config_MAC_filename, params_set ) libSU2_run.SU2_MAC(Config_MAC_filename,partitions) # Create the fine grid and interpolate the adjoint solution from coarse to refined grid params_set = { 'KIND_ADAPT' : "FULL_ADJOINT" , 'SOLUTION_FLOW_FILENAME' : restart_flow_file , 'SOLUTION_ADJ_FILENAME' : restart_adj_file , 'RESTART_FLOW_FILENAME' : finest_flow_filename , 'RESTART_ADJ_FILENAME' : finest_adj_filename , 'MESH_FILENAME' : original_mesh_file , 'MESH_OUT_FILENAME' : finest_mesh_filename } if iAdaptCycle > 0: params_set.update( {'MESH_FILENAME' : Mesh_MAC_filename} ) # Run the mesh adaptation module libSU2.Set_ConfigParams( Config_MAC_filename, params_set ) libSU2_run.SU2_MAC(Config_MAC_filename,partitions) # Create the fine grid and interpolate the linear solution from coarse to refined grid if kind_adapt == "COMPUTABLE_ROBUST": params_set = { 'KIND_ADAPT' : "FULL_LINEAR" , 'SOLUTION_FLOW_FILENAME' : restart_flow_file , 'SOLUTION_LIN_FILENAME' : restart_lin_file , 'RESTART_FLOW_FILENAME' : finest_flow_filename , 'RESTART_ADJ_FILENAME' : finest_lin_filename , 'MESH_FILENAME' : original_mesh_file , 'MESH_OUT_FILENAME' : finest_mesh_filename } if iAdaptCycle > 0: params_set.update( {'MESH_FILENAME' : Mesh_MAC_filename} ) # Run the mesh adaptation module libSU2.Set_ConfigParams( Config_MAC_filename, params_set ) libSU2_run.SU2_MAC( Config_MAC_filename, partitions ) # Change the parameters to do one iteration of the flow solver on the finest grid # Always start from the interpolated solution and store the residual in the solution file for finest grid # No multigrid or convergence acceleration params_set = { 'MATH_PROBLEM' : 'DIRECT' , 'EXT_ITER' : 2 , 'RESTART_SOL' : 'YES' , 'SOLUTION_FLOW_FILENAME' : finest_flow_filename , 'STORE_RESIDUAL' : 'YES' , 'RESTART_FLOW_FILENAME' : finest_flow_filename , 'MESH_FILENAME' : finest_mesh_filename , 'FULLMG' : 'NO' , 'MGLEVEL' : 0 , 'MGCYCLE' : 0 , 'MG_PRE_SMOOTH' : '( 0 )' , 'MG_POST_SMOOTH' : '( 0 )' , 'MG_CORRECTION_SMOOTH' : '( 0 )' } libSU2.Set_ConfigParams( Config_CFD_filename, params_set ) if partitions > 1: parallel_computation( Config_CFD_filename, partitions ) else: libSU2_run.SU2_CFD( Config_CFD_filename, partitions ) # Change the parameters to do one iteration of the adjoint solver on the finest grid # Always start from the interpolated solution and store the residual in the solution file for finest grid # No multigrid or convergence acceleration params_set = { 'MATH_PROBLEM' : 'ADJOINT' , 'EXT_ITER' : 2 , 'RESTART_SOL' : 'YES' , 'SOLUTION_FLOW_FILENAME' : finest_flow_filename , 'SOLUTION_ADJ_FILENAME' : finest_adj_filename , 'MESH_FILENAME' : finest_mesh_filename , 'FULLMG' : 'NO' , 'MGLEVEL' : 0 , 'MGCYCLE' : 0 , 'MG_PRE_SMOOTH' : '( 0 )' , 'MG_POST_SMOOTH' : '( 0 )' , 'MG_CORRECTION_SMOOTH' : '( 0 )' } libSU2.Set_ConfigParams( Config_CFD_filename, params_set ) if partitions > 1: parallel_computation( Config_CFD_filename, partitions ) else: libSU2_run.SU2_CFD( Config_CFD_filename, partitions ) # Change the parameters to do one iteration of the linear solver on the finest grid # Always start from the interpolated solution and store the residual in the solution file for finest grid # No multigrid or convergence acceleration if kind_adapt == "COMPUTABLE_ROBUST": params_set = { 'MATH_PROBLEM' : 'LINEARIZED' , 'EXT_ITER' : 2 , 'RESTART_SOL' : 'YES' , 'SOLUTION_FLOW_FILENAME' : finest_flow_filename , 'SOLUTION_LIN_FILENAME' : finest_lin_filename , 'RESTART_LIN_FILENAME' : finest_lin_filename , 'MESH_FILENAME' : finest_mesh_filename , 'FULLMG' : 'NO' , 'MGLEVEL' : 0 , 'MGCYCLE' : 0 , 'MG_PRE_SMOOTH' : '( 0 )' , 'MG_POST_SMOOTH' : '( 0 )' , 'MG_CORRECTION_SMOOTH' : '( 0 )' } libSU2.Set_ConfigParams( Config_CFD_filename, params_set ) if partitions > 1: parallel_computation( Config_CFD_filename, partitions ) else: libSU2_run.SU2_CFD( Config_CFD_filename, partitions ) # Perform adaptation using above solution files if( (kind_adapt == "GRAD_FLOW") or (kind_adapt == "GRAD_ADJOINT") or (kind_adapt == "GRAD_FLOW_ADJ")): params_set = { 'SOLUTION_FLOW_FILENAME' : restart_flow_file, 'SOLUTION_ADJ_FILENAME' : restart_adj_file } elif( (kind_adapt == "COMPUTABLE") or (kind_adapt == "REMAINING") ): params_set = { 'SOLUTION_FLOW_FILENAME' : finest_flow_filename, 'SOLUTION_ADJ_FILENAME' : finest_adj_filename , 'RESTART_FLOW_FILENAME' : restart_flow_file , 'RESTART_ADJ_FILENAME' : restart_adj_file } elif( (kind_adapt == "ROBUST") or (kind_adapt == "COMPUTABLE_ROBUST") ): params_set = { 'SOLUTION_FLOW_FILENAME' : finest_flow_filename, 'SOLUTION_ADJ_FILENAME' : finest_adj_filename , 'SOLUTION_LIN_FILENAME' : finest_lin_filename , 'RESTART_FLOW_FILENAME' : restart_flow_file , 'RESTART_ADJ_FILENAME' : restart_adj_file , 'RESTART_LIN_FILENAME' : restart_lin_file } params_set.update({'KIND_ADAPT' : kind_adapt, 'MESH_OUT_FILENAME' : Mesh_MAC_filename}) if iAdaptCycle > 0: params_set.update({'MESH_FILENAME' : Mesh_MAC_filename}) # Run the mesh adaptation module libSU2.Set_ConfigParams( Config_MAC_filename, params_set ) libSU2_run.SU2_MAC( Config_MAC_filename, partitions ) # Copy cycle mesh file if save_all: print "Saving cycle " + str(iAdaptCycle) + " mesh file..." shutil.copy( Mesh_MAC_filename, Mesh_MAC_filename.replace(".su2", "_cycle"+str(iAdaptCycle)+".su2")) # Clean up if overwrite : os.rename( Mesh_MAC_filename, original_mesh_file ) if( (kind_adapt == "ROBUST") or (kind_adapt == "COMPUTABLE") or (kind_adapt == "COMPUTABLE_ROBUST") or (kind_adapt == "REMAINING") ): os.remove(finest_mesh_filename) os.remove(finest_flow_filename) if kind_adapt == "COMPUTABLE_ROBUST": os.remove(finest_lin_filename) if save_all: os.remove(Mesh_MAC_filename) os.remove(Config_MAC_filename) os.remove(Config_CFD_filename)