sustainableaviation / EcoPyLot

πŸƒπŸ›©οΈ Prospective environmental and economic life cycle assessment of aircraft made blazing fast
http://ecopylot.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
2 stars 0 forks source link

Evaluate `GenericAirplaneModel (GAM)` by ISAE-SUPAERO #12

Open michaelweinold opened 5 months ago

michaelweinold commented 5 months ago

@julienmctighe found this project:

which might be useful to (at least some sub-part) of our project.

romainsacchi commented 5 months ago

Here is what ChatGPT has to say about it:

The code you've provided appears to be a Python script related to conceptual airplane design, created by the Conceptual Airplane Design & Operations (CADO) team at ENAC. The script includes various Python imports such as NumPy, SciPy, Pandas, and Matplotlib, which are commonly used for numerical computing, data analysis, and plotting.

From the initial portion of the code, it's clear that the script is likely to involve mathematical computations and data handling related to airplane design. It might include functions for solving equations, interpolating data, and plotting results.

The script contains a class named GAM. This name suggests it could be an acronym, possibly related to a specific concept in airplane design or modeling. Since this is the only class or major section identified in the initial analysis, the script is likely centered around this GAM class.

To understand the functionalities and purpose of the GAM class, I'll need to delve into its methods and properties. Let's examine the GAM class in more detail to understand what it does. ​​

The GAM class in the script appears to be a data-driven modeling class related to aircraft design. The initial part of the class includes:

Constructor (init): This method initializes the class. It defines various categories and types related to aircraft, such as: Aircraft categories like 'general', 'commuter', 'regional', 'business', 'short_medium' (single aisle), and 'long_range' (twin aisle). Types of thrusters, such as 'propeller' and 'fan'. Types of engines, with 'turbofan' being mentioned. This setup suggests that the GAM class is designed to model different types of aircraft with varying configurations (like engine types and aircraft categories). The class likely contains methods to perform calculations or simulations based on these configurations.

To provide a more comprehensive understanding, I will further analyze the methods and functionalities within the GAM class. Let's look at the other methods and properties defined in this class. ​​

The GAM class contains a variety of methods and properties, with the initial ones primarily focused on defining different categories and types relevant to aircraft. The class starts with an init method (constructor), which sets up various properties such as:

self.general self.commuter self.regional self.business self.short_medium self.long_range self.propeller self.fan self.turbofan These properties are likely used to categorize different types of aircraft and their components, such as engine types and aircraft categories.

To understand the full capabilities and the logic implemented in the GAM class, we should explore more methods beyond these initial property definitions. These methods likely contain the core functionality of the class, such as calculations, data processing, or simulations related to aircraft design.

Let's continue analyzing the class to uncover more about its functionalities. ​​

The continuation of the GAM class definition further elaborates on the different types of aircraft components and configurations:

Additional engine types like turboprop, piston, emotor (possibly electric motor), power_elec, and fuel_cell. Various types of energy storage such as petrol, kerosene, gasoline, gh2 (compressed hydrogen), lh2 (liquid hydrogen), lch4 (liquid methane), lnh3 (liquid ammonia), and battery. A color coding system for different aircraft categories, likely used for visualization purposes. For example, general category is associated with "green", commuter with "gold", and so on. Definition of dictionary structures like main_power_system and scnd_power_system, which include keys for thruster type, engine type, bypass ratio (bpr), energy type, and a flag for hybrid systems. These structures are probably used to define and store the characteristics of different power systems used in aircraft. These details indicate that the GAM class is a comprehensive tool for modeling and analyzing various aspects of aircraft design, particularly focusing on power systems and energy storage options. This could be a part of a larger simulation or analysis framework used for aircraft design and performance assessment.

I'll further explore the class to see if there are specific methods that handle calculations, simulations, or data processing related to these configurations. Let's continue the analysis. ​​

The further analysis of the GAM class reveals:

Additional properties under scnd_power_system include hybrid_ratio, which suggests this class also considers hybrid power systems. Definitions of maximum capacity, range, and other characteristics for different aircraft categories in a category dictionary. This includes: general: Small capacity (6 passengers), short range (500 km), and speed (300 km/h), typically using turboprop engines and propeller thrusters. commuter: Slightly larger capacity (19 passengers), medium range (1500 km), and higher speed (400 km/h), also using turboprop engines and propeller thrusters. regional: Larger capacity (120 passengers), longer range (4500 km), and a speed corresponding to 0.5 Mach, using turbofan engines with a bypass ratio (bpr) of 12, and fan thrusters. short_medium: Even larger capacity (250 passengers) and range (8000 km), with a speed of 0.78 Mach, indicating a focus on single-aisle, medium-haul flights, using turbofan engines and fan thrusters. These configurations indicate that the GAM class is a sophisticated tool for modeling different types of aircraft, taking into account various parameters such as capacity, range, speed, engine type, and thruster type. This class seems to be a part of a larger framework used for aircraft design, possibly for conceptual studies, performance analysis, or educational purposes.

