예제 #1
0
def test_layer_names():
    """Test layer names"""

    # Converter (layer boundaries are defined based on geopotential height)
    H2h = Atmosphere.geop2geom_height
    eps = 1e-6

    # Single value input
    assert Atmosphere(H2h(-3e3)).layer_name[0] == 'troposphere'
    assert Atmosphere(H2h(0)).layer_name[0] == 'troposphere'

    assert Atmosphere(H2h(11e3 + eps)).layer_name[0] == 'tropopause'
    assert Atmosphere(H2h(15e3)).layer_name[0] == 'tropopause'

    assert Atmosphere(H2h(20e3 + eps)).layer_name[0] == 'stratosphere'
    assert Atmosphere(H2h(25e3)).layer_name[0] == 'stratosphere'
    assert Atmosphere(H2h(32e3)).layer_name[0] == 'stratosphere'

    assert Atmosphere(H2h(47e3 + eps)).layer_name[0] == 'stratopause'
    assert Atmosphere(H2h(50e3)).layer_name[0] == 'stratopause'

    assert Atmosphere(H2h(51e3 + eps)).layer_name[0] == 'mesosphere'
    assert Atmosphere(H2h(75e3)).layer_name[0] == 'mesosphere'
    assert Atmosphere(H2h(80e3)).layer_name[0] == 'mesosphere'

    # Test matrix
    h = np.array([[0, 12, 22], [30, 49, 75]]) * 1e3
    expected = np.char.array([['troposphere', 'tropopause', 'stratosphere'],
                              ['stratosphere', 'stratopause', 'mesosphere']])

    computed = Atmosphere(h).layer_name
    assert np.testing.assert_array_equal(computed, expected) is None
예제 #2
0
파일: validation.py 프로젝트: Rlmuniz/toa
def validate_result(p, airplane, runway, flap_angle):
    ## Ground roll
    mu = 0.025
    g = 9.80665
    atmos = Atmosphere(runway.elevation)

    VR = p.get_val('traj.initial_run.timeseries.states:V')[-1]

    T0 = p.get_val('traj.initial_run.timeseries.thrust')[0]
    TR = p.get_val('traj.initial_run.timeseries.thrust')[-1]

    W0 = p.get_val('traj.initial_run.timeseries.states:mass')[0] * g
    WR = p.get_val('traj.initial_run.timeseries.states:mass')[-1] * g

    Sngr_opt = p.get_val('traj.initial_run.timeseries.states:x')[-1]

    CLg = p.get_val('traj.initial_run.timeseries.CLg')[-1]
    CDg = p.get_val('traj.initial_run.timeseries.CD')[-1]

    agV0 = g * (T0 / W0 - mu - runway.slope)
    agVR = g * ((TR / WR - mu) - (CDg - mu * CLg) * atmos.density[0] * VR**2 /
                (2 * WR / airplane.wing.area) - runway.slope)

    k = ((1 - agVR / agV0) / math.log(agV0 / agVR))
    agave = k * agV0

    Sngr = VR**2 / (2 * agave)

    print(
        f"Sngr: {Sngr}, Sngr_opt: {Sngr_opt}, diff: {(Sngr_opt - Sngr)/Sngr_opt * 100}"
    )

    ## Rotation
    Vlof = p.get_val('traj.rotation.timeseries.states:V')[-1]
    tr = p.get_val('traj.rotation.timeseries.time')[-1] - p.get_val(
        'traj.rotation.timeseries.time')[0]
    alpha_max = p.get_val('traj.rotation.timeseries.states:theta')[-1]
    Sr = 0.5 * (VR + Vlof) * tr
    Sr_opt = p.get_val('traj.rotation.timeseries.states:x')[-1] - Sngr_opt

    print(
        f"Sngr: {Sr}, Sngr_opt: {Sr_opt}, diff: {(Sr_opt - Sr) / Sr_opt * 100}, alpha_max: {alpha_max}, tr: {tr}"
    )
    p.get_val('traj.transition.timeseries.time')[-1] - p.get_val(
        'traj.rotation.timeseries.time')[-1]
    ## Transition
    if flap_angle == 0:
        CLmax = 1.4156
    elif flap_angle == 5:
        CLmax = 2.0581687373857513
    elif flap_angle == 10:
        CLmax = 2.1299732557370072
    else:
        CLmax = 2.2234101823709764

    vlof_vs = p.get_val('traj.transition.timeseries.V_Vstall')[0]

    deltaCL = 0.5 * (vlof_vs**2 - 1) * (CLmax * (vlof_vs**2 - 0.53) + 0.38)
    W = p.get_val('traj.rotation.timeseries.states:mass')[-1] * g
    Rtr = 2 * (W / airplane.wing.area) / (atmos.density[0] * g * deltaCL)
    T = p.get_val('traj.rotation.timeseries.thrust')[-1]
    D = p.get_val('traj.rotation.timeseries.D')[-1]
    theta = (T - D) / W

    Str = Rtr * math.sin(theta)

    htr = Str * theta / 2
    hscreen = p.get_val('traj.transition.timeseries.h_mlg', units='m')[-1]
    if htr > hscreen:
        Scl = 0
    if htr < hscreen:
        Scl = (hscreen - htr) / math.tan(theta)

    Sa = Str + Scl

    Sa_opt = p.get_val('traj.transition.timeseries.states:x')[-1] - p.get_val(
        'traj.transition.timeseries.states:x')[0]

    print(f"Sa: {Sa}, Sa_opt: {Sa_opt}, diff: {(Sa_opt - Sa) / Sa_opt * 100}")

    Sroskam = Sngr + Sr + Sa
    Sopt = p.get_val('traj.transition.timeseries.x_mlg')[-1]
    print(
        f"Sroskam: {Sroskam}, Programa: {Sopt}, diff: {(Sopt - Sroskam)/Sopt * 100}"
    )
