Issue with the VLM script in the version 2.3.1

196 views
Skip to first unread message

Matheus Monjon

unread,
Jan 25, 2021, 9:26:47 PM1/25/21
to SUAVE FORUM
Dear SUAVE team, 

I developed a script in the 2.1.0 version using as a base the "battery propeller". Everything was working well in this version. 

When recently I updated SUAVE to version 2.3.1, I faced the issue below. I notice that this issue is happening not only with my script but also with the tutorials 2.3.0 (mission_B737, for example). 


  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Methods\Aerodynamics\Common\Fidelity_Zero\Lift\VLM.py", line 99, in VLM
    x_mac      = geometry.wings['main_wing'].aerodynamic_center[0] + geometry.wings['main_wing'].origin[0][0]

TypeError: 'float' object is not subscriptable

Are there any changes that I need to make in my code regarding the change of the use of "weissinger_vortex_lattice" to "VLM"? 

I appreciate any kind of help in this issue. 

Best regards, 
Matheus Monjon


Emilio Botero

unread,
Jan 25, 2021, 9:44:56 PM1/25/21
to SUAVE FORUM
Hi Matheus,
This is an easy fix to your vehicle setup. A few minor things changed between 2.1 and 2.3.

The wing origins are now 2D lists or 2D arrays. Just add another set of brackets around your origin from what you have.

This may seem weird, but it makes wing origins consistent with propulsors which have can multiple elements. This was a necessary change to do arbitrary CG calculations and allows for more flexible wing geometry in the future.

-Emilio

Matheus Monjon

unread,
Jan 27, 2021, 9:15:28 PM1/27/21
to SUAVE FORUM
Hi Emilio, 

Thanks, this solved the issue with the main wing. 

Now, I am facing new errors, as I will describe below. 

Do you have any .py example (similar to the battery_propeller) that I can see the differences in the structure from the 2.1 to 2.3.1 version and then "correct" my code to run in the 2.3.1 version? 
I am just asking this because if the modification efforts are not worth it, I will continue my work on version 2.1.


After applying the correction in the brackets, the following error appears: 

Defaulting to scaled DAE51
Traceback (most recent call last):

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Core\Data.py", line 59, in __getattribute__
    return dictgetitem(self,k)

KeyError: 'airfoil'


