Пример #1
0
class TestAddNonexistentVar(unittest.TestCase):
    def setUp(self):
        self.nn = 3
        self.p = Problem(model=Group())
        self.ivc = DictIndepVarComp(data_dict=data)
        self.ivc.add_output(name='a', shape=(self.nn,))
        self.ivc.add_output(name='b', shape=(self.nn,))

    def test_nonexistent_key(self):
        self.assertRaises(KeyError,self.ivc.add_output_from_dict,'geom|S_ref_blah')

    def test_no_value(self):
        self.assertRaises(KeyError,self.ivc.add_output_from_dict,'geom|noval')
Пример #2
0
    def setup(self):
        # Define number of analysis points to run pers mission segment
        nn = 11

        # Define a bunch of design varaiables and airplane-specific parameters
        dv_comp = self.add_subsystem('dv_comp',
                                     DictIndepVarComp(acdata, seperator='|'),
                                     promotes_outputs=["*"])
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output_from_dict('ac|num_engines')

        # Ensure that any state variables are connected across the mission as intended
        connect_phases = ['rotate', 'climb', 'cruise', 'descent']
        connect_states = ['range', 'fuel_used', 'fltcond|h']
        extra_states_tuple = [(connect_state, connect_phases)
                              for connect_state in connect_states]

        # Run a full mission analysis including takeoff, climb, cruise, and descent
        analysis = self.add_subsystem('analysis',
                                      FullMissionAnalysis(
                                          num_nodes=nn,
                                          aircraft_model=KingAirC90GTModel,
                                          extra_states=extra_states_tuple),
                                      promotes_inputs=['*'],
                                      promotes_outputs=['*'])
Пример #3
0
    def setup(self):
        # Define number of analysis points to run pers mission segment
        nn = 9

        # Define a bunch of design varaiables and airplane-specific parameters
        dv_comp = self.add_subsystem('dv_comp', DictIndepVarComp(acdata, seperator='|'),
                                     promotes_outputs=["*"])
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|AR')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|hstab|taper')
        dv_comp.add_output_from_dict('ac|geom|hstab|toverc')
        # dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|vstab|AR')
        dv_comp.add_output_from_dict('ac|geom|vstab|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|vstab|taper')
        dv_comp.add_output_from_dict('ac|geom|vstab|toverc')
        # dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        # dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        # dv_comp.add_output_from_dict('ac|geom|maingear|length')
        dv_comp.add_output_from_dict('ac|geom|nacelle|length')
        dv_comp.add_output_from_dict('ac|geom|nacelle|diameter')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')

        dv_comp.add_output_from_dict('ac|propulsion|max_thrust')
        dv_comp.add_output_from_dict('ac|propulsion|num_engine')

        dv_comp.add_output_from_dict('ac|misc|num_passengers_max')

        analysis = self.add_subsystem('analysis',
                                      AirlinerFullMissionAnalysis(num_nodes=nn,
                                                          aircraft_model=A320200AirplaneModel,
                                                          num_climb=4, num_descent=3), 
                                      promotes_inputs=['*'], promotes_outputs=['*'])
Пример #4
0
    def setup(self):
        # Define number of analysis points to run pers mission segment
        nn = 11

        # Define a bunch of design varaiables and airplane-specific parameters
        dv_comp = self.add_subsystem('dv_comp',
                                     DictIndepVarComp(acdata),
                                     promotes_outputs=["*"])
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output_from_dict('ac|num_engines')

        # Run a full mission analysis including takeoff, climb, cruise, and descent
        analysis = self.add_subsystem('analysis',
                                      FullMissionAnalysis(
                                          num_nodes=nn,
                                          aircraft_model=KingAirC90GTModel),
                                      promotes_inputs=['*'],
                                      promotes_outputs=['*'])
    def setUp(self):
        self.nn = 3
        self.p = Problem(model=Group())
        ivc = DictIndepVarComp(data_dict=data)
        ivc.add_output(name='a', shape=(self.nn, ))
        ivc.add_output(name='b', shape=(self.nn, ))
        ivc.add_output_from_dict('geom|S_ref')
        ivc.add_output_from_dict('aero|CLmax|flaps30')
        ivc.add_output_from_dict('aero|CLmax|flaps10')

        self.p.model.add_subsystem(name='ivc',
                                   subsys=ivc,
                                   promotes_outputs=['*'])

        self.p.setup()

        self.p['a'] = np.random.rand(self.nn, )
        self.p['b'] = np.random.rand(self.nn, )

        self.p.run_model()
Пример #6
0
    def setup(self):
        # Define number of analysis points to run pers mission segment
        nn = 11

        # Define a bunch of design varaiables and airplane-specific parameters
        dv_comp = self.add_subsystem('dv_comp',  DictIndepVarComp(acdata),
                                     promotes_outputs=["*"])
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')
        dv_comp.add_output_from_dict('ac|weights|W_battery')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')
        dv_comp.add_output_from_dict('ac|propulsion|generator|rating')
        dv_comp.add_output_from_dict('ac|propulsion|motor|rating')
        dv_comp.add_output('ac|propulsion|battery|specific_energy',val=300,units='W*h/kg')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output_from_dict('ac|num_engines')

        mission_data_comp = self.add_subsystem('mission_data_comp',IndepVarComp(),promotes_outputs=["*"])
        mission_data_comp.add_output('batt_soc_target', val=0.1, units=None)

        analysis = self.add_subsystem('analysis',FullMissionAnalysis(num_nodes=nn,
                                                                     aircraft_model=SeriesHybridTwinModel),
                                                 promotes_inputs=['*'],promotes_outputs=['*'])

        margins = self.add_subsystem('margins',ExecComp('MTOW_margin = MTOW - OEW - total_fuel - W_battery - payload',
                                                        MTOW_margin={'units':'lbm','value':100},
                                                        MTOW={'units':'lbm','value':10000},
                                                        OEW={'units':'lbm','value':5000},
                                                        total_fuel={'units':'lbm','value':1000},
                                                        W_battery={'units':'lbm','value':1000},
                                                        payload={'units':'lbm','value':1000}),
                                                        promotes_inputs=['payload'])
        self.connect('cruise.OEW','margins.OEW')
        self.connect('descent.fuel_used_final','margins.total_fuel')
        self.connect('ac|weights|MTOW','margins.MTOW')
        self.connect('ac|weights|W_battery','margins.W_battery')

        augobj = self.add_subsystem('aug_obj', AugmentedFBObjective(), promotes_outputs=['mixed_objective'])
        self.connect('ac|weights|MTOW','aug_obj.ac|weights|MTOW')
        self.connect('descent.fuel_used_final','aug_obj.fuel_burn')
 def setUp(self):
     self.nn = 3
     self.p = Problem(model=Group())
     self.ivc = DictIndepVarComp(data_dict=data)
     self.ivc.add_output(name='a', shape=(self.nn, ))
     self.ivc.add_output(name='b', shape=(self.nn, ))