예제 #3
0
def test_repr():
    assert repr(Atmosphere(0)) == 'Atmosphere(array([0.]))'
    assert repr(Atmosphere([1, 100, 1000
                            ])) == 'Atmosphere(array([   1.,  100., 1000.]))'
예제 #4
0
current_dir = os.path.dirname(os.path.realpath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)

from aircraft import JetStar
import numpy as np
import matplotlib.pyplot as plt
from ambiance import Atmosphere
from Interpolacao import DragPolar
from scipy.optimize import fsolve
import Cruzeiro as cr

# =============================================
jet = JetStar(1)

sealevel = Atmosphere(0)
beta = 9296
rho0 = sealevel.density[0]

drag_asc = DragPolar()
drag_asc.CLp = 0

# =============================================

def gamma(h,T0,n,W,V):
    
    T = cr.jet_buoyancy(h, T0, n)[0]
    D = cr.total_drag(V, h)[0][0]
    return (T - D)/W

def h_dot(h,T0,n,W,V):
예제 #5
0
from ambiance import Atmosphere

print("alt,pressure,temperature")
for level in range(-300, 30000, 1):
    atm = Atmosphere(level)
    print("%s,%s,%s" % (level, atm.pressure[0], atm.temperature[0]))
예제 #6
0
def test_str():

    assert str(Atmosphere(0)) == 'Atmosphere([0.0])'
    assert str(Atmosphere([1, 100,
                           1000])) == 'Atmosphere([1.0, 100.0, 1000.0])'
