Example #1
0
    def test_run_apply(self):
        # This test makes sure that we correctly apply the "run_apply" flag
        # to all targets in the "broken" connection, even when they are
        # nested in Groups.

        prob = Problem()
        root = prob.root = Group()

        sub1 = root.add('sub1', Group())
        sub2 = root.add('sub2', Group())

        sub1.add('p1', Paraboloid())
        sub1.add('p2', Paraboloid())
        sub2.add('p1', Paraboloid())
        sub2.add('p2', Paraboloid())

        root.connect('sub1.p1.f_xy', 'sub2.p1.x')
        root.connect('sub1.p2.f_xy', 'sub2.p1.y')
        root.connect('sub1.p1.f_xy', 'sub2.p2.x')
        root.connect('sub1.p2.f_xy', 'sub2.p2.y')
        root.connect('sub2.p1.f_xy', 'sub1.p1.x')
        root.connect('sub2.p2.f_xy', 'sub1.p1.y')
        root.connect('sub2.p1.f_xy', 'sub1.p2.x')
        root.connect('sub2.p2.f_xy', 'sub1.p2.y')

        root.nl_solver = NLGaussSeidel()
        root.ln_solver = ScipyGMRES()

        prob.setup(check=False)

        # Will be True in one group and False in the other, depending on
        # where it cuts.
        self.assertTrue(root.sub1.p1._run_apply != root.sub2.p1._run_apply)
        self.assertTrue(root.sub1.p2._run_apply != root.sub2.p2._run_apply)
Example #2
0
    def __init__(self):
        super(SellarDerivatives, self).__init__()

        self.add('px', IndepVarComp('x1', 1.0), promotes=['x1'])
        self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z'])

        self.add('d1', SellarDisc1(), promotes=['z', 'x1', 'y1', 'y2'])
        self.add('d2', SellarDisc2(), promotes=['z', 'y1', 'y2'])

        self.add('obj_cmp',
                 ExecComp('obj = x1**2 + z[1] + y1 + exp(-y2)',
                          z=np.array([5.0, 2.0]),
                          x1=1.0,
                          y1=0.0,
                          y2=0.0),
                 promotes=['obj', 'x1', 'z', 'y1', 'y2'])
        self.add('con_cmp1',
                 ExecComp('con1 = -y1 + 3.16', y1=0.0),
                 promotes=['y1', 'con1'])
        self.add('con_cmp2',
                 ExecComp('con2 = y2 - 24.0', y2=0.0),
                 promotes=['y2', 'con2'])

        self.n1_solver = NLGaussSeidel()
        self.n1_solver.options['atol'] = 1.0e-12

        self.ln_solver = ScipyGMRES()
Example #3
0
    def __init__(self):
        super(SellarDerivatives, self).__init__()

        # params will be provided by parent group
        self.add('px', IndepVarComp('x', 1.0), promotes=['x'])
        self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z'])

        self.add('d1',
                 SellarDis1withDerivatives(),
                 promotes=['x', 'z', 'y1', 'y2'])
        self.add('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2'])

        self.add('obj_cmp',
                 ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',
                          z=np.array([0.0, 0.0]),
                          x=0.0),
                 promotes=['obj', 'x', 'z', 'y1', 'y2'])

        self.add('con_cmp1',
                 ExecComp('con1 = 3.16 - y1'),
                 promotes=['con1', 'y1'])
        self.add('con_cmp2',
                 ExecComp('con2 = y2 - 24.0'),
                 promotes=['con2', 'y2'])

        self.nl_solver = NLGaussSeidel()
        self.ln_solver = ScipyGMRES()
Example #4
0
    def __init__(self,
                 nTurbines,
                 direction_id=0,
                 datasize=0,
                 differentiable=True,
                 use_rotor_components=False,
                 nSamples=0,
                 wake_model=floris_wrapper,
                 wake_model_options=None):

        super(RotorSolveGroup, self).__init__()

        if wake_model_options is None:
            wake_model_options = {
                'differentiable': differentiable,
                'use_rotor_components': use_rotor_components,
                'nSamples': nSamples
            }

        from openmdao.core.mpi_wrap import MPI

        # set up iterative solvers
        epsilon = 1E-6
        if MPI:
            self.ln_solver = PetscKSP()
        else:
            self.ln_solver = ScipyGMRES()
        self.nl_solver = NLGaussSeidel()
        self.ln_solver.options['atol'] = epsilon

        self.add('CtCp',
                 CPCT_Interpolate_Gradients_Smooth(nTurbines,
                                                   direction_id=direction_id,
                                                   datasize=datasize),
                 promotes=[
                     'gen_params:*',
                     'yaw%i' % direction_id,
                     'wtVelocity%i' % direction_id, 'Cp_out'
                 ])

        # TODO refactor the model component instance
        self.add('floris',
                 wake_model(nTurbines,
                            direction_id=direction_id,
                            wake_model_options=wake_model_options),
                 promotes=([
                     'model_params:*', 'wind_speed', 'axialInduction',
                     'turbineXw', 'turbineYw', 'rotorDiameter',
                     'yaw%i' % direction_id, 'hubHeight',
                     'wtVelocity%i' % direction_id
                 ] if (nSamples == 0) else [
                     'model_params:*', 'wind_speed', 'axialInduction',
                     'turbineXw', 'turbineYw', 'rotorDiameter',
                     'yaw%i' % direction_id, 'hubHeight',
                     'wtVelocity%i' %
                     direction_id, 'wsPositionX', 'wsPositionY', 'wsPositionZ',
                     'wsArray%i' % direction_id
                 ]))
        self.connect('CtCp.Ct_out', 'floris.Ct')
    def __init__(self, problem_id=0):
        super(SellarDerivativesSubGroup, self).__init__()

        self.add('d1', SellarDis1(problem_id=problem_id), promotes=['*'])
        self.add('d2', SellarDis2(problem_id=problem_id), promotes=['*'])

        self.nl_solver = NLGaussSeidel()
        self.nl_solver.options['atol'] = 1.0e-12

        if impl is not None:
            self.ln_solver = PetscKSP()
    def test_sellar(self):

        prob = Problem()
        prob.root = SellarNoDerivatives()
        prob.root.nl_solver = NLGaussSeidel()

        prob.setup(check=False)
        prob.run()

        assert_rel_error(self, prob['y1'], 25.58830273, .00001)
        assert_rel_error(self, prob['y2'], 12.05848819, .00001)

        # Make sure we aren't iterating like crazy
        self.assertLess(prob.root.nl_solver.iter_count, 8)
Example #7
0
    def test_indirect_errors_divide_subbed(self):

        # Make sure that two stacked solvers don't double append.

        top = Problem(debug=True)
        top.root = root = Group()
        sub = root.add('sub', Group())
        sub.add('comp1', ErrorComp('xx'))
        sub.add('comp2', ErrorComp('indirect_divide'))
        root.connect('sub.comp1.out', 'sub.comp2.in')
        root.connect('sub.comp2.out', 'sub.comp1.in')

        root.nl_solver = NLGaussSeidel()
        root.ln_solver = ScipyGMRES()
        sub.nl_solver = NLGaussSeidel()
        sub.ln_solver = ScipyGMRES()

        top.setup(check=False)

        with self.assertRaises(FloatingPointError) as err:
            top.run()

        expected_msg = "invalid value encountered in subtract\nThe following unknowns are nonfinite: ['comp1.out', 'comp2.out']\nThe following resids are nonfinite: ['comp1.out']\nThe following params are nonfinite: ['comp1.in']"
        self.assertEqual(str(err.exception), expected_msg)
Example #8
0
    def setUp(self):
        root = ParallelGroup()

        root.nl_solver = NLGaussSeidel()

        root.add('C1', IndepVarComp('x', 5.))
        root.add('C2', ExecComp('y=x*2.0'))
        root.add('C3', ExecComp('y=x*2.0'))
        root.add('C4', ExecComp('y=x*2.0'))

        root.connect("C1.x", "C2.x")
        root.connect("C2.y", "C4.x")
        root.connect("C4.y", "C3.x")

        self.root = root
Example #9
0
    def test_sellar_analysis_error(self):

        prob = Problem()
        prob.root = SellarNoDerivatives()
        prob.root.nl_solver = NLGaussSeidel()
        prob.root.nl_solver.options['maxiter'] = 2
        prob.root.nl_solver.options['err_on_maxiter'] = True

        prob.setup(check=False)

        try:
            prob.run()
        except AnalysisError as err:
            self.assertEqual(str(err), "Solve in '': NLGaussSeidel FAILED to converge after 2 iterations")
        else:
            self.fail("expected AnalysisError")