Пример #8
0
    def setup(self):
        # Define number of analysis points to run pers mission segment
        nn = 11

        # Define a bunch of design varaiables and airplane-specific parameters
        dv_comp = self.add_subsystem('dv_comp',
                                     DictIndepVarComp(acdata, seperator='|'),
                                     promotes_outputs=["*"])
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')
        dv_comp.add_output_from_dict('ac|weights|W_battery')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')
        dv_comp.add_output_from_dict('ac|propulsion|generator|rating')
        dv_comp.add_output_from_dict('ac|propulsion|motor|rating')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output_from_dict('ac|num_engines')

        mission_data_comp = self.add_subsystem('mission_data_comp',
                                               IndepVarComp(),
                                               promotes_outputs=["*"])
        mission_data_comp.add_output('batt_soc_target', val=0.1, units=None)

        # Ensure that any state variables are connected across the mission as intended
        connect_phases = ['rotate', 'climb', 'cruise', 'descent']
        connect_states = [
            'range', 'fuel_used', 'fltcond|h', 'propmodel.batt1.SOC'
        ]
        extra_states_tuple = [(connect_state, connect_phases)
                              for connect_state in connect_states]
        extra_states_tuple.append(
            ('propmodel.batt1.SOC', ['v0v1', 'v1vr', 'rotate']))
        analysis = self.add_subsystem('analysis',
                                      FullMissionAnalysis(
                                          num_nodes=nn,
                                          aircraft_model=SeriesHybridTwinModel,
                                          extra_states=extra_states_tuple),
                                      promotes_inputs=['*'],
                                      promotes_outputs=['*'])

        margins = self.add_subsystem(
            'margins',
            ExecComp(
                'MTOW_margin = MTOW - OEW - total_fuel - W_battery - payload',
                MTOW_margin={
                    'units': 'lbm',
                    'value': 100
                },
                MTOW={
                    'units': 'lbm',
                    'value': 10000
                },
                OEW={
                    'units': 'lbm',
                    'value': 5000
                },
                total_fuel={
                    'units': 'lbm',
                    'value': 1000
                },
                W_battery={
                    'units': 'lbm',
                    'value': 1000
                },
                payload={
                    'units': 'lbm',
                    'value': 1000
                }),
            promotes_inputs=['payload'])
        self.connect('cruise.OEW', 'margins.OEW')
        self.connect('descent.fuel_used_final', 'margins.total_fuel')
        self.connect('ac|weights|MTOW', 'margins.MTOW')
        self.connect('ac|weights|W_battery', 'margins.W_battery')

        augobj = self.add_subsystem('aug_obj',
                                    AugmentedFBObjective(),
                                    promotes_outputs=['mixed_objective'])
        self.connect('ac|weights|MTOW', 'aug_obj.ac|weights|MTOW')
        self.connect('descent.fuel_used_final', 'aug_obj.fuel_burn')