During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File "C:\Users\Matheus\OneDrive\.......\Electric_19seat_mission_battery_propeller.py", line 1598, in <module>
    main()

  File "C:\Users\Matheus\OneDrive\.......\Electric_19seat_mission_battery_propeller.py", line 38, in main
    analyses.finalize()

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Analysis.py", line 271, in finalize
    analysis.finalize(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Analysis.py", line 271, in finalize
    analysis.finalize(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Analysis.py", line 271, in finalize
    analysis.finalize(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Aerodynamics\Fidelity_Zero.py", line 138, in initialize
    self.process.compute.lift.inviscid_wings.initialize(use_surrogate,n_sw,n_cw,propeller_wake_model,ito,wdt)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Aerodynamics\Vortex_Lattice.py", line 145, in initialize
    self.sample_training()

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Aerodynamics\Vortex_Lattice.py", line 388, in sample_training
    calculate_VLM(konditions,settings,geometry)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Aerodynamics\Vortex_Lattice.py", line 580, in calculate_VLM
    total_lift_coeff,total_induced_drag_coeff, CM, CL_wing, CDi_wing, cl_y , cdi_y , CPi , vel_profile = VLM(conditions,settings,geometry)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Methods\Aerodynamics\Common\Fidelity_Zero\Lift\VLM.py", line 120, in VLM
    VD   = generate_wing_vortex_distribution(geometry,settings)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Methods\Aerodynamics\Common\Fidelity_Zero\Lift\generate_wing_vortex_distribution.py", line 480, in generate_wing_vortex_distribution
    airfoil_data = import_airfoil_geometry(wing.Airfoil.airfoil.coordinate_file)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Core\Data.py", line 61, in __getattribute__
    return objgetattrib(self,k)

AttributeError: 'Data' object has no attribute 'airfoil'

I defined the main wing airfoil as follows:

    # ------------------------------------------------------------------        
    #   Main Wing
    # ------------------------------------------------------------------        
    
    wing = SUAVE.Components.Wings.Main_Wing()
    wing.tag = 'main_wing'
     .
     .
     .

    airfoil = SUAVE.Components.Wings.Airfoils.Airfoil()
    
    airfoil.tag                = 'naca23015'
    airfoil.thickness_to_chord = 0.15
    airfoil.coordinate_file    = 'C:/Users/Matheus/OneDrive/Folder/...../naca23015.dat'
    wing.Airfoil.append(airfoil)



Now, if I remove the definition of the desired airfoil, the following error appears:


Defaulting to scaled DAE51
Traceback (most recent call last):

  File "C:\Users\Matheus\OneDrive\TG\Backup Paper-TG-SUAVE-VSP\Electric_19pax_SUAVE\Teste2_script\Electric Battery-Propeller\Electric_19seat_mission_battery_propeller.py", line 1598, in <module>
    main()

  File "C:\Users\Matheus\OneDrive\TG\Backup Paper-TG-SUAVE-VSP\Electric_19pax_SUAVE\Teste2_script\Electric Battery-Propeller\Electric_19seat_mission_battery_propeller.py", line 46, in main
    results = mission.evaluate()

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Mission\Segments\Segment.py", line 199, in evaluate
    self.process(self)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Process.py", line 96, in __call__
    return self.evaluate(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Process.py", line 67, in evaluate
    result = step(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Methods\Missions\Segments\Common\Sub_Segments.py", line 131, in sequential_sub_segments
    sub_segment.evaluate()

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Mission\Segments\Segment.py", line 199, in evaluate
    self.process(self)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Process.py", line 96, in __call__
    return self.evaluate(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Process.py", line 65, in evaluate
    result = step.evaluate(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Analyses\Process.py", line 67, in evaluate
    result = step(*args,**kwarg)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\suave-2.3.0-py3.8.egg\SUAVE\Methods\Missions\Segments\converge_root.py", line 50, in converge_root
    unknowns,infodict,ier,msg = root_finder( iterate,

  File "C:\Users\Matheus\anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 160, in fsolve
    res = _root_hybr(func, x0, args, jac=fprime, **options)

  File "C:\Users\Matheus\anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 226, in _root_hybr
    shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))

  File "C:\Users\Matheus\anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 38, in _check_func
    raise TypeError(msg)

TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument 'iterate'.Shape should be (28,) but it is (21,).

I would appreciate any help to handle with the mentioned errors. 

Best regards,
Matheus Monjon

Emilio Botero

unread,
Jan 28, 2021, 1:51:11 PM1/28/21
to SUAVE FORUM
Hi Matheus,
For the airfoil issue, looks like the data structure isn't setup right for that. The proper way to add an airfoil is this way:
wing.append_airfoil(airfoil)

But I couldn't figure out why the way you didn't wouldn't work.

For the fsolve error, that has nothing to do with the VLM or airfoils. When you setup your mission you need to have a matching number of residuals and unknowns. Looks like you didn't match those. I don't know what sort of mission you're running, so I couldn't tell you what is missing or what has been erroneously added.

-Emilio


Matheus Monjon

unread,
Jan 28, 2021, 8:40:19 PM1/28/21
to SUAVE FORUM
Hello Emilio, 

Thanks for answering. 

I tried some attempts to correct the "fsolve" error, but without any progression. 

I'm writing here the part related to the mission setup (I don't know why but I'm unable to attach the code file at this moment here).

If possible, would you be so kind to give a rapid look in the code and see if there is something missing or wrong related to residuals and unknowns? 

If I cannot fix this issues, I think I will just downgrade to the 2.1.0 version because the code was working well in this version. 

Thanks!


# ----------------------------------------------------------------------
#   Define the Mission
# ----------------------------------------------------------------------

def mission_setup(analyses,vehicle): # add ,vehicle

    # ------------------------------------------------------------------
    #   Initialize the Mission
    # ------------------------------------------------------------------

    mission = SUAVE.Analyses.Mission.Sequential_Segments()
    mission.tag = 'the_mission'

    #airport
    airport = SUAVE.Attributes.Airports.Airport()
    airport.altitude   =  0.0  * Units.ft #Denver 5434 ft
    airport.delta_isa  =  15.0 #ISA +15ºC
    airport.atmosphere = SUAVE.Attributes.Atmospheres.Earth.US_Standard_1976()

    mission.airport = airport    

    # unpack Segments module
    Segments = SUAVE.Analyses.Mission.Segments

    # base segment
    base_segment = Segments.Segment()
    atmosphere=SUAVE.Attributes.Atmospheres.Earth.US_Standard_1976()
    planet = SUAVE.Attributes.Planets.Earth()

    #he battery network has a more complex voltage model that requires an additional unknown and residual.
    ones_row     = base_segment.state.ones_row
    base_segment.process.iterate.initials.initialize_battery = SUAVE.Methods.Missions.Segments.Common.Energy.initialize_battery
    base_segment.process.iterate.conditions.planet_position  = SUAVE.Methods.skip
    base_segment.state.numerics.number_control_points        = 4
    base_segment.process.iterate.unknowns.network            = vehicle.propulsors.battery_propeller.unpack_unknowns
    base_segment.process.iterate.residuals.network           = vehicle.propulsors.battery_propeller.residuals
    base_segment.state.unknowns.propeller_power_coefficient  = 0.005 * ones_row(1) 
    base_segment.state.unknowns.battery_voltage_under_load   = vehicle.propulsors.battery_propeller.battery.max_voltage * ones_row(1)  
    base_segment.state.residuals.network                     = 0. * ones_row(2)
     

    # ------------------------------------------------------------------
    #   Takeoff Roll
    # ------------------------------------------------------------------

    segment = Segments.Ground.Takeoff(base_segment)
    segment.tag = "Takeoff"
    segment.analyses.extend( analyses.takeoff )
    segment.battery_energy  = vehicle.propulsors.battery_propeller.battery.max_energy* 0.89 # Charge de battery to start
    Vstall_ft = 140 #ft/s # 153.61 km/h 
    Vstall = Vstall_ft/3.281
    segment.velocity_start           = 0.* Units['m/s']
    segment.velocity_end             = 1.2*Vstall * Units['m/s']
    TLF                              = 800 * Units.meters  # Take-off field lenght in meters
    t_TLF                            = 2*TLF/(segment.velocity_end)
    segment.friction_coefficient     = 0.04
    segment.time                     = t_TLF
    segment.state.unknowns.throttle  = 0.85 * ones_row(1)  

    #print('Segment velocity end (m/s): ',segment.velocity_end)
    #print('TFL (m): ', TLF)
    #print('t_takeoff (s): ',t_TLF)

    # add to misison
    mission.append_segment(segment)


    # ------------------------------------------------------------------
    #   First Climb Segment: Constant Speed, Constant Rate
    # ------------------------------------------------------------------


    segment = Segments.Climb.Constant_Speed_Constant_Rate(base_segment)
    segment.tag = "climb_1"

    segment.analyses.extend( analyses.takeoff )
    #segment.state.numerics.number_control_points = 64
    segment.battery_energy  = vehicle.propulsors.battery_propeller.battery.max_energy #* 0.89 # Charge de battery to start
    segment.altitude_start = 0.0   * Units.km
    segment.altitude_end   = 15000. * Units.ft
    segment.air_speed      = 244.1 * Units['km/hr'] #
    segment.climb_rate     = 1750. * Units['ft/min']
    segment.state.unknowns.throttle          = 0.85 * ones_row(1) #that means that the initial guess for your throttle setting in that segment is 85%. The true value will be calculated through the iteration process. 

    # add to misison
    mission.append_segment(segment)

    # ------------------------------------------------------------------
    #   Second Climb Segment: Constant Speed, Constant Rate
    # ------------------------------------------------------------------    

    segment = Segments.Climb.Constant_Speed_Constant_Rate(base_segment)
    segment.tag = "climb_2"

    segment.analyses.extend( analyses.cruise )

    segment.altitude_end = 20000. * Units.ft
    segment.air_speed    = 297.5 * Units['km/hr'] 
    segment.climb_rate   = 1300. * Units['ft/min']
    segment.state.unknowns.throttle   = 0.9 *  ones_row(1)

    # add to mission
    mission.append_segment(segment)


    # ------------------------------------------------------------------    
    #   Cruise Segment: Constant Speed, Constant Altitude
    # ------------------------------------------------------------------    

    segment = Segments.Cruise.Constant_Speed_Constant_Altitude(base_segment)
    segment.tag = "cruise"

    segment.analyses.extend( analyses.cruise )

    
    segment.air_speed  = 336.6 * Units['km/hr'] # Ref 350 km/h
    segment.distance   = 330.0 * Units.km # Only cruise
    segment.state.unknowns.throttle   = 0.9 *  ones_row(1)

    # add to mission
    mission.append_segment(segment)

    # ------------------------------------------------------------------
    #   First Descent Segment: Constant Speed, Constant Rate
    # ------------------------------------------------------------------

    segment = Segments.Descent.Constant_Speed_Constant_Rate(base_segment)
    segment.tag = "descent_1"

    segment.analyses.extend( analyses.cruise )

    segment.altitude_end = 7500. * Units.ft
    segment.air_speed    = 305.7  * Units['km/hr']
    segment.descent_rate = 880. * Units['ft/min']
    segment.state.unknowns.throttle  = 0.9 * ones_row(1) 

    # add to mission
    mission.append_segment(segment)

    # ------------------------------------------------------------------
    #   Second Descent Segment: Constant Speed, Constant Rate
    # ------------------------------------------------------------------

    segment = Segments.Descent.Constant_Speed_Constant_Rate(base_segment)
    segment.tag = "descent_2"

    segment.analyses.extend( analyses.landing )

    segment.altitude_end = 0. * Units.ft
    segment.air_speed    = 260.3  * Units['km/hr']
    segment.descent_rate = 750. * Units['ft/min']
    segment.state.unknowns.throttle   = 0.9 *  ones_row(1)

    # add to mission
    mission.append_segment(segment)

Emilio Botero

unread,
Jan 28, 2021, 9:08:27 PM1/28/21
to SUAVE FORUM
Hi Matheus,
Looks like you added an extra throttle unknown to your takeoff?

You can see these are the available inputs to a takeoff segment. Most pilots prefer 100% throttle on takeoff.

Another thing that's sort of confusing, and I apologize, is that to set the delta ISA in a mission should be done this way:
segment.temperature_deviation

The airport information is only really used in the correlation based takeoff field length calculations.

Also as a heads up, the battery is charged twice, not sure if that's what you want.

-Emilio

Matheus Monjon

unread,
Feb 2, 2021, 10:04:28 PM2/2/21
to SUAVE FORUM
Hello Emilio, 

Thank you for the tips. I changed the delta ISA and battery charge.

Using version 2.2.0, worked well but I had to disregard the takeoff segment because the problem is in this segment. 

Regarding the airfoil, I will address the issue in a new topic because this can be some else doubt too. 

Talking specific to the takeoff segment, is there anything wrong with the following setting? 

When I use this takeoff segment, all segments do not converge and, at the beginning of the segment, some points appear in a negative time. 

I don't know what I can change or simplify. I made some changes living only a few inputs (such as velocity_start, velocity_end, friction_coefficient ) but the issue did not disappear. 

    # ------------------------------------------------------------------
    #   Takeoff Roll
    # ------------------------------------------------------------------

    #segment = Segments.Ground.Takeoff(base_segment)
    #segment.tag = "Takeoff"

    #segment.analyses.extend( analyses.takeoff )
    #segment.battery_energy  = vehicle.propulsors.battery_propeller.battery.max_energy -> If using takeoff segment, use only here
    
    #Vstall_ft = 140 #ft/s # 153.61 km/h 
    #Vstall = Vstall_ft/3.281
    #segment.velocity_start            = 0.* Units['m/s']
    #segment.velocity_end             = 1.2*Vstall * Units['m/s']
    #segment.altitude                     = 0
    #TLF                                         = 800 * Units.meters  # Take-off field lenght in meters
    #t_TLF                                      = 2*TLF/(segment.velocity_end)
    #segment.time                          = t_TLF
    #segment.friction_coefficient    = 0.04

    # add to misison
    #mission.append_segment(segment)

Best regards,
Matheus Monjon

Emilio Botero

unread,
Feb 5, 2021, 12:23:29 PM2/5/21
to SUAVE FORUM
Hi,
Try this:
    # ------------------------------------------------------------------
    #   Takeoff Roll
    # ------------------------------------------------------------------

    segment = Segments.Ground.Takeoff(base_segment)
    segment.tag = "Takeoff"

    segment.analyses.extend( analyses.takeoff )
    segment.velocity_start           = 1.* Units.knots
    segment.velocity_end             = 1.2*140.0 * Units['ft/s']
    segment.friction_coefficient     = 0.04
    segment.altitude                 = 0.0

    # add to misison
    mission.append_segment(segment)


-Emilio

Matheus Monjon

unread,
Feb 15, 2021, 11:16:46 AM2/15/21
to SUAVE FORUM
Hi Emilio, 

The solution above did not work. 

Only the takeoff roll still not converging. I will try to address this segment in another way.

Thanks for helping me. 


Best regards, 
Matheus Monjon
Reply all
Reply to author
Forward
0 new messages