def create_xml(cpacs_out, NAME): """ Function that creates a copy of the cpacs file, inside the ToolInput folder, into the ToolOutput folder INPUT (char) cpacs_out --Arg.: Relative location of the xml file in the ToolOutput folder. (char) NAME --Arg.: Aircraft Name. OUTPUT (char) out_xml --Out.: Relative location of the xml file in the ToolOutut folder. """ root = ET.Element('cpacs') head = ET.SubElement(root, 'header') cp1 = ET.SubElement(head, 'cpacsVersion').text = '3.0' name = ET.SubElement(head, 'name').text = NAME ups = ET.SubElement(head, 'updates') up = ET.SubElement(ups, 'update') cp2 = ET.SubElement(up, 'cpacsVersion').text = '3.0' veh = ET.SubElement(root, 'vehicles') air = ET.SubElement(veh, 'aircraft') mod = ET.SubElement(air, 'model') tree = ET.ElementTree(root) tree.write(cpacs_out) tixi = cpf.open_tixi(cpacs_out) tixi.saveDocument(cpacs_out) cpf.close_tixi(tixi, cpacs_out) return (cpacs_out)
def write_outputs(y, outputs): """Write outputs to cpacs. Write the predicted output of the model to the CPACS file. Args: y (DataFrame): Contains the outputs, locations. outputs (np.array): Values of the outputs. Returns: None. """ tixi = cpsf.open_tixi(cpacs_path) tigl = cpsf.open_tigl(tixi) aircraft = cpud.get_aircraft(tigl) wings = aircraft.get_wings() fuselage = aircraft.get_fuselages().get_fuselage(1) y.fillna('-', inplace=True) for i, name in enumerate(y.index): if y.loc[name, 'setcmd'] != '-': exec('{} = {}'.format(name, outputs[0][i])) eval(y.loc[name, 'setcmd']) elif y.loc[name, 'getcmd'] != '-': xpath = y.loc[name, 'getcmd'] cpsf.create_branch(tixi, xpath) tixi.updateDoubleElement(xpath, outputs[0][i], '%g') tigl.close() cpsf.close_tixi(tixi, cpacs_path_out)
def get_default_df(module_list): tixi = cpsf.open_tixi(CPACS_OPTIM_PATH) for mod_name, specs in mif.get_all_module_specs().items(): if specs and mod_name in module_list: get_variables(tixi, specs, mod_name) cpsf.close_tixi(tixi, CPACS_OPTIM_PATH) # Add the default values for the variables df = pd.DataFrame(columns=['Name'], data=var['Name']) df['type'] = var['type'] df['initial value'] = var['init'] df['min'] = var['min'] df['max'] = var['max'] df['getpath'] = var['xpath'] # Add geometry parameters as design variables (only design type for the moment) tixi = cpsf.open_tixi(CPACS_OPTIM_PATH) geom_var = dct.init_design_var_dict(tixi) for key, (var_name, [init_value], lower_bound, upper_bound, setcmd, getcmd) in geom_var.items(): new_row = { 'Name': var_name, 'type': 'des', 'initial value': init_value, 'min': lower_bound, 'max': upper_bound, 'getpath': getcmd, 'setpath': setcmd } df = df.append(new_row, ignore_index=True) return df
def get_user_inputs(self, cpacs_path): """Take user inputs from the GUI.""" tixi = cpsf.open_tixi(CPACS_OPTIM_PATH) # Problem setup objectives = cpsf.get_value_or_default(tixi, OPTIM_XPATH + 'objective', 'cl') self.objective = objectives.split(';') self.minmax = cpsf.get_value_or_default(tixi, OPTIM_XPATH + 'minmax', 'max') # Global parameters self.driver = cpsf.get_value_or_default( tixi, OPTIM_XPATH + 'parameters/driver', 'COBYLA') self.max_iter = int( cpsf.get_value_or_default(tixi, OPTIM_XPATH + 'iterationNB', 200)) self.tol = float( cpsf.get_value_or_default(tixi, OPTIM_XPATH + 'tolerance', 1e-3)) self.save_iter = int( cpsf.get_value_or_default(tixi, OPTIM_XPATH + 'saving/perIter', 1)) # Specific DoE parameters self.doedriver = cpsf.get_value_or_default( tixi, OPTIM_XPATH + 'parameters/DoE/driver', 'uniform') self.samplesnb = int( cpsf.get_value_or_default(tixi, OPTIM_XPATH + 'parameters/DoE/sampleNB', 3)) # User specified configuration file path self.user_config = cpsf.get_value_or_default( tixi, OPTIM_XPATH + 'Config/filepath', '../Optimisation/Default_config.csv') cpsf.close_tixi(tixi, CPACS_OPTIM_PATH)
def get_inside_dim(self, cpacs_path): """ Get user input from the CPACS file The function 'get_inside_dim' extracts from the CPACS file the required aircraft inside dimension, the code will use the default value when they are missing. Args: cpacs_path (str): Path to CPACS file """ tixi = open_tixi(cpacs_path) # Get inside dimension from the CPACS file if exit self.seat_width = get_value_or_default(tixi, GEOM_XPATH + '/seatWidth', 0.525) self.seat_length = get_value_or_default(tixi, GEOM_XPATH + '/seatLength', self.seat_length) self.aisle_width = get_value_or_default(tixi, GEOM_XPATH + '/aisleWidth', 0.42) self.fuse_thick = get_value_or_default(tixi, GEOM_XPATH + '/fuseThick', 6.63) self.toilet_length = get_value_or_default(tixi, GEOM_XPATH + '/toiletLength', self.toilet_length) close_tixi(tixi, cpacs_path)
def transformer(input_file, output_file='output_cpacs.xml', geometry_dict={}): """Transforms a CPACS aircraft geometry by rescaling individual sections Parameters ---------- input_file : str The location of the CPACS file output_file : str The name of the output file (default output_cpacs.xml) geometry_dict : dict A dictionary of aircraft geometry parameters with the values that the output CPACS file should have dict keywords: fuselage_length, wing_span """ fuse_length_change = geometry_dict.get('fuse_length', 'None') name = aircraft_name(input_file) ag = geometry.geometry_eval(input_file, name) fuse_length = ag.fuse_length[0] scale = fuse_length_change / fuse_length tixi_handle = open_tixi(input_file) tixi_handle = section_transformer(tixi_handle, scale, ag.fuse_sec_nb[0]) tixi_handle = positioning_transformer(tixi_handle, scale) close_tixi(tixi_handle, output_file) return 'done'
def extract_am_data(Tool): """Get training data from aeromap. Retrieve training dataset from an aeromap. The inputs are [alt, mach, aoa, aos] parameters and the outputs are [cl, cd, cs, cml, cmd, cms]. Args: Tool (Prediction_tool): Class containing the user specification. Returns: xd (4*m numpy array): Set of m points in the 4-dimensionnal design space. yd (6*m numpy array): Set of m points in the 6-dimensionnal result space. """ cpacs_path = mif.get_toolinput_file_path('SMTrain') tixi = cpsf.open_tixi(cpacs_path) Tool.df = gen_df_from_am(tixi) Aeromap = apmf.get_aeromap(tixi, Tool.aeromap_uid) xd = np.array([Aeromap.alt, Aeromap.mach, Aeromap.aoa, Aeromap.aos]) yd = np.array([ Aeromap.cl, Aeromap.cd, Aeromap.cs, Aeromap.cml, Aeromap.cmd, Aeromap.cms ]) cpsf.close_tixi(tixi, cpacs_path) return xd.transpose(), yd.transpose()
def cpacs_generate(aircraftname, tot_len, nose_frac=0.1, tail_frac=0.1): """Generates a new CPACS file with a fuselage defined in it Parameters ---------- aircraftname : str The name of the aircraft and filename of the output CPACS file tot_len : float Total length of the fuselage nose_frac : float, default = 0.1 Fraction of the total length that comprises the nose section tail_frac : float, default = 0.1 Fraction of the total length that comprises the tail section Outputs ------- A CPACS file named aircraftname.xml """ # Instantiate class and create handle for it tixi_handle = tixi.Tixi3() tixi.Tixi3.create(tixi_handle, rootElementName='cpacs') # Generate CPACS XML tag structure tixi_handle = generate_cpacs_structure(tixi_handle, aircraftname) # Create fuselage tixi_handle = build_fuselage(tixi_handle, tot_len, nose_frac, tail_frac, 'Fuselage') # Check that CPACS file matches schema tixi_handle.schemaValidateFromFile('cpacs_schema.xsd') close_tixi(tixi_handle, f"cpacs/{aircraftname}.xml")
def toolspecific_update(fus_nb, awg, mw, out, cpacs_out_path): """ The function that update the cpacs file after the Weight_unc_main program. Args: fus_nb (integer): Number of fuselage [-]. awg (class): AircraftWingGeometry class. mw (class): Masses and Weights class. out (class): Output class. cpacs_out_path (str): Path of the output file. """ tixi = cpsf.open_tixi(cpacs_out_path) # Path definition CEASIOM_PATH = '/cpacs/toolspecific/CEASIOMpy' WEIGHT_XPATH = CEASIOM_PATH + '/weight' CREW_XPATH = WEIGHT_XPATH + '/crew' cpsf.create_branch(tixi, CREW_XPATH + '/cabinCrewMembers', False) PASS_XPATH = WEIGHT_XPATH + '/passengers' cpsf.create_branch(tixi, PASS_XPATH, False) # Path update if not tixi.checkElement(CREW_XPATH + '/cabinCrewMembers/cabinCrewMemberNb'): tixi.createElement(CREW_XPATH + '/cabinCrewMembers', 'cabinCrewMemberNb') tixi.updateDoubleElement(CREW_XPATH + '/cabinCrewMembers/cabinCrewMemberNb',\ out.cabin_crew_nb, '%g') if not tixi.checkElement(PASS_XPATH + '/passNb'): tixi.createElement(PASS_XPATH, 'passNb') tixi.updateIntegerElement(PASS_XPATH + '/passNb', out.pass_nb, '%i') if not tixi.checkElement(PASS_XPATH + '/mass'): tixi.createElement(PASS_XPATH, 'mass') tixi.updateDoubleElement(PASS_XPATH + '/mass', mw.mass_pass, '%g') if not tixi.checkElement(PASS_XPATH + '/toiletNb'): tixi.createElement(PASS_XPATH, 'toiletNb') tixi.updateIntegerElement(PASS_XPATH + '/toiletNb',int(out.toilet_nb),'%i') if not tixi.checkElement(PASS_XPATH + '/fuelMassMaxpass'): tixi.createElement(PASS_XPATH, 'fuelMassMaxpass') FMP_PATH = PASS_XPATH + '/fuelMassMaxpass' if not tixi.checkElement(FMP_PATH + '/description'): tixi.createElement(FMP_PATH, 'description') tixi.updateTextElement(FMP_PATH + '/description', 'Maximum amount of '\ + 'fuel with maximum payload [kg]') if not tixi.checkElement(FMP_PATH + '/mass'): tixi.createElement(FMP_PATH, 'mass') tixi.updateDoubleElement(FMP_PATH + '/mass', mw.mass_fuel_maxpass, '%g') cpsf.close_tixi(tixi, cpacs_out_path) return()
def update_cpacs_file(cpacs_path, cpacs_out_path, optim_var_dict): """Function to update a CPACS file with value from the optimiser This function sets the new values of the design variables given by the routine driver to the CPACS file, using the Tigl and Tixi handler. Source: * See CPACSCreator api function, Args: cpacs_path (str): Path to CPACS file to update cpacs_out_path (str):Path to the updated CPACS file optim_var_dict (dict): Dictionary containing all the variable value/min/max and command to modify a CPACS file """ tixi = cpsf.open_tixi(cpacs_path) tigl = cpsf.open_tigl(tixi) aircraft = get_aircraft(tigl) # help(aircraft) wings = aircraft.get_wings() # help(wings) fuselage = aircraft.get_fuselages().get_fuselage(1) # help(fuselage) # Other functions which could be useful # help(wings.get_wing(1).get_section(1)) # uid = wings.get_wing(1).get_section(2).get_uid() # help(wings.get_wing(1).get_positioning_transformation(uid)) # wings.get_wing(1).get_section(2).set_rotation(geometry.CTiglPoint(40,40,-4)) # airfoil = wings.get_wing(1).get_section(1).get_section_element(1).get_airfoil_uid() # help(airfoil) # wings.get_wing(1).get_section(1).get_section_element(1).set_airfoil_uid('NACA0006') # scal = wings.get_wing(1).get_section(1).get_section_element(1).get_scaling() # help(wings.get_wing(1).get_section(2)) # Perform update of all the variable contained in 'optim_var_dict' for name, (val_type, listval, minval, maxval, getcommand, setcommand) in optim_var_dict.items(): if val_type == 'des' and listval[0] not in ['-', 'True', 'False']: if setcommand not in ['-', '']: # Define variable (var1,var2,..) locals()[str(name)] = listval[-1] # Execute the command coresponding to the variable if ';' in setcommand: # if more than one command on the line command_split = setcommand.split(';') for setcommand in command_split: eval(setcommand) else: eval(setcommand) else: xpath = getcommand tixi.updateTextElement(xpath, str(listval[-1])) aircraft.write_cpacs(aircraft.get_uid()) tigl.close() cpsf.close_tixi(tixi, cpacs_out_path)
def get_number_of_parts(cpacs_in): """ The fuction counts the number of fuselage and wings. Args: cpacs_in (str): Path to the CPACS file. Retrurns: fus_nb (int): Number of fuselages. wing_nb (int) : Number of wings. """ tixi = cpsf.open_tixi(cpacs_in) if tixi.checkElement('/cpacs/vehicles/aircraft/model/fuselages'): fus_nb = tixi.getNamedChildrenCount( '/cpacs/vehicles/aircraft/model/fuselages', 'fuselage') else: fus_nb = 0 if tixi.checkElement('/cpacs/vehicles/aircraft/model/wings'): wing_nb = tixi.getNamedChildrenCount( '/cpacs/vehicles/aircraft/model/wings', 'wing') else: wing_nb = 0 cpsf.close_tixi(tixi, cpacs_in) return (fus_nb, wing_nb)
def test_create_branch(): """Test the function 'create_branch'""" tixi_handle = open_tixi(CPACS_IN_PATH) update_branch = '/cpacs/header/updates/update' new_branch = '/cpacs/header/updates/update[3]/test/test1/test2' # This branch should be added tixi = create_branch(tixi_handle, update_branch, True) # This branch should not be added tixi = create_branch(tixi, update_branch, False) # 'new_branch' should be added tixi = create_branch(tixi, new_branch) # Save modified tixi in the output CPACS file close_tixi(tixi, CPACS_OUT_PATH) # Reopen the output CPACS file to check if branches have been added tixi_out = open_tixi(CPACS_OUT_PATH) # Check if the number of "update" child is equal to 3 namedchild_nb = tixi_out.getNamedChildrenCount('/cpacs/header/updates', 'update') assert namedchild_nb == 3 # Check if 'new_branch' has been added branch_check = tixi_out.checkElement(new_branch) assert branch_check
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) # Add new variables to dictionnary tixi = cpsf.open_tixi(cpacs_path) dct.update_dict(tixi, optim_var_dict) # Change local wkdir for the next iteration tixi.updateTextElement(opf.WKDIR_XPATH, ceaf.create_new_wkdir(Rt.date, Rt.type)) 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)
def compute(self, inputs, outputs): """Launches the module""" # Updating inputs in CPACS file cpacs_path = mif.get_toolinput_file_path(self.module_name) tixi = cpsf.open_tixi(cpacs_path) for name in inputs: if name in optim_var_dict: xpath = optim_var_dict[name][4] cpsf.add_float_vector(tixi, xpath, inputs[name]) cpsf.close_tixi(tixi, cpacs_path) # Running the module wkf.run_subworkflow([self.module_name]) # Feeding CPACS file restults to outputs cpacs_path = mif.get_tooloutput_file_path(self.module_name) tixi = cpsf.open_tixi(cpacs_path) for name in outputs: if name in optim_var_dict: xpath = optim_var_dict[name][4] outputs[name] = cpsf.get_value(tixi, xpath) # Copy CPACS to input folder of next module index = Rt.modules.index(self.module_name) + 1 if index != len(Rt.modules): cpacs_path = mif.get_toolinput_file_path(Rt.modules[index]) else: cpacs_path = mif.get_toolinput_file_path(Rt.modules[0]) cpsf.close_tixi(tixi, cpacs_path)
def get_number_of_parts(cpacs_in): """ The fuction counts the number of fuselage and wings. INPUT (char) cpacs_in --Arg.: Relative position of the xml file. OUTPUT (int) f_nb --Out.: Number of fuselages. (int) W_nb --Out.: Number of wings. """ # Opening tixi and tigl tixi = cpf.open_tixi(cpacs_in) if not tixi.checkElement('/cpacs/vehicles/aircraft\ /model/fuselages'): f_nb = 0 else: f_nb = tixi.getNamedChildrenCount( '/cpacs/vehicles/aircraft\ /model/fuselages', 'fuselage') if not tixi.checkElement('/cpacs/vehicles/aircraft\ /model/wings'): w_nb = 0 else: w_nb = tixi.getNamedChildrenCount( '/cpacs/vehicles/aircraft\ /model/wings', 'wing') cpf.close_tixi(tixi, cpacs_in) return (f_nb, w_nb)
def add_skin_friction(cpacs_path, cpacs_out_path): """ Function to add the skin frinction drag coeffienct to the CPACS file Function 'add_skin_friction' add the skin friction drag 'cd0' to the CPACS file, then it could be added to the drag coeffienct obtain with Euler calcualtions or other methods Args: cpacs_path (str): Path to CPACS file cpacs_out_path (str): Path to CPACS output file """ tixi = open_tixi(cpacs_path) tigl = open_tigl(tixi) wing_area_max, wing_span_max = get_largest_wing_dim(tixi, tigl) analysis_xpath = '/cpacs/toolspecific/CEASIOMpy/geometry/analysis' range_xpath = '/cpacs/toolspecific/CEASIOMpy/ranges' # Requiered input data from CPACS wetted_area = get_value(tixi, analysis_xpath + '/wettedArea') # Not requiered input data (a default value will be used if no # value has been found in the CPACS file) wing_area_xpath = analysis_xpath + '/wingArea' tixi, wing_area = get_value_or_default(tixi, wing_area_xpath, wing_area_max) if wing_area != wing_area_max: log.warning('Wing area found in the CPACS file /toolspecific is \ different from the one calculated from geometry, \ /toolspecific value will be used') wing_span_xpath = analysis_xpath + '/wingSpan' tixi, wing_span = get_value_or_default(tixi, wing_span_xpath, wing_span_max) if wing_span != wing_span_max: log.warning('Wing span found in the CPACS file /toolspecific is \ different from the one calculated from geometry, \ /toolspecific value will be used') cruise_alt_xpath = range_xpath + '/cruiseAltitude' tixi, cruise_alt = get_value_or_default(tixi, cruise_alt_xpath, 12000) cruise_mach_xpath = range_xpath + '/cruiseMach' tixi, cruise_mach = get_value_or_default(tixi, cruise_mach_xpath, 0.78) # Calculate Cd0 cd0 = estimate_skin_friction_coef(wetted_area,wing_area,wing_span, \ cruise_mach,cruise_alt) # Save Cd0 in the CPACS file cd0_xpath = '/cpacs/toolspecific/CEASIOMpy/aerodynamics/skinFriction/cd0' tixi = create_branch(tixi, cd0_xpath) tixi.updateDoubleElement(cd0_xpath, cd0, '%g') log.info('Skin friction drag coeffienct (cd0) has been saved in the \ CPACS file') close_tixi(tixi, cpacs_out_path)
def create_routine_folder(): """Create the working dicrectory of the routine. Create a folder in which all CEASIOMpy runs and routine parameters will be saved. This architecture may change in the future. For now the architecture of the folder is as such : > CEASIOMpy_Run_XX-XX-XX -> Optim --> Geometry --> Runs ---> Run_XX-XX-XX -> Optim2 | -> OptimX -> DoE Args: None. """ global optim_dir_path, Rt # Create the main working directory tixi = cpsf.open_tixi(opf.CPACS_OPTIM_PATH) wkdir = ceaf.get_wkdir_or_create_new(tixi) optim_dir_path = os.path.join(wkdir, Rt.type) Rt.date = wkdir[-19:] # Save the path to the directory in the CPACS if tixi.checkElement(opf.OPTWKDIR_XPATH): tixi.removeElement(opf.OPTWKDIR_XPATH) cpsf.create_branch(tixi, opf.OPTWKDIR_XPATH) tixi.updateTextElement(opf.OPTWKDIR_XPATH, optim_dir_path) # Add subdirectories if not os.path.isdir(optim_dir_path): os.mkdir(optim_dir_path) os.mkdir(optim_dir_path + '/Geometry') os.mkdir(optim_dir_path + '/Runs') else: index = 2 optim_dir_path = optim_dir_path + str(index) while os.path.isdir(optim_dir_path): index += 1 optim_dir_path = optim_dir_path.split( Rt.type)[0] + Rt.type + str(index) os.mkdir(optim_dir_path) os.mkdir(optim_dir_path + '/Geometry') os.mkdir(optim_dir_path + '/Runs') tixi.updateTextElement(opf.OPTWKDIR_XPATH, optim_dir_path) tixi.updateTextElement(opf.WKDIR_XPATH, optim_dir_path) cpsf.close_tixi(tixi, opf.CPACS_OPTIM_PATH)
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 cpacs_engine_update(ui, ed, mw, out_xml): """ The function that update the cpacs file after the Weight_unc_main program. INPUT (class) mw --Arg.: MassesWeihts class. (class) ui --Arg.: UserInputs class. (class) ed --Arg.: EngineData class. ##======= Class are defined in the Input_Classes folder =======## (char) out_xml --Arg.: Path of the output file. OUTPUT (file) cpacs.xml --Out.: Updated cpacs file. """ tixi = cpf.open_tixi(out_xml) tigl = cpf.open_tigl(tixi) # Path creation ========================================================== EN_PATH = '/cpacs/vehicles/engines' if tixi.checkElement(EN_PATH): tixi.removeElement(EN_PATH) for e in range(0, ed.NE): EN_PATH = '/cpacs/vehicles/engines/engine' + str(e + 1) tixi = cpf.create_branch(tixi, EN_PATH, True) EN_UID = 'EngineuID_' + str(e + 1) tixi = cpf.add_uid(tixi, EN_PATH, EN_UID) tixi.createElement(EN_PATH, 'name') if not ed.EN_NAME[e]: EN_NAME = 'Engine_' + str(e + 1) tixi.updateTextElement(EN_PATH + '/name', EN_NAME) else: tixi.updateTextElement(EN_PATH + '/name', ed.EN_NAME[e]) ENA_PATH = EN_PATH + '/analysis/mass' tixi = cpf.create_branch(tixi, ENA_PATH, False) tixi = cpf.add_uid(tixi, EN_PATH, EN_UID + '_mass') tixi.createElement(ENA_PATH, 'mass') tixi.updateDoubleElement(ENA_PATH + '/mass', ed.en_mass, '%g') ENT_PATH = EN_PATH + '/analysis' tixi.createElement(ENT_PATH, 'thrust00') tixi.updateDoubleElement(ENT_PATH + '/thrust00', ed.max_thrust, '%g') # Saving and closing the new cpacs file inside the ToolOutput folder ----- tixi.saveDocument(out_xml) cpf.close_tixi(tixi, out_xml) # Openign and closing again the cpacs file, formatting purpose ----------- tixi = cpf.open_tixi(out_xml) tigl = cpf.open_tigl(tixi) tixi.saveDocument(out_xml) cpf.close_tixi(tixi, out_xml) return ()
def get_cl(cpacs_path, cpacs_out_path): """ Function to calculate CL requiered as a function of the parameter found in the CPACS file. Function 'get_cl' find input value in the CPACS file, calculate the requiered CL (with calculate_cl) and save the CL value in /cpacs/toolspecific/CEASIOMpy/aerodynamics/su2/targetCL Args: cpacs_path (str): Path to CPACS file cpacs_out_path (str): Path to CPACS output file """ tixi = open_tixi(cpacs_path) # XPath definition model_xpath = '/cpacs/vehicles/aircraft/model' ref_area_xpath = model_xpath + '/reference/area' mtom_xpath = model_xpath + '/analyses/massBreakdown/designMasses/mTOM/mass' range_xpath = '/cpacs/toolspecific/CEASIOMpy/ranges' cruise_alt_xpath = range_xpath + '/cruiseAltitude' cruise_mach_xpath = range_xpath + '/cruiseMach' load_fact_xpath = range_xpath + '/loadFactor' su2_xpath = '/cpacs/toolspecific/CEASIOMpy/aerodynamics/su2' # Requiered input data from CPACS ref_area = get_value(tixi, ref_area_xpath) mtom = get_value(tixi, mtom_xpath) # Requiered input data that could be replace by a default value if missing cruise_alt = get_value_or_default(tixi, cruise_alt_xpath, 12000.0) cruise_mach = get_value_or_default(tixi, cruise_mach_xpath, 0.78) load_fact = get_value_or_default(tixi, load_fact_xpath, 1.05) # Get atmosphere from cruise altitude Atm = get_atmosphere(cruise_alt) # CL calculation target_cl = calculate_cl(ref_area, cruise_alt, cruise_mach, mtom, load_fact) # Save TargetCL create_branch(tixi, su2_xpath) create_branch(tixi, su2_xpath + '/targetCL') create_branch(tixi, su2_xpath + '/fixedCL') tixi.updateDoubleElement(su2_xpath + '/targetCL', target_cl, '%g') tixi.updateTextElement(su2_xpath + '/fixedCL', 'YES') log.info('Target CL has been saved in the CPACS file') close_tixi(tixi, cpacs_out_path)
def get_user_fuel(fus_nb, ui, cpacs_in): """Function to extract fuel data from a CPACS file Function 'get_user_fuel' extracts fuel data from the CPACS file, the code will use the default value when they are missing. Args: fus_nb (int): Number of fuselage. ui (class): UserInputs class cpacs_in (str): Path to the CPACS file Returns: ui (class): Modified UserInputs class """ log.info('Starting data extraction from CPACS file') tixi = cpsf.open_tixi(cpacs_in) FUEL_XPATH = '/cpacs/toolspecific/CEASIOMpy/fuels' cpsf.create_branch(tixi, FUEL_XPATH, False) if fus_nb: for i in range(0, fus_nb): if fus_nb > 1: F = 'fuelOnCabin' + str(i + 1) else: F = 'fuelOnCabin' if not tixi.checkElement(FUEL_XPATH + '/' + F): tixi.createElement(FUEL_XPATH, F) tixi.updateDoubleElement(FUEL_XPATH + '/' + F, ui.F_FUEL[i], '%g') else: ui.F_FUEL[i] = tixi.getDoubleElement(FUEL_XPATH + '/' + F) else: if not tixi.checkElement(FUEL_XPATH + '/fuelOnCabin'): tixi.createElement(FUEL_XPATH, 'fuelOnCabin') tixi.updateDoubleElement(FUEL_XPATH + '/fuelOnCabin', ui.FUEL_ON_CABIN, '%g') else: temp = tixi.updateDoubleElement(FUEL_XPATH + '/fuelOnCabin', ui.FUEL_ON_CABIN, '%g') if temp != ui.FUEL_ON_CABIN and temp > 0: ui.FUEL_ON_CABIN = temp log.info('Data from CPACS file succesfully extracted') cpsf.close_tixi(tixi, cpacs_in) return (ui)
def get_user_inputs(self, cpacs_path): """ Get user input from the CPACS file The function 'get_user_inputs' extracts from the CPACS file the required input data, the code will use the default value when they are missing. Args: cpacs_path (str): Path to CPACS file """ tixi = open_tixi(cpacs_path) description = 'User geometry input' get_value_or_default(tixi, GEOM_XPATH + '/description', description) self.IS_DOUBLE_FLOOR = get_value_or_default( tixi, GEOM_XPATH + '/isDoubleFloor', 0) self.PILOT_NB = get_value_or_default(tixi, pilots_xpath + '/pilotNb', 2) self.MASS_PILOT = get_value_or_default(tixi, pilots_xpath + '/pilotMass', 102) self.MASS_CABIN_CREW = get_value_or_default( tixi, CC_XPATH + '/cabinCrewMemberMass', 68) self.MASS_PASS = get_value_or_default(tixi, PASS_XPATH + '/passMass', 105) self.PASS_PER_TOILET = get_value_or_default( tixi, PASS_XPATH + '/passPerToilet', 50) description = 'Desired max fuel volume [m^3] and payload mass [kg]' get_value_or_default(tixi, ML_XPATH + '/description', description) self.MAX_PAYLOAD = get_value_or_default(tixi, ML_XPATH + '/maxPayload', 0) self.MAX_FUEL_VOL = get_value_or_default(tixi, ML_XPATH + '/maxFuelVol', 0) self.MASS_CARGO = get_value_or_default(tixi, MC_XPATH + '/mass', 0.0) self.FUEL_DENSITY = get_value_or_default(tixi, F_XPATH + '/density', 800) self.TURBOPROP = get_value_or_default(tixi, PROP_XPATH + '/turboprop', False) self.RES_FUEL_PERC = get_value_or_default(tixi, FUEL_XPATH + '/resFuelPerc', 0.06) add_uid(tixi, F_XPATH, 'kerosene') close_tixi(tixi, cpacs_path)
def cpacs_engine_update(ui, ed, mw, cpacs_out_path): """ The function that update the cpacs file after the Weight_unc_main program. Args: mw (class): MassesWeihts class. ui (class): UserInputs class. ed (class): EngineData class. cpacs_out_path (str): Path of the CPACS output file. """ tixi = cpsf.open_tixi(cpacs_out_path) tigl = cpsf.open_tigl(tixi) EN_XPATH = '/cpacs/vehicles/engines' if tixi.checkElement(EN_XPATH): tixi.removeElement(EN_XPATH) for e in range(0,ed.NE): EN_XPATH = '/cpacs/vehicles/engines/engine' + str(e+1) cpsf.create_branch(tixi, EN_XPATH, True) EN_UID = 'EngineuID_' + str(e+1) cpsf.add_uid(tixi, EN_XPATH, EN_UID) tixi.createElement(EN_XPATH, 'name') if not ed.EN_NAME[e]: EN_NAME = 'Engine_' + str(e+1) tixi.updateTextElement(EN_XPATH + '/name', EN_NAME) else: tixi.updateTextElement(EN_XPATH + '/name', ed.EN_NAME[e]) ENA_XPATH = EN_XPATH + '/analysis/mass' cpsf.create_branch(tixi, ENA_XPATH, False) cpsf.add_uid(tixi, EN_XPATH, EN_UID+'_mass') tixi.createElement(ENA_XPATH, 'mass') tixi.updateDoubleElement(ENA_XPATH + '/mass', ed.en_mass, '%g') ENT_XPATH = EN_XPATH + '/analysis' tixi.createElement(ENT_XPATH, 'thrust00') tixi.updateDoubleElement(ENT_XPATH + '/thrust00', ed.max_thrust, '%g') cpsf.close_tixi(tixi, cpacs_out_path) return()
def compute(self, inputs, outputs): """Launches the module""" # Updating inputs in CPACS file cpacs_path = mif.get_toolinput_file_path(self.module_name) tixi = cpsf.open_tixi(cpacs_path) for name in inputs: if name in optim_var_dict: xpath = optim_var_dict[name][4] # Change only the first vector value for aeromap param if name in apmf.XSTATES: size = tixi.getVectorSize(xpath) v = list(tixi.getFloatVector(xpath, size)) v.pop(0) v.insert(0, inputs[name]) tixi.updateFloatVector(xpath, v, size, '%g') else: cpsf.add_float_vector(tixi, xpath, inputs[name]) cpsf.close_tixi(tixi, cpacs_path) # Running the module wkf.run_subworkflow([self.module_name]) # Feeding CPACS file results to outputs cpacs_path = mif.get_tooloutput_file_path(self.module_name) tixi = cpsf.open_tixi(cpacs_path) for name in outputs: if name in optim_var_dict: xpath = optim_var_dict[name][4] if name in apmf.COEF_LIST: val = cpsf.get_value(tixi, xpath) if isinstance(val, str): val = val.split(';') outputs[name] = val[0] else: outputs[name] = val else: outputs[name] = cpsf.get_value(tixi, xpath) # Copy CPACS to input folder of next module index = Rt.modules.index(self.module_name) + 1 if index != len(Rt.modules): cpacs_path = mif.get_toolinput_file_path(Rt.modules[index]) else: cpacs_path = mif.get_toolinput_file_path(Rt.modules[0]) cpsf.close_tixi(tixi, cpacs_path)
def get_fuselage_scaling(cpacs_path, cpacs_out_path): """Function to get fuselage scaling along x,y,z axis. Function 'get_fuselage_scaling' return the value of the scaling for the fuselage. (This is an example function just to show usaga of CPACS and tixi) Source: * Reference paper or book, with author and date Args: cpacs_path (str): Path to CPACS file cpacs_out_path (str):Path to CPACS output file Returns: Tuple with fuselage scaling * x (float): Scaling on x [-] * y (float): Scaling on y [-] * z (float): Scaling on z [-] """ # Open TIXI handle tixi = open_tixi(cpacs_path) # Create xpaths FUSELAGE_XPATH = '/cpacs/vehicles/aircraft/model/fuselages/fuselage' SCALING_XPATH = '/transformation/scaling' x_fus_scaling_xpath = FUSELAGE_XPATH + SCALING_XPATH + '/x' y_fus_scaling_xpath = FUSELAGE_XPATH + SCALING_XPATH + '/y' z_fus_scaling_xpath = FUSELAGE_XPATH + SCALING_XPATH + '/z' # Get values x = get_value(tixi, x_fus_scaling_xpath) y = get_value(tixi, y_fus_scaling_xpath) z = get_value(tixi, z_fus_scaling_xpath) # Log log.info('Fuselage x scaling is : ' + str(x)) log.info('Fuselage y scaling is : ' + str(y)) log.info('Fuselage z scaling is : ' + str(z)) # Close TIXI handle and save the CPACS file close_tixi(tixi, cpacs_out_path) return x, y, z
def create_aeromap(bounds, sample_type='Uniform', sample_nb=5, tixi=''): """Create an aeromap This function will generate an aeromap either as a CSV file or in a CPACS file depending on what is indicated. Args: bounds (np array): 4-by-2 array containing the boundaries for each variable tixi (Tixi3 handle): If no handle is given, a CSV file will be generated instead. sample_type (str): Choice of the method to generate the points. sample_nb (int): Number of samples to generate. """ s_t = sample_type.lower() if s_t in 'fullfactorial': sampling = smp.FullFactorial(xlimits=bounds) x = sampling(sample_nb) elif s_t in 'latinhypercube': sampling = smp.LHS(xlimits=bounds) x = sampling(sample_nb) elif s_t in 'random': sampling = smp.random(xlimits=bounds) x = sampling(sample_nb) else: x = np.array([np.linspace(b[0], b[1], sample_nb) for b in bounds]) x = x.transpose() if tixi != '': log.info('in tixi') desc = 'Aeromap generated by ' + sample_type + ' sampling' create_empty_aeromap(tixi, 'Aeromap_sample', description=desc) Param = AeroCoefficient() Param.alt = x[:, 0] Param.mach = x[:, 1] Param.aoa = x[:, 2] Param.aos = x[:, 3] save_parameters(tixi, 'Aeromap_sample', Param) cpsf.close_tixi(tixi, '../Optimisation/ToolInput/ToolInput.xml') else: np.savetxt('Aeromap_sample.csv', x, delimiter=',', header='alt,mach,aoa,aos')
def compute(self, inputs, outputs): """Make a prediction""" xp = [] for name in self.xd.index: xp.append(inputs[name][0]) xp = np.array([xp]) yp = self.Model.sm.predict_values(xp) for i, name in enumerate(self.yd.index): outputs[name] = yp[0][i] # Write the inouts to the CPACS cpacs_path = mif.get_toolinput_file_path('SMUse') tixi = cpsf.open_tixi(cpacs_path) smu.write_inouts(self.xd, xp, tixi) smu.write_inouts(self.yd, yp, tixi) cpacs_path_out = mif.get_tooloutput_file_path('SMUse') cpsf.close_tixi(tixi, cpacs_path_out)
def _save_quit(self): # Iterate over all existing tabs for tab in self.tab_list: # Iterate in Variable dictionary of each tab for key, var in tab.var_dict.items(): # Get the XPath from the GUI setting dictionary and crate a branch name = tab.gui_dict[key][0] xpath = tab.gui_dict[key][4] cpsf.create_branch(self.tixi,xpath) if name == '__AEROMAP_CHECHBOX': aeromap_uid_list_str = '' for aeromap_uid, aeromap_bool in tab.aeromap_var_dict.items(): if aeromap_bool.get(): aeromap_uid_list_str += aeromap_uid + ';' if aeromap_uid_list_str == '': messagebox.showerror('ValueError', 'In the Tab "' + \ tab.module_name + '", no value has been selected for "' + \ name + '" ') raise TypeError('No value has been selected for ' + name + ' !') self.tixi.updateTextElement(xpath, aeromap_uid_list_str) # '__AEROMAP_SELECTION' and list Type value will be saved as any other variable else: if str(var.get()) == '': # Not working when it expect an 'int' or a 'float' messagebox.showerror('ValueError', 'In the Tab "' + \ tab.module_name + '", no value has been entered for "' + \ name + '" ') raise TypeError('No value has been entered for ' + name + ' !') try: self.tixi.updateTextElement(xpath, str(var.get())) except: messagebox.showerror('TypeError', 'In the Tab "' + \ tab.module_name + '", the value "' + \ name + '" has not the correct type!') raise TypeError(name + ' has not the correct type!') cpsf.close_tixi(self.tixi, self.cpacs_out_path) self.quit()
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 copy_xml(cpacs_in, NAME): """ The function creates a copy of the cpacs file, inside the ToolInput folder, into the ToolOutput folder. INPUT (char) cpacs_in --Arg.: Relative location of the xml file in the ToolInput folder. (char) NAME --Arg.: tooloutput.xml or user_tooloutput.xml OUTPUT (char) out_xml --Out.: Relative location of the xml file in the ToolOutut folder. """ tixi = cpf.open_tixi(cpacs_in) out_xml = 'ToolOutput/' + NAME tixi.saveDocument(out_xml) cpf.close_tixi(tixi, out_xml) return (out_xml)