コード例 #1
0
    def test_single_comp_external_solve(self):

        model = set_as_top(Assembly())
        model.add('comp', MyComp_Deriv())
        #model.add('driver', BroydenSolver())
        model.add('driver', NewtonSolver())
        model.driver.workflow.add('comp')

        model.driver.add_parameter('comp.x', low=-100, high=100)
        model.driver.add_parameter('comp.y', low=-100, high=100)
        model.driver.add_parameter('comp.z', low=-100, high=100)

        model.driver.add_constraint('comp.res[0] = 0')
        model.driver.add_constraint('comp.res[1] = 0')
        model.driver.add_constraint('comp.res[2] = 0')

        model.comp.eval_only = True

        model.run()

        assert_rel_error(self, model.comp.x, 1.0, 1e-5)
        assert_rel_error(self, model.comp.y, -2.33333333, 1e-5)
        assert_rel_error(self, model.comp.z, -2.16666667, 1e-5)

        assert_rel_error(self, model.comp.y_out, -1.5, 1e-5)
コード例 #2
0
    def test_coupled_comps_external_solve(self):

        model = set_as_top(Assembly())
        model.add('comp1', Coupled1())
        model.add('comp2', Coupled2())
        model.add('driver', NewtonSolver())
        model.driver.workflow.add(['comp1', 'comp2'])

        model.connect('comp1.x', 'comp2.x')
        model.connect('comp1.y', 'comp2.y')
        model.connect('comp2.z', 'comp1.z')

        model.driver.add_parameter('comp1.x', low=-100, high=100)
        model.driver.add_parameter('comp1.y', low=-100, high=100)
        model.driver.add_parameter('comp2.z', low=-100, high=100)

        model.driver.add_constraint('comp1.res[0] = 0')
        model.driver.add_constraint('comp1.res[1] = 0')
        model.driver.add_constraint('comp2.res[0] = 0')

        model.comp1.eval_only = True
        model.comp2.eval_only = True
        model.run()

        assert_rel_error(self, model.comp1.x, 1.0, 1e-5)
        assert_rel_error(self, model.comp1.y, -2.33333333, 1e-5)
        assert_rel_error(self, model.comp2.z, -2.16666667, 1e-5)

        assert_rel_error(self, model.comp1.y_out, -1.5, 1e-5)
コード例 #3
0
    def configure(self):

        super(MDFOpt, self).configure()

        opt = self.add('driver', SLSQPdriver())
        # opt = self.add('driver', pyOptDriver())
        # opt.optimizer = 'SNOPT'
        # opt.options = {'Major feasibility tolerance': 1e-6,
        #                        'Minor feasibility tolerance': 1e-6,
        #                        'Major optimality tolerance': 1e-5,
        #                        'Function precision': 1e-8,
        #                        'Iterations limit': 500000000,
        #                        }
        opt.add_parameter('wing_weight.cbar', low=.3, high=5)
        opt.add_parameter('wing_weight.b', low=5, high=100, start=40)
        opt.add_parameter('wing_weight.fos', low=2.3, high=4)
        #opt.add_parameter('wing_weight.y_pod', low=0, high=15) #spanwise location of the outboard pods
        opt.add_objective('level.drag')
        opt.add_constraint('level.Cl < 1.1')
        opt.add_constraint('10*(wing_weight.tip_slope - .1) < 0')
        opt.add_constraint('wing_weight.tip_slope > 0')

        #MDF
        solver = self.add('solver', NewtonSolver())
        #state variables
        solver.add_parameter('level.alpha', low=0, high=5, start=3)
        solver.add_parameter('turning.alpha', low=0, high=10, start=3)
        #compatibility constraints
        solver.add_constraint(
            '(level.lift/9.81 - (wing_weight.M_tot + fuse_weight.M_tot))/2500 = 0 '
        )
        solver.add_constraint(
            '(turning.lift/9.81 - (turning.load_factor * (wing_weight.M_tot + fuse_weight.M_tot)))/1200 = 0'
        )
        opt.workflow.add('solver')