Пример #9
0
    def setup(self):
        n_int_per_seg = self.options['n_int_per_seg']
        mission_segments = ['climb','cruise','descent']
        nn, nn_tot_to, nn_tot_m, nn_tot = compute_num_nodes(n_int_per_seg, mission_segments)

        #Define input variables
        dv_comp = self.add_subsystem('dv_comp',DictIndepVarComp(acdata,seperator='|'),promotes_outputs=["*"])
        #eventually replace the following aerodynamic parameters with an analysis module (maybe OpenAeroStruct)
        dv_comp.add_output_from_dict('ac|aero|CLmax_flaps30')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')

        mission_data_comp = self.add_subsystem('mission_data_comp',DictIndepVarComp(missiondata),promotes_outputs=["*"])
        mission_data_comp.add_output_from_dict('takeoff|h')
        mission_data_comp.add_output_from_dict('climb|h0')
        mission_data_comp.add_output_from_dict('climb|time')
        mission_data_comp.add_output_from_dict('climb|Ueas')
        mission_data_comp.add_output_from_dict('cruise|h0')
        mission_data_comp.add_output_from_dict('cruise|Ueas')
        mission_data_comp.add_output_from_dict('descent|h0')
        mission_data_comp.add_output_from_dict('descent|hf')
        mission_data_comp.add_output_from_dict('descent|time')
        mission_data_comp.add_output_from_dict('descent|Ueas')
        mission_data_comp.add_output_from_dict('design_range')
        mission_data_comp.add_output_from_dict('payload')

        #==Define control settings for the propulsion system.
        # Recall that all flight points including takeoff roll are calculated all at once
        # The structure of the takeoff vector should be:
        #[ nn points (takeoff at full power, v0 to v1),
        #  nn points (takeoff at engine-out power (if applicable), v1 to vr),
        #  nn points (hard braking at zero power or even reverse, vr to v0),
        # !CAUTION! 1 point (transition at OEI power (if applicable), v_trans)
        # !CAUTION! 1 point (v2 climb at OEI power (if app), v2)
        # ]
        # The mission throttle vector should be set implicitly using the optimizer (driving T = D + sin(gamma)mg residual to 0)

        controls = self.add_subsystem('controls',IndepVarComp())
        #set the prop to 2000 rpm for all time
        controls.add_output('prop|rpm|takeoff', val=np.ones(nn_tot_to) * 2000, units='rpm')
        controls.add_output('prop|rpm|mission', val=np.ones(nn_tot_m) * 2000, units='rpm')

        TO_throttle_vec = np.concatenate([np.ones(nn),
                                          np.ones(nn) * 1.0,
                                          np.zeros(nn),
                                          np.ones(2) * 1.0])/1.21
        controls.add_output('motor|throttle|takeoff', val=TO_throttle_vec)

        self.add_subsystem('takeoff',BalancedFieldLengthTakeoff(n_int_per_seg=n_int_per_seg,
                                                                track_fuel=True, track_battery=False,
                                                                propulsion_system=TurbopropPropulsionSystem(num_nodes=nn_tot_to)),
                                                                promotes_inputs=['ac|aero*','ac|geom|*','ac|propulsion|*','ac|weights|*','takeoff|h'])
        self.connect('controls.prop|rpm|takeoff','takeoff.propmodel.prop1.rpm')
        self.connect('controls.motor|throttle|takeoff', 'takeoff.propmodel.throttle')

        mission_promote_inputs = ["ac|aero|*","ac|geom|*",'ac|propulsion|*','ac|weights|*','OEW','*|Ueas','*|h0','*|hf','*|time','design_range','payload']
        self.add_subsystem('design_mission',MissionAnalysis(n_int_per_seg=n_int_per_seg,track_battery=False,
                           propulsion_system=TurbopropPropulsionSystem(num_nodes=nn_tot_m)),
                           promotes_inputs=mission_promote_inputs)
        self.connect('design_mission.throttle','design_mission.propmodel.throttle')
        self.connect('takeoff.weight_after_takeoff','design_mission.weight_initial')
        self.connect('takeoff.total_fuel','design_mission.residuals.takeoff|total_fuel')
        self.connect('controls.prop|rpm|mission','design_mission.propmodel.prop1.rpm')


        #==This module is an empirical weight tool specific to a single-engine turboprop airplane. You will need to modify or replace it.
        self.add_subsystem('OEW',SingleTurboPropEmptyWeight(),promotes_inputs=["*"], promotes_outputs=['OEW'])
        self.connect('ac|propulsion|engine|rating','P_TO')
        #Don't forget to couple the propulsion system to the weights module like so:
        self.connect('design_mission.propmodel.prop1.component_weight','W_propeller')
        self.connect('design_mission.propmodel.eng1.component_weight','W_engine')

        components_list = ['eng1']
        opcost = self.add_subsystem('operating_cost',OperatingCost(n_components=len(components_list),n_batteries=None))
        self.connect('OEW','operating_cost.OEW')
        self.connect('design_mission.fuel_burn','operating_cost.fuel_burn')
        for i, component in enumerate(components_list):
            self.connect('design_mission.propmodel.'+component+'.component_weight','operating_cost.component_'+str(i+1)+'_weight')
            self.connect('design_mission.propmodel.'+component+'.component_cost','operating_cost.component_'+str(i+1)+'_NR_cost')