To provide a more comprehensive understanding, let's continue to explore the rest of the class for any specific computational methods or simulation functionalities. ​​

The continued analysis of the GAM class provides further insights:

Definition for long_range aircraft category, indicating a high capacity (550 passengers), very long range (15,000 km), and a cruising speed of 0.85 Mach. These characteristics are typical for twin-aisle, long-haul flights, and the configuration uses turbofan engines with a bypass ratio (bpr) of 12 and fan thrusters. Yearly utilization and mean range data are included, suggesting that the model takes into account operational aspects such as flight frequency and typical mission distances. This is represented by util_dist_list (a range list in Nautical Miles converted to meters) and util_list (yearly utilization numbers). Parameters like disa (perhaps referring to deviation in standard atmospheric conditions), take_off_time, and full_epower_time (possibly related to hybrid thermal-electrical power systems) are defined, indicating that the model considers various aspects of flight operations. Flight altitudes are specified for different aircraft categories, including cruise, diversion, and holding altitudes. For example, for the general category, altitudes of 5000, 3000, and 1500 feet are specified, likely converted into meters. These elements suggest that the GAM class is not just a static model but incorporates dynamic aspects of flight operations and performance. It seems designed to support detailed analysis and decision-making in aircraft design and operational planning, with a focus on energy efficiency and operational efficiency.

romainsacchi commented 5 months ago

i can also see that it includes a physics model, calculate the energy consumption. Froex example:

def lod_model(self, fuselage_length, fuselage_width, wing_span, wing_area, htp_area, vtp_area,
                  cruise_altp, cruise_speed, mass, design={}, full_output=False):
        if design != {}:
            fuselage_shape = design["fuselage_shape"]       # 0 : standard, 1 : smooth (plastic gliders)
            fuselage_surface = design["fuselage_surface"]   # 0 : standard, 1 : very thin (beam)
            laminar_ratio = design["wing_laminar_ratio"]    # Ratio of the chords with laminar flow
            surface_quality = design["surface_quality"]     # 0 : standard, 1 : very clean (plastic gliders)
        else:
            fuselage_shape = 0.
            fuselage_surface = 0.
            laminar_ratio = 0.
            surface_quality = 0.

        wing_ar = wing_span ** 2 / wing_area
        wing_tr = 0.35
        wing_cref = wing_area / wing_span
        wing_croot = (2 * wing_area) / ((1 + wing_tr) * wing_span)

        htp_ar = 5.0
        htp_cref = np.sqrt(htp_area / htp_ar)

        vtp_ar = 1.7
        vtp_cref = np.sqrt(vtp_area / vtp_ar)

        r, gam, cp, cv = phd.gas_data()
        pamb, tamb, g = phd.atmosphere_g(cruise_altp)
        rho, sig = phd.air_density(pamb, tamb)
        if 1 < cruise_speed:
            mach = cruise_speed / phd.sound_speed(tamb)
        else:
            mach = cruise_speed

        fuselage_wa = 0.86 * (1. - 0.8*fuselage_surface) * np.pi * fuselage_width * fuselage_length
        wing_wa = 2 * (wing_area - wing_croot * fuselage_width)
        htp_wa = 1.63 * htp_area
        vtp_wa = 2 * vtp_area

        chord = [fuselage_length, wing_cref, htp_cref, vtp_cref]
        laminar_factor = [0, laminar_ratio, 0, 0]
        wet_area = [fuselage_wa, wing_wa, htp_wa, vtp_wa]
        form_factor = [1.05, 1.4, 1.4, 1.4]

        cz = (2 * mass * g) / (gam * pamb * wing_area * mach ** 2)
        re = phd.reynolds_number(pamb, tamb, mach)
        fac = (1. + 0.126 * mach ** 2)

        ac_nwa = 0.
        cxf = 0.
        for j in range(4):
            ael = chord[j]
            nwa = wet_area[j]
            frm = form_factor[j]
            # Drag model is based on flat plane turbulent friction drag
            if laminar_factor[j]==0.:
                cxf += frm * (3.913 / np.log(re * ael) ** 2.58) * nwa / wing_area
            else:
                lam = laminar_factor[j]
                cxf += frm * ( (3.913/np.log(re*ael)**2.58)*nwa
                              -(3.913/np.log(re*ael*lam)**2.58)*(nwa*lam)
                              +(1.328/np.sqrt(re*ael*lam)*(nwa*lam))
                              ) / wing_area
            ac_nwa += nwa

        # Parasitic drag (seals, antennas, sensors, ...)
        # -----------------------------------------------------------------------------------------------------------
        knwa = ac_nwa / 1000.
        kp = (0.0247 * knwa - 0.11) * knwa + 0.166  # Parasitic drag factor, Reymers ? ou Thorenbeck ?
        cx_par = cxf * kp * (1 - surface_quality)

        # Additional drag
        # -----------------------------------------------------------------------------------------------------------
        X = np.array([1.0, 1.5, 2.4, 3.3, 4.0, 5.0])
        Y = np.array([0.036, 0.020, 0.0075, 0.0025, 0., 0.])
        param = 3.45
        cx_tap = interp1d(X, Y, kind="linear", fill_value="extrapolate")(param) * (1 - fuselage_shape)

        # Total zero lift drag
        # -----------------------------------------------------------------------------------------------------------
        cx0 = (cxf + cx_par + cx_tap)

        # Induced drag
        # -----------------------------------------------------------------------------------------------------------
        ki_wing = (1.05 + (fuselage_width / wing_span) ** 2) / (np.pi * wing_ar)  # Reymers ? ou Thorenbeck ?
        cxi = ki_wing * cz ** 2  # Induced drag

        # Compressibility drag
        # -----------------------------------------------------------------------------------------------------------
        # Freely inspired from Korn equation
        cz_design = 0.5
        mach_div = mach + (0.03 + 0.1 * (cz_design - cz))  # Voir Picolas

        if 0.55 < mach:
            cxc = 0.0025 * np.exp(40. * (mach - mach_div))   # To have 10% slope and cxc = 25 cts at Mach div
        else:
            cxc = 0.

        # Sum up
        # -----------------------------------------------------------------------------------------------------------
        cx = cx0 + cxi + cxc
        lod = cz / cx
        if full_output:
            return {"lod":lod, "cz":cz, "cx":cx, "cx0":cx0, "cxi":cxi, "cxc":cxc, "cxf":cxf, "cx_par":cx_par, "cx_tap":cx_tap}
        else:
            return lod
