From 2e5cdb30a9493d24e63d3157863bb36612ec7c77 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Mon, 26 Jun 2017 16:09:45 -0700 Subject: [PATCH 01/14] first commits from vtol --- ...onstant_Dynamic_Pressure_Constant_Angle.py | 59 +++++++++++++++++++ .../Climb/Constant_Mach_Constant_Angle.py | 20 ++++++- .../Climb/Constant_Mach_Linear_Altitude.py | 47 +++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py create mode 100644 trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py new file mode 100644 index 0000000000..e5c780492a --- /dev/null +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py @@ -0,0 +1,59 @@ +# Constant_Dynamic_Pressure_Constant_Rate.py +# +# Created: +# Modified: Feb 2016, Andrew Wendorff +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +# SUAVE imports +from SUAVE.Methods.Missions import Segments as Methods + +from Unknown_Throttle import Unknown_Throttle + +# Units +from SUAVE.Core import Units + +# ---------------------------------------------------------------------- +# Segment +# ---------------------------------------------------------------------- + +class Constant_Dynamic_Pressure_Constant_Angle(Unknown_Throttle): + + def __defaults__(self): + + # -------------------------------------------------------------- + # User inputs + # -------------------------------------------------------------- + self.altitude_start = None # Optional + self.altitude_end = 10. * Units.km + self.climb_angle = 3. * Units.degrees + self.dynamic_pressure = 1600 * Units.pascals + + # -------------------------------------------------------------- + # State + # -------------------------------------------------------------- + + # initials and unknowns + ones_row = self.state.ones_row + self.state.unknowns.altitudes = ones_row(1) * 0.0 + self.state.residuals.forces = ones_row(3) * 0.0 + + # -------------------------------------------------------------- + # The Solving Process + # -------------------------------------------------------------- + initialize = self.process.initialize + initialize.conditions = Methods.Climb.Constant_Dynamic_Pressure_Constant_Angle.initialize_conditions_unpack_unknowns + + + # Unpack Unknowns + iterate = self.process.iterate + iterate.unknowns.mission = Methods.Climb.Constant_Dynamic_Pressure_Constant_Angle.initialize_conditions_unpack_unknowns + + iterate.conditions.differentials = Methods.Climb.Optimized.update_differentials + + # Solve Residuals + iterate.residuals.total_forces = Methods.Climb.Constant_Dynamic_Pressure_Constant_Angle.residual_total_forces + + return + \ No newline at end of file diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py index f39be29473..7f29d2224a 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py @@ -31,13 +31,31 @@ def __defaults__(self): self.climb_angle = 3. * Units.deg self.mach = 0.7 + # -------------------------------------------------------------- + # State + # -------------------------------------------------------------- + + # initials and unknowns + ones_row = self.state.ones_row + self.state.unknowns.altitudes = ones_row(1) * 0.0 + self.state.residuals.forces = ones_row(3) * 0.0 + # -------------------------------------------------------------- # The Solving Process # -------------------------------------------------------------- # only need to change one setup step from constant_speed_constant_ate initialize = self.process.initialize - initialize.conditions = Methods.Climb.Constant_Mach_Constant_Angle.initialize_conditions + initialize.conditions = Methods.Climb.Constant_Mach_Constant_Angle.initialize_conditions_unpack_unknowns + + # Unpack Unknowns + iterate = self.process.iterate + iterate.unknowns.mission = Methods.Climb.Constant_Mach_Constant_Angle.initialize_conditions_unpack_unknowns + + iterate.conditions.differentials = Methods.Climb.Optimized.update_differentials + + # Solve Residuals + iterate.residuals.total_forces = Methods.Climb.Constant_Mach_Constant_Angle.residual_total_forces return diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py new file mode 100644 index 0000000000..4484189f89 --- /dev/null +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py @@ -0,0 +1,47 @@ + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +# SUAVE imports +from SUAVE.Analyses.Mission.Segments import Aerodynamic +from SUAVE.Analyses.Mission.Segments import Conditions +from SUAVE.Analyses.Mission.Segments.Cruise import Constant_Speed_Linear_Altitude + +from SUAVE.Methods.Missions import Segments as Methods + +from SUAVE.Analyses import Process + +# Units +from SUAVE.Core import Units + + +# ---------------------------------------------------------------------- +# Segment +# ---------------------------------------------------------------------- + +class Constant_Mach_Linear_Altitude(Constant_Speed_Linear_Altitude): + + def __defaults__(self): + + # -------------------------------------------------------------- + # User inputs + # -------------------------------------------------------------- + self.altitude = None + self.mach = 0.5 + self.distance = 10. * Units.km + self.altitude_start = None + self.altitude_end = None + + + # -------------------------------------------------------------- + # The Solving Process + # -------------------------------------------------------------- + + # only need to change one setup step from constant_speed_constant_altitude + initialize = self.process.initialize + initialize.conditions = Methods.Cruise.Constant_Mach_Linear_Altitude.initialize_conditions + + + return + From 8165f02b7c9c956ff4c307912a2cbac3f9c53206 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Mon, 26 Jun 2017 16:20:29 -0700 Subject: [PATCH 02/14] commits from vtol branch --- .../Climb/Constant_Speed_Linear_Altitude.py | 121 ++++++++++++++++++ .../Segments/Climb/Unknown_Throttle.py | 2 +- .../Mission/Segments/Climb/__init__.py | 4 +- .../Constant_Speed_Constant_Altitude.py | 2 +- ...Constant_Speed_Constant_Altitude_Loiter.py | 41 ++++++ .../Mission/Segments/Cruise/__init__.py | 3 +- .../Methods/Missions/Segments/Climb/Common.py | 1 - ...onstant_Dynamic_Pressure_Constant_Angle.py | 73 +++++++++++ ...Constant_Dynamic_Pressure_Constant_Rate.py | 2 +- .../Climb/Constant_EAS_Constant_Rate.py | 6 +- .../Climb/Constant_Mach_Constant_Angle.py | 42 ++++-- .../Cruise/Constant_Mach_Linear_Altitude.py | 49 +++++++ ...Constant_Speed_Constant_Altitude_Loiter.py | 41 ++++++ .../Cruise/Constant_Speed_Linear_Altitude.py | 38 ++++++ 14 files changed, 406 insertions(+), 19 deletions(-) create mode 100644 trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py create mode 100644 trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py create mode 100644 trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py create mode 100644 trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Mach_Linear_Altitude.py create mode 100644 trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py create mode 100644 trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Linear_Altitude.py diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py new file mode 100644 index 0000000000..49d548bd63 --- /dev/null +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py @@ -0,0 +1,121 @@ + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +# SUAVE imports +from SUAVE.Analyses.Mission.Segments import Aerodynamic +from SUAVE.Analyses.Mission.Segments import Conditions + +from SUAVE.Methods.Missions import Segments as Methods + +from SUAVE.Analyses import Process + +# Units +from SUAVE.Core import Units + + +# ---------------------------------------------------------------------- +# Segment +# ---------------------------------------------------------------------- + +class Constant_Speed_Linear_Altitude(Aerodynamic): + + def __defaults__(self): + + # -------------------------------------------------------------- + # User inputs + # -------------------------------------------------------------- + self.altitude = None + self.air_speed = 10. * Units['km/hr'] + self.distance = 10. * Units.km + self.altitude_start = None + self.altitude_end = None + + + # -------------------------------------------------------------- + # State + # -------------------------------------------------------------- + + # conditions + self.state.conditions.update( Conditions.Aerodynamics() ) + + # initials and unknowns + ones_row = self.state.ones_row + self.state.unknowns.throttle = ones_row(1) * 0.5 + self.state.unknowns.body_angle = ones_row(1) * 0.0 + self.state.residuals.forces = ones_row(2) * 0.0 + + + # -------------------------------------------------------------- + # The Solving Process + # -------------------------------------------------------------- + + # -------------------------------------------------------------- + # Initialize - before iteration + # -------------------------------------------------------------- + initialize = self.process.initialize + initialize.clear() + + initialize.expand_state = Methods.expand_state + initialize.differentials = Methods.Common.Numerics.initialize_differentials_dimensionless + initialize.conditions = Methods.Cruise.Constant_Speed_Linear_Altitude.initialize_conditions + + # -------------------------------------------------------------- + # Converge - starts iteration + # -------------------------------------------------------------- + converge = self.process.converge + converge.clear() + + converge.converge_root = Methods.converge_root + + # -------------------------------------------------------------- + # Iterate - this is iterated + # -------------------------------------------------------------- + iterate = self.process.iterate + iterate.clear() + + # Update Initials + iterate.initials = Process() + iterate.initials.time = Methods.Common.Frames.initialize_time + iterate.initials.weights = Methods.Common.Weights.initialize_weights + iterate.initials.inertial_position = Methods.Common.Frames.initialize_inertial_position + iterate.initials.planet_position = Methods.Common.Frames.initialize_planet_position + + + # Unpack Unknowns + iterate.unpack_unknowns = Methods.Cruise.Common.unpack_unknowns + + # Update Conditions + iterate.conditions = Process() + iterate.conditions.differentials = Methods.Common.Numerics.update_differentials_time + iterate.conditions.altitude = Methods.Common.Aerodynamics.update_altitude + iterate.conditions.atmosphere = Methods.Common.Aerodynamics.update_atmosphere + iterate.conditions.gravity = Methods.Common.Weights.update_gravity + iterate.conditions.freestream = Methods.Common.Aerodynamics.update_freestream + iterate.conditions.orientations = Methods.Common.Frames.update_orientations + iterate.conditions.aerodynamics = Methods.Common.Aerodynamics.update_aerodynamics + iterate.conditions.stability = Methods.Common.Aerodynamics.update_stability + iterate.conditions.propulsion = Methods.Common.Energy.update_thrust + iterate.conditions.weights = Methods.Common.Weights.update_weights + iterate.conditions.forces = Methods.Common.Frames.update_forces + iterate.conditions.planet_position = Methods.Common.Frames.update_planet_position + + # Solve Residuals + iterate.residuals = Process() + iterate.residuals.total_forces = Methods.Cruise.Common.residual_total_forces + + # -------------------------------------------------------------- + # Finalize - after iteration + # -------------------------------------------------------------- + finalize = self.process.finalize + finalize.clear() + + # Post Processing + finalize.post_process = Process() + finalize.post_process.inertial_position = Methods.Common.Frames.integrate_inertial_horizontal_position + finalize.post_process.stability = Methods.Common.Aerodynamics.update_stability + + + return + diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py index a7df62e5d4..889bb1496f 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py @@ -43,7 +43,7 @@ def __defaults__(self): # initials and unknowns ones_row = self.state.ones_row self.state.unknowns.throttle = ones_row(1) * 0.5 - self.state.unknowns.body_angle = ones_row(1) * 0.0 + self.state.unknowns.body_angle = ones_row(1) * 0.01 self.state.residuals.forces = ones_row(2) * 0.0 # -------------------------------------------------------------- diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/__init__.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/__init__.py index c08cf26600..f19234acc0 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/__init__.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/__init__.py @@ -10,4 +10,6 @@ from Linear_Speed_Constant_Rate import Linear_Speed_Constant_Rate from Unknown_Throttle import Unknown_Throttle from Constant_Speed_Constant_Angle import Constant_Speed_Constant_Angle -from Constant_EAS_Constant_Rate import Constant_EAS_Constant_Rate \ No newline at end of file +from Constant_EAS_Constant_Rate import Constant_EAS_Constant_Rate +from Constant_Dynamic_Pressure_Constant_Angle import Constant_Dynamic_Pressure_Constant_Angle +from Optimized import Optimized \ No newline at end of file diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude.py b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude.py index 4f27378838..e12e20da21 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude.py @@ -45,7 +45,7 @@ def __defaults__(self): # initials and unknowns ones_row = self.state.ones_row self.state.unknowns.throttle = ones_row(1) * 0.5 - self.state.unknowns.body_angle = ones_row(1) * 0.0 + self.state.unknowns.body_angle = ones_row(1) * 1.0 * Units.deg self.state.residuals.forces = ones_row(2) * 0.0 diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py new file mode 100644 index 0000000000..a224f603db --- /dev/null +++ b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py @@ -0,0 +1,41 @@ +# Constant_Mach_Constant_Altitude_Loiter.py +# +# Created: +# Modified: Feb 2016, Andrew Wendorff + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +# SUAVE imports +from SUAVE.Methods.Missions import Segments as Methods + +from Constant_Speed_Constant_Altitude import Constant_Speed_Constant_Altitude + +# Units +from SUAVE.Core import Units + +# ---------------------------------------------------------------------- +# Segment +# ---------------------------------------------------------------------- + +class Constant_Speed_Constant_Altitude_Loiter(Constant_Speed_Constant_Altitude): + + def __defaults__(self): + + # -------------------------------------------------------------- + # User inputs + # -------------------------------------------------------------- + self.altitude = None + self.air_speed = 1.0 + self.time = 1.0 * Units.sec + + # -------------------------------------------------------------- + # The Solving Process + # -------------------------------------------------------------- + initialize = self.process.initialize + initialize.conditions = Methods.Cruise.Constant_Speed_Constant_Altitude_Loiter.initialize_conditions + + + return + diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/__init__.py b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/__init__.py index 9bff9780cf..5e7f8c4e31 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/__init__.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/__init__.py @@ -7,4 +7,5 @@ from Constant_Dynamic_Pressure_Constant_Altitude_Loiter import Constant_Dynamic_Pressure_Constant_Altitude_Loiter from Constant_Acceleration_Constant_Altitude import Constant_Acceleration_Constant_Altitude from Constant_Pitch_Rate_Constant_Altitude import Constant_Pitch_Rate_Constant_Altitude -from Constant_Dynamic_Pressure_Constant_Altitude import Constant_Dynamic_Pressure_Constant_Altitude \ No newline at end of file +from Constant_Dynamic_Pressure_Constant_Altitude import Constant_Dynamic_Pressure_Constant_Altitude +from Constant_Speed_Constant_Altitude_Loiter import Constant_Speed_Constant_Altitude_Loiter \ No newline at end of file diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Common.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Common.py index 9278e951e5..1a349d9059 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Common.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Common.py @@ -63,7 +63,6 @@ def update_differentials_altitude(segment,state): t = state.numerics.dimensionless.control_points D = state.numerics.dimensionless.differentiate I = state.numerics.dimensionless.integrate - r = state.conditions.frames.inertial.position_vector v = state.conditions.frames.inertial.velocity_vector diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py new file mode 100644 index 0000000000..d7b91c5564 --- /dev/null +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py @@ -0,0 +1,73 @@ +# Constant_Dynamic_Pressure_Constant_Rate.py +# +# Created: Jul 2014, SUAVE Team +# Modified: Jan 2016, E. Botero + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- +import numpy as np +import SUAVE + +# ---------------------------------------------------------------------- +# Initialize Conditions +# ---------------------------------------------------------------------- + +def initialize_conditions_unpack_unknowns(segment,state): + + # unpack + climb_angle = segment.climb_angle + q = segment.dynamic_pressure + alt0 = segment.altitude_start + altf = segment.altitude_end + t_nondim = state.numerics.dimensionless.control_points + conditions = state.conditions + rho = conditions.freestream.density[:,0] + + # unpack unknowns + throttle = state.unknowns.throttle + theta = state.unknowns.body_angle + alts = state.unknowns.altitudes + + # Update freestream to get density + SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) + rho = conditions.freestream.density[:,0] + + # check for initial altitude + if alt0 is None: + if not state.initials: raise AttributeError('initial altitude not set') + alt0 = -1.0 * state.initials.conditions.frames.inertial.position_vector[-1,2] + + # pack conditions + conditions.freestream.altitude[:,0] = alts[:,0] # positive altitude in this context + + # Update freestream to get density + SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) + rho = conditions.freestream.density[:,0] + + # process velocity vector + v_mag = np.sqrt(2*q/rho) + v_x = v_mag * np.cos(climb_angle) + v_z = -v_mag * np.sin(climb_angle) + + # pack conditions + conditions.frames.inertial.velocity_vector[:,0] = v_x + conditions.frames.inertial.velocity_vector[:,2] = v_z + conditions.frames.inertial.position_vector[:,2] = -alts[:,0] # z points down + state.conditions.propulsion.throttle[:,0] = throttle[:,0] + state.conditions.frames.body.inertial_rotations[:,1] = theta[:,0] + + +def residual_total_forces(segment,state): + + FT = state.conditions.frames.inertial.total_force_vector + a = state.conditions.frames.inertial.acceleration_vector + m = state.conditions.weights.total_mass + alt_in = state.unknowns.altitudes[:,0] + alt_out = state.conditions.freestream.altitude[:,0] + + state.residuals.forces[:,0] = FT[:,0]/m[:,0] - a[:,0] + state.residuals.forces[:,1] = FT[:,2]/m[:,0] - a[:,2] + state.residuals.forces[:,2] = (alt_in - alt_out)/alt_out[-1] + + return \ No newline at end of file diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py index 3229a80deb..2db54b4a1a 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py @@ -37,7 +37,7 @@ def initialize_conditions(segment,state): alt = t_nondim * (altf-alt0) + alt0 # process velocity vector - v_mag = np.sqrt(q/rho) + v_mag = np.sqrt(2*q/rho) v_z = -climb_rate # z points down v_x = np.sqrt( v_mag**2 - v_z**2 ) diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_EAS_Constant_Rate.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_EAS_Constant_Rate.py index c84a170af2..becc8abb39 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_EAS_Constant_Rate.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_EAS_Constant_Rate.py @@ -32,6 +32,9 @@ def initialize_conditions(segment,state): # discretize on altitude alt = t_nondim * (altf-alt0) + alt0 + # pack conditions + conditions.freestream.altitude[:,0] = alt[:,0] # positive altitude in this context + # determine airspeed from equivalent airspeed SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) # get density for airspeed density = conditions.freestream.density[:,0] @@ -46,5 +49,4 @@ def initialize_conditions(segment,state): # pack conditions conditions.frames.inertial.velocity_vector[:,0] = v_x conditions.frames.inertial.velocity_vector[:,2] = v_z - conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down - conditions.freestream.altitude[:,0] = alt[:,0] # positive altitude in this context \ No newline at end of file + conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down \ No newline at end of file diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py index 224b9015b1..db20b1c76a 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py @@ -13,9 +13,8 @@ # Initialize Conditions # ---------------------------------------------------------------------- -def initialize_conditions(segment,state): +def initialize_conditions_unpack_unknowns(segment,state): - # unpack # unpack user inputs climb_angle = segment.climb_angle mach_number = segment.mach @@ -23,17 +22,23 @@ def initialize_conditions(segment,state): altf = segment.altitude_end t_nondim = state.numerics.dimensionless.control_points conditions = state.conditions - - # Update freestream to get speed of sound - SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) - a = conditions.freestream.speed_of_sound + + # unpack unknowns + throttle = state.unknowns.throttle + theta = state.unknowns.body_angle + alts = state.unknowns.altitudes + # check for initial altitude if alt0 is None: if not state.initials: raise AttributeError('initial altitude not set') alt0 = -1.0 * state.initials.conditions.frames.inertial.position_vector[-1,2] - - # discretize on altitude - alt = t_nondim * (altf-alt0) + alt0 + + # pack conditions + conditions.freestream.altitude[:,0] = alts[:,0] # positive altitude in this context + + # Update freestream to get speed of sound + SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) + a = conditions.freestream.speed_of_sound # process velocity vector v_mag = mach_number * a @@ -43,5 +48,20 @@ def initialize_conditions(segment,state): # pack conditions conditions.frames.inertial.velocity_vector[:,0] = v_x[:,0] conditions.frames.inertial.velocity_vector[:,2] = v_z[:,0] - conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down - conditions.freestream.altitude[:,0] = alt[:,0] # positive altitude in this context + conditions.frames.inertial.position_vector[:,2] = -alts[:,0] # z points down + state.conditions.propulsion.throttle[:,0] = throttle[:,0] + state.conditions.frames.body.inertial_rotations[:,1] = theta[:,0] + +def residual_total_forces(segment,state): + + FT = state.conditions.frames.inertial.total_force_vector + a = state.conditions.frames.inertial.acceleration_vector + m = state.conditions.weights.total_mass + alt_in = state.unknowns.altitudes[:,0] + alt_out = state.conditions.freestream.altitude[:,0] + + state.residuals.forces[:,0] = FT[:,0]/m[:,0] - a[:,0] + state.residuals.forces[:,1] = FT[:,2]/m[:,0] - a[:,2] + state.residuals.forces[:,2] = (alt_in - alt_out)/alt_out[-1] + + return \ No newline at end of file diff --git a/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Mach_Linear_Altitude.py b/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Mach_Linear_Altitude.py new file mode 100644 index 0000000000..2a2788860a --- /dev/null +++ b/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Mach_Linear_Altitude.py @@ -0,0 +1,49 @@ +import SUAVE + + +# ---------------------------------------------------------------------- +# Unpack Unknowns +# ---------------------------------------------------------------------- + +def initialize_conditions(segment,state): + + # unpack + alt0 = segment.altitude_start + altf = segment.altitude_end + xf = segment.distance + mach = segment.mach + conditions = state.conditions + + # Update freestream to get speed of sound + SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) + a = conditions.freestream.speed_of_sound + + # Update freestream to get speed of sound + SUAVE.Methods.Missions.Segments.Common.Aerodynamics.update_atmosphere(segment,state) + a = conditions.freestream.speed_of_sound + + # check for initial altitude + if alt0 is None: + if not state.initials: raise AttributeError('altitude not set') + alt0 = -1.0 * state.initials.conditions.frames.inertial.position_vector[-1,2] + #segment.altitude = alt + + # compute speed, constant with constant altitude + air_speed = mach * a + + # dimensionalize time + t_initial = conditions.frames.inertial.time[0,0] + t_final = xf / air_speed + t_initial + t_nondim = state.numerics.dimensionless.control_points + time = t_nondim * (t_final-t_initial) + t_initial + + # discretize on altitude + alt = t_nondim * (altf-alt0) + alt0 + + segment.altitude = 0.5*(alt0 + altf) + + # pack + state.conditions.freestream.altitude[:,0] = alt[:,0] + state.conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down + state.conditions.frames.inertial.velocity_vector[:,0] = air_speed[:,0] + state.conditions.frames.inertial.time[:,0] = time[:,0] \ No newline at end of file diff --git a/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py b/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py new file mode 100644 index 0000000000..aef0d173c5 --- /dev/null +++ b/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py @@ -0,0 +1,41 @@ +# Constant_Mach_Constant_Altitude_Loiter.py +# +# Created: Jul 2014, SUAVE Team +# Modified: Jan 2016, E. Botero + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +import SUAVE + +# ---------------------------------------------------------------------- +# Initialize Conditions +# ---------------------------------------------------------------------- + +def initialize_conditions(segment,state): + + # unpack + alt = segment.altitude + final_time = segment.time + air_speed = segment.air_speed + conditions = state.conditions + + # check for initial altitude + if alt is None: + if not state.initials: raise AttributeError('altitude not set') + alt = -1.0 * state.initials.conditions.frames.inertial.position_vector[-1,2] + segment.altitude = alt + + # dimensionalize time + t_initial = conditions.frames.inertial.time[0,0] + t_final = final_time + t_initial + t_nondim = state.numerics.dimensionless.control_points + time = t_nondim * (t_final-t_initial) + t_initial + + # pack + state.conditions.freestream.altitude[:,0] = alt + state.conditions.frames.inertial.position_vector[:,2] = -alt # z points down + state.conditions.frames.inertial.velocity_vector[:,0] = air_speed + state.conditions.frames.inertial.time[:,0] = time[:,0] + diff --git a/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Linear_Altitude.py b/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Linear_Altitude.py new file mode 100644 index 0000000000..d61001a1e9 --- /dev/null +++ b/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Linear_Altitude.py @@ -0,0 +1,38 @@ + + + +# ---------------------------------------------------------------------- +# Unpack Unknowns +# ---------------------------------------------------------------------- + +def initialize_conditions(segment,state): + + # unpack + alt0 = segment.altitude_start + altf = segment.altitude_end + xf = segment.distance + air_speed = segment.air_speed + conditions = state.conditions + + # check for initial altitude + if alt0 is None: + if not state.initials: raise AttributeError('altitude not set') + alt0 = -1.0 * state.initials.conditions.frames.inertial.position_vector[-1,2] + #segment.altitude = alt + + # dimensionalize time + t_initial = conditions.frames.inertial.time[0,0] + t_final = xf / air_speed + t_initial + t_nondim = state.numerics.dimensionless.control_points + time = t_nondim * (t_final-t_initial) + t_initial + + # discretize on altitude + alt = t_nondim * (altf-alt0) + alt0 + + segment.altitude = 0.5*(alt0 + altf) + + # pack + state.conditions.freestream.altitude[:,0] = alt[:,0] + state.conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down + state.conditions.frames.inertial.velocity_vector[:,0] = air_speed + state.conditions.frames.inertial.time[:,0] = time[:,0] \ No newline at end of file From 62633bf2d09b27dfe091edd3e58ff7e2a4a8ecdf Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Mon, 26 Jun 2017 16:40:09 -0700 Subject: [PATCH 03/14] adding optimized segments --- .../Climb/Constant_Dynamic_Pressure_Constant_Angle.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py index e5c780492a..89b5123a0c 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py @@ -1,7 +1,8 @@ # Constant_Dynamic_Pressure_Constant_Rate.py # -# Created: -# Modified: Feb 2016, Andrew Wendorff +# Created: Jun 2017, E. Botero +# Modified: + # ---------------------------------------------------------------------- # Imports # ---------------------------------------------------------------------- @@ -26,8 +27,8 @@ def __defaults__(self): # User inputs # -------------------------------------------------------------- self.altitude_start = None # Optional - self.altitude_end = 10. * Units.km - self.climb_angle = 3. * Units.degrees + self.altitude_end = 10. * Units.km + self.climb_angle = 3. * Units.degrees self.dynamic_pressure = 1600 * Units.pascals # -------------------------------------------------------------- @@ -45,7 +46,6 @@ def __defaults__(self): initialize = self.process.initialize initialize.conditions = Methods.Climb.Constant_Dynamic_Pressure_Constant_Angle.initialize_conditions_unpack_unknowns - # Unpack Unknowns iterate = self.process.iterate iterate.unknowns.mission = Methods.Climb.Constant_Dynamic_Pressure_Constant_Angle.initialize_conditions_unpack_unknowns From 37f2c07a1a5c4478b377175cf623542005e0a002 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Mon, 26 Jun 2017 16:59:30 -0700 Subject: [PATCH 04/14] rearranging and fixing headers --- .../Climb/Constant_Dynamic_Pressure_Constant_Angle.py | 2 +- .../Segments/Climb/Constant_Mach_Constant_Angle.py | 5 +++-- .../Segments/Climb/Constant_Mach_Linear_Altitude.py | 9 ++++----- .../Segments/Climb/Constant_Speed_Linear_Altitude.py | 4 ++++ .../Analyses/Mission/Segments/Climb/Unknown_Throttle.py | 3 ++- .../Cruise/Constant_Speed_Constant_Altitude_Loiter.py | 6 +++--- .../Climb/Constant_Dynamic_Pressure_Constant_Angle.py | 6 +++--- .../Climb/Constant_Dynamic_Pressure_Constant_Rate.py | 4 ++-- .../Segments/Climb/Constant_Mach_Constant_Angle.py | 1 + .../{Cruise => Climb}/Constant_Mach_Linear_Altitude.py | 0 .../{Cruise => Climb}/Constant_Speed_Linear_Altitude.py | 0 .../Segments/Climb/Linear_Speed_Constant_Rate.py | 3 ++- trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py | 3 ++- 13 files changed, 27 insertions(+), 19 deletions(-) rename trunk/SUAVE/Methods/Missions/Segments/{Cruise => Climb}/Constant_Mach_Linear_Altitude.py (100%) rename trunk/SUAVE/Methods/Missions/Segments/{Cruise => Climb}/Constant_Speed_Linear_Altitude.py (100%) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py index 89b5123a0c..b3ac7f6eae 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py @@ -1,4 +1,4 @@ -# Constant_Dynamic_Pressure_Constant_Rate.py +# Constant_Dynamic_Pressure_Constant_Angle.py # # Created: Jun 2017, E. Botero # Modified: diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py index 7f29d2224a..73d9a2e023 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Constant_Angle.py @@ -1,7 +1,8 @@ # Constant_Mach_Constant_Angle.py # -# Created: -# Modified: Feb 2016, Andrew Wendorff +# Created: June 2017, E. Botero +# Modified: + # ---------------------------------------------------------------------- # Imports # ---------------------------------------------------------------------- diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py index 4484189f89..1cd51acb2d 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Mach_Linear_Altitude.py @@ -1,21 +1,20 @@ +# Constant_Mach_Linear_Altitude.py +# +# Created: June 2017, E. Botero +# Modified: # ---------------------------------------------------------------------- # Imports # ---------------------------------------------------------------------- # SUAVE imports -from SUAVE.Analyses.Mission.Segments import Aerodynamic -from SUAVE.Analyses.Mission.Segments import Conditions from SUAVE.Analyses.Mission.Segments.Cruise import Constant_Speed_Linear_Altitude from SUAVE.Methods.Missions import Segments as Methods -from SUAVE.Analyses import Process - # Units from SUAVE.Core import Units - # ---------------------------------------------------------------------- # Segment # ---------------------------------------------------------------------- diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py index 49d548bd63..8796c59d63 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py @@ -1,3 +1,7 @@ +# Constant_Speed_Constant_Angle.py +# +# Created: June 2017, E. Botero +# Modified: # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py index 889bb1496f..69202f42da 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py @@ -1,7 +1,8 @@ # Unknown_Throttle.py # # Created: -# Modified: Feb 2016, Andrew Wendorff +# Modified: Feb 2016, A. Wendorff +# Jun 2017, E. Botero # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py index a224f603db..11240a9ea5 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Cruise/Constant_Speed_Constant_Altitude_Loiter.py @@ -1,7 +1,7 @@ -# Constant_Mach_Constant_Altitude_Loiter.py +# Constant_Speed_Constant_Altitude_Loiter.py # -# Created: -# Modified: Feb 2016, Andrew Wendorff +# Created: Jun 2017, E. Botero +# Modified: # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py index d7b91c5564..74276fa7cf 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py @@ -1,7 +1,7 @@ -# Constant_Dynamic_Pressure_Constant_Rate.py +# Constant_Dynamic_Pressure_Constant_Angle.py # -# Created: Jul 2014, SUAVE Team -# Modified: Jan 2016, E. Botero +# Created: Jun 2017, E. Botero +# Modified: # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py index 2db54b4a1a..59a3add593 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Rate.py @@ -1,7 +1,7 @@ # Constant_Dynamic_Pressure_Constant_Rate.py # -# Created: Jul 2014, SUAVE Team -# Modified: Jan 2016, E. Botero +# Created: Jan 2016, E. Botero +# Modified: Jun 2017, E. Botero # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py index db20b1c76a..b48d680e3c 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py @@ -2,6 +2,7 @@ # # Created: Jul 2014, SUAVE Team # Modified: Jan 2016, E. Botero +# Jun 2017, E. Botero # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Mach_Linear_Altitude.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Linear_Altitude.py similarity index 100% rename from trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Mach_Linear_Altitude.py rename to trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Linear_Altitude.py diff --git a/trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Linear_Altitude.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Speed_Linear_Altitude.py similarity index 100% rename from trunk/SUAVE/Methods/Missions/Segments/Cruise/Constant_Speed_Linear_Altitude.py rename to trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Speed_Linear_Altitude.py diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py index 28938a0835..6799aa2d9d 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py @@ -1,4 +1,4 @@ -# Linear_Mach_Constant_Rate.py +# Linear_Speed_Constant_Rate.py # # Created: Jul 2014, SUAVE Team # Modified: Jan 2016, E. Botero @@ -8,6 +8,7 @@ # ---------------------------------------------------------------------- import numpy as np +import SUAVE # ---------------------------------------------------------------------- # Initialize Conditions diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py index 793ed0752e..bd7b98db37 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py @@ -9,4 +9,5 @@ import Constant_Dynamic_Pressure_Constant_Rate import Constant_Speed_Constant_Angle import Constant_Speed_Constant_Angle_Noise -import Constant_EAS_Constant_Rate \ No newline at end of file +import Constant_EAS_Constant_Rate +import Constant_Mach_Linear_Altitude \ No newline at end of file From fd376209a120ddbd81e36e07e2679abd515f446e Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Mon, 26 Jun 2017 17:05:58 -0700 Subject: [PATCH 05/14] optimized temporary files --- .../Mission/Segments/Climb/Optimized.py | 133 ++++++++++++++++++ .../Missions/Segments/Climb/Optimized.py | 122 ++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py create mode 100644 trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py new file mode 100644 index 0000000000..f2d218e8e7 --- /dev/null +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py @@ -0,0 +1,133 @@ +# Optimized.py +# +# Created: Mar 2016, E. Botero +# Modified: + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +# SUAVE imports +from SUAVE.Analyses.Mission.Segments import Aerodynamic +from SUAVE.Analyses.Mission.Segments import Conditions + +from SUAVE.Methods.Missions import Segments as Methods + +from SUAVE.Analyses import Process + +# Units +from SUAVE.Core import Units +import SUAVE + +# ---------------------------------------------------------------------- +# Segment +# ---------------------------------------------------------------------- + +class Optimized(Aerodynamic): + + def __defaults__(self): + + # -------------------------------------------------------------- + # User inputs + # -------------------------------------------------------------- + self.altitude_start = None + self.altitude_end = None + self.air_speed_start = None + self.air_speed_end = None + self.objective = None # This will be a key + self.minimize = True + self.CL_limit = 1.e20 + + + # -------------------------------------------------------------- + # State + # -------------------------------------------------------------- + + # conditions + self.state.conditions.update( Conditions.Aerodynamics() ) + # initials and unknowns + ones_row = self.state.ones_row + self.state.unknowns.throttle = ones_row(1) * 0.5 + self.state.unknowns.body_angle = ones_row(1) * 10.0 + self.state.unknowns.flight_path_angle = ones_row(1) * 5.0 + self.state.unknowns.velocity = ones_row(1) * 1.0 + self.state.residuals.forces = ones_row(2) * 0.0 + self.state.inputs_last = None + self.state.objective_value = 0.0 + self.state.constraint_values = 0.0 + + # -------------------------------------------------------------- + # The Solving Process + # -------------------------------------------------------------- + + # -------------------------------------------------------------- + # Initialize - before iteration + # -------------------------------------------------------------- + initialize = self.process.initialize + + initialize.expand_state = Methods.expand_state + initialize.unknowns = Methods.Climb.Optimized.initialize_unknowns + initialize.differentials = Methods.Common.Numerics.initialize_differentials_dimensionless + initialize.conditions = SUAVE.Methods.skip + + # -------------------------------------------------------------- + # Converge - starts iteration + # -------------------------------------------------------------- + converge = self.process.converge + + converge.converge_root = Methods.converge_opt + + # -------------------------------------------------------------- + # Iterate - this is iterated + # -------------------------------------------------------------- + iterate = self.process.iterate + + # Update Initials + iterate.initials = Process() + iterate.initials.time = Methods.Common.Frames.initialize_time + iterate.initials.weights = Methods.Common.Weights.initialize_weights + iterate.initials.inertial_position = Methods.Common.Frames.initialize_inertial_position + iterate.initials.planet_position = Methods.Common.Frames.initialize_planet_position + + # Unpack Unknowns + iterate.unknowns = Process() + iterate.unknowns.mission = Methods.Climb.Optimized.unpack_unknowns + + # Update Conditions + iterate.conditions = Process() + iterate.conditions.differentials = Methods.Climb.Optimized.update_differentials + iterate.conditions.acceleration = Methods.Common.Frames.update_acceleration + iterate.conditions.altitude = Methods.Common.Aerodynamics.update_altitude + iterate.conditions.atmosphere = Methods.Common.Aerodynamics.update_atmosphere + iterate.conditions.gravity = Methods.Common.Weights.update_gravity + iterate.conditions.freestream = Methods.Common.Aerodynamics.update_freestream + iterate.conditions.orientations = Methods.Common.Frames.update_orientations + iterate.conditions.aerodynamics = Methods.Common.Aerodynamics.update_aerodynamics + iterate.conditions.stability = Methods.Common.Aerodynamics.update_stability + iterate.conditions.propulsion = Methods.Common.Energy.update_thrust + iterate.conditions.weights = Methods.Common.Weights.update_weights + iterate.conditions.forces = Methods.Common.Frames.update_forces + iterate.conditions.planet_position = Methods.Common.Frames.update_planet_position + + # Solve Residuals + iterate.residuals = Process() + iterate.residuals.total_forces = Methods.Climb.Common.residual_total_forces + + # Set outputs + iterate.outputs = Process() + iterate.outputs.objective = Methods.Climb.Optimized.objective + iterate.outputs.constraints = Methods.Climb.Optimized.constraints + iterate.outputs.cache_inputs = Methods.Climb.Optimized.cache_inputs + + # -------------------------------------------------------------- + # Finalize - after iteration + # -------------------------------------------------------------- + finalize = self.process.finalize + + # Post Processing + finalize.post_process = Process() + finalize.post_process.inertial_position = Methods.Common.Frames.integrate_inertial_horizontal_position + finalize.post_process.stability = Methods.Common.Aerodynamics.update_stability + + return + diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py new file mode 100644 index 0000000000..9bc96d755d --- /dev/null +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py @@ -0,0 +1,122 @@ +# Optimized.py +# +# Created: Dec 2016, E. Botero +# Modified: + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- +import numpy as np +from SUAVE.Core import Units + +# ---------------------------------------------------------------------- +# Unpack Unknowns +# ---------------------------------------------------------------------- + +def unpack_unknowns(segment,state): + + # unpack unknowns and givens + throttle = state.unknowns.throttle + theta1 = state.unknowns.body_angle + gamma1 = state.unknowns.flight_path_angle + vel = state.unknowns.velocity + alt0 = segment.altitude_start + altf = segment.altitude_end + vel0 = segment.air_speed_start + velf = segment.air_speed_end + + # Overide the speeds + #v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) + #v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) + v_mag = np.concatenate([[[vel0]],vel*vel0]) + #gamma = np.concatenate([[[0]],gamma1,[[0]]]) + #gamma = np.concatenate([gamma1* Units.degree,[[0]]]) + gamma = gamma1 * Units.degree + + # process velocity vector + v_x = v_mag * np.cos(gamma) + v_z = -v_mag * np.sin(gamma) + + theta = theta1 * Units.degrees + + #print v_mag + + # apply unknowns and pack conditions + state.conditions.propulsion.throttle[:,0] = throttle[:,0] + state.conditions.frames.body.inertial_rotations[:,1] = theta[:,0] + state.conditions.frames.inertial.velocity_vector[:,0] = v_x[:,0] + state.conditions.frames.inertial.velocity_vector[:,2] = v_z[:,0] + +def initialize_unknowns(segment,state): + + # unpack unknowns and givens + gamma = state.unknowns.flight_path_angle + vel = state.unknowns.velocity + v0 = segment.air_speed_start + ones = state.ones_row(1) + ones_m1 = state.ones_row_m1(1) + ones_m2 = state.ones_row_m2(1) + + # repack + state.unknowns.velocity = ones_m1 * vel[0] + state.unknowns.flight_path_angle = ones * gamma[0] + +def update_differentials(segment,state): + + # unpack + numerics = state.numerics + conditions = state.conditions + x = numerics.dimensionless.control_points + D = numerics.dimensionless.differentiate + I = numerics.dimensionless.integrate + r = state.conditions.frames.inertial.position_vector + v = state.conditions.frames.inertial.velocity_vector + alt0 = segment.altitude_start + altf = segment.altitude_end + + dz = altf - alt0 + vz = -v[:,2,None] # maintain column array + + # get overall time step + dt = (dz/np.dot(I,vz))[-1] + + # rescale operators + x = x * dt + D = D / dt + I = I * dt + + # Calculate the altitudes + alt = np.dot(I,vz) + segment.altitude_start + + # pack + t_initial = state.conditions.frames.inertial.time[0,0] + numerics.time.control_points = x + numerics.time.differentiate = D + numerics.time.integrate = I + conditions.frames.inertial.time[:,0] = t_initial + x[:,0] + conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down + conditions.freestream.altitude[:,0] = alt[:,0] # positive altitude in this context + + return + +def objective(segment,state): + + if segment.objective is not None: + if segment.minimize ==True: + objective = eval('state.'+segment.objective) + else: + objective = -eval('state.'+segment.objective) + else: + objective = 0. + + state.objective_value = objective + + +def constraints(segment,state): + + # Residuals + state.constraint_values = state.residuals.pack_array() + + +def cache_inputs(segment,state): + state.inputs_last = state.unknowns.pack_array() \ No newline at end of file From 26e2c69a9fab32cd2ba1cb9e840d724ab0f8addc Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Wed, 28 Jun 2017 13:47:27 -0700 Subject: [PATCH 06/14] fixing init --- trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py index bd7b98db37..c803022c0c 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/__init__.py @@ -10,4 +10,5 @@ import Constant_Speed_Constant_Angle import Constant_Speed_Constant_Angle_Noise import Constant_EAS_Constant_Rate -import Constant_Mach_Linear_Altitude \ No newline at end of file +import Constant_Mach_Linear_Altitude +import Optimized \ No newline at end of file From dd9233b075b24049281d520ac57721e3339614a2 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Wed, 28 Jun 2017 17:02:32 -0700 Subject: [PATCH 07/14] updating optimized segments --- .../Mission/Segments/Climb/Optimized.py | 6 +- .../Mission/Segments/Conditions/Conditions.py | 9 ++ .../Missions/Segments/Climb/Optimized.py | 27 ++-- .../Methods/Missions/Segments/__init__.py | 1 + .../Methods/Missions/Segments/optimize.py | 118 ++++++++++++++++++ 5 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 trunk/SUAVE/Methods/Missions/Segments/optimize.py diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py index f2d218e8e7..96264e14a4 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py @@ -47,9 +47,9 @@ def __defaults__(self): self.state.conditions.update( Conditions.Aerodynamics() ) # initials and unknowns ones_row = self.state.ones_row - self.state.unknowns.throttle = ones_row(1) * 0.5 - self.state.unknowns.body_angle = ones_row(1) * 10.0 - self.state.unknowns.flight_path_angle = ones_row(1) * 5.0 + self.state.unknowns.throttle = ones_row(1) * 0.8 + self.state.unknowns.body_angle = ones_row(1) * 5.0 * Units.degrees + self.state.unknowns.flight_path_angle = ones_row(1) * 3.0 * Units.degrees self.state.unknowns.velocity = ones_row(1) * 1.0 self.state.residuals.forces = ones_row(2) * 0.0 self.state.inputs_last = None diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py b/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py index 9149a2cd42..948bfcbe2f 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py @@ -26,6 +26,15 @@ def ones_row(self,cols): """ returns a row vector of ones with given number of columns """ return np.ones([self._size,cols]) + def ones_row_m1(self,cols): + """ returns a row vector of ones with given number of columns """ + return np.ones([self._size-1,cols]) + + def ones_row_m2(self,cols): + """ returns a row vector of ones with given number of columns """ + return np.ones([self._size-2,cols]) + + def expand_rows(self,rows): # store diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py index 9bc96d755d..ca6b3bf794 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py @@ -17,8 +17,8 @@ def unpack_unknowns(segment,state): # unpack unknowns and givens throttle = state.unknowns.throttle - theta1 = state.unknowns.body_angle - gamma1 = state.unknowns.flight_path_angle + theta = state.unknowns.body_angle + gamma = state.unknowns.flight_path_angle vel = state.unknowns.velocity alt0 = segment.altitude_start altf = segment.altitude_end @@ -26,20 +26,14 @@ def unpack_unknowns(segment,state): velf = segment.air_speed_end # Overide the speeds - #v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) - #v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) - v_mag = np.concatenate([[[vel0]],vel*vel0]) - #gamma = np.concatenate([[[0]],gamma1,[[0]]]) - #gamma = np.concatenate([gamma1* Units.degree,[[0]]]) - gamma = gamma1 * Units.degree + if segment.air_speed_end is None: + v_mag = np.concatenate([[[vel0]],vel*vel0]) + elif segment.air_speed_end is not None: + v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) # process velocity vector v_x = v_mag * np.cos(gamma) v_z = -v_mag * np.sin(gamma) - - theta = theta1 * Units.degrees - - #print v_mag # apply unknowns and pack conditions state.conditions.propulsion.throttle[:,0] = throttle[:,0] @@ -53,14 +47,21 @@ def initialize_unknowns(segment,state): gamma = state.unknowns.flight_path_angle vel = state.unknowns.velocity v0 = segment.air_speed_start + vf = segment.air_speed_end ones = state.ones_row(1) ones_m1 = state.ones_row_m1(1) ones_m2 = state.ones_row_m2(1) # repack - state.unknowns.velocity = ones_m1 * vel[0] state.unknowns.flight_path_angle = ones * gamma[0] + # Depending if the final airspeed is specified + if segment.air_speed_end is None: + state.unknowns.velocity = ones_m1 * vel[0] + elif segment.air_speed_end is not None: + state.unknowns.velocity = np.reshape(np.linspace(v0,vf,len(ones_m2)),np.shape(ones_m2)) + + def update_differentials(segment,state): # unpack diff --git a/trunk/SUAVE/Methods/Missions/Segments/__init__.py b/trunk/SUAVE/Methods/Missions/Segments/__init__.py index 9bd94d1d01..e41d407ab4 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/__init__.py +++ b/trunk/SUAVE/Methods/Missions/Segments/__init__.py @@ -1,6 +1,7 @@ from converge_root import converge_root from expand_state import expand_state +from optimize import converge_opt import Common import Cruise diff --git a/trunk/SUAVE/Methods/Missions/Segments/optimize.py b/trunk/SUAVE/Methods/Missions/Segments/optimize.py new file mode 100644 index 0000000000..89a6873110 --- /dev/null +++ b/trunk/SUAVE/Methods/Missions/Segments/optimize.py @@ -0,0 +1,118 @@ +# optimize.py +# +# Created: Dec 2016, E. Botero +# Modified: Jun 2017, E. Botero + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + +import scipy.optimize as opt +import numpy as np + +from SUAVE.Core.Arrays import array_type +from SUAVE.Core import Units + +# ---------------------------------------------------------------------- +# Converge Root +# ---------------------------------------------------------------------- + +def converge_opt(segment,state): + + # pack up the array + unknowns = state.unknowns.pack_array() + + # Have the optimizer call the wrapper + obj = lambda unknowns:get_objective(unknowns,(segment,state)) + econ = lambda unknowns:get_econstraints(unknowns,(segment,state)) + iecon = lambda unknowns:get_ieconstraints(unknowns,(segment,state)) + + # Setup the bnds of the problem + bnds = make_bnds(unknowns, (segment,state)) + + # Solve the problem + unknowns = opt.fmin_slsqp(obj,unknowns,f_eqcons=econ,f_ieqcons=iecon,bounds=bnds,iter=2000) + + return + +# ---------------------------------------------------------------------- +# Helper Functions +# ---------------------------------------------------------------------- + + +def get_objective(unknowns,(segment,state)): + + if isinstance(unknowns,array_type): + state.unknowns.unpack_array(unknowns) + else: + state.unknowns = unknowns + + if not np.all(state.inputs_last == state.unknowns): + segment.process.iterate(segment,state) + + objective = state.objective_value + + return objective + +def get_econstraints(unknowns,(segment,state)): + + if isinstance(unknowns,array_type): + state.unknowns.unpack_array(unknowns) + else: + state.unknowns = unknowns + + if not np.all(state.inputs_last == state.unknowns): + segment.process.iterate(segment,state) + + constraints = state.constraint_values + + return constraints + + +def make_bnds(unknowns,(segment,state)): + + ones = state.ones_row(1) + ones_m1 = state.ones_row_m1(1) + ones_m2 = state.ones_row_m2(1) + + throttle_bnds = ones*(0.,1.) + body_angle = ones*(0., 50.) + gamma = ones*(0., 50.) + + if segment.air_speed_end is None: + vels = ones_m1*(0.,2000.) + elif segment.air_speed_end is not None: + vels = ones_m2*(0.,2000.) + + bnds = np.vstack([vels,throttle_bnds,gamma,body_angle]) + + bnds = list(map(tuple, bnds)) + + return bnds + + +def get_ieconstraints(unknowns,(segment,state)): + + if isinstance(unknowns,array_type): + state.unknowns.unpack_array(unknowns) + else: + state.unknowns = unknowns + + if not np.all(state.inputs_last == state.unknowns): + segment.process.iterate(segment,state) + + # Time goes forward, not backward + t_final = state.conditions.frames.inertial.time[-1,0] + constraints = (state.conditions.frames.inertial.time[1:,0] - state.conditions.frames.inertial.time[0:-1,0])/t_final + + # Less than a specified CL limit + CL_limit = segment.CL_limit + constraints2 = (CL_limit - state.conditions.aerodynamics.lift_coefficient[:,0])/CL_limit + + # Altitudes are greater than 0 + constraints3 = state.conditions.freestream.altitude[:,0]/segment.altitude_end + + constraints = np.concatenate((constraints,constraints2,constraints3)) + + return constraints + From 7ab04ec67b9a9abb8ac4e0a6b6e953ea4e9626da Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Wed, 28 Jun 2017 17:09:07 -0700 Subject: [PATCH 08/14] updating a few headers --- .../Mission/Segments/Conditions/Conditions.py | 3 ++- .../Climb/Constant_Mach_Linear_Altitude.py | 15 +++++++++++---- .../Climb/Constant_Speed_Linear_Altitude.py | 7 ++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py b/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py index 948bfcbe2f..2645087cb2 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Conditions/Conditions.py @@ -1,7 +1,8 @@ # Conditions.py # # Created: -# Modified: Feb 2016, Andrew Wendorff +# Modified: Feb 2016, A. Wendorff +# Jun 2017, E. Botero # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Linear_Altitude.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Linear_Altitude.py index 2a2788860a..b3a8be4f41 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Linear_Altitude.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Linear_Altitude.py @@ -1,10 +1,18 @@ +# Constant_Mach_Linear_Altitude.py +# Created: Jul 2014, SUAVE Team +# Modified: Jun 2017, E. Botero + +# ---------------------------------------------------------------------- +# Imports +# ---------------------------------------------------------------------- + + import SUAVE # ---------------------------------------------------------------------- -# Unpack Unknowns +# initialize conditions # ---------------------------------------------------------------------- - def initialize_conditions(segment,state): # unpack @@ -26,8 +34,7 @@ def initialize_conditions(segment,state): if alt0 is None: if not state.initials: raise AttributeError('altitude not set') alt0 = -1.0 * state.initials.conditions.frames.inertial.position_vector[-1,2] - #segment.altitude = alt - + # compute speed, constant with constant altitude air_speed = mach * a diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Speed_Linear_Altitude.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Speed_Linear_Altitude.py index d61001a1e9..add46b2947 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Speed_Linear_Altitude.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Speed_Linear_Altitude.py @@ -1,8 +1,9 @@ - - +# Constant_Speed_Linear_Altitude.py +# Created: Jul 2014, SUAVE Team +# Modified: Jun 2017, E. Botero # ---------------------------------------------------------------------- -# Unpack Unknowns +# initialize conditions # ---------------------------------------------------------------------- def initialize_conditions(segment,state): From 1aff38608d88cff9d9f70e33fc0124680c488b43 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Fri, 7 Jul 2017 10:25:27 -0700 Subject: [PATCH 09/14] updates that were accidently applied to the wrong branch done right --- .../Segments/Climb/Constant_Speed_Linear_Altitude.py | 6 +++--- .../Analyses/Mission/Segments/Climb/Unknown_Throttle.py | 2 +- .../Climb/Constant_Dynamic_Pressure_Constant_Angle.py | 2 ++ .../Segments/Climb/Constant_Mach_Constant_Angle.py | 2 ++ trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py | 4 ++++ trunk/SUAVE/Methods/Missions/Segments/optimize.py | 8 ++++---- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py index 8796c59d63..67192764e1 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Constant_Speed_Linear_Altitude.py @@ -1,7 +1,7 @@ -# Constant_Speed_Constant_Angle.py +# Constant_Speed_Linear_Altitude.py # -# Created: June 2017, E. Botero -# Modified: +# Created: +# Modified: Jun 2017, E. Botero # ---------------------------------------------------------------------- # Imports diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py index 69202f42da..4e7ea86f53 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Unknown_Throttle.py @@ -44,7 +44,7 @@ def __defaults__(self): # initials and unknowns ones_row = self.state.ones_row self.state.unknowns.throttle = ones_row(1) * 0.5 - self.state.unknowns.body_angle = ones_row(1) * 0.01 + self.state.unknowns.body_angle = ones_row(1) * 1.0 * Units.degrees self.state.residuals.forces = ones_row(2) * 0.0 # -------------------------------------------------------------- diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py index 74276fa7cf..05d38f7acd 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Dynamic_Pressure_Constant_Angle.py @@ -60,12 +60,14 @@ def initialize_conditions_unpack_unknowns(segment,state): def residual_total_forces(segment,state): + # Unpack results FT = state.conditions.frames.inertial.total_force_vector a = state.conditions.frames.inertial.acceleration_vector m = state.conditions.weights.total_mass alt_in = state.unknowns.altitudes[:,0] alt_out = state.conditions.freestream.altitude[:,0] + # Residual in X and Z, as well as a residual on the guess altitude state.residuals.forces[:,0] = FT[:,0]/m[:,0] - a[:,0] state.residuals.forces[:,1] = FT[:,2]/m[:,0] - a[:,2] state.residuals.forces[:,2] = (alt_in - alt_out)/alt_out[-1] diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py index b48d680e3c..75f7c420b6 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Constant_Mach_Constant_Angle.py @@ -55,12 +55,14 @@ def initialize_conditions_unpack_unknowns(segment,state): def residual_total_forces(segment,state): + # Unpack results FT = state.conditions.frames.inertial.total_force_vector a = state.conditions.frames.inertial.acceleration_vector m = state.conditions.weights.total_mass alt_in = state.unknowns.altitudes[:,0] alt_out = state.conditions.freestream.altitude[:,0] + # Residual in X and Z, as well as a residual on the guess altitude state.residuals.forces[:,0] = FT[:,0]/m[:,0] - a[:,0] state.residuals.forces[:,1] = FT[:,2]/m[:,0] - a[:,2] state.residuals.forces[:,2] = (alt_in - alt_out)/alt_out[-1] diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py index ca6b3bf794..3d126ad624 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py @@ -48,6 +48,8 @@ def initialize_unknowns(segment,state): vel = state.unknowns.velocity v0 = segment.air_speed_start vf = segment.air_speed_end + + # Ones, N sized vector, and N-1 as well as N-2 vectors ones = state.ones_row(1) ones_m1 = state.ones_row_m1(1) ones_m2 = state.ones_row_m2(1) @@ -102,6 +104,7 @@ def update_differentials(segment,state): def objective(segment,state): + # If you have an objective set, either maximize or minimize if segment.objective is not None: if segment.minimize ==True: objective = eval('state.'+segment.objective) @@ -109,6 +112,7 @@ def objective(segment,state): objective = -eval('state.'+segment.objective) else: objective = 0. + # No objective is just solved constraint like a normal mission state.objective_value = objective diff --git a/trunk/SUAVE/Methods/Missions/Segments/optimize.py b/trunk/SUAVE/Methods/Missions/Segments/optimize.py index 89a6873110..cb5578a3b7 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/optimize.py +++ b/trunk/SUAVE/Methods/Missions/Segments/optimize.py @@ -103,16 +103,16 @@ def get_ieconstraints(unknowns,(segment,state)): # Time goes forward, not backward t_final = state.conditions.frames.inertial.time[-1,0] - constraints = (state.conditions.frames.inertial.time[1:,0] - state.conditions.frames.inertial.time[0:-1,0])/t_final + time_con = (state.conditions.frames.inertial.time[1:,0] - state.conditions.frames.inertial.time[0:-1,0])/t_final # Less than a specified CL limit CL_limit = segment.CL_limit - constraints2 = (CL_limit - state.conditions.aerodynamics.lift_coefficient[:,0])/CL_limit + CL_con = (CL_limit - state.conditions.aerodynamics.lift_coefficient[:,0])/CL_limit # Altitudes are greater than 0 - constraints3 = state.conditions.freestream.altitude[:,0]/segment.altitude_end + alt_con = state.conditions.freestream.altitude[:,0]/segment.altitude_end - constraints = np.concatenate((constraints,constraints2,constraints3)) + constraints = np.concatenate((tim_con,CL_con,alt_con)) return constraints From 3c076bf32ab1ff7924a60ef9ab41e0fcb7999e18 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Wed, 12 Jul 2017 11:34:10 -0700 Subject: [PATCH 10/14] updates to optimized segments --- .../Mission/Segments/Climb/Optimized.py | 5 +- .../Climb/Linear_Speed_Constant_Rate.py | 9 ++- .../Missions/Segments/Climb/Optimized.py | 63 ++++++++++++------- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py index 96264e14a4..7b3ed6ccfd 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py @@ -37,6 +37,7 @@ def __defaults__(self): self.objective = None # This will be a key self.minimize = True self.CL_limit = 1.e20 + self.seed_climb_rate = 100. * Units['feet/min'] # -------------------------------------------------------------- @@ -64,9 +65,9 @@ def __defaults__(self): # Initialize - before iteration # -------------------------------------------------------------- initialize = self.process.initialize - initialize.expand_state = Methods.expand_state - initialize.unknowns = Methods.Climb.Optimized.initialize_unknowns + initialize.solved_mission = Methods.Climb.Optimized.solve_linear_speed_constant_rate + #initialize.unknowns = Methods.Climb.Optimized.initialize_unknowns initialize.differentials = Methods.Common.Numerics.initialize_differentials_dimensionless initialize.conditions = SUAVE.Methods.skip diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py index 6799aa2d9d..6d8cc0d575 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Linear_Speed_Constant_Rate.py @@ -8,7 +8,6 @@ # ---------------------------------------------------------------------- import numpy as np -import SUAVE # ---------------------------------------------------------------------- # Initialize Conditions @@ -18,9 +17,9 @@ def initialize_conditions(segment,state): # unpack # unpack user inputs - climb_rate = self.climb_rate - Vo = self.air_speed_start - Vf = self.air_speed_end + climb_rate = segment.climb_rate + Vo = segment.air_speed_start + Vf = segment.air_speed_end alt0 = segment.altitude_start altf = segment.altitude_end t_nondim = state.numerics.dimensionless.control_points @@ -40,7 +39,7 @@ def initialize_conditions(segment,state): v_x = np.sqrt( v_mag**2 - v_z**2 ) # pack conditions - conditions.frames.inertial.velocity_vector[:,0] = v_x + conditions.frames.inertial.velocity_vector[:,0] = v_x[:,0] conditions.frames.inertial.velocity_vector[:,2] = v_z conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down conditions.freestream.altitude[:,0] = alt[:,0] # positive altitude in this context \ No newline at end of file diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py index 3d126ad624..0184aae153 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py @@ -8,6 +8,7 @@ # ---------------------------------------------------------------------- import numpy as np from SUAVE.Core import Units +import SUAVE # ---------------------------------------------------------------------- # Unpack Unknowns @@ -41,28 +42,6 @@ def unpack_unknowns(segment,state): state.conditions.frames.inertial.velocity_vector[:,0] = v_x[:,0] state.conditions.frames.inertial.velocity_vector[:,2] = v_z[:,0] -def initialize_unknowns(segment,state): - - # unpack unknowns and givens - gamma = state.unknowns.flight_path_angle - vel = state.unknowns.velocity - v0 = segment.air_speed_start - vf = segment.air_speed_end - - # Ones, N sized vector, and N-1 as well as N-2 vectors - ones = state.ones_row(1) - ones_m1 = state.ones_row_m1(1) - ones_m2 = state.ones_row_m2(1) - - # repack - state.unknowns.flight_path_angle = ones * gamma[0] - - # Depending if the final airspeed is specified - if segment.air_speed_end is None: - state.unknowns.velocity = ones_m1 * vel[0] - elif segment.air_speed_end is not None: - state.unknowns.velocity = np.reshape(np.linspace(v0,vf,len(ones_m2)),np.shape(ones_m2)) - def update_differentials(segment,state): @@ -112,7 +91,7 @@ def objective(segment,state): objective = -eval('state.'+segment.objective) else: objective = 0. - # No objective is just solved constraint like a normal mission + # No objective is just solved constraint like a normal mission state.objective_value = objective @@ -124,4 +103,40 @@ def constraints(segment,state): def cache_inputs(segment,state): - state.inputs_last = state.unknowns.pack_array() \ No newline at end of file + state.inputs_last = state.unknowns.pack_array() + + +def solve_linear_speed_constant_rate(segment,state): + + mini_mission = SUAVE.Analyses.Mission.Sequential_Segments() + + LSCR = SUAVE.Analyses.Mission.Segments.Climb.Linear_Speed_Constant_Rate() + LSCR.air_speed_start = segment.air_speed_start + + if segment.air_speed_end is not None: + LSCR.air_speed_end = segment.air_speed_end + else: + LSCR.air_speed_end = segment.air_speed_start + + LSCR.altitude_start = segment.altitude_start + LSCR.altitude_end = segment.altitude_end + LSCR.climb_rate = segment.seed_climb_rate + LSCR.analyses = segment.analyses + LSCR.state.conditions = state.conditions + LSCR.state.numerics = state.numerics + mini_mission.append_segment(LSCR) + + results = mini_mission.evaluate() + LSCR_res = results.segments.analysis + + state.unknowns.body_angle = LSCR_res.unknowns.body_angle + state.unknowns.throttle = LSCR_res.unknowns.throttle + state.unknowns.flight_path_angle = LSCR_res.unknowns.body_angle - LSCR_res.conditions.aerodynamics.angle_of_attack + + # Make the velocity vector + v_mag = np.linalg.norm(LSCR_res.conditions.frames.inertial.velocity_vector,axis=1) + + if segment.air_speed_end is None: + state.unknowns.velocity = np.reshape(v_mag[1:],(-1, 1)) + elif segment.air_speed_end is not None: + state.unknowns.velocity = np.reshape(v_mag[1:-1],(-1, 1)) \ No newline at end of file From e1fc1e6915440603819af63a2acb357ed9b50807 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Wed, 12 Jul 2017 11:47:17 -0700 Subject: [PATCH 11/14] fixing scaling bug --- trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py index 0184aae153..f9318cf07b 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py @@ -28,7 +28,7 @@ def unpack_unknowns(segment,state): # Overide the speeds if segment.air_speed_end is None: - v_mag = np.concatenate([[[vel0]],vel*vel0]) + v_mag = np.concatenate([[[vel0]],vel]) elif segment.air_speed_end is not None: v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) From 26cb5427efc579e028c9ba989891875387bd9923 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Wed, 12 Jul 2017 11:49:14 -0700 Subject: [PATCH 12/14] time not tim --- trunk/SUAVE/Methods/Missions/Segments/optimize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/SUAVE/Methods/Missions/Segments/optimize.py b/trunk/SUAVE/Methods/Missions/Segments/optimize.py index cb5578a3b7..eacec74282 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/optimize.py +++ b/trunk/SUAVE/Methods/Missions/Segments/optimize.py @@ -112,7 +112,7 @@ def get_ieconstraints(unknowns,(segment,state)): # Altitudes are greater than 0 alt_con = state.conditions.freestream.altitude[:,0]/segment.altitude_end - constraints = np.concatenate((tim_con,CL_con,alt_con)) + constraints = np.concatenate((time_con,CL_con,alt_con)) return constraints From 4cc1c0dee65be969cb193f8bcf1da8fbafa43a17 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Tue, 25 Jul 2017 12:39:40 -0700 Subject: [PATCH 13/14] changes to allow SNOPT --- .../Mission/Segments/Climb/Optimized.py | 1 + .../Missions/Segments/Climb/Optimized.py | 10 ++- .../Methods/Missions/Segments/optimize.py | 81 +++++++++++++++++-- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py index 7b3ed6ccfd..cee19481cb 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py @@ -38,6 +38,7 @@ def __defaults__(self): self.minimize = True self.CL_limit = 1.e20 self.seed_climb_rate = 100. * Units['feet/min'] + self.algorithm = 'SLSQP' # -------------------------------------------------------------- diff --git a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py index f9318cf07b..bd21339d3e 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Methods/Missions/Segments/Climb/Optimized.py @@ -28,9 +28,15 @@ def unpack_unknowns(segment,state): # Overide the speeds if segment.air_speed_end is None: - v_mag = np.concatenate([[[vel0]],vel]) + v_mag = np.concatenate([[[vel0]],vel*vel0]) elif segment.air_speed_end is not None: v_mag = np.concatenate([[[vel0]],vel,[[velf]]]) + + if np.all(gamma == 0.): + gamma[gamma==0.] = 1.e-16 + + if np.all(vel == 0.): + vel[vel==0.] = 1.e-16 # process velocity vector v_x = v_mag * np.cos(gamma) @@ -75,7 +81,7 @@ def update_differentials(segment,state): numerics.time.control_points = x numerics.time.differentiate = D numerics.time.integrate = I - conditions.frames.inertial.time[:,0] = t_initial + x[:,0] + conditions.frames.inertial.time[1:,0] = t_initial + x[1:,0] conditions.frames.inertial.position_vector[:,2] = -alt[:,0] # z points down conditions.freestream.altitude[:,0] = alt[:,0] # positive altitude in this context diff --git a/trunk/SUAVE/Methods/Missions/Segments/optimize.py b/trunk/SUAVE/Methods/Missions/Segments/optimize.py index eacec74282..830457d9c2 100644 --- a/trunk/SUAVE/Methods/Missions/Segments/optimize.py +++ b/trunk/SUAVE/Methods/Missions/Segments/optimize.py @@ -23,16 +23,50 @@ def converge_opt(segment,state): unknowns = state.unknowns.pack_array() # Have the optimizer call the wrapper - obj = lambda unknowns:get_objective(unknowns,(segment,state)) - econ = lambda unknowns:get_econstraints(unknowns,(segment,state)) - iecon = lambda unknowns:get_ieconstraints(unknowns,(segment,state)) + obj = lambda unknowns:get_objective(unknowns,(segment,state)) + econ = lambda unknowns:get_econstraints(unknowns,(segment,state)) + iecon = lambda unknowns:get_ieconstraints(unknowns,(segment,state)) # Setup the bnds of the problem bnds = make_bnds(unknowns, (segment,state)) - # Solve the problem - unknowns = opt.fmin_slsqp(obj,unknowns,f_eqcons=econ,f_ieqcons=iecon,bounds=bnds,iter=2000) + # Solve the problem, based on chosen algorithm + if segment.algorithm == 'SLSQP': + unknowns = opt.fmin_slsqp(obj,unknowns,f_eqcons=econ,f_ieqcons=iecon,bounds=bnds,iter=2000) + + elif segment.algorithm == 'SNOPT': + + # SNOPT imports + import pyOpt + import pyOpt.pySNOPT + + # Have the optimizer call the wrapper + obj_pyopt = lambda unknowns:get_problem_pyopt(unknowns,(segment,state)) + + opt_prob = pyOpt.Optimization('SUAVE',obj_pyopt) + opt_prob.addObj(segment.objective) + + for ii in xrange(0,len(unknowns)): + lbd = (bnds[ii][0]) + ubd = (bnds[ii][1]) + vartype = 'c' + opt_prob.addVar(str(ii),vartype,lower=lbd,upper=ubd,value=unknowns[ii]) + + # Setup constraints + segment_points = state.numerics.number_control_points + for ii in xrange(0,2*segment_points): + opt_prob.addCon(str(ii), type='e', equal=0.) + for ii in xrange(0,3*segment_points-1): + opt_prob.addCon(str(ii+segment_points*2), type='i', lower=0.,upper=np.inf) + + print opt_prob + + snopt = pyOpt.pySNOPT.SNOPT() + outputs = snopt(opt_prob) + print outputs + print opt_prob.solution(0) + return # ---------------------------------------------------------------------- @@ -76,8 +110,8 @@ def make_bnds(unknowns,(segment,state)): ones_m2 = state.ones_row_m2(1) throttle_bnds = ones*(0.,1.) - body_angle = ones*(0., 50.) - gamma = ones*(0., 50.) + body_angle = ones*(0., np.pi/2.) + gamma = ones*(0., np.pi/2.) if segment.air_speed_end is None: vels = ones_m1*(0.,2000.) @@ -107,7 +141,7 @@ def get_ieconstraints(unknowns,(segment,state)): # Less than a specified CL limit CL_limit = segment.CL_limit - CL_con = (CL_limit - state.conditions.aerodynamics.lift_coefficient[:,0])/CL_limit + CL_con = (CL_limit - state.conditions.aerodynamics.lift_coefficient[:,0])/CL_limit # Altitudes are greater than 0 alt_con = state.conditions.freestream.altitude[:,0]/segment.altitude_end @@ -116,3 +150,34 @@ def get_ieconstraints(unknowns,(segment,state)): return constraints +def get_problem_pyopt(unknowns,(segment,state)): + + if isinstance(unknowns,array_type): + state.unknowns.unpack_array(unknowns) + else: + state.unknowns = unknowns + + if not np.all(state.inputs_last == state.unknowns): + segment.process.iterate(segment,state) + + obj = state.objective_value + + # Time goes forward, not backward + t_final = state.conditions.frames.inertial.time[-1,0] + time_con = (state.conditions.frames.inertial.time[1:,0] - state.conditions.frames.inertial.time[0:-1,0])/t_final + + # Less than a specified CL limit + CL_limit = segment.CL_limit + CL_con = (CL_limit - state.conditions.aerodynamics.lift_coefficient[:,0])/CL_limit + + # Altitudes are greater than 0 + alt_con = state.conditions.freestream.altitude[:,0]/segment.altitude_end + + # Put the equality and inequality constraints together + constraints = np.concatenate((state.constraint_values,time_con,CL_con,alt_con)) + + obj = state.objective_value + const = constraints.tolist() + fail = np.array(np.isnan(obj.tolist()) or np.isnan(np.array(const).any())).astype(int) + + return obj,const,fail \ No newline at end of file From ee674aed17033080d05abf490060ec3f88ae6f91 Mon Sep 17 00:00:00 2001 From: Emilio Botero Date: Tue, 25 Jul 2017 15:33:40 -0700 Subject: [PATCH 14/14] removing commented out code --- trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py | 1 - 1 file changed, 1 deletion(-) diff --git a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py index cee19481cb..5665c5f41a 100644 --- a/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py +++ b/trunk/SUAVE/Analyses/Mission/Segments/Climb/Optimized.py @@ -68,7 +68,6 @@ def __defaults__(self): initialize = self.process.initialize initialize.expand_state = Methods.expand_state initialize.solved_mission = Methods.Climb.Optimized.solve_linear_speed_constant_rate - #initialize.unknowns = Methods.Climb.Optimized.initialize_unknowns initialize.differentials = Methods.Common.Numerics.initialize_differentials_dimensionless initialize.conditions = SUAVE.Methods.skip