Пример #10
0
    def setup(self):
        n_int_per_seg = self.options['n_int_per_seg']
        nn_tot_to = (2 * n_int_per_seg + 1) * 3 + 2  #v0v1,v1vr,v1v0, vtr, v2
        nn_tot_m = (2 * n_int_per_seg + 1) * 3
        nn_tot = nn_tot_to + nn_tot_m
        nn = (2 * n_int_per_seg + 1)

        #Define input variables
        dv_comp = self.add_subsystem('dv_comp',
                                     DictIndepVarComp(acdata, seperator='|'),
                                     promotes_outputs=["*"])
        #eventually replace the following aerodynamic parameters with an analysis module (maybe OpenAeroStruct)
        dv_comp.add_output_from_dict('ac|aero|CLmax_flaps30')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')

        mission_data_comp = self.add_subsystem('mission_data_comp',
                                               DictIndepVarComp(missiondata),
                                               promotes_outputs=["*"])
        mission_data_comp.add_output_from_dict('mission|takeoff|h')
        mission_data_comp.add_output_from_dict('mission|climb|vs')
        mission_data_comp.add_output_from_dict('mission|climb|Ueas')
        mission_data_comp.add_output_from_dict('mission|cruise|h')
        mission_data_comp.add_output_from_dict('mission|cruise|Ueas')
        mission_data_comp.add_output_from_dict('mission|descent|vs')
        mission_data_comp.add_output_from_dict('mission|descent|Ueas')
        mission_data_comp.add_output_from_dict('mission|range')
        mission_data_comp.add_output_from_dict('mission|payload')

        #== Compute the stall speed (necessary for takeoff analysis - leave this alone)
        vstall = self.add_subsystem('vstall', StallSpeed())
        self.connect('ac|weights|MTOW', 'vstall.weight')
        self.connect('ac|geom|wing|S_ref', 'vstall.ac|geom|wing|S_ref')
        self.connect('ac|aero|CLmax_flaps30', 'vstall.CLmax')

        # ==Calculate flight conditions for the takeoff and mission segments here (leave this alone)
        mission_conditions = self.add_subsystem(
            'mission_conditions',
            MissionFlightConditions(n_int_per_seg=n_int_per_seg),
            promotes_inputs=["mission|*"],
            promotes_outputs=["mission|*", "fltcond|mission|*"])

        takeoff_conditions = self.add_subsystem(
            'takeoff_conditions',
            TakeoffFlightConditions(n_int_per_seg=n_int_per_seg),
            promotes_inputs=["mission|takeoff|*"],
            promotes_outputs=["fltcond|takeoff|*", "mission|takeoff|*"])
        self.connect('vstall.Vstall_eas', 'takeoff_conditions.Vstall_eas')

        fltcondcombiner = VectorConcatenateComp(
            output_name='fltcond|h',
            input_names=['fltcond|takeoff|h', 'fltcond|mission|h'],
            units='m',
            vec_sizes=[nn_tot_to, nn_tot_m])
        fltcondcombiner.add_relation(
            output_name='fltcond|Ueas',
            input_names=['fltcond|takeoff|Ueas', 'fltcond|mission|Ueas'],
            units='m/s',
            vec_sizes=[nn_tot_to, nn_tot_m])
        self.add_subsystem(
            'fltcondcombiner',
            subsys=fltcondcombiner,
            promotes_inputs=["fltcond|takeoff|*", "fltcond|mission|*"],
            promotes_outputs=["fltcond|Ueas", "fltcond|h"])

        #==Calculate atmospheric properties and true airspeeds for all mission segments
        atmos = self.add_subsystem(
            'atmos',
            ComputeAtmosphericProperties(num_nodes=nn_tot),
            promotes_inputs=["fltcond|h", "fltcond|Ueas"],
            promotes_outputs=["fltcond|rho", "fltcond|Utrue", "fltcond|q"])

        #==Define control settings for the propulsion system.
        # Recall that all flight points including takeoff roll are calculated all at once
        # The structure of the takeoff vector should be:
        #[ nn points (takeoff at full power, v0 to v1),
        #  nn points (takeoff at engine-out power (if applicable), v1 to vr),
        #  nn points (hard braking at zero power or even reverse, vr to v0),
        # !CAUTION! 1 point (transition at OEI power (if applicable), v_trans)
        # !CAUTION! 1 point (v2 climb at OEI power (if app), v2)
        # ]
        # The mission throttle vector should be set implicitly using the optimizer (driving T = D + sin(gamma)mg residual to 0)

        controls = self.add_subsystem('controls', IndepVarComp())
        #set the prop to 2000 rpm for all time
        controls.add_output('prop1|rpm',
                            val=np.ones(nn_tot) * 2000,
                            units='rpm')
        TO_throttle_vec = np.concatenate(
            [np.ones(nn),
             np.ones(nn) * 1.0,
             np.zeros(nn),
             np.ones(2) * 1.0]) / 1.21
        controls.add_output('motor1|throttle|takeoff', val=TO_throttle_vec)

        #combine the various controls together into one vector
        throttle_combiner = VectorConcatenateComp(
            output_name='motor1|throttle',
            input_names=['motor1|throttle|takeoff', 'motor1|throttle|mission'],
            vec_sizes=[nn_tot_to, nn_tot_m])
        self.add_subsystem('throttle_combiner',
                           subsys=throttle_combiner,
                           promotes_outputs=["motor1|throttle"])
        self.connect('controls.motor1|throttle|takeoff',
                     'throttle_combiner.motor1|throttle|takeoff')

        #==Calculate engine thrusts and fuel flows. You will need to override this module to vary number of engines, prop architecture, etc
        # Your propulsion model must promote up a single variable called "thrust" and a single variable called "fuel_flow". You may need to sum these at a lower level in the prop model group
        # You will probably need to add more control parameters if you use multiple engines. You may also need to add implicit solver states if, e.g. turbogenerator power setting depends on motor power setting

        prop = self.add_subsystem(
            'propmodel',
            TurbopropPropulsionSystem(num_nodes=nn_tot),
            promotes_inputs=["fltcond|*", "ac|propulsion|*"],
            promotes_outputs=["fuel_flow", "thrust"])
        #connect control settings to the various states in the propulsion model
        self.connect('controls.prop1|rpm', 'propmodel.prop1.rpm')
        self.connect('motor1|throttle', 'propmodel.throttle')

        #now we have flight conditions and propulsion outputs for all flight conditions. Split into our individual analysis phases
        #== Leave this alone==#
        splitter_inst = VectorSplitComp()

        inputs_to_split = ['fltcond|q', 'fltcond|Utrue', 'fuel_flow', 'thrust']
        segments_to_split_into = ['takeoff', 'mission']
        units = ['N * m**-2', 'm/s', 'kg/s', 'N']
        nn_each_segment = [nn_tot_to, nn_tot_m]

        for kth, input_name in enumerate(inputs_to_split):
            output_names_list = []
            for segment in segments_to_split_into:
                inpnamesplit = input_name.split('|')
                inpnamesplit.insert(-1, segment)
                output_names_list.append('|'.join(inpnamesplit))
            splitter_inst.add_relation(output_names=output_names_list,
                                       input_name=input_name,
                                       vec_sizes=nn_each_segment,
                                       units=units[kth])

        self.add_subsystem('splitter',
                           subsys=splitter_inst,
                           promotes_inputs=["*"],
                           promotes_outputs=["*"])

        #==This next module calculates balanced field length, if applicable. Your optimizer or solver MUST implicitly drive the abort distance and oei takeoff distances to the same value by varying v1

        takeoff = self.add_subsystem(
            'takeoff',
            TakeoffTotalDistance(n_int_per_seg=n_int_per_seg, track_fuel=True),
            promotes_inputs=[
                'ac|aero*', 'ac|weights|MTOW', 'ac|geom|*',
                'fltcond|takeoff|*', 'takeoff|thrust', 'takeoff|fuel_flow',
                'mission|takeoff|v*'
            ])

        #==This module computes fuel consumption during the entire mission
        mission = self.add_subsystem(
            'mission',
            MissionNoReserves(n_int_per_seg=n_int_per_seg),
            promotes_inputs=[
                "ac|aero|*", "ac|geom|*", "fltcond|mission|*",
                "mission|thrust", "mission|fuel_flow", "mission|*"
            ])
        #remember that you will need to set the mission throttle implicitly using the optimizer/solver. This was done above when we mashed the control vectors all together.
        self.connect('takeoff.weight_after_takeoff', 'mission|weight_initial')

        #==This module is an empirical weight tool specific to a single-engine turboprop airplane. You will need to modify or replace it.
        self.add_subsystem('OEW',
                           SingleTurboPropEmptyWeight(),
                           promotes_inputs=["*"])
        self.connect('ac|propulsion|engine|rating', 'P_TO')
        #Don't forget to couple the propulsion system to the weights module like so:
        self.connect('propmodel.prop1.component_weight', 'W_propeller')
        self.connect('propmodel.eng1.component_weight', 'W_engine')

        #==Finally, we need to compute certain quantities to ensure the airplane is feasible. Compute whether enough fuel volume exists, and whether the airplane burned more fuel than it can carry
        missionmargins = self.add_subsystem(
            'missionmargins',
            ComputeDesignMissionResiduals(include_takeoff=True),
            promotes_inputs=[
                'ac|weights|MTOW', "mission|*", "ac|weights|W_fuel_max"
            ],
            promotes_outputs=['fuel_burn'])
        self.connect('OEW.OEW', 'missionmargins.OEW')
        self.connect('mission.mission|total_fuel', 'mission|total_fuel')
        self.connect('takeoff.takeoff|total_fuel',
                     'missionmargins.takeoff|total_fuel')

        #==Calculate the difference between the one-engine-out abort distance and one-engine-out takeoff distance with obstacle clearance
        bflmargins = self.add_subsystem('bflmargins',
                                        ComputeBalancedFieldLengthResidual(),
                                        promotes_inputs=['mission|takeoff|v*'])
        self.connect('takeoff.takeoff|distance', 'bflmargins.takeoff|distance')
        self.connect('takeoff.takeoff|distance_abort',
                     'bflmargins.takeoff|distance_abort')

        implicit_solve = self.add_subsystem(
            'implicit_solve', SolveImplicitStates(n_int_per_seg=n_int_per_seg))
        self.connect('mission.thrust_resid.thrust_residual',
                     'implicit_solve.thrust_residual')
        self.connect('bflmargins.BFL_combined', 'implicit_solve.BFL_residual')
        #dv_comp.add_output('mission|takeoff|v1', val=48, units='m/s')
        # self.connect('mission|takeoff|v1','takeoff.v0v1_dist.upper_limit')
        # self.connect('mission|takeoff|v1','takeoff.v1vr_dist.lower_limit')
        # self.connect('mission|takeoff|v1','takeoff.v1v0_dist.lower_limit')
        # self.connect('mission|takeoff|v1','takeoff.reaction.mission|takeoff|vr')
        self.connect('implicit_solve.mission|takeoff|v1', 'mission|takeoff|v1')
        self.connect('implicit_solve.throttle',
                     'throttle_combiner.motor1|throttle|mission')

        components_list = ['eng1']
        opcost = self.add_subsystem(
            'operating_cost',
            OperatingCost(n_components=len(components_list), n_batteries=None))
        self.connect('OEW.OEW', 'operating_cost.OEW')
        self.connect('fuel_burn', 'operating_cost.fuel_burn')
        for i, component in enumerate(components_list):
            self.connect('propmodel.' + component + '.component_weight',
                         'operating_cost.component_' + str(i + 1) + '_weight')
            self.connect('propmodel.' + component + '.component_cost',
                         'operating_cost.component_' + str(i + 1) + '_NR_cost')

        dummy_range = self.add_subsystem(
            'dummypayload',
            DummyPayload(),
            promotes_outputs=['payload_objective'])
        self.connect('mission|payload', 'dummypayload.payload_DV')