romainsacchi commented 5 months ago

I have asked the maintainer to provide us with the aircraft database file the model draws on to build regression fits.

romainsacchi commented 5 months ago

My non-expert opinion is that it looks sophisticated. From a code standpoint, it would require massive refactoring. Also the code could use more comments and documentation. But I believe it could save us significant time.

romainsacchi commented 5 months ago

It does not do all the things we want to do. For example, efficiencies are static:

# Efficiencies
        self.prop_eff = 0.80
        self.fan_eff = 0.82
        self.emotor_eff = 0.90  # MAGNIX
        self.fuel_cell_eff = 0.50  # (Horizon Fuel Cell)
        self.fuel_energy_ratio = 2.28   # eta_fan / (eta_prop * eta_thermal), 0.8 / (0.7 * 0.5), FHV * SFC / SEC
michaelweinold commented 5 months ago

@romainsacchi, senior scientist and prompt engineer πŸ€–

romainsacchi commented 5 months ago

I'm afraid though that the lack of documentation can be an obstacle. For example:

# Additional drag
        # -----------------------------------------------------------------------------------------------------------
        X = np.array([1.0, 1.5, 2.4, 3.3, 4.0, 5.0])
        Y = np.array([0.036, 0.020, 0.0075, 0.0025, 0., 0.])
        param = 3.45
        cx_tap = interp1d(X, Y, kind="linear", fill_value="extrapolate")(param) * (1 - fuselage_shape)

Hard to say where these numbers come from.

romainsacchi commented 5 months ago

There's a conference paper linked to the model, but I could not find it (and I doubt it provided extensive documentation on the model, anyway).

Kambiri et al., Energy consumption of Aircraft with new propulsion systems and storage media, Scitech Forum, Orlando, January 2024

romainsacchi commented 5 months ago

In summary, without additional documentation or direct cooperation with the authors, it will be difficult to vouch for the model's quality and correctness despite its apparent qualities.

julienmctighe commented 5 months ago

Here is a link to the paper referenced: https://arc.aiaa.org/doi/abs/10.2514/6.2024-1707. I have not been able to access the PDF from home or from ETH. Might have better luck at PSI.

The weight and drag estimations look similar to other conceptual design papers (Torenbeek & Raymer methods). Those should be relatively straightforward to verify, just a little time intensive.

To me, it looks quite similar to the approach we discussed, it just considers a single point in time (constant efficiencies and power densities) and sizes the aircraft directly.

I think we will need to wait on the aircraft database and/or paper to compare the sizing method to the other designs compiled.

julienmctighe commented 5 months ago

kambiri-et-al-2024-energy-consumption-of-aircraft-with-new-propulsion-systems-and-storage-media.pdf

julienmctighe commented 5 months ago

The paper is a little rough. Overall, I would say the model is a helpful starting point, but certainly needs some adaptation. Main limitations include a lack of fuel volume estimate, lack of hybrid power systems, and a reliance on regression using an aircraft database of unknown source with no time variable. It does look like they intend to implement fuel volume calcs & hybrids and correspondence might address the database source.

michaelweinold commented 4 months ago

...some more information which was provided by the GAM team in an email to @romainsacchi on 7th March 2024:

The code is distributed under the CeCILL-C license (reuse and modification possible provided the authors are cited) and the database under the ODbL license (reuse and modification possible provided the DOI and the authors are cited, the derived databases must be published under ODbL license).

The code posted on Gitlab is a somewhat β€œlite” version. We continue to actively develop new features for our own needs, including more in-depth consumption calculations.