Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
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))
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
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)