def generate_results(prob): """Create all results from the routine. Extract the data that has been retrieved by OpenMDAO and use them to generate, plot and save results. Args: prob (om.Problem object): Current problem that is being defined """ if Rt.use_aeromap and Rt.type == 'DoE': dct.add_am_to_dict(optim_var_dict, am_dict) ## Generate N2 scheme ## om.n2(optim_dir_path + '/circuit.sqlite', optim_dir_path + '/circuit.html', False) ## Recap of the problem inputs/outputs ## prob.model.list_inputs() prob.model.list_outputs() ## Results processing ## tls.plot_results(optim_dir_path, '', optim_var_dict) tls.save_results(optim_dir_path, optim_var_dict) wkf.copy_module_to_module(Rt.modules[-1], 'out', 'Optimisation', 'out')
def first_run(Rt): """Run subworkflow once for the optimisation problem. This function runs a first loop to ensure that all problem variables are created an can be fed to the optimisation setup program. Args: Rt (Routine object): Class that contains the routine informations. Returns: None. """ log.info('Launching initialization workflow') Rt.modules.insert(0, 'Optimisation') # Settings needed for CFD calculation added_gui = False if 'SettingsGUI' not in Rt.modules: Rt.modules.insert(0, 'SettingsGUI') added_gui = True # First iteration to create aeromap results if no pre-workflow wkf.copy_module_to_module('Optimisation', 'in', Rt.modules[0], 'in') wkf.run_subworkflow(Rt.modules) wkf.copy_module_to_module(Rt.modules[-1], 'out', 'Optimisation', 'in') # SettingsGUI only needed at the first iteration if 'SettingsGUI' in Rt.modules and added_gui: Rt.modules.remove('SettingsGUI') # Optimisation parameters only needed for the first run Rt.modules.remove('Optimisation')
def one_iteration(): """ Compute the objective function. Function 'one_iteration' will exectute in order all the module contained in '...' and extract the ... value from the last CPACS file, this value will be returned to the optimizer CPACSUpdater.... """ global counter counter += 1 # Create the parameter in CPACS with 'CPACSUpdater' module cpacs_path = mi.get_toolinput_file_path('CPACSUpdater') cpacs_out_path = mi.get_tooloutput_file_path('CPACSUpdater') tixi = cpsf.open_tixi(cpacs_path) wkdir_path = ceaf.create_new_wkdir(Rt.date) WKDIR_XPATH = '/cpacs/toolspecific/CEASIOMpy/filesPath/wkdirPath' tixi.updateTextElement(WKDIR_XPATH, wkdir_path) # TODO: improve this part! (maybe move somewhere else) # To delete coef from previous iter if opf.get_aeromap_path(Rt.modules) != 'None': xpath = opf.get_aeromap_path(Rt.modules) aeromap_uid = cpsf.get_value(tixi, xpath + '/aeroMapUID') Coef = apmf.get_aeromap(tixi, aeromap_uid) apmf.delete_aeromap(tixi, aeromap_uid) apmf.create_empty_aeromap(tixi, aeromap_uid, 'test_optim') apmf.save_parameters(tixi, aeromap_uid, Coef) cpsf.close_tixi(tixi, cpacs_path) # Update the CPACS file with the parameters contained in design_var_dict update_cpacs_file(cpacs_path, cpacs_out_path, design_var_dict) # Save the CPACS file if counter % 1 == 0: file_copy_from = mi.get_tooloutput_file_path('CPACSUpdater') shutil.copy( file_copy_from, optim_dir_path + '/Geometry/' + 'iter_{}.xml'.format(counter)) # Run optimisation sub workflow wkf.copy_module_to_module('CPACSUpdater', 'out', Rt.modules[0], 'in') wkf.run_subworkflow(Rt.modules) wkf.copy_module_to_module(Rt.modules[-1], 'out', 'CPACSUpdater', 'in') # Extract results TODO: improve this part cpacs_results_path = mi.get_tooloutput_file_path(Rt.modules[-1]) log.info('Results will be extracted from:' + cpacs_results_path) tixi = cpsf.open_tixi(cpacs_results_path) # Update the constraints values update_res_var_dict(tixi) return compute_obj()
def routine_setup(modules, routine_type, modules_pre=[]): """ Set up optimisation. Retrieve the list of modules to use in the optimization loop and launches the optimization process. """ log.info('----- Start of Optimisation module -----') global Rt, design_var_dict, res_var_dict, optim_dir_path # Setup parameters of the routine Rt.type = routine_type Rt.modules = modules Rt.driver = 'COBYLA' Rt.objective = 'cl/cd' # Rt.design_vars = Rt.constraints = ['cms'] Rt.date = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') Rt.doetype = 'uniform' Rt.samplesnb = 3 cpacs_path = mi.get_toolinput_file_path('Optimisation') # Create Optim folder for results tixi = cpsf.open_tixi(cpacs_path) wkdir = ceaf.get_wkdir_or_create_new(tixi) optim_dir_path = os.path.join(wkdir, Rt.type) if not os.path.isdir(optim_dir_path): os.mkdir(optim_dir_path) os.mkdir(optim_dir_path + '/Geometry') # Initiates dictionnaries res_var_dict, design_var_dict = init_dict(cpacs_path, modules, modules_pre) # Copy to CPACSUpdater to pass to next modules wkf.copy_module_to_module('Optimisation', 'in', 'CPACSUpdater', 'in') # Display routine info log.info('------ Problem description ------') log.info('Routine type : {}'.format(routine_type)) log.info('Objective function : {}'.format(Rt.objective)) [ log.info('Design variables : {}'.format(k)) for k in design_var_dict.keys() ] [log.info('constraints : {}'.format(k)) for k in res_var_dict.keys()] run_routine() log.info('----- End of Optimisation module -----')
def first_run(module_list, modules_pre_list=[]): """Run subworkflow once for the optimisation problem. This function runs a first loop to ensure that all problem variables are created an can be fed to the optimisation setup program. Args: module_list (lst) : List of modules to run. module_pre_list (lst) : List of modules that were run in a previous workflow. Returns: None. """ # Check if aeromap results already exists, else run workflow global XPATH global XPATH_PRE log.info('Launching initialization workflow') XPATH = tls.get_aeromap_path(module_list) if 'PyTornado' in modules_pre_list or 'SU2Run' in modules_pre_list: XPATH_PRE = tls.get_aeromap_path(modules_pre_list) else: XPATH_PRE = XPATH # Settings needed for CFD calculation if 'Optimisation' not in modules_pre_list: module_list.insert(0, 'Optimisation') if 'SettingsGUI' not in module_list or 'SettingsGUI' not in modules_pre_list: module_list.insert(0, 'SettingsGUI') # First iteration to create aeromap results if no pre-workflow if XPATH != XPATH_PRE or modules_pre_list == []: wkf.copy_module_to_module('Optimisation', 'in', module_list[0], 'in') wkf.run_subworkflow(module_list) wkf.copy_module_to_module(module_list[-1], 'out', 'Optimisation', 'in') # SettingsGUI only needed at the first iteration if 'SettingsGUI' in module_list: module_list.pop(module_list.index('SettingsGUI')) # Optimisation parameters only needed for the first run module_list.pop(module_list.index('Optimisation'))
def init_dict(cpacs_path, module_list, modules_pre_list=[]): """ Create dictionnaries for the optimisation problem. Parameters ---------- cpacs_path : String Path to the CPACS file. module_list : List List of modules. Returns ------- Dict All dictionnaries needed for the optimisation problem. """ # Check if aeromap results already exists, else run workflow global XPATH global XPATH_PRE XPATH = optf.get_aeromap_path(module_list) if 'PyTornado' in modules_pre_list or 'SU2Run' in modules_pre_list: XPATH_PRE = optf.get_aeromap_path(modules_pre_list) else: XPATH_PRE = XPATH # Settings needed for CFD calculation if 'SettingsGUI' not in module_list or 'SettingsGUI' not in modules_pre_list: module_list.insert(0, 'SettingsGUI') # First iteration to create aeromap results if no pre-workflow if XPATH != XPATH_PRE or modules_pre_list == []: wkf.copy_module_to_module('Optimisation', 'in', module_list[0], 'in') wkf.run_subworkflow(module_list) wkf.copy_module_to_module(module_list[-1], 'out', 'Optimisation', 'in') # If settingsGUI only needed at the first iteration if 'SettingsGUI' in module_list: module_list.pop(module_list.index('SettingsGUI')) tixi = cpsf.open_tixi(cpacs_path) return init_res_dict(tixi), init_design_var_dict(tixi)
def test_copy_module_to_module(): """ Tests the copy_module_to_module function """ module_from = MODULE_DIR module_to = MODULE_DIR io_from = "in" io_to = "out" copy_module_to_module(module_from, io_from, module_to, io_to) # Read Input and Ouput CPACS file as text, to compare them with open(CPACS_IN_PATH) as file_in: lines_cpacs_in = file_in.readlines() with open(CPACS_OUT_PATH) as file_out: lines_cpacs_out = file_out.readlines() assert lines_cpacs_in == lines_cpacs_out
def routine_launcher(Opt): """Run an optimisation routine or DoE using the OpenMDAO library. This function launches the setup for the routine by setting up the problem with the OpenMDAO component, creating of reading a file containing all the problem parameters and launching the driver. It also specifies where to save the case recordings and launches the results plotting at the end of the routine. Args: Opt (class) : Indicates which modules to use and the routine type (Optim or DoE). """ global optim_var_dict, am_dict, Rt, am_length Rt.type = Opt.optim_method Rt.modules = Opt.module_optim ## Initialize CPACS file and problem dictionary ## create_routine_folder() opf.first_run(Rt) tixi = cpsf.open_tixi(opf.CPACS_OPTIM_PATH) tixi.updateTextElement(opf.WKDIR_XPATH, ceaf.create_new_wkdir(optim_dir_path)) Rt.get_user_inputs(tixi) optim_var_dict = opf.create_variable_library(Rt, tixi, optim_dir_path) am_dict = opf.create_am_lib(Rt, tixi) cpsf.close_tixi(tixi, opf.CPACS_OPTIM_PATH) wkf.copy_module_to_module('Optimisation', 'in', Rt.modules[0], 'in') ## Instantiate components and subsystems ## prob = om.Problem() create_om_problem(prob) ## Run the model ## prob.run_driver() generate_results(prob)
def compute(self, inputs, outputs): """Compute the objective expression""" global counter counter += 1 cpacs_path = mif.get_tooloutput_file_path(Rt.modules[-1]) # Save the CPACS file for this iteration if counter % Rt.save_iter == 0: loc = optim_dir_path + '/Geometry/' + 'iter_{}.xml'.format(counter) shutil.copy(cpacs_path, loc) log.info('Copy current CPACS to ' + optim_dir_path) # Add new variables to dictionnary tixi = cpsf.open_tixi(cpacs_path) dct.update_dict(tixi, optim_var_dict) # Save the whole aeromap if needed if Rt.use_aeromap: dct.update_am_dict(tixi, Rt.aeromap_uid, am_dict) # Change local wkdir for the next iteration tixi.updateTextElement(opf.WKDIR_XPATH, ceaf.create_new_wkdir(optim_dir_path)) for obj in Rt.objective: var_list = splt('[+*/-]', obj) for v in var_list: if not v.isdigit() and v != '': exec('{} = inputs["{}"]'.format(v, v)) result = eval(obj) if Rt.minmax == 'min': outputs['Objective function ' + obj] = result else: outputs['Objective function ' + obj] = -result cpsf.close_tixi(tixi, cpacs_path) wkf.copy_module_to_module(Rt.modules[-1], 'out', Rt.modules[0], 'in')
tixi = cpsf.open_tixi(Opt.cpacs_path) wkdir = ceaf.get_wkdir_or_create_new(tixi) cpsf.close_tixi(tixi, Opt.cpacs_path) # Run Pre-otimisation workflow if Opt.module_pre: wkf.run_subworkflow(Opt.module_pre, Opt.cpacs_path) if not Opt.module_optim and not Opt.module_post: shutil.copy(mi.get_tooloutput_file_path(Opt.module_pre[-1]), cpacs_path_out) # Run Optimisation workflow if Opt.module_optim: if Opt.module_pre: wkf.copy_module_to_module(Opt.module_pre[-1], 'out', 'Optimisation', 'in') else: wkf.copy_module_to_module('WorkflowCreator', 'in', 'Optimisation', 'in') if Opt.optim_method != 'None': routine_launcher(Opt) else: log.warning('No optimization method has been selected!') log.warning('The modules will be run as a simple workflow') wkf.run_subworkflow(Opt.module_optim) if not Opt.module_post: shutil.copy(mi.get_tooloutput_file_path(Opt.module_optim[-1]), cpacs_path_out)
objectives = ['cl/cd', 'cms'] file = 'Aeromap_generated100_points.csv' # file = '_Variable_history.csv' aeromap = True modules = ['WeightConventional', 'PyTornado'] if os.path.isfile(file): log.info('File found, will be used to generate the model') elif aeromap and not os.path.isfile(file): log.info('Specific aeromap case') modules.insert(0, 'SettingsGUI') file = aeromap_case_gen(modules) else: log.info('No file found, running DoE') wkf.copy_module_to_module('PredictiveTool', 'in', 'Optimisation', 'in') opt.routine_setup(modules, 'DoE') wkf.copy_module_to_module('Optimisation', 'out', 'PredictiveTool', 'in') cpacs_path = mi.get_tooloutput_file_path('Optimisation') tixi = cpsf.open_tixi(cpacs_path) file = cpsf.get_value(tixi, opf.OPTWKDIR_XPATH) + '/Variable_history.csv' objectives = cpsf.get_value(tixi, opf.OPTIM_XPATH + '/objectives') xd, yd = extract_data_set(file) sm = create_model(xd, yd) log.info('End of Predictive tool')
def run_workflow(Otp): """ Run the complete Worflow Args: Opt (class): Cl cpacs_out_path (str): Path to the output CPACS file module_list (list): List of module to inclue in the GUI """ # Copy ToolInput.xml in ToolInput dir if not already there cpacs_path = mi.get_toolinput_file_path(MODULE_NAME) if not os.path.abspath(Opt.cpacs_path) == os.path.abspath(cpacs_path): shutil.copy(Opt.cpacs_path, cpacs_path) Opt.cpacs_path = os.path.abspath(cpacs_path) # Create a new wkdir tixi = cpsf.open_tixi(Opt.cpacs_path) wkdir = ceaf.get_wkdir_or_create_new(tixi) cpsf.close_tixi(tixi, Opt.cpacs_path) # Run Pre-otimisation workflow if Opt.module_pre: wkf.run_subworkflow(Opt.module_pre, Opt.cpacs_path) if not Opt.module_optim and not Opt.module_post: shutil.copy(mi.get_tooloutput_file_path(Opt.module_pre[-1]), cpacs_path_out) # Run Optimisation workflow if Opt.module_optim: if Opt.module_pre: wkf.copy_module_to_module(Opt.module_pre[-1], 'out', 'Optimisation', 'in') else: wkf.copy_module_to_module('WorkflowCreator', 'in', 'Optimisation', 'in') if Opt.optim_method != 'None': routine_launcher(Opt) else: log.warning('No optimization method has been selected!') log.warning('The modules will be run as a simple workflow') wkf.run_subworkflow(Opt.module_optim) if not Opt.module_post: shutil.copy(mi.get_tooloutput_file_path(Opt.module_optim[-1]), cpacs_path_out) # Run Post-optimisation workflow if Opt.module_post: if Opt.module_optim: wkf.copy_module_to_module(Opt.module_optim[-1], 'out', Opt.module_post[0], 'in') elif Opt.module_pre: wkf.copy_module_to_module(Opt.module_pre[-1], 'out', Opt.module_post[0], 'in') else: wkf.copy_module_to_module('WorkflowCreator', 'in', Opt.module_post[0], 'in') # wkf.copy_module_to_module('CPACSUpdater','out',Opt.module_post[0],'in') usefuel? wkf.run_subworkflow(Opt.module_post) shutil.copy(mi.get_tooloutput_file_path(Opt.module_post[-1]), cpacs_path_out)
def one_optim_iter(): """Function to evaluate the value to optimize. Function 'one_optim_iter' will exectute in order all the module contained in '...' and extract the ... value from the last CPACS file, this value will be returned to the optimizer CPACSUpdater.... """ # Create the parameter in CPACS with 'CPACSUpdater' module cpacs_path = mi.get_toolinput_file_path('CPACSUpdater') cpacs_out_path = mi.get_tooloutput_file_path('CPACSUpdater') tixi = cpsf.open_tixi(cpacs_path) wkdir_path = ceaf.create_new_wkdir() WKDIR_XPATH = '/cpacs/toolspecific/CEASIOMpy/filesPath/wkdirPath' tixi.updateTextElement(WKDIR_XPATH, wkdir_path) # TODO: improve this part! (maybe move somewhere else) # To delete coef from previous iter aeromap_uid = cpsf.get_value(tixi, SU2_XPATH + '/aeroMapUID') Coef = apmf.get_aeromap(tixi, aeromap_uid) apmf.delete_aeromap(tixi, aeromap_uid) apmf.create_empty_aeromap(tixi, aeromap_uid, 'test_optim') apmf.save_parameters(tixi, aeromap_uid, Coef) cpsf.close_tixi(tixi, cpacs_path) # Update the CPACS file with the parameters contained in optim_var_dict update_cpacs_file(cpacs_path, cpacs_out_path, optim_var_dict) # Run optimisation sub workflow wkf.copy_module_to_module('CPACSUpdater', 'out', module_optim[0], 'in') wkf.run_subworkflow(module_optim) wkf.copy_module_to_module(module_optim[-1], 'out', 'CPACSUpdater', 'in') # Extract results TODO: improve this part cpacs_results_path = mi.get_tooloutput_file_path(module_optim[-1]) log.info('Results will be extracted from:' + cpacs_results_path) tixi = cpsf.open_tixi(cpacs_results_path) mtom = cpsf.get_value( tixi, '/cpacs/vehicles/aircraft/model/analyses/massBreakdown/designMasses/mTOM/mass' ) aeromap_uid = cpsf.get_value(tixi, SU2_XPATH + '/aeroMapUID') Coef = apmf.get_aeromap(tixi, aeromap_uid) cl = Coef.cl[0] cd = Coef.cd[0] cm = Coef.cms[0] log.info('=========================') for key, (name, listval, minval, maxval, command) in optim_var_dict.items(): log.info(name, ': ', listval[-1]) log.info('Cl/Cd: ' + str(cl / cd)) log.info('Cl: ' + str(cl)) log.info('Cd: ' + str(cd)) log.info('Cd: ' + str(cm)) log.info('MTOM:' + str(mtom)) log.info('(Cl)/MTOM:' + str(cl / mtom)) log.info('=========================') # TODO: add option to choose what will be returned # return -mtom # return -cl # return cd # return -cl/cd return -cl / cd / mtom
# Mission analysis: 'Range' # Copy-Paste the module you want to execute, they will be run in order module_pre = ['SettingsGUI','WeightConventional','SkinFriction','CLCalculator','Range'] module_optim = ['WeightConventional','PyTornado'] module_post = [] optim = True doe = False # Pre Workflow (only run once)------------------------ wkf.run_subworkflow(module_pre,cpacs_path) # Optim Workflow ------------------------------------ if optim: wkf.copy_module_to_module(module_pre[-1],'out','CPACSUpdater','in') #run_optimizer() optimize(module_optim) # Post optim ------------------------------- if module_post: wkf.copy_module_to_module('CPACSUpdater','out',module_post[0],'in') wkf.run_subworkflow(module_post) shutil.copy(mi.get_tooloutput_file_path(module_post[-1]),cpacs_path_out) else: shutil.copy(mi.get_tooloutput_file_path(module_optim[-1]),cpacs_path_out) elif doe: pass else: