コード例 #1
0
    def __init__(self):
        super(TopLevelSystem, self).__init__()
        
        print('running...')
        
        # add design variables - Q. is this even needed?
        self.add('indep1', IndepVarComp('range', 10000.0))
        self.add('indep2', IndepVarComp('rProp', 1.0))
        self.add('indep3', IndepVarComp('cruiseSpeed', 50.0))
        self.add('indep4', IndepVarComp('batteryMass', 117.0))
        self.add('indep5', IndepVarComp('motorMass', 30.0))
        self.add('indep6', IndepVarComp('mtom', 650.0))
        self.add('indep7', IndepVarComp('vehicle', u'tiltwing'))  # TypeError: In subproblem 'subprob': Type <type 'str'> of source 'indep7.vehicle' must be the same as type <type 'unicode'> of target 'ConfigWeight.Vehicle'.
        
        # add components
        self.add('MassToWeight', mass_2_weight())
        self.add('CruisePower', CruisePower())
        self.add('HoverPower', HoverPower())
        self.add('LoiterPower', loiter_power())
        self.add('SimpleMission', mission())
        self.add('ReserveMission', mission())
        self.add('WingMass', wing_mass())  # TEMPORARY
        self.add('CanardMass', wing_mass())  # TEMPORARY
        self.add('WireMass', wire_mass())
        self.add('ConfigWeight', config_weight())
        self.add('ToolingCost', tooling_cost())
        self.add('OperatingCost', operating_cost())
        
        # add component constants - Q. is there a better way to do this?
        self.add('simpleMissionConst1', IndepVarComp('hops', 1.0))
        self.add('simpleMissionConst2', IndepVarComp('loiterTime', 0.0))
        self.add('reserveMissionConst1', IndepVarComp('hops', 2.0))
        self.add('reserveMissionConst2', IndepVarComp('loiterTime', 1020.0))
        self.add('wingMassConst1', IndepVarComp('winglet', 0.2))
        self.add('wingMassConst2', IndepVarComp('fc', 0.4))
        self.add('canardMassConst1', IndepVarComp('winglet', 0.0))
        self.add('canardMassConst2', IndepVarComp('fc', 0.6))
        self.add('wireMassConst1', IndepVarComp('fuselageLength', 5.0))
        self.add('wireMassConst2', IndepVarComp('fuselageHeight', 1.65))
        self.add('configWeightConst1', IndepVarComp('payload_mass', 114.0))
        self.add('configWeightConst2', IndepVarComp('fuselage_mass', 55.0))
        self.add('configWeightConst3', IndepVarComp('prop_mass', 14.0))
        #self.add('configWeightConst4', IndepVarComp('wing_mass', 40.0))  # TEMPORARY: This constant is a workaround until I add wing_mass.py back
        #self.add('configWeightConst5', IndepVarComp('canard_mass', 38.0))  # TEMPORARY: This constant is a workaround until I add wing_mass.py back
        self.add('costBuildupConst1', IndepVarComp('partsPerTool', 1000.0))
        
        # add constraint equations
        self.add('con1', ExecComp('c = (mBattery*230.0*0.95/1000.0) - EReserve'))
        self.add('con2', ExecComp('c = mMotors*5.0 - hoverPower_PMax / 1000.0'))
        self.add('con3', ExecComp('c = mtow*9.8 - mass_W'))
        #self.add('con4', ExecComp('c = 0.5*1.0/3.0*mass_rotor*hoverPower_Vtip**2.0 - 0.5*mass_m*hoverPower_VAutoRotation**2.0'))  # Helicopter only - doesn't work for this version
        
        # connect components
        self.connect('indep6.mtom', 'MassToWeight.mass')  # MassToWeight inputs
        
        self.connect('indep2.rProp', 'CruisePower.rProp')  # CruisePower inputs
        self.connect('indep3.cruiseSpeed', 'CruisePower.V')
        self.connect('indep7.vehicle', 'CruisePower.Vehicle')
        self.connect('MassToWeight.weight', 'CruisePower.W')
        
        self.connect('CruisePower.omega', 'HoverPower.cruisePower_omega')  # HoverPower inputs
        self.connect('indep2.rProp', 'HoverPower.rProp')
        self.connect('indep7.vehicle', 'HoverPower.Vehicle')
        self.connect('MassToWeight.weight', 'HoverPower.W')
        
        self.connect('CruisePower.B', 'LoiterPower.B')  # LoiterPower inputs
        self.connect('CruisePower.AR', 'LoiterPower.cruiseOutputAR')
        self.connect('CruisePower.Cd0', 'LoiterPower.cruiseOutputCd0')
        self.connect('CruisePower.e', 'LoiterPower.cruiseOutputE')
        self.connect('CruisePower.etaMotor', 'LoiterPower.cruiseOutputEtaMotor')
        self.connect('CruisePower.etaProp', 'LoiterPower.cruiseOutputEtaProp')
        self.connect('CruisePower.omega', 'LoiterPower.cruiseOutputOmega')
        self.connect('CruisePower.PCruise', 'LoiterPower.cruiseOutputP')
        self.connect('CruisePower.PBattery', 'LoiterPower.cruiseOutputPBattery')
        self.connect('CruisePower.SCdFuse', 'LoiterPower.cruiseOutputSCdFuse')
        self.connect('CruisePower.sigma', 'LoiterPower.cruiseOutputSigma')
        self.connect('CruisePower.SRef', 'LoiterPower.cruiseOutputSRef')
        self.connect('indep2.rProp', 'LoiterPower.rProp')
        self.connect('indep3.cruiseSpeed', 'LoiterPower.V')
        self.connect('indep7.vehicle', 'LoiterPower.Vehicle')
        self.connect('MassToWeight.weight', 'LoiterPower.W')
          
        self.connect('CruisePower.PBattery', 'SimpleMission.cruiseOutput_PBattery')  # SimpleMission inputs
        self.connect('simpleMissionConst1.hops', 'SimpleMission.hops')
        self.connect('HoverPower.hoverPower_PBattery', 'SimpleMission.hoverOutput_PBattery')
        self.connect('simpleMissionConst2.loiterTime', 'SimpleMission.loiterTime')
        self.connect('indep1.range', 'SimpleMission.range')
        self.connect('indep2.rProp', 'SimpleMission.rProp')
        self.connect('indep3.cruiseSpeed', 'SimpleMission.V')
        self.connect('indep7.vehicle', 'SimpleMission.Vehicle')
        
        self.connect('CruisePower.PBattery', 'ReserveMission.cruiseOutput_PBattery')  # ReserveMission inputs
        self.connect('reserveMissionConst1.hops', 'ReserveMission.hops')
        self.connect('HoverPower.hoverPower_PBattery', 'ReserveMission.hoverOutput_PBattery')
        self.connect('LoiterPower.PBattery', 'ReserveMission.loiterOutput_PBattery')
        self.connect('reserveMissionConst2.loiterTime', 'ReserveMission.loiterTime')
        self.connect('indep1.range', 'ReserveMission.range')
        self.connect('indep2.rProp', 'ReserveMission.rProp')
        self.connect('indep3.cruiseSpeed', 'ReserveMission.V')
        self.connect('indep7.vehicle', 'ReserveMission.Vehicle')
        
        self.connect('CruisePower.cRef', 'WingMass.chord')  # WingMass inputs # TEMPORARY 
        self.connect('wingMassConst2.fc', 'WingMass.fc')
        self.connect('indep2.rProp', 'WingMass.rProp')
        self.connect('CruisePower.bRef', 'WingMass.span')
        self.connect('HoverPower.TMax', 'WingMass.thrust')
        self.connect('MassToWeight.weight', 'WingMass.W')
        self.connect('wingMassConst1.winglet', 'WingMass.winglet')

        self.connect('CruisePower.cRef', 'CanardMass.chord')  # CanardMass inputs # TEMPORARY 
        self.connect('canardMassConst2.fc', 'CanardMass.fc')
        self.connect('indep2.rProp', 'CanardMass.rProp')
        self.connect('CruisePower.bRef', 'CanardMass.span') 
        self.connect('HoverPower.TMax', 'CanardMass.thrust')
        self.connect('MassToWeight.weight', 'CanardMass.W')
        self.connect('canardMassConst1.winglet', 'CanardMass.winglet')
        
        self.connect('wireMassConst2.fuselageHeight', 'WireMass.fuselageHeight')  # WireMass inputs
        self.connect('wireMassConst1.fuselageLength', 'WireMass.fuselageLength')
        self.connect('HoverPower.hoverPower_PMax', 'WireMass.power')
        self.connect('indep2.rProp', 'WireMass.rProp')
        self.connect('CruisePower.bRef', 'WireMass.span')
        
        self.connect('CanardMass.mass', 'ConfigWeight.canard_mass')  # ConfigWeight inputs # TEMPORARY 
        self.connect('configWeightConst2.fuselage_mass', 'ConfigWeight.fuselage_mass')
        self.connect('HoverPower.hoverPower_PMax', 'ConfigWeight.hoverOutput_PMax')
        self.connect('indep4.batteryMass', 'ConfigWeight.mBattery')
        self.connect('indep5.motorMass', 'ConfigWeight.mMotors')
        self.connect('indep6.mtom', 'ConfigWeight.mtow')
        self.connect('configWeightConst1.payload_mass', 'ConfigWeight.payload')
        self.connect('configWeightConst3.prop_mass', 'ConfigWeight.prop_mass')
        self.connect('indep2.rProp', 'ConfigWeight.rProp')
        self.connect('indep7.vehicle', 'ConfigWeight.Vehicle')
        self.connect('WingMass.mass', 'ConfigWeight.wing_mass')  # TEMPORARY
        self.connect('WireMass.mass', 'ConfigWeight.wire_mass')
        
        self.connect('CruisePower.bRef', 'ToolingCost.cruiseOutput_bRef')  # ToolingCost inputs
        self.connect('CruisePower.cRef', 'ToolingCost.cruiseOutput_cRef')
        self.connect('costBuildupConst1.partsPerTool', 'ToolingCost.partsPerTool')
        self.connect('indep2.rProp', 'ToolingCost.rProp')
        self.connect('indep7.vehicle', 'ToolingCost.Vehicle')
        
        self.connect('SimpleMission.E', 'OperatingCost.E')  # OperatingCost inputs
        self.connect('SimpleMission.t', 'OperatingCost.flightTime')
        self.connect('indep4.batteryMass', 'OperatingCost.mass_battery')
        self.connect('indep5.motorMass', 'OperatingCost.mass_motors')
        self.connect('ConfigWeight.mass_structural', 'OperatingCost.mass_structural')
        self.connect('indep2.rProp', 'OperatingCost.rProp')
        self.connect('ToolingCost.toolCostPerVehicle', 'OperatingCost.toolingCost')
        self.connect('indep7.vehicle', 'OperatingCost.Vehicle')
  
        self.connect('ReserveMission.E', 'con1.EReserve')  # Constraint inputs
        self.connect('indep4.batteryMass', 'con1.mBattery')
        self.connect('HoverPower.hoverPower_PMax', 'con2.hoverPower_PMax')
        self.connect('indep5.motorMass', 'con2.mMotors')
        self.connect('ConfigWeight.mass_W', 'con3.mass_W')
        self.connect('indep6.mtom', 'con3.mtow')