Пример #11
0
    def setup(self):
        # Define number of analysis points to run pers mission segment
        nn = 11

        # Define a bunch of design varaiables and airplane-specific parameters
        dv_comp = self.add_subsystem('dv_comp',  DictIndepVarComp(acdata),
                                     promotes_outputs=["*"])
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')
        dv_comp.add_output_from_dict('ac|weights|W_battery')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')
        dv_comp.add_output_from_dict('ac|propulsion|generator|rating')
        dv_comp.add_output_from_dict('ac|propulsion|motor|rating')

        dv_comp.add_output('ac|propulsion|thermal|hx|coolant_mass',val=10.,units='kg')
        dv_comp.add_output('ac|propulsion|thermal|hx|channel_width',val=1.,units='mm')
        dv_comp.add_output('ac|propulsion|thermal|hx|channel_height',20.,units='mm')
        dv_comp.add_output('ac|propulsion|thermal|hx|channel_length',val=0.2,units='m')
        dv_comp.add_output('ac|propulsion|thermal|hx|n_parallel',val=50,units=None)
        # dv_comp.add_output('ac|propulsion|thermal|duct|area_nozzle',val=58.*np.ones((nn,)),units='inch**2')
        dv_comp.add_output('ac|propulsion|thermal|hx|n_wide_cold',val=430,units=None)
        dv_comp.add_output('ac|propulsion|battery|specific_energy',val=300,units='W*h/kg')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output_from_dict('ac|num_engines')

        mission_data_comp = self.add_subsystem('mission_data_comp',IndepVarComp(),promotes_outputs=["*"])
        mission_data_comp.add_output('batt_soc_target', val=0.1, units=None)
        mission_data_comp.add_output('T_motor_initial', val=15, units='degC')
        mission_data_comp.add_output('T_res_initial', val=15.1, units='degC')
        mission_data_comp.add_output('T_batt_initial', val=10.1, units='degC')

        # Ensure that any state variables are connected across the mission as intended
        analysis = self.add_subsystem('analysis',FullMissionAnalysis(num_nodes=nn,
                                                                     aircraft_model=SeriesHybridTwinModel),
                                                 promotes_inputs=['*'],promotes_outputs=
                                                 ['*'])

        margins = self.add_subsystem('margins',ExecComp('MTOW_margin = MTOW - OEW - total_fuel - W_battery - payload',
                                                        MTOW_margin={'units':'lbm','value':100},
                                                        MTOW={'units':'lbm','value':10000},
                                                        OEW={'units':'lbm','value':5000},
                                                        total_fuel={'units':'lbm','value':1000},
                                                        W_battery={'units':'lbm','value':1000},
                                                        payload={'units':'lbm','value':1000}),
                                                        promotes_inputs=['payload'])
        self.connect('cruise.OEW','margins.OEW')
        self.connect('descent.fuel_used_final','margins.total_fuel')
        self.connect('ac|weights|MTOW','margins.MTOW')
        self.connect('ac|weights|W_battery','margins.W_battery')

        augobj = self.add_subsystem('aug_obj', AugmentedFBObjective(), promotes_outputs=['mixed_objective'])
        self.connect('ac|weights|MTOW','aug_obj.ac|weights|MTOW')
        self.connect('descent.fuel_used_final','aug_obj.fuel_burn')

        self.connect('T_motor_initial','v0v1.propmodel.motorheatsink.T_initial')
        self.connect('T_res_initial','v0v1.propmodel.reservoir.T_initial')
        self.connect('T_batt_initial','v0v1.propmodel.batteryheatsink.T_initial')
