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 save_aeromap_from_df(tixi, aeromap_df, aeromap_uid, description='No decription'): """ Saves AeroMap DataFrame into a CPACS file. Function 'save_aeromap_from_df' will add all the required nodes for a new aeroPerformanceMap, no value will be stored but function like 'create_aeromap' and '???' could be used to fill it then. Args: tixi (handles): TIXI Handle of the CPACS file aeromap_df (str): UID of the aeroPerformanceMap to create aeromap_uid (str): UID of the aeroPerformanceMap to create description (str): description of the aeroPerformanceMap to create """ if tixi.uIDCheckExists(aeromap_uid): log.warning('This UID already exits! The aeromap will be erase!') delete_aeromap(tixi, aeromap_uid) else: log.info(aeromap_uid + ' aeroMap will be created.') # Add the /aeroMap node, or a new child is already exists cpsf.create_branch(tixi, AEROPERFORMANCE_XPATH + '/aeroMap', True) am_count = tixi.getNamedChildrenCount(AEROPERFORMANCE_XPATH, 'aeroMap') aeromap_xpath = AEROPERFORMANCE_XPATH + '/aeroMap[' + str(am_count) + ']' # Add UID and sub nodes cpsf.add_uid(tixi, aeromap_xpath, aeromap_uid) tixi.addTextElement(aeromap_xpath, 'name', aeromap_uid) tixi.addTextElement(aeromap_xpath, 'description', description) apm_bc_xpath = aeromap_xpath + '/boundaryConditions' cpsf.create_branch(tixi, apm_bc_xpath) tixi.addTextElement(apm_bc_xpath, 'atmosphericModel', 'ISA') # Add /AeroPerformanceMap and sub nodes apm_xpath = aeromap_xpath + '/aeroPerformanceMap' cpsf.create_branch(tixi, apm_xpath) # Add states for state, xstate in zip(STATES, XSTATES): if not state in aeromap_df: raise ValueError('Missing {} value in the AeroMap!'.format(state)) state_xpath = apm_xpath + '/' + xstate cpsf.create_branch(tixi, state_xpath) cpsf.add_float_vector(tixi, state_xpath, aeromap_df[state].tolist()) # Add coefficients for coef in COEF_LIST: if coef in aeromap_df: coef_xpath = apm_xpath + '/' + coef cpsf.create_branch(tixi, coef_xpath) cpsf.add_float_vector(tixi, coef_xpath, aeromap_df[coef].tolist()) else: log.info( 'There is no {} coefficient in this AeroMap!'.format(coef))
def save_parameters(tixi, aeromap_uid, Param): """ Save aerodynamic parameter in an aeroMap Function 'save_parameters' will save parameters (alt,mach,aoa,aos) into an aeroMap ... TODO: create it if not exist ??? Source : * ...CPACS Documentation? Args: tixi (handles): TIXI Handle of the CPACS file aeromap_uid (str): UID of the aeroMap used to save parameters Param (object): Object containing aerodynamic parameters (alt,mach,aoa,aos) """ apm_xpath = tixi.uIDGetXPath(aeromap_uid) + '/aeroPerformanceMap' # Check if the vality of parameters is OK Param.check_validity() # Add parameters to the aeroPerformanceMap cpsf.add_float_vector(tixi, apm_xpath + '/altitude', Param.alt) cpsf.add_float_vector(tixi, apm_xpath + '/machNumber', Param.mach) cpsf.add_float_vector(tixi, apm_xpath + '/angleOfAttack', Param.aoa) cpsf.add_float_vector(tixi, apm_xpath + '/angleOfSideslip', Param.aos)
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 test_add_float_vector(): """ Test the function 'add_float_vector'""" tixi = cpsf.open_tixi(CPACS_IN_PATH) xpath = '/cpacs/toolspecific/CEASIOMpy/testVector/' # Add a new vector float_vector = [0.0, 1.1, 5.5] cpsf.add_float_vector(tixi, xpath, float_vector) added_float_vector = list(tixi.getFloatVector(xpath, 3)) assert added_float_vector == float_vector # Update a vector float_vector = [2.9, 10.999, 1e5] cpsf.add_float_vector(tixi, xpath, float_vector) added_float_vector = list(tixi.getFloatVector(xpath, 3)) assert added_float_vector == float_vector
def test_get_float_vector(): """ Test the function 'get_float_vector'""" tixi = cpsf.open_tixi(CPACS_IN_PATH) xpath = '/cpacs/toolspecific/CEASIOMpy/testVector' # Add a new vector float_vector = [0.0, 1.1, 5.5] cpsf.add_float_vector(tixi, xpath, float_vector) # Get a float vector float_vector_get = cpsf.get_float_vector(tixi, xpath) assert float_vector_get == float_vector # Raise an error when the XPath is wrong wrong_xpath = '/cpacs/toolspecific/CEASIOMpy/testVectorWrong' with pytest.raises(ValueError): vector = cpsf.get_float_vector(tixi, wrong_xpath) # Raise an error when no value at XPath no_value_xpath = '/cpacs/toolspecific/CEASIOMpy' with pytest.raises(ValueError): vector = cpsf.get_float_vector(tixi, no_value_xpath)
def save_coefficients(tixi, aeromap_uid, Coef): """ Save aerodynamic coefficients in an aeroMap Function 'save_coefficients' will save aerodynamic coefficients into an aeroMap ... TODO: create it if not exist ??? Source : * ...CPACS Documentation? Args: tixi (handles): TIXI Handle of the CPACS file aeromap_uid (str): UID of the aeroMap used to save coefficients Coef (object): Object containing aerodynamic coefficients """ apm_xpath = tixi.uIDGetXPath(aeromap_uid) + '/aeroPerformanceMap' param_count = Coef.get_count() # CL coefficients if len(Coef.cl) == 0: log.warning('No "cl" value have been found, this node will stay empty') elif len(Coef.cl) == param_count: cpsf.add_float_vector(tixi, apm_xpath + '/cl', Coef.cl) log.info('"cl" values have been added to the corresponding node') else: raise ValueError('The number of "cl" values is incorrect, it must be \ either equal to the number of parameters or 0') # CD coefficients if len(Coef.cd) == 0: log.warning('No "cd" value have been found, this node will stay empty') elif len(Coef.cd) == param_count: cpsf.add_float_vector(tixi, apm_xpath + '/cd', Coef.cd) log.info('"cd" values have been added to the corresponding node') else: raise ValueError('The number of "cd" values is incorrect, it must be \ either equal to the number of parameters or 0') # CS coefficients if len(Coef.cs) == 0: log.warning('No "cs" value have been found, this node will stay empty') elif len(Coef.cs) == param_count: cpsf.add_float_vector(tixi, apm_xpath + '/cs', Coef.cs) log.info('"cs" values have been added to the corresponding node') else: raise ValueError('The number of "cs" values is incorrect, it must \ either equal to the number of parameters or 0') # Cml coefficients if len(Coef.cml) == 0: log.warning( 'No "cml" value have been found, this node will stay empty') elif len(Coef.cml) == param_count: cpsf.add_float_vector(tixi, apm_xpath + '/cml', Coef.cml) log.info('"cml" values have been added to the corresponding node') else: raise ValueError('The number of "cml" values is incorrect, it must \ either equal to the number of parameters or 0') # Cmd coefficients if len(Coef.cmd) == 0: log.warning( 'No "cmd" value have been found, this node will stay empty') elif len(Coef.cmd) == param_count: cpsf.add_float_vector(tixi, apm_xpath + '/cmd', Coef.cmd) log.info('"cmd" values have been added to the corresponding node') else: raise ValueError('The number of "cmd" values is incorrect, it must \ either equal to the number of parameters or 0') # Cms coefficients if len(Coef.cms) == 0: log.warning( 'No "cms" value have been found, this node will stay empty') elif len(Coef.cms) == param_count: cpsf.add_float_vector(tixi, apm_xpath + '/cms', Coef.cms) log.info('"cms" values have been added to the corresponding node') else: raise ValueError('The number of "cms" values is incorrect, it must \ either equal to the number of parameters or 0') # DampingDerivative if len(Coef.damping_derivatives.dcldpstar): # TODO: Improve this check cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcldpstar', Coef.damping_derivatives.dcldpstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcddpstar', Coef.damping_derivatives.dcddpstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcsdpstar', Coef.damping_derivatives.dcsdpstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmldpstar', Coef.damping_derivatives.dcmldpstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmddpstar', Coef.damping_derivatives.dcmddpstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmsdpstar', Coef.damping_derivatives.dcmsdpstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcldqstar', Coef.damping_derivatives.dcldqstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcddqstar', Coef.damping_derivatives.dcddqstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcsdqstar', Coef.damping_derivatives.dcsdqstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmldqstar', Coef.damping_derivatives.dcmldqstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmddqstar', Coef.damping_derivatives.dcmddqstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmsdqstar', Coef.damping_derivatives.dcmsdqstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcldrstar', Coef.damping_derivatives.dcldrstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcddrstar', Coef.damping_derivatives.dcddrstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcsdrstar', Coef.damping_derivatives.dcsdrstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmldrstar', Coef.damping_derivatives.dcmldrstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmddrstar', Coef.damping_derivatives.dcmddrstar) cpsf.add_float_vector( tixi, apm_xpath + '/dampingDerivatives/positiveRates/dcmsdrstar', Coef.damping_derivatives.dcmsdrstar)
def static_stability_analysis(cpacs_path, cpacs_out_path): """Function to analyse a full Aeromap Function 'static_stability_analysis' analyses longitudinal static static stability and directionnal static. Args: cpacs_path (str): Path to CPACS file cpacs_out_path (str):Path to CPACS output file plot (boolean): Choise to plot graph or not Returns: * Adrvertisements certifying if the aircraft is stable or Not * In case of longitudinal static UNstability or unvalid test on data: - Plot cms VS aoa for constant Alt, Mach and different aos - Plot cms VS aoa for const alt and aos=0 and different mach - plot cms VS aoa for constant mach, aos=0 and different altitudes * In case of directionnal static UNstability or unvalid test on data: - Pcot cml VS aos for constant Alt, Mach and different aoa - Plot cml VS aos for const alt and aoa and different mach - plot cml VS aos for constant mach, AOA and different altitudes * Plot one graph of cruising angles of attack for different mach and altitudes Make the following tests: (To put in the documentation) * Check the CPACS path * For longitudinal static stability analysis: - If there is more than one angle of attack for a given altitude, mach, aos - If cml values are only zeros for a given altitude, mach, aos - If there one aoa value which is repeated for a given altitude, mach, aos * For directionnal static stability analysis: - If there is more than one angle of sideslip for a given altitude, mach, aoa - If cms values are only zeros for a given altitude, mach, aoa - If there one aos value which is repeated for a given altitude, mach, aoa """ # TODO: add as CPACS option plot_for_different_mach = False # To check Mach influence plot_for_different_alt = False # To check Altitude influence tixi = cpsf.open_tixi(cpacs_path) # Get aeromap uid aeromap_uid = cpsf.get_value(tixi, STATIC_ANALYSIS_XPATH + '/aeroMapUid') log.info('The following aeroMap will be analysed: ' + aeromap_uid) show_plots = cpsf.get_value_or_default( tixi, STATIC_ANALYSIS_XPATH + '/showPlots', False) save_plots = cpsf.get_value_or_default( tixi, STATIC_ANALYSIS_XPATH + '/savePlots', False) # Aircraft mass configuration selected_mass_config_xpath = STATIC_ANALYSIS_XPATH + '/massConfiguration' mass_config = cpsf.get_value(tixi, selected_mass_config_xpath) # TODO: use get value or default instead and deal with not mass config log.info('The aircraft mass configuration used for analysis is: ' + mass_config) model_xpath = '/cpacs/vehicles/aircraft/model' masses_location_xpath = model_xpath + '/analyses/massBreakdown/designMasses' mass_config_xpath = masses_location_xpath + '/' + mass_config if tixi.checkElement(mass_config_xpath): mass_xpath = mass_config_xpath + '/mass' m = cpsf.get_value(tixi, mass_xpath) # aircraft mass [Kg] else: raise ValueError( ' !!! The mass configuration : {} is not defined in the CPACS file !!!' .format(mass_config)) # Wing plane AREA. ref_area_xpath = model_xpath + '/reference/area' s = cpsf.get_value( tixi, ref_area_xpath ) # Wing area : s for non-dimonsionalisation of aero data. Coeffs = apmf.get_aeromap(tixi, aeromap_uid) Coeffs.print_coef_list() alt_list = Coeffs.alt mach_list = Coeffs.mach aoa_list = Coeffs.aoa aos_list = Coeffs.aos cl_list = Coeffs.cl cd_list = Coeffs.cd cml_list = Coeffs.cml cms_list = Coeffs.cms cmd_list = Coeffs.cmd alt_unic = get_unic(alt_list) mach_unic = get_unic(mach_list) aos_unic = get_unic(aos_list) aoa_unic = get_unic(aoa_list) # TODO: get incremental map from CPACS # Incremental map elevator incrementalMap = False # if increment map available # aeromap_xpath = tixi.uIDGetXPath(aeromap_uid) # dcms_xpath = aeromap_xpath + '/aeroPerformanceMap/incrementMaps/incrementMap' + ' ....to complete' # TODO from incremental map # dcms_list = [0.52649,0.53744,0.54827,0.55898,0.56955,0.58001,0.59033,0.6005,0.61053,0.62043,0.63018,0.63979,0.64926,0.65859,0.66777,0.67684,0.53495,0.54603,0.55699,0.56783,0.57854,0.58912,0.59957,0.60986,0.62002,0.63004,0.63991,0.64964,0.65923,0.66867,0.67798,0.68717,0.55,0.56131,0.5725,0.58357,0.59451,0.60531,0.61598,0.62649,0.63687,0.64709,0.65718,0.66712,0.67691,0.68658,0.69609,0.70548,0.57333,0.585,0.59655,0.60796,0.61925,0.63038,0.64138,0.65224,0.66294,0.67349,0.68389,0.69415,0.70427,0.71424,0.72408,0.7338,0.60814,0.62033,0.63239,0.6443,0.65607,0.6677,0.67918,0.6905,0.70168,0.7127,0.72357,0.7343,0.74488,0.75532,0.76563,0.77581,0.66057,0.6735,0.68628,0.69891,0.71139,0.72371,0.73588,0.74789,0.75974,0.77144,0.78298,0.79438,0.80562,0.81673,0.82772,0.83858,\ # 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\ # -0.61653,-0.61254,-0.60842,-0.60419,-0.59988,-0.59549,-0.59105,-0.58658,-0.5821,-0.57762,-0.57318,-0.56879,-0.56447,-0.56025,-0.55616,-0.55221,-0.62605,-0.62194,-0.6177,-0.61336,-0.60894,-0.60444,-0.59988,-0.59531,-0.59072,-0.58614,-0.58159,-0.57711,-0.5727,-0.56841,-0.56423,-0.5602,-0.64293,-0.63862,-0.63418,-0.62963,-0.62499,-0.62029,-0.61554,-0.61076,-0.60598,-0.60123,-0.5965,-0.59185,-0.58728,-0.58282,-0.5785,-0.57433,-0.66906,-0.6644,-0.65963,-0.65475,-0.64978,-0.64476,-0.63971,-0.63461,-0.62954,-0.62449,-0.61949,-0.61456,-0.60973,-0.60503,-0.60048,-0.59609,-0.70787,-0.70268,-0.69739,-0.692,-0.68653,-0.68101,-0.67546,-0.66991,-0.66437,-0.65888,-0.65344,-0.6481,-0.64289,-0.63781,-0.6329,-0.62819,-0.76596,-0.75994,-0.75382,-0.74762,-0.74135,-0.73505,-0.72874,-0.72243,-0.71617,-0.70997,-0.70387,-0.69788,-0.69205,-0.68639,-0.68094,-0.67573] # dcms are given for a relative deflection of [-1,0,1] of the # # TODO get from CPACS # elevator_deflection = 15 # Gather trim aoa conditions trim_alt_longi_list = [] trim_mach_longi_list = [] trim_aoa_longi_list = [] trim_aos_longi_list = [] trim_legend_longi_list = [] trim_derivative_longi_list = [] # Gather trim aos_list for different Alt & mach , for aoa = 0 trim_alt_lat_list = [] trim_mach_lat_list = [] trim_aoa_lat_list = [] trim_aos_lat_list = [] trim_legend_lat_list = [] trim_derivative_lat_list = [] # Gather trim aos_list for different Alt & mach , for aoa = 0 trim_alt_direc_list = [] trim_mach_direc_list = [] trim_aoa_direc_list = [] trim_aos_direc_list = [] trim_legend_direc_list = [] trim_derivative_direc_list = [] # To store in cpacs result longi_unstable_cases = [] lat_unstable_cases = [] direc_unstable_cases = [] cpacs_stability_longi = 'True' cpacs_stability_lat = 'True' cpacs_stability_direc = 'True' # Aero analyses for all given altitude, mach and aos_list, over different for alt in alt_unic: Atm = get_atmosphere(alt) g = Atm.grav a = Atm.sos rho = Atm.dens # Find index of altitude which have the same value idx_alt = [i for i in range(len(alt_list)) if alt_list[i] == alt] # Prepar trim condition lists trim_alt_longi = [] trim_mach_longi = [] trim_aoa_longi = [] trim_aos_longi = [] trim_legend_longi = [] trim_derivative_longi = [] # Prepar trim condition lists trim_alt_lat = [] trim_mach_lat = [] trim_aoa_lat = [] trim_aos_lat = [] trim_legend_lat = [] trim_derivative_lat = [] # Prepar trim condition lists trim_alt_direc = [] trim_mach_direc = [] trim_aoa_direc = [] trim_aos_direc = [] trim_legend_direc = [] trim_derivative_direc = [] for mach in mach_unic: u0 = a * mach # Find index of mach which have the same value idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] # Longitudinal stability # Analyse in function of the angle of attack for given, alt, mach and aos_list # Prepare variables for plots plot_cms = [] plot_aoa = [] plot_legend = [] plot_title = r'Pitch moment coefficeint $C_M$ vs $\alpha$ @ Atl = ' + str( alt) + 'm, and Mach = ' + str(mach) xlabel = r'$\alpha$ [°]' ylabel = r'$C_M$ [-]' # Init for determining if it's an unstable case longitudinaly_stable = True # by default, cms don't cross 0 line crossed = False # Find index at which aos= 0 idx_aos = [j for j in range(len(aos_list)) if aos_list[j] == 0] find_idx = get_index(idx_alt, idx_mach, idx_aos) # If find_idx is empty an APM function would have corrected before # If there there is only one value in find_idx for a given Alt, Mach, aos_list, no analyse can be performed if len(find_idx) == 1: log.info('Longitudinal : only one data, one aoa(' +str(aoa_list[find_idx[0]]) \ + '), for Altitude = '+ str(alt) + '[m] , Mach = ' \ + str(mach) + ' and aos = 0 , no stability analyse will be performed' ) cpacs_stability_longi = 'NotCalculated' elif len(find_idx ) > 1: # if there is at least 2 values in find_idx : # Find all cms_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cms = [] aoa = [] cl = [] cd = [] for index in find_idx: cms.append(cms_list[index]) aoa.append(aoa_list[index]) cl.append(cl_list[index]) cd.append(cd_list[index]) # Save values which will be plot plot_cms.append(cms) plot_aoa.append(aoa) curve_legend = r'$\beta$ = 0°' plot_legend.append(curve_legend) # If all aoa values are the same while the calculating the derivative, a division by zero will be prevented. aoa_good = True for jj in range(len(aoa) - 1): if aoa[jj] == aoa[jj + 1]: aoa_good = False log.error( 'Alt = {} , at least 2 aoa values are equal in aoa list: {} at Mach= {}, aos = 0' .format(alt, aoa, mach)) break if aoa_good: # Required lift for level flight cl_required = (m * g) / (0.5 * rho * u0**2 * s) (trim_aoa, idx_trim_before, idx_trim_after, ratio) = trim_condition(alt, mach, cl_required, cl, aoa) if trim_aoa: trim_cms = interpolation(cms, idx_trim_before, idx_trim_after, ratio) pitch_moment_derivative_deg = ( cms[idx_trim_after] - cms[idx_trim_before]) / ( aoa[idx_trim_after] - aoa[idx_trim_before]) # Find incremental cms if incrementalMap: for index, mach_number in enumerate(mach_unic, 0): if mach_number == mach: mach_index = index dcms_before = dcms_list[mach_index * len(aoa_unic) + idx_trim_before] dcms_after = dcms_list[mach_index * len(aoa_unic) + idx_trim_after] dcms = dcms_before + ratio * (dcms_after - dcms_before) trim_elevator_relative_deflection = -trim_cms / dcms trim_elevator = trim_elevator_relative_deflection * elevator_deflection # Trim elevator deflection in [°] else: dcms = None trim_elevator = None else: trim_cms = None pitch_moment_derivative_deg = None dcms = None trim_elevator = None fig = plt.figure(figsize=(9, 3)) plot_title___ = r'$C_L$ and $C_m$ vs $\alpha$ at Mach = {}'.format( mach) plt.title(plot_title___, fontdict=None, loc='center', pad=None) plt.plot(aoa, cl, marker='o', markersize=4, linewidth=1) plt.plot(aoa, cms, marker='+', markerfacecolor='orange', markersize=12) plt.plot([aoa[0], aoa[-1]], [cl_required, cl_required], markerfacecolor='red', markersize=12) plt.legend([r'$C_L$', r'$C_M$', r'$C_{Lrequired}$']) ax = plt.gca() ax.annotate(r'$\alpha$ [°]', xy=(1, 0), ha='right', va='top', xycoords='axes fraction', fontsize=12) # ax.annotate('Coefficient', xy=(0,1), ha='left', va='center', xycoords='axes fraction', fontsize=12) plt.grid(True) if show_plots: plt.show() # Conclusion about stability, if the cms curve has crossed the 0 line and there is not 2 repeated aoa for the same alt, mach and aos. # if idx_trim_before != idx_trim_after allow to know if the cm curve crosses the 0 line. ' if idx_trim_before != idx_trim_after and aoa_good: if pitch_moment_derivative_deg < 0: log.info('Vehicle longitudinaly staticaly stable.') trim_alt_longi.append(alt) trim_mach_longi.append(mach) trim_aoa_longi.append(trim_aoa) trim_aos_longi.append(0) trim_derivative_longi.append( pitch_moment_derivative_deg) elif pitch_moment_derivative_deg == 0: longitudinaly_stable = False log.error( 'Alt = ' + str(alt) + 'Vehicle longitudinaly staticaly neutral stable.') else: #pitch_moment_derivative_deg > 0 longitudinaly_stable = False log.error( 'Alt = ' + str(alt) + 'Vehicle *NOT* longitudinaly staticaly stable.') # If not stable store the set [alt, mach, aos] at which the aircraft is unstable. if not longitudinaly_stable: longi_unstable_cases.append([alt, mach, 0]) # To write in the output CPACS that the aircraft is not longitudinaly stable cpacs_stability_longi = 'False' #PLot cms VS aoa for constant Alt, Mach and different aos if plot_cms: plot_multicurve(plot_cms, plot_aoa, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ## LATERAL plot_cmd = [] plot_aos = [] plot_legend = [] plot_title = r'Roll moment coefficient $C_L$ vs $\beta$ @ Atl = ' + str( alt) + 'm, and Mach = ' + str(mach) xlabel = r'$\beta$ [°]' ylabel = r'$C_L$ [-]' # Init for determinig if it is an unstability case laterally_stable = True # Find INDEX for aoa in aoa_unic: # by default, don't cross 0 line crossed = False idx_aoa = [ j for j in range(len(aoa_list)) if aoa_list[j] == aoa ] find_idx = get_index(idx_alt, idx_mach, idx_aoa) # If find_idx is empty an APM function would have corrected before # If there there is only one value in find_idx for a given Alt, Mach, aos_list, no analyse can be performed if len(find_idx) == 1: log.info('Laterral-Directional : only one data, one aos (' + str(aos_list[find_idx[0]]) \ +'), for Altitude = '+str(alt)+'[m], Mach = ' \ + str(mach) + ' and aoa = ' + str(aoa) \ + ' no stability analyse performed') cpacs_stability_lat = 'NotCalculated' elif len(find_idx ) > 1: #if there is at least 2 values in find_idx cmd = [] aos = [] for index in find_idx: cmd.append( -cmd_list[index] ) # menus sign because cmd sign convention on ceasiom is the oposite as books convention aos.append(aos_list[index]) aos, cmd = order_correctly( aos, cmd) # To roder the lists with values for growing aos # If cmd Curve crosses th 0 line more than once na stability analysis can be performed curve_legend = r'$\alpha$ = ' + str(aoa) + r' °' # Save values which will be plotted plot_cmd.append(cmd) plot_aos.append(aos) plot_legend.append(curve_legend) aos_good = True for jj in range(len(aos) - 1): if aos[jj] == aos[jj + 1]: aos_good = False log.error( 'Alt = {} , at least 2 aos values are equal in aos list: {} , Mach= {}, aos = {}' .format(alt, aoa, mach, aos)) break if aos_good: cruise_aos, roll_moment_derivative, idx_trim_before, idx_trim_after, ratio = trim_derivative( alt, mach, cmd, aos) if idx_trim_before != idx_trim_after and aos_good: if roll_moment_derivative < 0: log.info('Vehicle laterally staticaly stable.') if aoa == 0: trim_alt_lat.append(alt) trim_mach_lat.append(mach) trim_aoa_lat.append(cruise_aos) trim_aos_lat.append(aoa) trim_derivative_lat.append( roll_moment_derivative) if roll_moment_derivative == 0: laterally_stable = False log.error( 'At alt = ' + str(alt) + 'Vehicle laterally staticaly neutral stable.') if roll_moment_derivative > 0: laterally_stable = False log.error( 'Alt = ' + str(alt) + 'Vehicle *NOT* laterally staticaly stable.') # If not stable store the set [alt, mach, aos] at which the aircraft is unstable. if not laterally_stable: lat_unstable_cases.append([alt, mach, aoa]) # To write in the output CPACS that the aircraft is not longitudinaly stable cpacs_stability_lat = 'False' #PLot cmd VS aos for constant alt, mach and different aoa if not stable if plot_cmd: plot_multicurve(plot_cmd, plot_aos, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ## Directional plot_cml = [] plot_aos = [] plot_legend = [] plot_title = r'Yaw moment coefficient $C_N$ vs $\beta$ @ Atl = ' + str( alt) + 'm, and Mach = ' + str(mach) xlabel = r'$\beta$ [°]' ylabel = r'$C_N$ [-]' # Init for determinig if it is an unstability case dirrectionaly_stable = True # Find INDEX for aoa in aoa_unic: # by default, don't cross 0 line crossed = False idx_aoa = [ j for j in range(len(aoa_list)) if aoa_list[j] == aoa ] find_idx = get_index(idx_alt, idx_mach, idx_aoa) # If find_idx is empty an APM function would have corrected before # If there there is only one value in find_idx for a given Alt, Mach, aos_list, no analyse can be performed if len(find_idx) == 1: log.info('Laterral-Directional : only one data, one aos (' + str(aos_list[find_idx[0]]) \ +'), for Altitude = '+str(alt)+'[m], Mach = ' \ + str(mach) + ' and aoa = ' + str(aoa) \ + ' no stability analyse performed') cpacs_stability_direc = 'NotCalculated' elif len(find_idx ) > 1: #if there is at least 2 values in find_idx cml = [] aos = [] for index in find_idx: cml.append( -cml_list[index] ) # menus sign because cml sign convention on ceasiom is the oposite as books convention aos.append(aos_list[index]) aos, cml = order_correctly( aos, cml) # To order values with growing aos # If cml Curve crosses th 0 line more than once na stability analysis can be performed curve_legend = r'$\alpha$ = ' + str(aoa) + r' °' # Save values which will be plot plot_cml.append(cml) plot_aos.append(aos) plot_legend.append(curve_legend) aos_good = True for jj in range(len(aos) - 1): if aos[jj] == aos[jj + 1]: aos_good = False log.error( 'Alt = {} , at least 2 aos values are equal in aos list: {} , Mach= {}, aos = {}' .format(alt, aoa, mach, aos)) break if aos_good: cruise_aos, side_moment_derivative, idx_trim_before, idx_trim_after, ratio = trim_derivative( alt, mach, cml, aos) if idx_trim_before != idx_trim_after and aos_good: if side_moment_derivative > 0: log.info('Vehicle directionnaly staticaly stable.') if aoa == 0: trim_alt_direc.append(alt) trim_mach_direc.append(mach) trim_aoa_direc.append(cruise_aos) trim_aos_direc.append(aoa) trim_derivative_direc.append( side_moment_derivative) if side_moment_derivative == 0: dirrectionaly_stable = False log.error( 'At alt = ' + str(alt) + 'Vehicle directionnaly staticaly neutral stable.' ) if side_moment_derivative < 0: dirrectionaly_stable = False log.error( 'Alt = ' + str(alt) + 'Vehicle *NOT* directionnaly staticaly stable.' ) # If not stable store the set [alt, mach, aos] at which the aircraft is unstable. if not dirrectionaly_stable: direc_unstable_cases.append([alt, mach, aoa]) # To write in the output CPACS that the aircraft is not longitudinaly stable cpacs_stability_direc = 'False' # PLot cml VS aos for constant alt, mach and different aoa if not stable if plot_cml: plot_multicurve(plot_cml, plot_aos, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) # Add trim conditions for the given altitude (longi analysis) if trim_aoa_longi: trim_aoa_longi_list.append(trim_aoa_longi) trim_mach_longi_list.append(trim_mach_longi) trim_legend_longi_list.append('Altitude = ' + str(alt) + '[m]') trim_alt_longi_list.append(trim_alt_longi) trim_aos_longi_list.append(trim_aos_longi) trim_derivative_longi_list.append(trim_derivative_longi) if trim_aos_lat: trim_aos_lat_list.append(trim_aos_lat) trim_mach_lat_list.append(trim_mach_lat) trim_legend_lat_list.append('Alt = ' + str(alt) + '[m]') trim_alt_lat_list.append(trim_alt_lat) trim_aoa_lat_list.append(trim_aoa_lat) trim_derivative_lat_list.append(trim_derivative_lat) # Add trim conditions for the given altitude (direcanalysis) if trim_aos_direc: trim_aos_direc_list.append(trim_aos_direc) trim_mach_direc_list.append(trim_mach_direc) trim_legend_direc_list.append('Alt = ' + str(alt) + '[m]') trim_alt_direc_list.append(trim_alt_direc) trim_aoa_direc_list.append(trim_aoa_direc) trim_derivative_direc_list.append(trim_derivative_direc) # MACH PLOTS if plot_for_different_mach: # To check Altitude Mach ## LONGI # Plot cms vs aoa for const alt and aos = 0 and different mach idx_aos = [k for k in range(len(aos_list)) if aos_list[k] == 0] plot_cms = [] plot_aoa = [] plot_legend = [] plot_title = r'Pitch moment coefficient $C_M$ vs $\alpha$ @ Atl = ' + str( alt) + r'm, and $\beta$ = 0 °' xlabel = r'$\alpha$ [°]' ylabel = r'$C_M$ [-]' # Init for determinig if it is an unstability case longitudinaly_stable = True for mach in mach_unic: idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] find_idx = get_index(idx_alt, idx_aos, idx_mach) # If there is only one value in Find_idx # An error message has been already printed through the first part of the code # Check if it is an unstability case detected previously for combination in longi_unstable_cases: if combination[0] == alt and combination[ 1] == mach and combination[2] == aos: longitudinaly_stable = False # If there is at list 2 values in find_idx : if len(find_idx) > 1: # Find all cms_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cms = [] aoa = [] for index in find_idx: cms.append(cms_list[index]) aoa.append(aoa_list[index]) # Save values which will be plot plot_cms.append(cms) plot_aoa.append(aoa) curve_legend = 'Mach = ' + str(mach) plot_legend.append(curve_legend) #PLot cms VS aoa for constant Alt, aoa and different mach if plot_cms: plot_multicurve(plot_cms, plot_aoa, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ## LATERAL # Plot cmd vs aos for const alt and aoa and different mach for aoa in aoa_unic: idx_aoa = [ k for k in range(len(aoa_list)) if aoa_list[k] == aoa ] plot_cmd = [] plot_aos = [] plot_legend = [] plot_title = r'Roll moment coefficiel $C_L$ vs $\beta$ @ Atl = ' + str( alt) + r'm, and $\alpha$= ' + str(aoa) + r' °' xlabel = r'$\beta$ [°]' ylabel = r'$C_L$ [-]' # Init for determinig if it is an unstability case laterally_stable = True for mach in mach_unic: idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] find_idx = get_index(idx_alt, idx_aoa, idx_mach) #If there is only one valur in find_idx # An error message has been already printed through the first part of the code # Check if it is an unstability case detected previously for combination in lat_unstable_cases: if combination[0] == alt and combination[ 1] == mach and combination[2] == aoa: laterally_stable = False # If there is at list 2 values in find_idx : if len(find_idx) > 1: # Find all cmd_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cmd = [] aos = [] for index in find_idx: cmd.append(-cmd_list[index]) aos.append(aos_list[index]) aos, cmd = order_correctly( aos, cmd) # To order values with growing aos # Save values which will be plot plot_cmd.append(cmd) plot_aos.append(aos) curve_legend = 'Mach = ' + str(mach) plot_legend.append(curve_legend) if plot_cmd: # Plot cmd VS aos for constant Alt, aoa and different mach plot_multicurve(plot_cmd, plot_aos, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ## Directional # Plot cml vs aos for const alt and aoa and different mach for aoa in aoa_unic: idx_aoa = [ k for k in range(len(aoa_list)) if aoa_list[k] == aoa ] plot_cml = [] plot_aos = [] plot_legend = [] plot_title = r'Yaw moment coefficiel $C_N$ vs $\beta$ @ Atl = ' + str( alt) + r'm, and $\alpha$= ' + str(aoa) + r' °' xlabel = r'$\beta$ [°]' ylabel = r'$C_N$ [-]' # Init for determinig if it is an unstability case dirrectionaly_stable = True for mach in mach_unic: idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] find_idx = get_index(idx_alt, idx_aoa, idx_mach) #If there is only one valur in find_idx # An error message has been already printed through the first part of the code # Check if it is an unstability case detected previously for combination in direc_unstable_cases: if combination[0] == alt and combination[ 1] == mach and combination[2] == aoa: dirrectionaly_stable = False # If there is at list 2 values in find_idx : if len(find_idx) > 1: # Find all cml_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cml = [] aos = [] for index in find_idx: cml.append(-cml_list[index]) aos.append(aos_list[index]) aos, cml = order_correctly( aos, cml) # To order values with growing aos # Save values which will be plot plot_cml.append(cml) plot_aos.append(aos) curve_legend = 'Mach = ' + str(mach) plot_legend.append(curve_legend) if plot_cml: # Plot cml VS aos for constant Alt, aoa and different mach plot_multicurve(plot_cml, plot_aos, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ############ MACH PLOTS END ########## # TRIM CONDITIONS PLOTS # Plot trim_aoa VS mach for different alt # If there is at least 1 element in list of trim conditions then, plot them if trim_derivative_longi_list: log.info('graph : trim aoa vs mach genrated') plot_multicurve(trim_aoa_longi_list, trim_mach_longi_list, trim_legend_longi_list, r'$\alpha_{trim}$ vs Mach', 'Mach', r'$\alpha_{trim}$ [°]', show_plots, save_plots) log.info('graph : pitch moment derivative at trim vs mach genrated') plot_multicurve(trim_derivative_longi_list, trim_mach_longi_list, trim_legend_longi_list, r'$C_{M_{\alpha trim}}$ vs Mach', 'Mach', r'$C_{M_{\alpha trim}}$ [1/°]', show_plots, save_plots) if trim_derivative_lat_list: log.info('graph : roll moment derivative at trim vs mach genrated') plot_multicurve(trim_derivative_lat_list, trim_mach_lat_list, trim_legend_lat_list, r'$C_{L_{\beta trim}}$vs Mach', 'Mach', r'$C_{L_{\beta trim}}$ [1/°]', show_plots, save_plots) if trim_derivative_direc_list: log.info('graph : yaw moment at trim vs mach genrated') plot_multicurve(trim_derivative_direc_list, trim_mach_direc_list, trim_legend_direc_list, r'$C_{N_{\beta trim}}$ vs Mach', 'Mach', r'$C_{N_{\beta trim}}$ [1/°]', show_plots, save_plots) # ALTITUDE PLOTS if plot_for_different_alt: # To check Altitude Influence # plot cms VS aoa for constant mach, aos= 0 and different altitudes: # Find index of altitude which have the same value idx_aos = [i for i in range(len(aos_list)) if aos_list[i] == 0] for mach in mach_unic: # Find index of mach which have the same value idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] # Prepare variables for plots plot_cms = [] plot_aoa = [] plot_legend = [] plot_title = r'Pitch moment coefficient $C_M$ vs $\alpha$ @ Mach = ' + str( mach) + r' and $\beta$ = 0°' xlabel = r'$\alpha$ [°]' ylabel = r'$C_M$ [-]' longitudinaly_stable = True # Find index of slip angle which have the same value for alt in alt_unic: idx_alt = [ j for j in range(len(alt_list)) if alt_list[j] == alt ] find_idx = get_index(idx_aos, idx_mach, idx_alt) # If find_idx is empty an APM function would have corrected before # If there is only one value in find_idx for a given Alt, Mach, aos_list, no analyse can be performed # An error message has been already printed through the first part of the code # Check if it is an unstability case detected previously for combination in longi_unstable_cases: if combination[0] == alt and combination[ 1] == mach and combination[2] == aos: longitudinaly_stable = False # If there is at list 2 values in find_idx : if len(find_idx) > 1: # Find all cms_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cms = [] aoa = [] for index in find_idx: cms.append(cms_list[index]) aoa.append(aoa_list[index]) # Save values which will be plot plot_cms.append(cms) plot_aoa.append(aoa) curve_legend = 'Altitude = ' + str(alt) + ' m' plot_legend.append(curve_legend) if plot_cms: # PLot cms VS aoa for constant Mach, aos and different Alt plot_multicurve(plot_cms, plot_aoa, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ## Lateral # plot cmd VS aos for constant mach, aoa_list and different altitudes: for aoa in aoa_unic: # Find index of altitude which have the same value idx_aoa = [i for i in range(len(aoa_list)) if aoa_list[i] == aoa] for mach in mach_unic: # Find index of mach which have the same value idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] # Prepare variables for plots plot_cmd = [] plot_aos = [] plot_legend = [] plot_title = r'Roll moment coefficient $C_L$ vs $\beta$ @ Mach = ' + str( mach) + r' and $\alpha$= ' + str(aoa) + r' °' xlabel = r'$\beta$ [°]' ylabel = r'$C_L$ [-]' laterally_stable = True # Find index of slip angle which have the same value for alt in alt_unic: idx_alt = [ j for j in range(len(alt_list)) if alt_list[j] == alt ] find_idx = get_index(idx_aoa, idx_mach, idx_alt) # If find_idx is empty an APM function would have corrected before # If there there is only one value in find_idx for a given Alt, Mach, aos_list, no analyse can be performed # An error message has been already printed through the first part of the code # Check if it is an unstability case detected previously for combination in lat_unstable_cases: if combination[0] == alt and combination[ 1] == mach and combination[2] == aoa: laterally_stable = False # If there is at list 2 values in find_idx : if len(find_idx) > 1: # Find all cmd_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cmd = [] aos = [] for index in find_idx: cmd.append(-cmd_list[index]) aos.append(aos_list[index]) # Save values which will be plot plot_cmd.append(cmd) plot_aos.append(aos) curve_legend = 'Altitude = ' + str(alt) + ' m' plot_legend.append(curve_legend) if plot_cmd: # PLot cmd VS aos for constant Mach, aoa and different alt plot_multicurve(plot_cmd, plot_aos, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) ## DIRECTIONAL # plot cml VS aos for constant mach, aoa_list and different altitudes: for aoa in aoa_unic: # Find index of altitude which have the same value idx_aoa = [i for i in range(len(aoa_list)) if aoa_list[i] == aoa] for mach in mach_unic: # Find index of mach which have the same value idx_mach = [ j for j in range(len(mach_list)) if mach_list[j] == mach ] # Prepare variables for plots plot_cml = [] plot_aos = [] plot_legend = [] plot_title = r'Yaw moment coefficient $C_N$ vs $\beta$ @ Mach = ' + str( mach) + r' and $\alpha$= ' + str(aoa) + r' °' xlabel = r'$\beta$ [°]' ylabel = r'$C_N$ [-]' dirrectionaly_stable = True # Find index of slip angle which have the same value for alt in alt_unic: idx_alt = [ j for j in range(len(alt_list)) if alt_list[j] == alt ] find_idx = get_index(idx_aoa, idx_mach, idx_alt) # Check if it is an unstability case detected previously for combination in direc_unstable_cases: if combination[0] == alt and combination[ 1] == mach and combination[2] == aoa: dirrectionaly_stable = False # If there is at list 2 values in find_idx : if len(find_idx) > 1: # Find all cml_list values for index corresonding to an altitude, a mach, an aos_list=0, and different aoa_list cml = [] aos = [] for index in find_idx: cml.append(-cml_list[index]) aos.append(aos_list[index]) # Save values which will be plot plot_cml.append(cml) plot_aos.append(aos) curve_legend = 'Altitude = ' + str(alt) + ' m' plot_legend.append(curve_legend) if plot_cml: # PLot cml VS aos for constant Mach, aoa and different alt plot_multicurve(plot_cml, plot_aos, plot_legend, plot_title, xlabel, ylabel, show_plots, save_plots) # Save in the CPACS file stability results: trim_alt_longi_list = extract_subelements(trim_alt_longi_list) trim_mach_longi_list = extract_subelements(trim_mach_longi_list) trim_aoa_longi_list = extract_subelements(trim_aoa_longi_list) trim_aos_longi_list = extract_subelements(trim_aos_longi_list) trim_derivative_longi_list = extract_subelements( trim_derivative_longi_list) trim_alt_lat_list = extract_subelements(trim_alt_lat_list) trim_mach_lat_list = extract_subelements(trim_mach_lat_list) trim_aoa_lat_list = extract_subelements(trim_aoa_lat_list) trim_aos_lat_list = extract_subelements(trim_aos_lat_list) trim_derivative_lat_list = extract_subelements(trim_derivative_lat_list) trim_alt_direc_list = extract_subelements(trim_alt_direc_list) trim_mach_direc_list = extract_subelements(trim_mach_direc_list) trim_aoa_direc_list = extract_subelements(trim_aoa_direc_list) trim_aos_direc_list = extract_subelements(trim_aos_direc_list) trim_derivative_direc_list = extract_subelements( trim_derivative_direc_list) # xpath definition # TODO: add uid of the coresponding aeropm for results longi_xpath = STATIC_ANALYSIS_XPATH + '/results/longitudinalStaticStable' lat_xpath = STATIC_ANALYSIS_XPATH + '/results/lateralStaticStable' direc_xpath = STATIC_ANALYSIS_XPATH + '/results/directionnalStaticStable' longi_trim_xpath = STATIC_ANALYSIS_XPATH + '/trimConditions/longitudinal' lat_trim_xpath = STATIC_ANALYSIS_XPATH + '/trimConditions/lateral' direc_trim_xpath = STATIC_ANALYSIS_XPATH + '/trimConditions/directional' cpsf.create_branch(tixi, longi_xpath) cpsf.create_branch(tixi, lat_xpath) cpsf.create_branch(tixi, direc_xpath) # Store in the CPACS the stability results tixi.updateTextElement(longi_xpath, str(cpacs_stability_longi)) tixi.updateTextElement(lat_xpath, str(cpacs_stability_lat)) tixi.updateTextElement(direc_xpath, str(cpacs_stability_direc)) cpsf.create_branch(tixi, longi_trim_xpath) cpsf.create_branch(tixi, lat_trim_xpath) cpsf.create_branch(tixi, direc_trim_xpath) # TODO: Normaly this "if" is not required, but the tixi function to add a vector does not support an empty vercor... if trim_alt_longi_list: cpsf.add_float_vector(tixi, longi_trim_xpath + '/altitude', trim_alt_longi_list) cpsf.add_float_vector(tixi, longi_trim_xpath + '/machNumber', trim_mach_longi_list) cpsf.add_float_vector(tixi, longi_trim_xpath + '/angleOfAttack', trim_aoa_longi_list) cpsf.add_float_vector(tixi, longi_trim_xpath + '/angleOfSideslip', trim_aos_longi_list) if trim_alt_lat_list: cpsf.add_float_vector(tixi, lat_trim_xpath + '/altitude', trim_alt_lat_list) cpsf.add_float_vector(tixi, lat_trim_xpath + '/machNumber', trim_mach_lat_list) cpsf.add_float_vector(tixi, lat_trim_xpath + '/angleOfAttack', trim_aoa_lat_list) cpsf.add_float_vector(tixi, lat_trim_xpath + '/angleOfSideslip', trim_aos_lat_list) if trim_alt_direc_list: cpsf.add_float_vector(tixi, direc_trim_xpath + '/altitude', trim_alt_direc_list) cpsf.add_float_vector(tixi, direc_trim_xpath + '/machNumber', trim_mach_direc_list) cpsf.add_float_vector(tixi, direc_trim_xpath + '/angleOfAttack', trim_aoa_direc_list) cpsf.add_float_vector(tixi, direc_trim_xpath + '/angleOfSideslip', trim_aos_direc_list) cpsf.close_tixi(tixi, cpacs_out_path)