コード例 #4
0
    def configure(self):

        self.add('d1', Discipline1_WithDerivatives())
        self.d1.x1 = 1.0
        self.d1.y1 = 1.0
        self.d1.y2 = 1.0
        self.d1.z1 = 5.0
        self.d1.z2 = 2.0

        self.add('d2', Discipline2_WithDerivatives())
        self.d2.y1 = 1.0
        self.d2.y2 = 1.0
        self.d2.z1 = 5.0
        self.d2.z2 = 2.0

        self.add('P1', Paraboloid())
        self.add('P2', Paraboloid())

        self.connect('d1.y1', 'd2.y1')
        self.connect('P1.f_xy', 'd1.x1')
        self.connect('d1.y1', 'P2.x')
        self.connect('d2.y2', 'P2.y')

        self.add('driver', SimpleDriver())
        self.add('driver2', Driver())
        self.add('subdriver', NewtonSolver())
        self.driver.workflow.add(['P1', 'subdriver', 'P2'])
        self.subdriver.workflow.add(['d1', 'd2'])

        self.subdriver.add_parameter('d1.y2', low=-1e99, high=1e99)
        self.subdriver.add_constraint('d1.y2 = d2.y2')

        self.driver.add_parameter('P1.x', low=-1e99, high=1e99)
        self.driver.add_constraint('P2.f_xy < 0')
コード例 #5
0
    def configure(self):
        self.add("driver", NewtonSolver())
        self.add("X", Array(np.zeros(self.m), iotype="in"))
        self.add("roots", Array(np.zeros(self.m), iotype="in"))

        self.driver.add_parameter("X", low=-1e30, high=1e30)
        for i in xrange(self.m):
            compname = "p%s" % str(i)
            self.add(compname, PolyComp(self.m))
            self.driver.workflow.add(compname)
            self.connect("X", compname + ".X")
            self.connect("roots", compname + ".roots")
            self.driver.add_constraint("p%s.F = 0.0" % str(i))
コード例 #6
0
    def test_coupled_comps_internal_solve(self):

        model = set_as_top(Assembly())
        model.add('comp1', Coupled1())
        model.add('comp2', Coupled2())
        model.add('driver', NewtonSolver())
        model.driver.workflow.add(['comp1', 'comp2'])

        model.connect('comp1.x', 'comp2.x')
        model.connect('comp1.y', 'comp2.y')
        model.connect('comp2.z', 'comp1.z')

        d_edges = model._depgraph.get_directional_interior_edges(
            'comp1', 'comp2')
        self.assertTrue(('comp1.x', 'comp2.x') in d_edges)
        self.assertTrue(('comp1.y', 'comp2.y') in d_edges)

        model.run()

        assert_rel_error(self, model.comp1.x, 1.0, 1e-5)
        assert_rel_error(self, model.comp1.y, -2.33333333, 1e-5)
        assert_rel_error(self, model.comp2.z, -2.16666667, 1e-5)

        assert_rel_error(self, model.comp1.y_out, -1.5, 1e-5)