Example #10
0
    def test_sellar_with_Aitken(self):
        # This test makes sure the Aitken acc. feature is working correctly

        prob = Problem()
        prob.root = SellarNoDerivatives()
        prob.root.nl_solver = NLGaussSeidel()

        prob.root.nl_solver.options['use_aitken'] = True
        prob.root.cycle.set_order(['d1', 'd2'])

        prob.setup(check=False)
        prob.run()
        
        # check the Aitken relaxation factor value
        assert_rel_error(self, prob.root.nl_solver.aitken_alpha, 0.980998467864, .00001)
        
        # check that the problem converges in 4 iters (1 less than w/o Aitken)
        self.assertTrue(prob.root.nl_solver.iter_count == 4)
    def __init__(self):
        super(SellarDerivatives, self).__init__()

        self.add('px', IndepVarComp('x', 1.0), promotes=['*'])
        self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['*'])

        self.add('d1', SellarDis1(), promotes=['*'])
        self.add('d2', SellarDis2(), promotes=['*'])

        self.add('obj_cmp',
                 ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',
                          z=np.array([0.0, 0.0])),
                 promotes=['*'])

        self.add('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['*'])
        self.add('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['*'])

        self.nl_solver = NLGaussSeidel()
        self.nl_solver.options['atol'] = 1.0e-12
Example #12
0
    def test_sellar_group(self):

        prob = Problem()
        prob.root = SellarDerivativesGrouped()
        prob.root.nl_solver = NLGaussSeidel()
        prob.root.nl_solver.options['atol'] = 1e-9
        prob.root.mda.nl_solver.options['atol'] = 1e-3
        prob.root.nl_solver.options['iprint'] = 2 # so that print_norm is in coverage

        prob.setup(check=False)

        old_stdout = sys.stdout
        sys.stdout = cStringIO() # so we don't see the iprint output during testing
        try:
            prob.run()
        finally:
            sys.stdout = old_stdout

        assert_rel_error(self, prob['y1'], 25.58830273, .00001)
        assert_rel_error(self, prob['y2'], 12.05848819, .00001)
Example #13
0
    def test_sellar_utol(self):

        prob = Problem()
        prob.root = SellarNoDerivatives()
        prob.root.nl_solver = NLGaussSeidel()

        prob.setup(check=False)

        # make sure we trigger convergence from utol
        prob.root.nl_solver.options['rtol'] = 1e-99
        prob.root.nl_solver.options['atol'] = 1e-99
        prob.root.nl_solver.options['utol'] = 1e-6

        prob.run()

        assert_rel_error(self, prob['y1'], 25.58830273, .00001)
        assert_rel_error(self, prob['y2'], 12.05848819, .00001)

        # Make sure we aren't iterating like crazy
        self.assertLess(prob.root.nl_solver.iter_count, 8)
Example #14
0
    def test_sellar(self):

        prob = Problem()
        prob.root = SellarNoDerivatives()
        prob.root.nl_solver = NLGaussSeidel()

        prob.setup(check=False)
        prob.run()

        assert_rel_error(self, prob['y1'], 25.58830273, .00001)
        assert_rel_error(self, prob['y2'], 12.05848819, .00001)

        # Make sure we aren't iterating like crazy
        self.assertLess(prob.root.nl_solver.iter_count, 8)

        # Make sure we only call apply_linear on 'heads'
        nd1 = prob.root.cycle.d1.execution_count
        nd2 = prob.root.cycle.d2.execution_count
        if prob.root.cycle.d1._run_apply == True:
            self.assertEqual(nd1, 2 * nd2)
        else:
            self.assertEqual(2 * nd1, nd2)
Example #15
0
    def __init__(self):
        super(Drivetrain, self).__init__()

        # self.add('InputVoltage', IndepVarComp('Voltage', 500.0))

        self.add('Motor', ElectricMotor())
        self.add('Inverter', Inverter())
        self.add('Battery', Battery(), promotes=['des_time', 'time_of_flight'])

        # connect ElectricMotor outputs to Inverter inputs
        self.connect('Motor.frequency', 'Inverter.output_frequency')
        self.connect('Motor.phase_voltage', 'Inverter.output_voltage')
        self.connect('Motor.phase_current', 'Inverter.output_current')

        # connect Inverter outputs to Battery inputs
        self.connect('Inverter.input_current', 'Battery.des_current')
        self.connect('Inverter.input_power', 'Battery.des_power')

        # connect Battery outputs to Inverter inputs
        # self.connect('Battery.output_voltage', 'Inverter.input_voltage')

        self.nl_solver = NLGaussSeidel()
        self.nl_solver.options['atol'] = 1.0e-12
        self.ln_solver = ScipyGMRES()
Example #16
0
    root.add('vlmfuncs', vlmfuncs_comp, promotes=['*'])

    # Add components to the coupled MDA here
    coupled = Group()
    coupled.add('mesh', mesh_comp, promotes=["*"])

    ############################################################
    # Problem 2b:
    # Try different nonlinear solvers on the coupled and root groups.
    # Nonlinear Gauss Seidel is included as an example.
    # Examine http://openmdao.readthedocs.io/en/latest/srcdocs/packages/openmdao.solvers.html
    # to see syntax for other options.
    ############################################################

    ## Nonlinear Gauss Seidel on the coupled group
    coupled.nl_solver = NLGaussSeidel()
    coupled.nl_solver.options['iprint'] = 1
    coupled.nl_solver.options['atol'] = 1e-5
    coupled.nl_solver.options['rtol'] = 1e-12

    ############################################################
    # Problem 2c:
    # Try different linear solvers for the coupled group.
    # Again examine http://openmdao.readthedocs.io/en/latest/srcdocs/packages/openmdao.solvers.html
    # for linear solver options.
    ############################################################

    ## Krylov Solver - LNGS preconditioning
    coupled.ln_solver = ScipyGMRES()
    coupled.ln_solver.options['iprint'] = 1
    coupled.ln_solver.preconditioner = LinearGaussSeidel()
Example #17
0
    def setup_aerostruct(self):
        """
        Specific method to add the necessary components to the problem for an
        aerostructural problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'aerostruct'

        # Create the base root-level group
        root = Group()
        coupled = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']
            tmp_group = Group()

            # Add independent variables that do not belong to a specific component
            indep_vars = [
                (name + 'twist_cp', numpy.zeros(surface['num_twist'])),
                (name + 'thickness_cp', numpy.ones(surface['num_thickness']) *
                 numpy.max(surface['t'])), (name + 'r', surface['r']),
                (name + 'dihedral', surface['dihedral']),
                (name + 'sweep', surface['sweep']),
                (name + 'span', surface['span']),
                (name + 'taper', surface['taper'])
            ]

            # Obtain the Jacobians to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])
            jac_thickness = get_bspline_mtx(surface['num_thickness'],
                                            surface['num_y'] - 1)

            # Add components to include in the '_pre_solve' group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline(name + 'twist_cp', name + 'twist',
                                  jac_twist),
                          promotes=['*'])
            tmp_group.add('thickness_bsp',
                          Bspline(name + 'thickness_cp', name + 'thickness',
                                  jac_thickness),
                          promotes=['*'])
            tmp_group.add('tube', MaterialsTube(surface), promotes=['*'])

            # Add tmp_group to the problem with the name of the surface and
            # '_pre_solve' appended.
            name_orig = name  #.strip('_')
            name = name + 'pre_solve'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=["*"])')

            # Add components to the 'coupled' group for each surface
            tmp_group = Group()
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('def_mesh',
                          TransferDisplacements(surface),
                          promotes=['*'])
            tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*'])
            tmp_group.add('spatialbeamstates',
                          SpatialBeamStates(surface),
                          promotes=['*'])
            tmp_group.spatialbeamstates.ln_solver = LinearGaussSeidel()

            name = name_orig + 'group'
            exec(name + ' = tmp_group')
            exec('coupled.add("' + name + '", ' + name + ', promotes=["*"])')

            # Add a loads component to the coupled group
            exec('coupled.add("' + name_orig + 'loads' + '", ' +
                 'TransferLoads(surface)' + ', promotes=["*"])')

            # Add a '_post_solve' group which evaluates the data after solving
            # the coupled system
            tmp_group = Group()

            tmp_group.add('spatialbeamfuncs',
                          SpatialBeamFunctionals(surface),
                          promotes=['*'])
            tmp_group.add('vlmfuncs', VLMFunctionals(surface), promotes=['*'])

            name = name_orig + 'post_solve'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=["*"])')

        # Add a single 'VLMStates' component for the whole system
        coupled.add('vlmstates',
                    VLMStates(self.surfaces, self.prob_dict),
                    promotes=['*'])

        # Set solver properties for the coupled group
        coupled.ln_solver = ScipyGMRES()
        coupled.ln_solver.options['iprint'] = 1
        coupled.ln_solver.preconditioner = LinearGaussSeidel()
        coupled.vlmstates.ln_solver = LinearGaussSeidel()

        coupled.nl_solver = NLGaussSeidel()
        coupled.nl_solver.options['iprint'] = 1

        # Ensure that the groups are ordered correctly within the coupled group
        order_list = []
        for surface in self.surfaces:
            order_list.append(surface['name'] + 'group')
        order_list.append('vlmstates')
        for surface in self.surfaces:
            order_list.append(surface['name'] + 'loads')
        coupled.set_order(order_list)

        # Add the coupled group to the root problem
        root.add('coupled', coupled, promotes=['*'])

        # Add problem information as an independent variables component
        prob_vars = [('v', self.prob_dict['v']),
                     ('alpha', self.prob_dict['alpha']),
                     ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']),
                     ('rho', self.prob_dict['rho'])]
        root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*'])

        # Add functionals to evaluate performance of the system
        root.add('fuelburn',
                 FunctionalBreguetRange(self.surfaces, self.prob_dict),
                 promotes=['*'])
        root.add('eq_con',
                 FunctionalEquilibrium(self.surfaces, self.prob_dict),
                 promotes=['*'])

        self.setup_prob()
Example #18
0
    # driver.options['optimizer'] = 'SLSQP'
    params = (('fin_gap', 0.001, {
        'units': 'm'
    }), ('fin_w', 0.0009, {
        'units': 'm'
    }))
    root.add('input_vars', IndepVarComp(params))
    root.connect('input_vars.fin_gap', 'inverter.fin_gap')
    root.connect('input_vars.fin_w', 'inverter.fin_w')
    #driver.add_desvar('input_vars.fin_gap', lower=.7, scaler=1.0)
    #driver.add_desvar('input_vars.fin_w', lower=.7, scaler=1.0)
    #driver.add_objective('inverter.R_hs')
    #top.driver.add_constraint('con1.c1', lower=0.0, scaler=1000.0)
    #top.driver.add_constraint('con2.c2', lower=0.0)
    root.ln_solver = ScipyGMRES()
    root.nl_solver = NLGaussSeidel()
    root.nl_solver.options['maxiter'] = 50
    # root.nl_solver.options['iprint'] = 1
    #p.print_all_convergence()

    p.root.set_order(['input_vars', 'inverter', 'balance'])
    p.setup()
    #root.list_connections()
    # view_tree(p)
    # exit()
    p.run()
    print('# of fins : %f' % p['inverter.n_fins'])
    print(p['inverter.h'], p['inverter.min_area'], p['inverter.Re'])
    print('R_hs : %f' % p['inverter.R_hs'])
    print('V_0, V_avg : %f, %f' % (p['inverter.V_0'], p['inverter.V_avg']))
    # print('Min Area : %f m^2' %p['inverter.min_area'])
Example #19
0
    def setup_aerostruct(self):
        """
        Specific method to add the necessary components to the problem for an
        aerostructural problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'aerostruct'

        # Create the base root-level group
        root = Group()
        coupled = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']
            tmp_group = Group()

            # Add independent variables that do not belong to a specific component
            indep_vars = [
                ('twist_cp', numpy.zeros(surface['num_twist'])),
                ('thickness_cp', numpy.ones(surface['num_thickness']) *
                 numpy.max(surface['t'])), ('r', surface['r']),
                ('dihedral', surface['dihedral']), ('sweep', surface['sweep']),
                ('span', surface['span']), ('taper', surface['taper'])
            ]

            # Obtain the Jacobians to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])
            jac_thickness = get_bspline_mtx(surface['num_thickness'],
                                            surface['num_y'] - 1)

            # Add components to include in the surface's group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline('twist_cp', 'twist', jac_twist),
                          promotes=['*'])
            tmp_group.add('thickness_bsp',
                          Bspline('thickness_cp', 'thickness', jac_thickness),
                          promotes=['*'])
            tmp_group.add('tube', MaterialsTube(surface), promotes=['*'])

            # Add tmp_group to the problem with the name of the surface.
            name_orig = name
            name = name[:-1]
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=[])')

            # Add components to the 'coupled' group for each surface.
            # The 'coupled' group must contain all components and parameters
            # needed to converge the aerostructural system.
            tmp_group = Group()
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('def_mesh',
                          TransferDisplacements(surface),
                          promotes=['*'])
            tmp_group.add('aero_geom', VLMGeometry(surface), promotes=['*'])
            tmp_group.add('struct_states',
                          SpatialBeamStates(surface),
                          promotes=['*'])
            tmp_group.struct_states.ln_solver = LinearGaussSeidel()

            name = name_orig
            exec(name + ' = tmp_group')
            exec('coupled.add("' + name[:-1] + '", ' + name + ', promotes=[])')

            # Add a loads component to the coupled group
            exec('coupled.add("' + name_orig + 'loads' + '", ' +
                 'TransferLoads(surface)' + ', promotes=[])')

            # Add a performance group which evaluates the data after solving
            # the coupled system
            tmp_group = Group()

            tmp_group.add('struct_funcs',
                          SpatialBeamFunctionals(surface),
                          promotes=['*'])
            tmp_group.add('aero_funcs',
                          VLMFunctionals(surface),
                          promotes=['*'])

            name = name_orig + 'perf'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name +
                 ', promotes=["rho", "v", "alpha", "Re", "M"])')

        # Add a single 'aero_states' component for the whole system within the
        # coupled group.
        coupled.add('aero_states',
                    VLMStates(self.surfaces, self.prob_dict),
                    promotes=['v', 'alpha', 'rho'])

        # Explicitly connect parameters from each surface's group and the common
        # 'aero_states' group.
        for surface in self.surfaces:
            name = surface['name']

            # Perform the connections with the modified names within the
            # 'aero_states' group.
            root.connect('coupled.' + name[:-1] + '.def_mesh',
                         'coupled.aero_states.' + name + 'def_mesh')
            root.connect('coupled.' + name[:-1] + '.b_pts',
                         'coupled.aero_states.' + name + 'b_pts')
            root.connect('coupled.' + name[:-1] + '.c_pts',
                         'coupled.aero_states.' + name + 'c_pts')
            root.connect('coupled.' + name[:-1] + '.normals',
                         'coupled.aero_states.' + name + 'normals')

            # Connect the results from 'aero_states' to the performance groups
            root.connect('coupled.aero_states.' + name + 'sec_forces',
                         name + 'perf' + '.sec_forces')

            # Connect the results from 'coupled' to the performance groups
            root.connect('coupled.' + name[:-1] + '.def_mesh',
                         'coupled.' + name + 'loads.def_mesh')
            root.connect('coupled.aero_states.' + name + 'sec_forces',
                         'coupled.' + name + 'loads.sec_forces')
            root.connect('coupled.' + name + 'loads.loads',
                         name + 'perf.loads')

            # Connect the output of the loads component with the FEM
            # displacement parameter. This links the coupling within the coupled
            # group that necessitates the subgroup solver.
            root.connect('coupled.' + name + 'loads.loads',
                         'coupled.' + name[:-1] + '.loads')

            # Connect aerodyamic design variables
            root.connect(name[:-1] + '.dihedral',
                         'coupled.' + name[:-1] + '.dihedral')
            root.connect(name[:-1] + '.span', 'coupled.' + name[:-1] + '.span')
            root.connect(name[:-1] + '.sweep',
                         'coupled.' + name[:-1] + '.sweep')
            root.connect(name[:-1] + '.taper',
                         'coupled.' + name[:-1] + '.taper')
            root.connect(name[:-1] + '.twist',
                         'coupled.' + name[:-1] + '.twist')

            # Connect structural design variables
            root.connect(name[:-1] + '.A', 'coupled.' + name[:-1] + '.A')
            root.connect(name[:-1] + '.Iy', 'coupled.' + name[:-1] + '.Iy')
            root.connect(name[:-1] + '.Iz', 'coupled.' + name[:-1] + '.Iz')
            root.connect(name[:-1] + '.J', 'coupled.' + name[:-1] + '.J')

            # Connect performance calculation variables
            root.connect(name[:-1] + '.r', name + 'perf.r')
            root.connect(name[:-1] + '.A', name + 'perf.A')

            # Connection performance functional variables
            root.connect(name + 'perf.weight', 'fuelburn.' + name + 'weight')
            root.connect(name + 'perf.weight', 'eq_con.' + name + 'weight')
            root.connect(name + 'perf.L', 'eq_con.' + name + 'L')
            root.connect(name + 'perf.CL', 'fuelburn.' + name + 'CL')
            root.connect(name + 'perf.CD', 'fuelburn.' + name + 'CD')

            # Connect paramters from the 'coupled' group to the performance
            # group.
            root.connect('coupled.' + name[:-1] + '.nodes',
                         name + 'perf.nodes')
            root.connect('coupled.' + name[:-1] + '.disp', name + 'perf.disp')
            root.connect('coupled.' + name[:-1] + '.S_ref',
                         name + 'perf.S_ref')

        # Set solver properties for the coupled group
        coupled.ln_solver = ScipyGMRES()
        coupled.ln_solver.options['iprint'] = 1
        coupled.ln_solver.preconditioner = LinearGaussSeidel()
        coupled.aero_states.ln_solver = LinearGaussSeidel()

        coupled.nl_solver = NLGaussSeidel()
        coupled.nl_solver.options['iprint'] = 1

        # Ensure that the groups are ordered correctly within the coupled group
        # so that a system with multiple surfaces is solved corretly.
        order_list = []
        for surface in self.surfaces:
            order_list.append(surface['name'][:-1])
        order_list.append('aero_states')
        for surface in self.surfaces:
            order_list.append(surface['name'] + 'loads')
        coupled.set_order(order_list)

        # Add the coupled group to the root problem
        root.add('coupled', coupled, promotes=['v', 'alpha', 'rho'])

        # Add problem information as an independent variables component
        prob_vars = [('v', self.prob_dict['v']),
                     ('alpha', self.prob_dict['alpha']),
                     ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']),
                     ('rho', self.prob_dict['rho'])]
        root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*'])

        # Add functionals to evaluate performance of the system.
        # Note that only the interesting results are promoted here; not all
        # of the parameters.
        root.add('fuelburn',
                 FunctionalBreguetRange(self.surfaces, self.prob_dict),
                 promotes=['fuelburn'])
        root.add('eq_con',
                 FunctionalEquilibrium(self.surfaces, self.prob_dict),
                 promotes=['eq_con', 'fuelburn'])

        # Actually set up the system
        self.setup_prob()