Пример #12
0
    def setup(self):
        nn = 11

        dv_comp = self.add_subsystem('dv_comp',
                                     DictIndepVarComp(acdata, seperator='|'),
                                     promotes_outputs=["*"])
        #eventually replace the following aerodynamic parameters with an analysis module (maybe OpenAeroStruct)
        dv_comp.add_output_from_dict('ac|aero|CLmax_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output('ac|propulsion|motor|rating', val=850, units='hp')
        dv_comp.add_output('ac|weights|W_battery', val=2000, units='lb')

        mission_data_comp = self.add_subsystem('mission_data_comp',
                                               IndepVarComp(),
                                               promotes_outputs=["*"])
        # mission_data_comp.add_output('cruise|h0',val=6000, units='m')
        # mission_data_comp.add_output('design_range',val=150,units='NM')
        mission_data_comp.add_output('T_motor_initial', val=15, units='degC')
        mission_data_comp.add_output('T_res_initial', val=15.1, units='degC')

        connect_phases_1 = [
            'v0v1', 'v1vr', 'rotate', 'climb', 'cruise', 'descent'
        ]
        connect_states_1 = [
            'propmodel.batt1.SOC', 'propmodel.motorheatsink.T',
            'propmodel.reservoir.T'
        ]
        extra_states_tuple_1 = [(connect_state, connect_phases_1)
                                for connect_state in connect_states_1]
        connect_phases_2 = ['rotate', 'climb', 'cruise', 'descent']
        connect_states_2 = ['range', 'fltcond|h']
        extra_states_tuple_2 = [(connect_state, connect_phases_2)
                                for connect_state in connect_states_2]
        extra_states_tuple = extra_states_tuple_1 + extra_states_tuple_2
        analysis = self.add_subsystem('analysis',
                                      FullMissionAnalysis(
                                          num_nodes=nn,
                                          aircraft_model=ElectricTBM850Model,
                                          extra_states=extra_states_tuple,
                                          transition_method='ode'),
                                      promotes_inputs=['*'],
                                      promotes_outputs=['*'])

        self.connect('T_motor_initial',
                     'v0v1.propmodel.motorheatsink.T_initial')
        self.connect('T_res_initial', 'v0v1.propmodel.reservoir.T_initial')
Пример #13
0
    def setup(self):
        n_int_per_seg = self.options['n_int_per_seg']
        mission_segments = ['climb', 'cruise', 'descent']
        nn, nn_tot_to, nn_tot_m, nn_tot = compute_num_nodes(
            n_int_per_seg, mission_segments)

        constant_hybridization = self.options['constant_hybridization']
        specific_energy = self.options['specific_energy']

        #Define input variables
        dv_comp = self.add_subsystem('dv_comp',
                                     DictIndepVarComp(acdata),
                                     promotes_outputs=["*"])
        #eventually replace the following aerodynamic parameters with an analysis module (maybe OpenAeroStruct)
        dv_comp.add_output_from_dict('ac|aero|CLmax_flaps30')
        dv_comp.add_output_from_dict('ac|aero|polar|e')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_TO')
        dv_comp.add_output_from_dict('ac|aero|polar|CD0_cruise')

        dv_comp.add_output_from_dict('ac|geom|wing|S_ref')
        dv_comp.add_output_from_dict('ac|geom|wing|AR')
        dv_comp.add_output_from_dict('ac|geom|wing|c4sweep')
        dv_comp.add_output_from_dict('ac|geom|wing|taper')
        dv_comp.add_output_from_dict('ac|geom|wing|toverc')
        dv_comp.add_output_from_dict('ac|geom|hstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|hstab|c4_to_wing_c4')
        dv_comp.add_output_from_dict('ac|geom|vstab|S_ref')
        dv_comp.add_output_from_dict('ac|geom|fuselage|S_wet')
        dv_comp.add_output_from_dict('ac|geom|fuselage|width')
        dv_comp.add_output_from_dict('ac|geom|fuselage|length')
        dv_comp.add_output_from_dict('ac|geom|fuselage|height')
        dv_comp.add_output_from_dict('ac|geom|nosegear|length')
        dv_comp.add_output_from_dict('ac|geom|maingear|length')

        dv_comp.add_output_from_dict('ac|weights|MTOW')
        dv_comp.add_output_from_dict('ac|weights|W_fuel_max')
        dv_comp.add_output_from_dict('ac|weights|MLW')
        dv_comp.add_output_from_dict('ac|weights|W_battery')

        dv_comp.add_output_from_dict('ac|propulsion|engine|rating')
        dv_comp.add_output_from_dict('ac|propulsion|propeller|diameter')
        dv_comp.add_output_from_dict('ac|propulsion|generator|rating')
        dv_comp.add_output_from_dict('ac|propulsion|motor|rating')

        dv_comp.add_output_from_dict('ac|num_passengers_max')
        dv_comp.add_output_from_dict('ac|q_cruise')
        dv_comp.add_output_from_dict('ac|num_engines')

        mission_data_comp = self.add_subsystem('mission_data_comp',
                                               DictIndepVarComp(missiondata),
                                               promotes_outputs=["*"])
        mission_data_comp.add_output_from_dict('takeoff|h')
        mission_data_comp.add_output_from_dict('climb|h0')
        mission_data_comp.add_output_from_dict('climb|time')
        mission_data_comp.add_output_from_dict('climb|Ueas')
        mission_data_comp.add_output_from_dict('cruise|h0')
        mission_data_comp.add_output_from_dict('cruise|Ueas')
        mission_data_comp.add_output_from_dict('descent|h0')
        mission_data_comp.add_output_from_dict('descent|hf')
        mission_data_comp.add_output_from_dict('descent|time')
        mission_data_comp.add_output_from_dict('descent|Ueas')
        mission_data_comp.add_output_from_dict('design_range')
        mission_data_comp.add_output_from_dict('payload')

        #==Define control settings for the propulsion system.
        # Recall that all flight points including takeoff roll are calculated all at once
        # The structure of the takeoff vector should be:
        #[ nn points (takeoff at full power, v0 to v1),
        #  nn points (takeoff at engine-out power (if applicable), v1 to vr),
        #  nn points (hard braking at zero power or even reverse, vr to v0),
        # !CAUTION! 1 point (transition at OEI power (if applicable), v_trans)
        # !CAUTION! 1 point (v2 climb at OEI power (if app), v2)
        # ]
        # The mission throttle vector should be set implicitly using the optimizer (driving T = D + sin(gamma)mg residual to 0)

        controls = self.add_subsystem('controls', IndepVarComp())
        #set the prop to 1900 rpm for all time
        controls.add_output('prop|rpm|takeoff',
                            val=np.ones(nn_tot_to) * 1900,
                            units='rpm')
        controls.add_output('prop|rpm|mission',
                            val=np.ones(nn_tot_m) * 1900,
                            units='rpm')

        motor1_TO_throttle_vec = np.concatenate(
            [np.ones(nn),
             np.ones(nn) * 1.0,
             np.zeros(nn),
             np.ones(2) * 1.0]) * 1.1
        motor2_TO_throttle_vec = np.concatenate(
            [np.ones(nn),
             np.zeros(nn) * 0.0,
             np.zeros(nn),
             np.zeros(2) * 0.0]) * 1.1
        controls.add_output('motor1|throttle|takeoff',
                            val=motor1_TO_throttle_vec)
        controls.add_output('motor2|throttle|takeoff',
                            val=motor2_TO_throttle_vec)

        controls.add_output('hybrid_split|takeoff', val=1)
        controls.add_output('eng1|throttle|takeoff', val=np.zeros(nn_tot_to))
        self.add_subsystem('hybrid_TO',
                           LinearInterpolator(num_nodes=nn_tot_to))
        self.connect('controls.hybrid_split|takeoff',
                     ['hybrid_TO.start_val', 'hybrid_TO.end_val'])

        if constant_hybridization:
            controls.add_output('hybrid_split|percentage', val=0.5)
        hybrid_comps = []
        for segment_name in mission_segments:
            hybrid_comps.append('hybrid_' + segment_name)
            self.add_subsystem('hybrid_' + segment_name,
                               LinearInterpolator(num_nodes=nn))
            if constant_hybridization:
                self.connect('controls.hybrid_split|percentage',
                             'hybrid_' + segment_name + '.start_val')
                self.connect('controls.hybrid_split|percentage',
                             'hybrid_' + segment_name + '.end_val')
            else:
                controls.add_output('hybrid_split|' + segment_name + '_0',
                                    val=0.5)
                controls.add_output('hybrid_split|' + segment_name + '_f',
                                    val=0.5)
                self.connect('hybrid_split|' + segment_name + '_0',
                             'hybrid_' + segment_name + '.start_val')
                self.connect('hybrid_split|' + segment_name + '_f',
                             'hybrid_' + segment_name + '.end_val')
        hybrid_combiner = self.add_subsystem(
            'hybrid_combiner',
            VectorConcatenateComp(output_name='hybrid_split|mission',
                                  input_names=hybrid_comps,
                                  vec_sizes=[nn, nn, nn]))
        for segment_name in mission_segments:
            self.connect('hybrid_' + segment_name + '.vec',
                         'hybrid_combiner.hybrid_' + segment_name)

        #==Calculate engine thrusts and fuel flows. You will need to override this module to vary number of engines, prop architecture, etc
        # Your propulsion model must promote up a single variable called "thrust" and a single variable called "fuel_flow". You may need to sum these at a lower level in the prop model group
        # You will probably need to add more control parameters if you use multiple engines. You may also need to add implicit solver states if, e.g. turbogenerator power setting depends on motor power setting

        #connect control settings to the various states in the propulsion model

        #now we have flight conditions and propulsion outputs for all flight conditions. Split into our individual analysis phases

        #==This next module calculates balanced field length, if applicable. Your optimizer or solver MUST implicitly drive the abort distance and oei takeoff distances to the same value by varying v1

        self.add_subsystem(
            'takeoff',
            BalancedFieldLengthTakeoff(
                n_int_per_seg=n_int_per_seg,
                track_fuel=True,
                track_battery=True,
                propulsion_system=TwinSeriesHybridElectricPropulsionSystem(
                    num_nodes=nn_tot_to, specific_energy=specific_energy)),
            promotes_inputs=[
                'ac|aero*', 'ac|geom|*', 'ac|propulsion|*', 'ac|weights|*',
                'takeoff|h'
            ])

        self.connect(
            'controls.prop|rpm|takeoff',
            ['takeoff.propmodel.prop1.rpm', 'takeoff.propmodel.prop2.rpm'])
        self.connect('controls.motor1|throttle|takeoff',
                     'takeoff.propmodel.motor1.throttle')
        self.connect('controls.motor2|throttle|takeoff',
                     'takeoff.propmodel.motor2.throttle')
        self.connect('hybrid_TO.vec',
                     'takeoff.propmodel.hybrid_split.power_split_fraction')
        self.connect('controls.eng1|throttle|takeoff',
                     'takeoff.propmodel.eng1.throttle')

        #==This module computes fuel consumption during the entire mission
        mission_promote_inputs = [
            "ac|aero|*", "ac|geom|*", 'ac|propulsion|*', 'ac|weights|*', 'OEW',
            '*|Ueas', '*|h0', '*|hf', '*|time', 'design_range', 'payload'
        ]
        self.add_subsystem(
            'design_mission',
            MissionAnalysis(
                n_int_per_seg=n_int_per_seg,
                track_battery=True,
                propulsion_system=TwinSeriesHybridElectricPropulsionSystem(
                    num_nodes=nn_tot_m, specific_energy=specific_energy)),
            promotes_inputs=mission_promote_inputs)
        self.connect('design_mission.throttle', [
            'design_mission.propmodel.motor1.throttle',
            'design_mission.propmodel.motor2.throttle'
        ])
        self.connect('takeoff.weight_after_takeoff',
                     'design_mission.weight_initial')
        self.connect(
            'hybrid_combiner.hybrid_split|mission',
            'design_mission.propmodel.hybrid_split.power_split_fraction')
        self.connect('controls.prop|rpm|mission', [
            'design_mission.propmodel.prop1.rpm',
            'design_mission.propmodel.prop2.rpm'
        ])

        #==This module is an empirical weight tool specific to a single-engine turboprop airplane. You will need to modify or replace it.
        self.add_subsystem('OEW',
                           TwinSeriesHybridEmptyWeight(),
                           promotes_inputs=["*"],
                           promotes_outputs=['OEW'])
        self.connect('ac|propulsion|engine|rating', 'P_TO')
        self.connect('design_mission.propmodel.propellers_weight',
                     'W_propeller')
        self.connect('design_mission.propmodel.eng1.component_weight',
                     'W_engine')
        self.connect('design_mission.propmodel.gen1.component_weight',
                     'W_generator')
        self.connect('design_mission.propmodel.motors_weight', 'W_motors')

        #==Finally, we need to compute certain quantities to ensure the airplane is feasible. Compute whether enough fuel volume exists, and whether the airplane burned more fuel than it can carry
        self.connect('takeoff.total_fuel',
                     'design_mission.residuals.takeoff|total_fuel')
        self.connect('takeoff.total_battery_energy',
                     'design_mission.residuals.takeoff|total_battery_energy')
        self.connect('design_mission.propmodel.batt1.max_energy',
                     'design_mission.residuals.battery_max_energy')

        #==Calculate the difference between the one-engine-out abort distance and one-engine-out takeoff distance with obstacle clearance
        self.add_subsystem('implicit_solve',
                           SolveImplicitStates(n_int_per_seg=n_int_per_seg))
        self.connect('design_mission.propmodel.eng_gen_resid.eng_gen_residual',
                     'implicit_solve.eng_gen_residual')
        self.connect('implicit_solve.eng_throttle',
                     'design_mission.propmodel.eng1.throttle')

        components_list = ['eng1', 'motor1', 'motor2', 'gen1']
        opcost = self.add_subsystem(
            'operating_cost',
            OperatingCost(n_components=len(components_list), n_batteries=1))
        self.connect('design_mission.propmodel.batt1.component_cost',
                     'operating_cost.battery_1_NR_cost')
        self.connect('design_mission.battery_energy_used',
                     'operating_cost.battery_1_energy_used')

        self.connect('OEW', 'operating_cost.OEW')
        self.connect('design_mission.fuel_burn', 'operating_cost.fuel_burn')
        for i, component in enumerate(components_list):
            self.connect(
                'design_mission.propmodel.' + component + '.component_weight',
                'operating_cost.component_' + str(i + 1) + '_weight')
            self.connect(
                'design_mission.propmodel.' + component + '.component_cost',
                'operating_cost.component_' + str(i + 1) + '_NR_cost')

        dummy_range = self.add_subsystem(
            'dummypayload',
            DummyPayload(),
            promotes_outputs=['payload_objective'])
        self.connect('payload', 'dummypayload.payload_DV')
        dummy_obj = self.add_subsystem('dummyobj',
                                       AugmentedFBObjective(),
                                       promotes_inputs=['ac|weights|MTOW'],
                                       promotes_outputs=['mixed_objective'])
        self.connect('design_mission.fuel_burn', 'dummyobj.fuel_burn')