예제 #7
0
def air_density(Temp, h):
    '''densidade fora da ISA; Temp em Celcius'''
    P = Atmosphere(h).pressure[0]
    Temp_isa_mod = Atmosphere(h).temperature[0] + Temp - (15)
    rho = P / (R_gas * Temp_isa_mod)
    return rho
    def computeDerivedVariables(self, t, state, models):
        from models.flight import FlightModel

        from rellipsoid import earth
        from ambiance import Atmosphere

        surfaceAltitude = assumptions.launchSeaLevelAltitude.get(
        ) + models["flight"]["state"][FlightModel.states_z]
        if surfaceAltitude < 0:
            surfaceAltitude = 0
        if surfaceAltitude > 80000:
            surfaceAltitude = 80000

        atmosphere = Atmosphere(surfaceAltitude)
        pressure = atmosphere.pressure[0]
        density = atmosphere.density[0]
        speedOfSound = atmosphere.speed_of_sound[0]
        temperature = atmosphere.temperature[0]

        pressure = pressure * (assumptions.initialAtmosphericPressure.get() /
                               seaLevelPressure)
        density = density * (assumptions.initialAtmosphericPressure.get() /
                             seaLevelPressure)
        speedOfSound = speedOfSound * (
            assumptions.initialAtmosphericPressure.get() / seaLevelPressure)
        temperature = temperature * (
            assumptions.initialAtmosphericTemperature.get() /
            seaLevelTemperature)
        viscosity = atmosphere.dynamic_viscosity[0]
        thermalConductivity = atmosphere.thermal_conductivity[0]

        velocityThroughAir = np.linalg.norm([
            models["flight"]["state"][FlightModel.states_vx],
            models["flight"]["state"][FlightModel.states_vy],
            models["flight"]["state"][FlightModel.states_vz]
        ])
        dynamicPressure = 0.5 * density * velocityThroughAir * velocityThroughAir

        stagnationPressure = pressure - dynamicPressure

        airCp = CP.PropsSI('CPMASS', 'T', temperature, 'P', pressure, 'air')
        airCv = CP.PropsSI('CVMASS', 'T', temperature, 'P', pressure, 'air')
        airGamma = airCp / airCv

        mach = velocityThroughAir / speedOfSound

        # This is the adiabatic stagnation temperature on the surface of the rocket
        stagnationTemperature = temperature * (
            1 + (airGamma - 1) / 2 * mach * mach)

        launchLatitudeRadians = assumptions.launchLatitudeDegrees.get(
        ) / 180 * math.pi

        # todo for future: take into account the present latitude, not just the starting one
        verticalGravity, northwardGravity = earth.get_analytic_gravity(
            launchLatitudeRadians, surfaceAltitude)

        return [
            pressure, density, speedOfSound, verticalGravity, northwardGravity,
            viscosity, thermalConductivity, temperature, dynamicPressure,
            stagnationPressure, stagnationTemperature
        ]
예제 #9
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

from ambiance import Atmosphere

# Make an atmosphere object
heights = np.linspace(-5e3, 80e3, num=1000)
atmosphere = Atmosphere(heights)