Example #20
0
    def __init__(self):
        """TODOs

        Params
        ------
        tube_pressure : float
            Tube total pressure (Pa)
        pressure_initial : float
            initial Pressure before the pump down . Default value is 760.2.
        speed : float
            Pumping speed. Default value is 163333.3.
        pwr : float
            Motor rating. Default value is 18.5.
        electricity_price : float
            Cost of electricity per kilowatt hour. Default value is 0.13.
        time_down : float
            Desired pump down time. Default value is 300.0.
        gamma : float
            Operational percentage of the pump per day. Default value is 0.8.
        pump_weight : float
            Weight of one pump. Default value is 715.0.
        tube_thickness : float
            Thickness of tube in m. Default value is .05
        tube_length : float
            Total length of tube from Mission (m)
        vf : float
            Top pod speed after boosting section. Default value is 335 m/s. Value will be taken from aero module
        vo : float
            Speed of pod when it enters boosting section. Default value is 324 m/s.
        num_thrust : float
            Number of propulsion thrusts required for trip (unitless)
        time_thrust : float
            Time required to accelerate pod to 1G (s)
        pod_mach : float
            Vehicle mach number (unitless)
        comp.map.PRdes : float
            Pressure ratio of compressor (unitless)
        nozzle.Ps_exhaust : float
            Exit pressure of nozzle (psi)
        comp_inlet_area : float
            Inlet area of compressor. (m**2)
        des_time : float
            time until design power point (h)
        time_of_flight : float
            total mission time (h)
        motor_max_current : float
            max motor phase current (A)
        motor_LD_ratio : float
            length to diameter ratio of motor (unitless)
        motor_oversize_factor : float
            scales peak motor power by this figure
        inverter_efficiency : float
            power out / power in (W)
        battery_cross_section_area : float
            cross_sectional area of battery used to compute length (cm^2)
        n_passengers : float
            Number of passengers per pod. Default value is 28
        A_payload : float
            Cross sectional area of passenger compartment. Default value is 2.72
        
        Returns
        -------
        S : float
            Platform area of the pod
        total_pod_mass : float
            Pod Mass (kg)

        References
        ----------
        .. [1] Friend, Paul. Magnetic Levitation Train Technology 1. Thesis.
           Bradley University, 2004. N.p.: n.p., n.d. Print.
        """
        super(TubeAndPod, self).__init__()

        self.add('tube',
                 TubeGroup(),
                 promotes=[
                     'pressure_initial', 'pwr', 'num_pods', 'Cd', 'speed',
                     'time_down', 'gamma', 'pump_weight', 'electricity_price',
                     'tube_thickness', 'r_pylon', 'tube_length', 'h', 'vf',
                     'v0', 'num_thrust', 'time_thrust', 'fl_start.W', 'depth',
                     'pod_period'
                 ])
        self.add('pod',
                 PodGroup(),
                 promotes=[
                     'pod_mach', 'tube_pressure', 'comp.map.PRdes',
                     'nozzle.Ps_exhaust', 'comp_inlet_area', 'des_time',
                     'time_of_flight', 'motor_max_current', 'motor_LD_ratio',
                     'motor_oversize_factor', 'inverter_efficiency',
                     'battery_cross_section_area', 'n_passengers', 'A_payload',
                     'S', 'total_pod_mass', 'vel_b', 'h_lev', 'vel',
                     'mag_drag', 'L_pod'
                 ])
        self.add('cost',
                 TicketCost(),
                 promotes=['land_length', 'water_length', 'track_length'])
        self.add('mission', SampleMission())

        # Connects promoted group level params
        self.connect('tube_pressure',
                     ['tube.p_tunnel', 'cost.p_tunnel', 'mission.p_tunnel'])

        # Connects tube group outputs to pod
        self.connect('tube.temp_boundary', 'pod.tube_temp')

        # Connects pod group outputs to tube
        self.connect('pod.nozzle.Fg',
                     ['tube.nozzle_thrust', 'mission.nozzle_thrust'])
        self.connect('pod.inlet.F_ram', ['tube.ram_drag', 'mission.ram_drag'])
        self.connect('pod.nozzle.Fl_O:tot:T', 'tube.nozzle_air_Tt')
        self.connect('pod.nozzle.Fl_O:stat:W', 'tube.nozzle_air_W')
        self.connect('pod.A_tube', 'tube.tube_area')
        self.connect('S', ['tube.S', 'cost.S', 'mission.S'])
        self.connect('L_pod', 'tube.L_pod')
        self.connect('mag_drag', ['tube.D_mag', 'cost.D_mag', 'mission.D_mag'])
        self.connect('total_pod_mass',
                     ['tube.m_pod', 'cost.m_pod', 'mission.m_pod'])
        self.connect('vf', 'cost.vf')
        self.connect('pod_period', 'cost.pod_period')
        self.connect('tube.Struct.total_material_cost', 'cost.land_cost')
        self.connect('tube.Vacuum.pwr_tot', 'cost.vac_power')
        self.connect('tube.PropMech.pwr_req', 'cost.prop_power')
        self.connect('pod.cycle.comp.power', 'cost.pod_power')
        self.connect('tube.comp.power', 'cost.steady_vac_power')
        self.connect('tube.SubmergedTube.material_cost', 'cost.water_cost')
        self.connect('pod_mach', 'mission.M_pod')
        self.connect('track_length', 'mission.track_length')

        self.nl_solver = NLGaussSeidel()
        self.nl_solver.options['maxiter'] = 20
        self.nl_solver.options['atol'] = 0.0001
        # self.nl_solver.options['iprint'] = 2

        self.ln_solver = ScipyGMRES()
        self.ln_solver.options['maxiter'] = 20