コード例 #7
0
ファイル: nest_segment.py プロジェクト: jiaxu825/pyMission
    def configure(self):
        """ Set it all up. """

        # Place all design variables on the Assembly boundary.
        self.add('S', Float(0.0, iotype='in', desc='Wing Area'))
        self.add('ac_w',
                 Float(0.0, iotype='in', desc='Weight of aircraft + payload'))
        self.add('SFCSL', Float(0.0, iotype='in', desc='sea-level SFC value'))
        self.add('thrust_sl',
                 Float(0.0, iotype='in', desc='Maximum sea-level thrust'))
        self.add('AR', Float(0.0, iotype='in', desc='Aspect Ratio'))
        self.add('oswald', Float(0.0, iotype='in', desc="Oswald's efficiency"))

        # Splines
        self.add(
            'SysXBspline',
            SysXBspline(num_elem=self.num_elem,
                        num_pt=self.num_pt,
                        x_init=self.x_pts,
                        jac_h=self.jac_h))
        self.SysXBspline.x_pt = self.x_pts

        self.add(
            'SysHBspline',
            SysHBspline(num_elem=self.num_elem,
                        num_pt=self.num_pt,
                        x_init=self.x_pts,
                        jac_h=self.jac_h))

        self.add(
            'SysMVBspline',
            SysMVBspline(num_elem=self.num_elem,
                         num_pt=self.num_pt,
                         x_init=self.x_pts,
                         jac_h=self.jac_h))

        self.add(
            'SysGammaBspline',
            SysGammaBspline(num_elem=self.num_elem,
                            num_pt=self.num_pt,
                            x_init=self.x_pts,
                            jac_gamma=self.jac_gamma))

        # Atmospherics
        self.add('SysSFC', SysSFC(num_elem=self.num_elem))
        self.add('SysTemp', SysTemp(num_elem=self.num_elem))
        self.add('SysRho', SysRho(num_elem=self.num_elem))
        self.add('SysSpeed', SysSpeed(num_elem=self.num_elem))

        self.connect('SFCSL', 'SysSFC.SFCSL')
        self.connect('SysHBspline.h', 'SysSFC.h')
        self.connect('SysHBspline.h', 'SysTemp.h')
        self.connect('SysHBspline.h', 'SysRho.h')
        self.connect('SysTemp.temp', 'SysRho.temp')
        self.connect('SysTemp.temp', 'SysSpeed.temp')
        self.connect('SysMVBspline.M', 'SysSpeed.M')
        self.connect('SysMVBspline.v_spline', 'SysSpeed.v_spline')

        # -----------------------------------
        # Comps for Coupled System begin here
        # -----------------------------------

        # Vertical Equilibrium
        self.add('SysCLTar', SysCLTar(num_elem=self.num_elem))

        self.connect('S', 'SysCLTar.S')
        self.connect('ac_w', 'SysCLTar.ac_w')
        self.connect('SysRho.rho', 'SysCLTar.rho')
        self.connect('SysGammaBspline.Gamma', 'SysCLTar.Gamma')
        self.connect('SysSpeed.v', 'SysCLTar.v')

        # Tripan Alpha
        self.add(
            'SysTripanCLSurrogate',
            SysTripanCLSurrogate(num_elem=self.num_elem,
                                 num=self.num,
                                 CL=self.CL_arr))
        self.connect('SysMVBspline.M', 'SysTripanCLSurrogate.M')
        self.connect('SysHBspline.h', 'SysTripanCLSurrogate.h')
        self.connect('SysCLTar.CL', 'SysTripanCLSurrogate.CL_tar')

        # Tripan Eta
        self.add(
            'SysTripanCMSurrogate',
            SysTripanCMSurrogate(num_elem=self.num_elem,
                                 num=self.num,
                                 CM=self.CM_arr))
        self.connect('SysMVBspline.M', 'SysTripanCMSurrogate.M')
        self.connect('SysHBspline.h', 'SysTripanCMSurrogate.h')
        self.connect('SysTripanCLSurrogate.alpha',
                     'SysTripanCMSurrogate.alpha')

        # Tripan Drag
        self.add(
            'SysTripanCDSurrogate',
            SysTripanCDSurrogate(num_elem=self.num_elem,
                                 num=self.num,
                                 CD=self.CD_arr))
        self.connect('SysMVBspline.M', 'SysTripanCDSurrogate.M')
        self.connect('SysHBspline.h', 'SysTripanCDSurrogate.h')
        self.connect('SysTripanCMSurrogate.eta', 'SysTripanCDSurrogate.eta')
        self.connect('SysTripanCLSurrogate.alpha',
                     'SysTripanCDSurrogate.alpha')

        # Horizontal Equilibrium
        self.add('SysCTTar', SysCTTar(num_elem=self.num_elem))

        self.connect('SysGammaBspline.Gamma', 'SysCTTar.Gamma')
        self.connect('SysTripanCDSurrogate.CD', 'SysCTTar.CD')
        self.connect('SysTripanCLSurrogate.alpha', 'SysCTTar.alpha')
        self.connect('SysRho.rho', 'SysCTTar.rho')
        self.connect('SysSpeed.v', 'SysCTTar.v')
        self.connect('S', 'SysCTTar.S')
        self.connect('ac_w', 'SysCTTar.ac_w')

        # Weight
        self.add('SysFuelWeight', SysFuelWeight(num_elem=self.num_elem))
        self.SysFuelWeight.fuel_w = np.linspace(1.0, 0.0, self.num_elem + 1)

        self.connect('SysSpeed.v', 'SysFuelWeight.v')
        self.connect('SysGammaBspline.Gamma', 'SysFuelWeight.Gamma')
        self.connect('SysCTTar.CT_tar', 'SysFuelWeight.CT_tar')
        self.connect('SysXBspline.x', 'SysFuelWeight.x')
        self.connect('SysSFC.SFC', 'SysFuelWeight.SFC')
        self.connect('SysRho.rho', 'SysFuelWeight.rho')
        self.connect('S', 'SysFuelWeight.S')

        # ------------------------------------------------
        # Coupled Analysis - Newton for outer loop
        # TODO: replace with GS/Newton cascaded solvers when working
        # -----------------------------------------------

        self.add('coupled_solver', NewtonSolver())

        # Direct connections (cycles) are faster.
        self.connect('SysFuelWeight.fuel_w', 'SysCLTar.fuel_w')
        self.connect('SysCTTar.CT_tar', 'SysCLTar.CT_tar')
        self.connect('SysTripanCLSurrogate.alpha', 'SysCLTar.alpha')
        self.connect('SysTripanCMSurrogate.eta', 'SysTripanCLSurrogate.eta')
        self.connect('SysFuelWeight.fuel_w', 'SysCTTar.fuel_w')

        #self.coupled_solver.add_parameter('SysCLTar.fuel_w')
        #self.coupled_solver.add_constraint('SysFuelWeight.fuel_w = SysCLTar.fuel_w')
        #self.coupled_solver.add_parameter('SysCLTar.CT_tar')
        #self.coupled_solver.add_constraint('SysCTTar.CT_tar = SysCLTar.CT_tar')
        #self.coupled_solver.add_parameter('SysCLTar.alpha')
        #self.coupled_solver.add_constraint('SysTripanCLSurrogate.alpha = SysCLTar.alpha')
        #self.coupled_solver.add_parameter('SysTripanCLSurrogate.eta')
        #self.coupled_solver.add_constraint('SysTripanCMSurrogate.eta = SysTripanCLSurrogate.eta')
        #self.coupled_solver.add_parameter('SysCTTar.fuel_w')
        #self.coupled_solver.add_constraint('SysFuelWeight.fuel_w = SysCTTar.fuel_w')

        # (Implicit comps)
        self.coupled_solver.add_parameter('SysTripanCLSurrogate.alpha')
        self.coupled_solver.add_constraint(
            'SysTripanCLSurrogate.alpha_res = 0')
        self.coupled_solver.add_parameter('SysTripanCMSurrogate.eta')
        self.coupled_solver.add_constraint('SysTripanCMSurrogate.CM = 0')

        # --------------------
        # Downstream of solver
        # --------------------

        # Functionals (i.e., components downstream of the coupled system.)
        self.add('SysTau', SysTau(num_elem=self.num_elem))
        self.add('SysTmin', SysTmin(num_elem=self.num_elem))
        self.add('SysTmax', SysTmax(num_elem=self.num_elem))
        #self.add('SysSlopeMin', SysSlopeMin(num_elem=self.num_elem))
        #self.add('SysSlopeMax', SysSlopeMax(num_elem=self.num_elem))
        self.add('SysFuelObj', SysFuelObj(num_elem=self.num_elem))
        self.add('SysHi', SysHi(num_elem=self.num_elem))
        self.add('SysHf', SysHf(num_elem=self.num_elem))
        self.add('SysMi', SysMi(num_elem=self.num_elem))
        self.add('SysMf', SysMf(num_elem=self.num_elem))
        self.add('SysBlockTime', SysBlockTime(num_elem=self.num_elem))

        self.connect('S', 'SysTau.S')
        self.connect('thrust_sl', 'SysTau.thrust_sl')
        self.connect('SysRho.rho', 'SysTau.rho')
        self.connect('SysCTTar.CT_tar', 'SysTau.CT_tar')
        self.connect('SysHBspline.h', 'SysTau.h')
        self.connect('SysSpeed.v', 'SysTau.v')
        self.connect('SysTau.tau', 'SysTmin.tau')
        self.connect('SysTau.tau', 'SysTmax.tau')
        #self.connect('SysGammaBspline.Gamma', 'SysSlopeMin.Gamma')
        #self.connect('SysGammaBspline.Gamma', 'SysSlopeMax.Gamma')
        self.connect('SysFuelWeight.fuel_w', 'SysFuelObj.fuel_w')
        self.connect('SysHBspline.h', 'SysHi.h')
        self.connect('SysHBspline.h', 'SysHf.h')
        self.connect('SysMVBspline.M', 'SysMi.M')
        self.connect('SysMVBspline.M', 'SysMf.M')
        self.connect('SysXBspline.x', 'SysBlockTime.x')
        self.connect('SysSpeed.v', 'SysBlockTime.v')
        self.connect('SysGammaBspline.Gamma', 'SysBlockTime.Gamma')

        # Promote useful variables to the boundary.
        self.create_passthrough('SysHBspline.h_pt')
        self.connect('h_pt', 'SysGammaBspline.h_pt')
        self.create_passthrough('SysMVBspline.v_pt')
        self.create_passthrough('SysMVBspline.M_pt')
        self.create_passthrough('SysTmin.Tmin')
        self.create_passthrough('SysTmax.Tmax')
        self.create_passthrough('SysFuelObj.fuelburn')
        self.create_passthrough('SysHi.h_i')
        self.create_passthrough('SysHf.h_f')

        #-------------------------
        # Iteration Hierarchy
        #-------------------------
        #self.driver.workflow.add(['SysXBspline', 'SysHBspline',
        #'SysMVBspline', 'SysGammaBspline',
        #'SysSFC', 'SysTemp', 'SysRho', 'SysSpeed',
        #'coupled_solver',
        #'SysTau', 'SysTmin', 'SysTmax',
        #'SysFuelObj', 'SysHi', 'SysHf', 'SysMi', 'SysMf', 'SysBlockTime'])

        self.add('bsplines', Driver())
        self.add('atmosphere', Driver())
        self.add('SysCLTar_Sub', Driver())
        self.add('SysTripanCLSurrogate_Sub', Driver())
        self.add('SysTripanCMSurrogate_Sub', Driver())
        self.add('SysTripanCDSurrogate_Sub', Driver())
        self.add('SysCTTar_Sub', Driver())
        self.add('SysFuelWeight_Sub', Driver())

        self.driver.workflow.add([
            'bsplines', 'atmosphere', 'coupled_solver', 'SysTau', 'SysTmin',
            'SysTmax', 'SysFuelObj', 'SysHi', 'SysHf', 'SysMi', 'SysMf',
            'SysBlockTime'
        ])

        self.bsplines.workflow.add(
            ['SysXBspline', 'SysHBspline', 'SysMVBspline', 'SysGammaBspline'])

        self.atmosphere.workflow.add(
            ['SysSFC', 'SysTemp', 'SysRho', 'SysSpeed'])

        self.coupled_solver.workflow.add([
            'SysCLTar_Sub', 'SysTripanCLSurrogate_Sub',
            'SysTripanCMSurrogate_Sub', 'SysTripanCDSurrogate_Sub',
            'SysCTTar_Sub', 'SysFuelWeight_Sub'
        ])

        self.SysCLTar_Sub.workflow.add(['SysCLTar'])
        self.SysTripanCLSurrogate_Sub.workflow.add(['SysTripanCLSurrogate'])
        self.SysTripanCMSurrogate_Sub.workflow.add(['SysTripanCMSurrogate'])
        self.SysTripanCDSurrogate_Sub.workflow.add(['SysTripanCDSurrogate'])
        self.SysCTTar_Sub.workflow.add(['SysCTTar'])
        self.SysFuelWeight_Sub.workflow.add(['SysFuelWeight'])

        #-------------------------
        # Driver Settings
        #-------------------------

        self.driver.gradient_options.lin_solver = "linear_gs"
        self.driver.gradient_options.maxiter = 1
        self.driver.gradient_options.derivative_direction = 'adjoint'

        self.coupled_solver.atol = 1e-9
        self.coupled_solver.rtol = 1e-9
        self.coupled_solver.max_iteration = 15
        self.coupled_solver.gradient_options.atol = 1e-14
        self.coupled_solver.gradient_options.rtol = 1e-20
        self.coupled_solver.gradient_options.maxiter = 50
        self.coupled_solver.iprint = 1