# Make plot
plt.plot(atmosphere.temperature_in_celsius, heights / 1000)
plt.ylabel('Height [km]')
plt.xlabel('Temperature [°C]')
plt.grid()
plt.show()
예제 #10
0
def generate_su2_cfd_config(cpacs_path, cpacs_out_path, wkdir):
    """Function to create SU2 confif file.

    Function 'generate_su2_cfd_config' reads data in the CPACS file and generate
    configuration files for one or multible flight conditions (alt,mach,aoa,aos)

    Source:
        * SU2 config template: https://github.com/su2code/SU2/blob/master/config_template.cfg

    Args:
        cpacs_path (str): Path to CPACS file
        cpacs_out_path (str):Path to CPACS output file
        wkdir (str): Path to the working directory

    """

    # Get value from CPACS
    cpacs = CPACS(cpacs_path)

    # Get SU2 mesh path
    su2_mesh_path = get_value(cpacs.tixi, SU2MESH_XPATH)

    # Get SU2 settings
    max_iter_xpath = SU2_XPATH + "/settings/maxIter"
    max_iter = get_value_or_default(cpacs.tixi, max_iter_xpath, 200)
    cfl_nb_xpath = SU2_XPATH + "/settings/cflNumber"
    cfl_nb = get_value_or_default(cpacs.tixi, cfl_nb_xpath, 1.0)
    mg_level_xpath = SU2_XPATH + "/settings/multigridLevel"
    mg_level = get_value_or_default(cpacs.tixi, mg_level_xpath, 3)

    # Mesh Marker
    bc_wall_xpath = SU2_XPATH + "/boundaryConditions/wall"
    bc_farfield_xpath = SU2_XPATH + "/boundaryConditions/farfield"
    bc_wall_list, engine_bc_list = get_mesh_marker(su2_mesh_path)

    create_branch(cpacs.tixi, bc_wall_xpath)
    bc_wall_str = ";".join(bc_wall_list)
    cpacs.tixi.updateTextElement(bc_wall_xpath, bc_wall_str)

    create_branch(cpacs.tixi, bc_farfield_xpath)
    bc_farfiled_str = ";".join(engine_bc_list)
    cpacs.tixi.updateTextElement(bc_farfield_xpath, bc_farfiled_str)

    # Fixed CL parameters
    fixed_cl_xpath = SU2_XPATH + "/fixedCL"
    fixed_cl = get_value_or_default(cpacs.tixi, fixed_cl_xpath, "NO")
    target_cl_xpath = SU2_XPATH + "/targetCL"
    target_cl = get_value_or_default(cpacs.tixi, target_cl_xpath, 1.0)

    if fixed_cl == "NO":
        active_aeroMap_xpath = SU2_XPATH + "/aeroMapUID"
        aeromap_uid = get_value(cpacs.tixi, active_aeroMap_xpath)

        log.info(
            f'Configuration file for "{aeromap_uid}" calculation will be created.'
        )

        active_aeromap = cpacs.get_aeromap_by_uid(aeromap_uid)

        # Get parameters of the aeroMap (altitude, machNumber, angleOfAttack, angleOfSideslip)
        alt_list = active_aeromap.get("altitude").tolist()
        mach_list = active_aeromap.get("machNumber").tolist()
        aoa_list = active_aeromap.get("angleOfAttack").tolist()
        aos_list = active_aeromap.get("angleOfSideslip").tolist()

        param_count = len(alt_list)

    else:  # if fixed_cl == 'YES':
        log.info(
            "Configuration file for fixed CL calculation will be created.")

        # Parameters fixed CL calulation
        param_count = 1

        # Create a new aeroMap
        fix_cl_aeromap = cpacs.create_aeromap("aeroMap_fixedCL_SU2")
        fix_cl_aeromap.description = "AeroMap created for SU2 fixed CL value of: " + str(
            target_cl)

        # Get cruise mach and altitude
        cruise_mach_xpath = RANGE_XPATH + "/cruiseMach"
        mach = get_value_or_default(cpacs.tixi, cruise_mach_xpath, 0.78)
        cruise_alt_xpath = RANGE_XPATH + "/cruiseAltitude"
        alt = get_value_or_default(cpacs.tixi, cruise_alt_xpath, 12000)

        # Add new parameters to the aeroMap and save it
        fix_cl_aeromap.add_row(alt=alt, mach=mach, aos=0.0, aoa=0.0)
        fix_cl_aeromap.save()

        # Parameter lists
        alt_list = [alt]
        mach_list = [mach]
        aoa_list = [0.0]
        aos_list = [0.0]

    # Get and modify the default configuration file
    cfg = ConfigFile(DEFAULT_CONFIG_PATH)

    # General parmeters
    cfg["REF_LENGTH"] = cpacs.aircraft.ref_lenght
    cfg["REF_AREA"] = cpacs.aircraft.ref_area
    cfg["REF_ORIGIN_MOMENT_X"] = cpacs.aircraft.ref_point_x
    cfg["REF_ORIGIN_MOMENT_Y"] = cpacs.aircraft.ref_point_y
    cfg["REF_ORIGIN_MOMENT_Z"] = cpacs.aircraft.ref_point_z

    # Settings
    cfg["INNER_ITER"] = int(max_iter)
    cfg["CFL_NUMBER"] = cfl_nb
    cfg["MGLEVEL"] = int(mg_level)

    # Fixed CL mode (AOA will not be taken into account)
    cfg["FIXED_CL_MODE"] = fixed_cl
    cfg["TARGET_CL"] = target_cl
    cfg["DCL_DALPHA"] = "0.1"
    cfg["UPDATE_AOA_ITER_LIMIT"] = "50"
    cfg["ITER_DCL_DALPHA"] = "80"
    # TODO: correct value for the 3 previous parameters ??

    # Mesh Marker
    bc_wall_str = "(" + ",".join(bc_wall_list) + ")"
    cfg["MARKER_EULER"] = bc_wall_str
    cfg["MARKER_FAR"] = " (Farfield, " + ",".join(engine_bc_list) + ")"
    cfg["MARKER_SYM"] = " (0)"  # TODO: maybe make that a variable?
    cfg["MARKER_PLOTTING"] = bc_wall_str
    cfg["MARKER_MONITORING"] = bc_wall_str
    cfg["MARKER_MOVING"] = "( NONE )"  # TODO: when do we need to define MARKER_MOVING?
    cfg["DV_MARKER"] = bc_wall_str

    # Parameters which will vary for the different cases (alt,mach,aoa,aos)
    for case_nb in range(param_count):

        cfg["MESH_FILENAME"] = su2_mesh_path

        alt = alt_list[case_nb]
        mach = mach_list[case_nb]
        aoa = aoa_list[case_nb]
        aos = aos_list[case_nb]

        Atm = Atmosphere(alt)

        cfg["MACH_NUMBER"] = mach
        cfg["AOA"] = aoa
        cfg["SIDESLIP_ANGLE"] = aos
        cfg["FREESTREAM_PRESSURE"] = Atm.pressure[0]
        cfg["FREESTREAM_TEMPERATURE"] = Atm.temperature[0]
        cfg["ROTATION_RATE"] = "0.0 0.0 0.0"

        config_file_name = "ConfigCFD.cfg"

        case_dir_name = "".join([
            "Case",
            str(case_nb).zfill(2),
            "_alt",
            str(alt),
            "_mach",
            str(round(mach, 2)),
            "_aoa",
            str(round(aoa, 1)),
            "_aos",
            str(round(aos, 1)),
        ])

        case_dir_path = os.path.join(wkdir, case_dir_name)
        if not os.path.isdir(case_dir_path):
            os.mkdir(case_dir_path)

        config_output_path = os.path.join(wkdir, case_dir_name,
                                          config_file_name)
        cfg.write_file(config_output_path, overwrite=True)

        # Damping derivatives
        damping_der_xpath = SU2_XPATH + "/options/clalculateDampingDerivatives"
        damping_der = get_value_or_default(cpacs.tixi, damping_der_xpath,
                                           False)

        if damping_der:

            rotation_rate_xpath = SU2_XPATH + "/options/rotationRate"
            rotation_rate = get_value_or_default(cpacs.tixi,
                                                 rotation_rate_xpath, 1.0)

            cfg["GRID_MOVEMENT"] = "ROTATING_FRAME"

            cfg["ROTATION_RATE"] = str(rotation_rate) + " 0.0 0.0"
            os.mkdir(os.path.join(wkdir, case_dir_name + "_dp"))
            config_output_path = os.path.join(wkdir, case_dir_name + "_dp",
                                              config_file_name)
            cfg.write_file(config_output_path, overwrite=True)

            cfg["ROTATION_RATE"] = "0.0 " + str(rotation_rate) + " 0.0"
            os.mkdir(os.path.join(wkdir, case_dir_name + "_dq"))
            config_output_path = os.path.join(wkdir, case_dir_name + "_dq",
                                              config_file_name)
            cfg.write_file(config_output_path, overwrite=True)

            cfg["ROTATION_RATE"] = "0.0 0.0 " + str(rotation_rate)
            os.mkdir(os.path.join(wkdir, case_dir_name + "_dr"))
            config_output_path = os.path.join(wkdir, case_dir_name + "_dr",
                                              config_file_name)
            cfg.write_file(config_output_path, overwrite=True)
            log.info("Damping derivatives cases directory has been created.")

        # Control surfaces deflections
        control_surf_xpath = SU2_XPATH + "/options/clalculateCotrolSurfacesDeflections"
        control_surf = get_value_or_default(cpacs.tixi, control_surf_xpath,
                                            False)

        if control_surf:

            # Get deformed mesh list
            su2_def_mesh_xpath = SU2_XPATH + "/availableDeformedMesh"
            if cpacs.tixi.checkElement(su2_def_mesh_xpath):
                su2_def_mesh_list = get_string_vector(cpacs.tixi,
                                                      su2_def_mesh_xpath)
            else:
                log.warning("No SU2 deformed mesh has been found!")
                su2_def_mesh_list = []

            for su2_def_mesh in su2_def_mesh_list:

                mesh_path = os.path.join(wkdir, "MESH", su2_def_mesh)

                config_dir_path = os.path.join(
                    wkdir, case_dir_name + "_" + su2_def_mesh.split(".")[0])
                os.mkdir(config_dir_path)
                cfg["MESH_FILENAME"] = mesh_path

                config_file_name = "ConfigCFD.cfg"
                config_output_path = os.path.join(wkdir, config_dir_path,
                                                  config_file_name)
                cfg.write_file(config_output_path, overwrite=True)

    # TODO: change that, but if it is save in tooloutput it will be erease by results...
    cpacs.save_cpacs(cpacs_out_path, overwrite=True)