コード例 #2
0
    def __init__(self):
        super(TopLevelSystem, self).__init__()

        print('running...')

        # add design variables
        self.add('indep1', IndepVarComp('range', 50.0))
        self.add('indep2', IndepVarComp('rProp', 30.0))
        self.add('indep3', IndepVarComp('cruiseSpeed', 50.0))
        self.add('indep4', IndepVarComp('batteryMass', 11.70))
        self.add('indep5', IndepVarComp('motorMass', 3.00))
        self.add('indep6', IndepVarComp('mtom', 6.500))
        self.add(
            'indep7', IndepVarComp('vehicle', u'helicopter')
        )  # TypeError: In subproblem 'subprob': Type <type 'str'> of source 'indep7.vehicle' must be the same as type <type 'unicode'> of target 'ConfigWeight.Vehicle'.

        # design variable scaling - this is CRITICAL or else the COBYLA optimizer WILL NOT WORK
        self.add('scale2', ExecComp('scaled = orig*0.1'))
        self.add('scale3', ExecComp('scaled = orig*1.0'))
        self.add('scale4', ExecComp('scaled = orig*10.0'))
        self.add('scale5', ExecComp('scaled = orig*10.0'))
        self.add('scale6', ExecComp('scaled = orig*100.0'))

        self.connect('indep2.rProp', 'scale2.orig')
        self.connect('indep3.cruiseSpeed', 'scale3.orig')
        self.connect('indep4.batteryMass', 'scale4.orig')
        self.connect('indep5.motorMass', 'scale5.orig')
        self.connect('indep6.mtom', 'scale6.orig')

        # add components
        self.add('MassToWeight', mass_2_weight())
        self.add('CruisePower', CruisePower())
        self.add('HoverPower', HoverPower())
        self.add('LoiterPower', loiter_power())
        self.add('SimpleMission', mission())
        self.add('ReserveMission', mission())
        self.add('WireMass', wire_mass())
        self.add('PropMass', prop_mass())
        self.add('PropMass_Tail', prop_mass())
        self.add('FuselageMass', fuselage_mass())
        self.add('ConfigWeight', config_weight())
        self.add('ToolingCost', tooling_cost())
        self.add('OperatingCost', operating_cost())

        # add component constants - Q. is there a better way to do this?
        self.add('simpleMissionConst1', IndepVarComp('hops', 1.0))
        self.add('simpleMissionConst2', IndepVarComp('loiterTime', 0.0))
        self.add('reserveMissionConst1', IndepVarComp('hops', 2.0))
        self.add('reserveMissionConst2', IndepVarComp('loiterTime', 1020.0))
        self.add('wingMassConst1', IndepVarComp('winglet', 0.2))
        self.add('wingMassConst2', IndepVarComp('fc', 0.4))
        self.add('canardMassConst1', IndepVarComp('winglet', 0.0))
        self.add('canardMassConst2', IndepVarComp('fc', 0.6))
        #self.add('wireMassConst1', IndepVarComp('fuselageLength', 5.0))
        self.add('wireMassConst2', IndepVarComp('fuselageHeight', 2.0))
        self.add('wireMassConst3', IndepVarComp('span', 0.0))
        self.add('wireMassConst4', IndepVarComp('xmotor', 0.0))
        #self.add('fuselageMassConst1', IndepVarComp('length', 5.0))  # Not needed for Helicopter configuration
        self.add('fuselageMassConst2', IndepVarComp('width', 1.0))
        self.add('fuselageMassConst3', IndepVarComp('height', 2.0))
        self.add('fuselageMassConst4', IndepVarComp('span', 1.0))
        self.add('configWeightConst1', IndepVarComp('payload_mass', 113.398))
        self.add('costBuildupConst1', IndepVarComp('partsPerTool', 1000.0))

        # add constraint equations
        self.add('con1',
                 ExecComp('c1 = (mBattery*230.0*0.95/1000.0) - EReserve'))
        self.add('con2',
                 ExecComp('c2 = mMotors*5.0 - hoverPower_PMax / 1000.0'))
        self.add('con3', ExecComp('c3 = mtow*9.8 - mass_W'))
        self.add(
            'con4',
            ExecComp(
                'c4 = (0.5*1.0/3.0*mass_rotor*(hoverPower_Vtip**2.0)) - (0.5*mass_m*(hoverPower_VAutoRotation**2.0))'
            ))

        # connect components - as Jonathan pointed out, the alternative is to use a consistent naming convetion and promote variables. This is a pain without a wrapper *cough* OpenMETA *cough*.
        self.connect('scale6.scaled',
                     'MassToWeight.mass')  # MassToWeight inputs

        self.connect('scale2.scaled',
                     'CruisePower.rProp')  # CruisePower inputs
        self.connect('scale3.scaled', 'CruisePower.V')
        self.connect('indep7.vehicle', 'CruisePower.Vehicle')
        self.connect('MassToWeight.weight', 'CruisePower.W')

        self.connect('CruisePower.omega',
                     'HoverPower.cruisePower_omega')  # HoverPower inputs
        self.connect('scale2.scaled', 'HoverPower.rProp')
        self.connect('indep7.vehicle', 'HoverPower.Vehicle')
        self.connect('MassToWeight.weight', 'HoverPower.W')

        self.connect('CruisePower.B', 'LoiterPower.B')  # LoiterPower inputs
        self.connect('CruisePower.AR', 'LoiterPower.cruiseOutputAR')
        self.connect('CruisePower.Cd0', 'LoiterPower.cruiseOutputCd0')
        self.connect('CruisePower.e', 'LoiterPower.cruiseOutputE')
        self.connect('CruisePower.etaMotor',
                     'LoiterPower.cruiseOutputEtaMotor')
        self.connect('CruisePower.etaProp', 'LoiterPower.cruiseOutputEtaProp')
        self.connect('CruisePower.omega', 'LoiterPower.cruiseOutputOmega')
        self.connect('CruisePower.PCruise', 'LoiterPower.cruiseOutputP')
        self.connect('CruisePower.PBattery',
                     'LoiterPower.cruiseOutputPBattery')
        self.connect('CruisePower.SCdFuse', 'LoiterPower.cruiseOutputSCdFuse')
        self.connect('CruisePower.sigma', 'LoiterPower.cruiseOutputSigma')
        self.connect('CruisePower.SRef', 'LoiterPower.cruiseOutputSRef')
        self.connect('scale2.scaled', 'LoiterPower.rProp')
        self.connect('scale3.scaled', 'LoiterPower.V')
        self.connect('indep7.vehicle', 'LoiterPower.Vehicle')
        self.connect('MassToWeight.weight', 'LoiterPower.W')

        self.connect(
            'CruisePower.PBattery',
            'SimpleMission.cruiseOutput_PBattery')  # SimpleMission inputs
        self.connect('simpleMissionConst1.hops', 'SimpleMission.hops')
        self.connect('HoverPower.hoverPower_PBattery',
                     'SimpleMission.hoverOutput_PBattery')
        self.connect('simpleMissionConst2.loiterTime',
                     'SimpleMission.loiterTime')
        self.connect('indep1.range', 'SimpleMission.range')
        self.connect('scale2.scaled', 'SimpleMission.rProp')
        self.connect('scale3.scaled', 'SimpleMission.V')
        self.connect('indep7.vehicle', 'SimpleMission.Vehicle')

        self.connect(
            'CruisePower.PBattery',
            'ReserveMission.cruiseOutput_PBattery')  # ReserveMission inputs
        self.connect('reserveMissionConst1.hops', 'ReserveMission.hops')
        self.connect('HoverPower.hoverPower_PBattery',
                     'ReserveMission.hoverOutput_PBattery')
        self.connect('LoiterPower.PBattery',
                     'ReserveMission.loiterOutput_PBattery')
        self.connect('reserveMissionConst2.loiterTime',
                     'ReserveMission.loiterTime')
        self.connect('indep1.range', 'ReserveMission.range')
        self.connect('scale2.scaled', 'ReserveMission.rProp')
        self.connect('scale3.scaled', 'ReserveMission.V')
        self.connect('indep7.vehicle', 'ReserveMission.Vehicle')

        self.add('WireMassInput1', ExecComp('length = 1.5+1.25*rProp'))
        self.connect('scale2.scaled', 'WireMassInput1.rProp')

        self.connect('wireMassConst2.fuselageHeight',
                     'WireMass.fuselageHeight')  # WireMass inputs
        self.connect('WireMassInput1.length', 'WireMass.fuselageLength')
        self.connect('HoverPower.hoverPower_PMaxBattery', 'WireMass.power')
        self.connect('wireMassConst4.xmotor', 'WireMass.xmotor')
        self.connect('wireMassConst3.span', 'WireMass.span')

        self.connect('scale2.scaled', 'PropMass.rProp')  # PropMass inputs
        self.connect('HoverPower.TMax', 'PropMass.thrust')

        self.add('PropMassInput1', ExecComp('R = rProp/5.0'))
        self.add('PropMassInput2',
                 ExecComp('T = 1.5*hoverOutput_QMax/(1.25*rProp)'))
        self.connect('scale2.scaled', 'PropMassInput1.rProp')
        self.connect('HoverPower.QMax', 'PropMassInput2.hoverOutput_QMax')
        self.connect('scale2.scaled', 'PropMassInput2.rProp')

        self.connect('PropMassInput1.R',
                     'PropMass_Tail.rProp')  # PropMass_Tail inputs
        self.connect('PropMassInput2.T', 'PropMass_Tail.thrust')

        self.add('FuselageMassInput1', ExecComp('length = 1.5+1.25*rProp'))
        self.connect('scale2.scaled', 'FuselageMassInput1.rProp')

        self.connect('FuselageMassInput1.length',
                     'FuselageMass.length')  # FuselageMass inputs
        self.connect('fuselageMassConst2.width', 'FuselageMass.width')
        self.connect('fuselageMassConst3.height', 'FuselageMass.height')
        self.connect('fuselageMassConst4.span', 'FuselageMass.span')
        self.connect('MassToWeight.weight', 'FuselageMass.weight')

        self.connect('FuselageMass.mass',
                     'ConfigWeight.fuselage_mass')  # ConfigWeight inputs
        self.connect('HoverPower.hoverPower_PMax',
                     'ConfigWeight.hoverOutput_PMax')
        self.connect('scale4.scaled', 'ConfigWeight.mBattery')
        self.connect('scale5.scaled', 'ConfigWeight.mMotors')
        self.connect('scale6.scaled', 'ConfigWeight.mtow')
        self.connect('configWeightConst1.payload_mass', 'ConfigWeight.payload')
        self.connect('PropMass.mass', 'ConfigWeight.prop_mass')
        self.connect('PropMass_Tail.mass', 'ConfigWeight.prop_mass_tail')
        self.connect('scale2.scaled', 'ConfigWeight.rProp')
        self.connect('indep7.vehicle', 'ConfigWeight.Vehicle')
        self.connect('WireMass.mass', 'ConfigWeight.wire_mass')

        self.connect('CruisePower.bRef',
                     'ToolingCost.cruiseOutput_bRef')  # ToolingCost inputs
        self.connect('CruisePower.cRef', 'ToolingCost.cruiseOutput_cRef')
        self.connect('costBuildupConst1.partsPerTool',
                     'ToolingCost.partsPerTool')
        self.connect('scale2.scaled', 'ToolingCost.rProp')
        self.connect('indep7.vehicle', 'ToolingCost.Vehicle')

        self.connect('SimpleMission.E',
                     'OperatingCost.E')  # OperatingCost inputs
        self.connect('SimpleMission.t', 'OperatingCost.flightTime')
        self.connect('scale4.scaled', 'OperatingCost.mass_battery')
        self.connect('scale5.scaled', 'OperatingCost.mass_motors')
        self.connect('ConfigWeight.mass_structural',
                     'OperatingCost.mass_structural')
        self.connect('scale2.scaled', 'OperatingCost.rProp')
        self.connect('ToolingCost.toolCostPerVehicle',
                     'OperatingCost.toolingCost')
        self.connect('indep7.vehicle', 'OperatingCost.Vehicle')

        self.connect('ReserveMission.E', 'con1.EReserve')  # Constraint inputs
        self.connect('scale4.scaled', 'con1.mBattery')
        self.connect('HoverPower.hoverPower_PMax', 'con2.hoverPower_PMax')
        self.connect('scale5.scaled', 'con2.mMotors')
        self.connect('ConfigWeight.mass_W', 'con3.mass_W')
        self.connect('scale6.scaled', 'con3.mtow')
        self.connect('ConfigWeight.mass_rotor', 'con4.mass_rotor')
        self.connect('HoverPower.hoverPower_Vtip', 'con4.hoverPower_Vtip')
        self.connect('HoverPower.hoverPower_VAutoRotation',
                     'con4.hoverPower_VAutoRotation')