コード例 #8
0
ファイル: segment_737.py プロジェクト: jiaxu825/pyMission
    def configure(self):
        """ Set it all up. """

        # Place all design variables on the Assembly boundary.
        self.add('S', Float(0.0, iotype='in', desc='Wing Area'))
        self.add('ac_w',
                 Float(0.0, iotype='in', desc='Weight of aircraft + payload'))
        self.add('SFCSL', Float(0.0, iotype='in', desc='sea-level SFC value'))
        self.add('thrust_sl',
                 Float(0.0, iotype='in', desc='Maximum sea-level thrust'))
        self.add('AR', Float(0.0, iotype='in', desc='Aspect Ratio'))
        self.add('oswald', Float(0.0, iotype='in', desc="Oswald's efficiency"))

        # Splines
        self.add(
            'SysXBspline',
            SysXBspline(num_elem=self.num_elem,
                        num_pt=self.num_pt,
                        x_init=self.x_pts,
                        jac_h=self.jac_h))
        self.SysXBspline.x_pt = self.x_pts

        self.add(
            'SysHBspline',
            SysHBspline(num_elem=self.num_elem,
                        num_pt=self.num_pt,
                        x_init=self.x_pts,
                        jac_h=self.jac_h))

        self.add(
            'SysMVBspline',
            SysMVBspline(num_elem=self.num_elem,
                         num_pt=self.num_pt,
                         x_init=self.x_pts,
                         jac_h=self.jac_h))

        self.add(
            'SysGammaBspline',
            SysGammaBspline(num_elem=self.num_elem,
                            num_pt=self.num_pt,
                            x_init=self.x_pts,
                            jac_gamma=self.jac_gamma))

        # Atmospherics
        self.add('SysSFC', SysSFC(num_elem=self.num_elem))
        self.add('SysTemp', SysTemp(num_elem=self.num_elem))
        self.add('SysRho', SysRho(num_elem=self.num_elem))
        self.add('SysSpeed', SysSpeed(num_elem=self.num_elem))

        self.connect('SFCSL', 'SysSFC.SFCSL')
        self.connect('SysHBspline.h', 'SysSFC.h')
        self.connect('SysHBspline.h', 'SysTemp.h')
        self.connect('SysHBspline.h', 'SysRho.h')
        self.connect('SysTemp.temp', 'SysRho.temp')
        self.connect('SysTemp.temp', 'SysSpeed.temp')
        self.connect('SysMVBspline.M', 'SysSpeed.M')
        self.connect('SysMVBspline.v_spline', 'SysSpeed.v_spline')

        # -----------------------------------
        # Comps for Coupled System begin here
        # -----------------------------------
        # Vertical Equilibrium
        self.add('SysCLTar', SysCLTar(num_elem=self.num_elem))

        self.connect('S', 'SysCLTar.S')
        self.connect('ac_w', 'SysCLTar.ac_w')
        self.connect('SysRho.rho', 'SysCLTar.rho')
        self.connect('SysGammaBspline.Gamma', 'SysCLTar.Gamma')
        self.connect('SysSpeed.v', 'SysCLTar.v')

        # Drag
        self.add('SysAeroSurrogate', SysAeroSurrogate(num_elem=self.num_elem))

        self.connect('AR', 'SysAeroSurrogate.AR')
        self.connect('oswald', 'SysAeroSurrogate.oswald')

        # Horizontal Equilibrium
        self.add('SysCTTar', SysCTTar(num_elem=self.num_elem))

        self.connect('S', 'SysCTTar.S')
        self.connect('ac_w', 'SysCTTar.ac_w')
        self.connect('SysRho.rho', 'SysCTTar.rho')
        self.connect('SysGammaBspline.Gamma', 'SysCTTar.Gamma')
        self.connect('SysSpeed.v', 'SysCTTar.v')
        self.connect('SysAeroSurrogate.CD', 'SysCTTar.CD')
        self.connect('SysAeroSurrogate.alpha', 'SysCTTar.alpha')

        # Moment Equilibrium
        self.add('SysCM', SysCM(num_elem=self.num_elem))
        self.connect('SysAeroSurrogate.alpha', 'SysCM.alpha')
        self.SysCM.eval_only = True

        # Weight
        self.add('SysFuelWeight', SysFuelWeight(num_elem=self.num_elem))
        self.SysFuelWeight.fuel_w = np.linspace(1.0, 0.0, self.num_elem + 1)

        self.connect('S', 'SysFuelWeight.S')
        self.connect('SysRho.rho', 'SysFuelWeight.rho')
        self.connect('SysXBspline.x', 'SysFuelWeight.x')
        self.connect('SysGammaBspline.Gamma', 'SysFuelWeight.Gamma')
        self.connect('SysSpeed.v', 'SysFuelWeight.v')
        self.connect('SysSFC.SFC', 'SysFuelWeight.SFC')
        self.connect('SysCTTar.CT_tar', 'SysFuelWeight.CT_tar')

        # ----------------------------------------
        # Drag subsystem - Newton for inner loop
        # ----------------------------------------
        self.add('drag_solver', NewtonSolver())
        self.drag_solver.add_parameter(('SysAeroSurrogate.alpha'))
        self.drag_solver.add_constraint('SysAeroSurrogate.CL = SysCLTar.CL')

        self.drag_solver.iprint = 1
        self.drag_solver.atol = 1e-9
        self.drag_solver.rtol = 1e-9
        self.drag_solver.max_iteration = 15
        self.drag_solver.gradient_options.atol = 1e-10
        self.drag_solver.gradient_options.rtol = 1e-10
        self.drag_solver.gradient_options.maxiter = 15

        # ------------------------------------------------
        # Coupled Analysis - Newton for outer loop
        # TODO: replace with GS/Newton cascaded solvers when working
        # -----------------------------------------------
        self.add('coupled_solver', NewtonSolver())

        # Old way, using params and eq-constraints
        # self.coupled_solver.add_parameter('SysCLTar.CT_tar')
        # self.coupled_solver.add_parameter('SysCLTar.fuel_w')
        # self.coupled_solver.add_parameter('SysCLTar.alpha')
        # self.coupled_solver.add_parameter('SysAeroSurrogate.eta')
        # self.coupled_solver.add_parameter('SysCTTar.fuel_w')
        #self.coupled_solver.add_constraint('SysCLTar.CT_tar = SysCTTar.CT_tar')
        #self.coupled_solver.add_constraint('SysCLTar.fuel_w = SysFuelWeight.fuel_w')
        #self.coupled_solver.add_constraint('SysCLTar.alpha = SysAeroSurrogate.alpha')
        #self.coupled_solver.add_constraint('SysAeroSurrogate.eta = SysCM.eta')
        #self.coupled_solver.add_constraint('SysCTTar.fuel_w = SysFuelWeight.fuel_w')
        # Direct connections (cycles) are faster.
        self.connect('SysCTTar.CT_tar', 'SysCLTar.CT_tar')
        self.connect('SysFuelWeight.fuel_w', 'SysCLTar.fuel_w')
        self.connect('SysAeroSurrogate.alpha', 'SysCLTar.alpha')
        self.connect('SysCM.eta', 'SysAeroSurrogate.eta')
        self.connect('SysFuelWeight.fuel_w', 'SysCTTar.fuel_w')

        # (Only non-GS pair)
        self.coupled_solver.add_parameter('SysCM.eta')
        self.coupled_solver.add_constraint('SysCM.eta_res = 0')

        self.coupled_solver.atol = 1e-9
        self.coupled_solver.rtol = 1e-9
        self.coupled_solver.max_iteration = 15
        self.coupled_solver.gradient_options.atol = 1e-14
        self.coupled_solver.gradient_options.rtol = 1e-14
        self.coupled_solver.gradient_options.maxiter = 18

        self.coupled_solver.iprint = 1

        # --------------------
        # Downstream of solver
        # --------------------
        # Functionals (i.e., components downstream of the coupled system.)
        self.add('SysTau', SysTau(num_elem=self.num_elem))
        self.add('SysTmin', SysTmin(num_elem=self.num_elem))
        self.add('SysTmax', SysTmax(num_elem=self.num_elem))
        self.add('SysSlopeMin', SysSlopeMin(num_elem=self.num_elem))
        self.add('SysSlopeMax', SysSlopeMax(num_elem=self.num_elem))
        self.add('SysFuelObj', SysFuelObj(num_elem=self.num_elem))
        self.add('SysHi', SysHi(num_elem=self.num_elem))
        self.add('SysHf', SysHf(num_elem=self.num_elem))

        self.connect('S', 'SysTau.S')
        self.connect('thrust_sl', 'SysTau.thrust_sl')
        self.connect('SysRho.rho', 'SysTau.rho')
        self.connect('SysCTTar.CT_tar', 'SysTau.CT_tar')
        self.connect('SysHBspline.h', 'SysTau.h')
        self.connect('SysSpeed.v', 'SysTau.v')
        self.connect('SysTau.tau', 'SysTmin.tau')
        self.connect('SysTau.tau', 'SysTmax.tau')
        self.connect('SysGammaBspline.Gamma', 'SysSlopeMin.Gamma')
        self.connect('SysGammaBspline.Gamma', 'SysSlopeMax.Gamma')
        self.connect('SysFuelWeight.fuel_w', 'SysFuelObj.fuel_w')
        self.connect('SysHBspline.h', 'SysHi.h')
        self.connect('SysHBspline.h', 'SysHf.h')

        # Promote useful variables to the boundary.
        self.create_passthrough('SysHBspline.h_pt')
        self.connect('h_pt', 'SysGammaBspline.h_pt')
        self.create_passthrough('SysMVBspline.M_pt')
        self.create_passthrough('SysTmin.Tmin')
        self.create_passthrough('SysTmax.Tmax')
        self.create_passthrough('SysFuelObj.fuelburn')
        self.create_passthrough('SysHi.h_i')
        self.create_passthrough('SysHf.h_f')

        #-------------------------
        # Iteration Hieararchy
        #-------------------------
        self.driver.workflow.add([
            'SysXBspline', 'SysHBspline', 'SysMVBspline', 'SysGammaBspline',
            'SysSFC', 'SysTemp', 'SysRho', 'SysSpeed', 'coupled_solver',
            'SysTau', 'SysTmin', 'SysTmax', 'SysSlopeMin', 'SysSlopeMax',
            'SysFuelObj', 'SysHi', 'SysHf'
        ])
        self.coupled_solver.workflow.add(
            ['SysCLTar', 'drag_solver', 'SysCTTar', 'SysCM', 'SysFuelWeight'])
        self.drag_solver.workflow.add(['SysAeroSurrogate'])

        # Change some scaling parameters so that we match what they were when
        # the pickle was created.
        self.SysTau.thrust_scale = 0.072
        self.SysCLTar.fuel_scale = 1e6
        self.SysCTTar.fuel_scale = 1e6
        self.SysFuelWeight.fuel_scale = 1e6