コード例 #3
0
    def __init__(self):
        super(TopLevelSystem, self).__init__()

        print('running...')

        # add design variables
        self.add('indep1', IndepVarComp('range', 50.0))
        self.add('indep2', IndepVarComp('rProp', 100.0))
        self.add('indep3', IndepVarComp('cruiseSpeed', 50.0))
        self.add('indep4', IndepVarComp('batteryMass', 11.70))
        self.add('indep5', IndepVarComp('motorMass', 3.00))
        self.add('indep6', IndepVarComp('mtom', 6.500))
        self.add(
            'indep7', IndepVarComp('vehicle', u'tiltwing')
        )  # TypeError: In subproblem 'subprob': Type <type 'str'> of source 'indep7.vehicle' must be the same as type <type 'unicode'> of target 'ConfigWeight.Vehicle'.

        # design variable scaling - this is CRITICAL or else the COBYLA optimizer WILL NOT WORK
        self.add('scale2', ExecComp('scaled = orig*0.01'))
        self.add('scale3', ExecComp('scaled = orig*1.0'))
        self.add('scale4', ExecComp('scaled = orig*10.0'))
        self.add('scale5', ExecComp('scaled = orig*10.0'))
        self.add('scale6', ExecComp('scaled = orig*100.0'))

        self.connect('indep2.rProp', 'scale2.orig')
        self.connect('indep3.cruiseSpeed', 'scale3.orig')
        self.connect('indep4.batteryMass', 'scale4.orig')
        self.connect('indep5.motorMass', 'scale5.orig')
        self.connect('indep6.mtom', 'scale6.orig')

        # add components
        self.add('MassToWeight', mass_2_weight())
        self.add('CruisePower', CruisePower())
        self.add('HoverPower', HoverPower())
        self.add('LoiterPower', loiter_power())
        self.add('SimpleMission', mission())
        self.add('ReserveMission', mission())
        self.add('WingMass', wing_mass())
        self.add('CanardMass', wing_mass())
        self.add('WireMass', wire_mass())
        self.add('FuselageMass', fuselage_mass())
        self.add('ConfigWeight', config_weight())
        self.add('ToolingCost', tooling_cost())
        self.add('OperatingCost', operating_cost())

        # add component constants - Q. is there a better way to do this?
        self.add('simpleMissionConst1', IndepVarComp('hops', 1.0))
        self.add('simpleMissionConst2', IndepVarComp('loiterTime', 0.0))
        self.add('reserveMissionConst1', IndepVarComp('hops', 2.0))
        self.add('reserveMissionConst2', IndepVarComp('loiterTime', 1020.0))
        self.add('wingMassConst1', IndepVarComp('winglet', 0.2))
        self.add('wingMassConst2', IndepVarComp('fc', 0.4))
        self.add('canardMassConst1', IndepVarComp('winglet', 0.0))
        self.add('canardMassConst2', IndepVarComp('fc', 0.6))
        self.add('wireMassConst1', IndepVarComp('fuselageLength', 5.0))
        self.add('wireMassConst2', IndepVarComp('fuselageHeight', 1.65))
        self.add('fuselageMassConst1', IndepVarComp('length', 5.0))
        self.add('fuselageMassConst2', IndepVarComp('width', 1.0))
        self.add('fuselageMassConst3', IndepVarComp('height', 1.65))
        self.add('configWeightConst1', IndepVarComp('payload_mass', 114.0))
        #self.add('configWeightConst2', IndepVarComp('fuselage_mass', 55.0))  # TEMPORARY: This constant is a workaround until I add fuselage_mass.py
        self.add(
            'configWeightConst3', IndepVarComp('prop_mass', 2.5)
        )  # TEMPORARY: This constant is a workaround until I add prop_mass.py
        #self.add('configWeightConst4', IndepVarComp('wing_mass', 40.0))  # TEMPORARY: This constant is a workaround until I add wing_mass.py
        #self.add('configWeightConst5', IndepVarComp('canard_mass', 38.0))  # TEMPORARY: This constant is a workaround until I add wing_mass.py
        self.add('costBuildupConst1', IndepVarComp('partsPerTool', 1000.0))

        # add constraint equations
        self.add('con1',
                 ExecComp('c1 = (mBattery*230.0*0.95/1000.0) - EReserve'))
        self.add('con2',
                 ExecComp('c2 = mMotors*5.0 - hoverPower_PMax / 1000.0'))
        self.add('con3', ExecComp('c3 = mtow*9.8 - mass_W'))
        #self.add('con4', ExecComp('c4 = 0.5*1.0/3.0*mass_rotor*hoverPower_Vtip**2.0 - 0.5*mass_m*hoverPower_VAutoRotation**2.0'))  # Helicopter only - doesn't work for this version
        self.add(
            'con5', ExecComp('c5 = ((1.0/3.0)*mtow) - mBattery')
        )  # "Most transport aircraft have a maximum fuel weight that is roughly 1/3 of the maximum takeoff weight..."

        # connect components - as Jonathan pointed out, the alternative is to use a consistent naming convetion and promote variables. This is a pain without a wrapper *cough* OpenMETA *cough*.
        self.connect('scale6.scaled',
                     'MassToWeight.mass')  # MassToWeight inputs

        self.connect('scale2.scaled',
                     'CruisePower.rProp')  # CruisePower inputs
        self.connect('scale3.scaled', 'CruisePower.V')
        self.connect('indep7.vehicle', 'CruisePower.Vehicle')
        self.connect('MassToWeight.weight', 'CruisePower.W')

        self.connect('CruisePower.omega',
                     'HoverPower.cruisePower_omega')  # HoverPower inputs
        self.connect('scale2.scaled', 'HoverPower.rProp')
        self.connect('indep7.vehicle', 'HoverPower.Vehicle')
        self.connect('MassToWeight.weight', 'HoverPower.W')

        self.connect('CruisePower.B', 'LoiterPower.B')  # LoiterPower inputs
        self.connect('CruisePower.AR', 'LoiterPower.cruiseOutputAR')
        self.connect('CruisePower.Cd0', 'LoiterPower.cruiseOutputCd0')
        self.connect('CruisePower.e', 'LoiterPower.cruiseOutputE')
        self.connect('CruisePower.etaMotor',
                     'LoiterPower.cruiseOutputEtaMotor')
        self.connect('CruisePower.etaProp', 'LoiterPower.cruiseOutputEtaProp')
        self.connect('CruisePower.omega', 'LoiterPower.cruiseOutputOmega')
        self.connect('CruisePower.PCruise', 'LoiterPower.cruiseOutputP')
        self.connect('CruisePower.PBattery',
                     'LoiterPower.cruiseOutputPBattery')
        self.connect('CruisePower.SCdFuse', 'LoiterPower.cruiseOutputSCdFuse')
        self.connect('CruisePower.sigma', 'LoiterPower.cruiseOutputSigma')
        self.connect('CruisePower.SRef', 'LoiterPower.cruiseOutputSRef')
        self.connect('scale2.scaled', 'LoiterPower.rProp')
        self.connect('scale3.scaled', 'LoiterPower.V')
        self.connect('indep7.vehicle', 'LoiterPower.Vehicle')
        self.connect('MassToWeight.weight', 'LoiterPower.W')

        self.connect(
            'CruisePower.PBattery',
            'SimpleMission.cruiseOutput_PBattery')  # SimpleMission inputs
        self.connect('simpleMissionConst1.hops', 'SimpleMission.hops')
        self.connect('HoverPower.hoverPower_PBattery',
                     'SimpleMission.hoverOutput_PBattery')
        self.connect('simpleMissionConst2.loiterTime',
                     'SimpleMission.loiterTime')
        self.connect('indep1.range', 'SimpleMission.range')
        self.connect('scale2.scaled', 'SimpleMission.rProp')
        self.connect('scale3.scaled', 'SimpleMission.V')
        self.connect('indep7.vehicle', 'SimpleMission.Vehicle')

        self.connect(
            'CruisePower.PBattery',
            'ReserveMission.cruiseOutput_PBattery')  # ReserveMission inputs
        self.connect('reserveMissionConst1.hops', 'ReserveMission.hops')
        self.connect('HoverPower.hoverPower_PBattery',
                     'ReserveMission.hoverOutput_PBattery')
        self.connect('LoiterPower.PBattery',
                     'ReserveMission.loiterOutput_PBattery')
        self.connect('reserveMissionConst2.loiterTime',
                     'ReserveMission.loiterTime')
        self.connect('indep1.range', 'ReserveMission.range')
        self.connect('scale2.scaled', 'ReserveMission.rProp')
        self.connect('scale3.scaled', 'ReserveMission.V')
        self.connect('indep7.vehicle', 'ReserveMission.Vehicle')

        self.connect('CruisePower.cRef', 'WingMass.chord')  # WingMass inputs
        self.connect('wingMassConst2.fc', 'WingMass.fc')
        self.connect('scale2.scaled', 'WingMass.rProp')
        self.connect('CruisePower.bRef', 'WingMass.span')
        self.connect('HoverPower.TMax', 'WingMass.thrust')
        self.connect('MassToWeight.weight', 'WingMass.W')
        self.connect('wingMassConst1.winglet', 'WingMass.winglet')

        self.connect('CruisePower.cRef',
                     'CanardMass.chord')  # CanardMass inputs
        self.connect('canardMassConst2.fc', 'CanardMass.fc')
        self.connect('scale2.scaled', 'CanardMass.rProp')
        self.connect('CruisePower.bRef', 'CanardMass.span')
        self.connect('HoverPower.TMax', 'CanardMass.thrust')
        self.connect('MassToWeight.weight', 'CanardMass.W')
        self.connect('canardMassConst1.winglet', 'CanardMass.winglet')

        self.connect('wireMassConst2.fuselageHeight',
                     'WireMass.fuselageHeight')  # WireMass inputs
        self.connect('wireMassConst1.fuselageLength',
                     'WireMass.fuselageLength')
        self.connect('HoverPower.hoverPower_PMaxBattery',
                     'WireMass.power')  # Make sure this is actually correct
        self.connect('scale2.scaled', 'WireMass.rProp')
        self.connect('CruisePower.bRef', 'WireMass.span')

        self.connect('fuselageMassConst1.length',
                     'FuselageMass.length')  # FuselageMass inputs
        self.connect('fuselageMassConst2.width', 'FuselageMass.width')
        self.connect('fuselageMassConst3.height', 'FuselageMass.height')
        self.connect('CruisePower.bRef', 'FuselageMass.span')
        self.connect('MassToWeight.weight', 'FuselageMass.weight')

        self.connect('CanardMass.mass',
                     'ConfigWeight.canard_mass')  # ConfigWeight inputs
        self.connect('FuselageMass.mass', 'ConfigWeight.fuselage_mass')
        self.connect('HoverPower.hoverPower_PMax',
                     'ConfigWeight.hoverOutput_PMax')
        self.connect('scale4.scaled', 'ConfigWeight.mBattery')
        self.connect('scale5.scaled', 'ConfigWeight.mMotors')
        self.connect('scale6.scaled', 'ConfigWeight.mtow')
        self.connect('configWeightConst1.payload_mass', 'ConfigWeight.payload')
        self.connect('configWeightConst3.prop_mass', 'ConfigWeight.prop_mass')
        self.connect('scale2.scaled', 'ConfigWeight.rProp')
        self.connect('indep7.vehicle', 'ConfigWeight.Vehicle')
        self.connect('WingMass.mass', 'ConfigWeight.wing_mass')
        self.connect('WireMass.mass', 'ConfigWeight.wire_mass')

        self.connect('CruisePower.bRef',
                     'ToolingCost.cruiseOutput_bRef')  # ToolingCost inputs
        self.connect('CruisePower.cRef', 'ToolingCost.cruiseOutput_cRef')
        self.connect('costBuildupConst1.partsPerTool',
                     'ToolingCost.partsPerTool')
        self.connect('scale2.scaled', 'ToolingCost.rProp')
        self.connect('indep7.vehicle', 'ToolingCost.Vehicle')

        self.connect('SimpleMission.E',
                     'OperatingCost.E')  # OperatingCost inputs
        self.connect('SimpleMission.t', 'OperatingCost.flightTime')
        self.connect('scale4.scaled', 'OperatingCost.mass_battery')
        self.connect('scale5.scaled', 'OperatingCost.mass_motors')
        self.connect('ConfigWeight.mass_structural',
                     'OperatingCost.mass_structural')
        self.connect('scale2.scaled', 'OperatingCost.rProp')
        self.connect('ToolingCost.toolCostPerVehicle',
                     'OperatingCost.toolingCost')
        self.connect('indep7.vehicle', 'OperatingCost.Vehicle')

        self.connect('ReserveMission.E', 'con1.EReserve')  # Constraint inputs
        self.connect('scale4.scaled', 'con1.mBattery')
        self.connect('HoverPower.hoverPower_PMax', 'con2.hoverPower_PMax')
        self.connect('scale5.scaled', 'con2.mMotors')
        self.connect('ConfigWeight.mass_W', 'con3.mass_W')
        self.connect('scale6.scaled', 'con3.mtow')
        self.connect('scale4.scaled', 'con5.mBattery')
        self.connect('scale6.scaled', 'con5.mtow')