Example #1
0
    def test_deprecated_solver_names(self):
        class DummySolver():
            pass

        model = Group()

        # check nl_solver setter & getter
        msg = "The 'nl_solver' attribute provides backwards compatibility " \
              "with OpenMDAO 1.x ; use 'nonlinear_solver' instead."

        with assert_warning(DeprecationWarning, msg):
            model.nl_solver = DummySolver()

        with assert_warning(DeprecationWarning, msg):
            solver = model.nl_solver

        self.assertTrue(isinstance(solver, DummySolver))

        # check ln_solver setter & getter
        msg = "The 'ln_solver' attribute provides backwards compatibility " \
              "with OpenMDAO 1.x ; use 'linear_solver' instead."

        with assert_warning(DeprecationWarning, msg):
            model.ln_solver = DummySolver()

        with assert_warning(DeprecationWarning, msg):
            solver = model.ln_solver

        self.assertTrue(isinstance(solver, DummySolver))
Example #2
0
    def test_deprecated_solver_names(self):
        class DummySolver():
            pass

        model = Group()

        # check nl_solver setter & getter
        msg = "The 'nl_solver' attribute provides backwards compatibility " \
              "with OpenMDAO 1.x ; use 'nonlinear_solver' instead."

        with assert_warning(DeprecationWarning, msg):
            model.nl_solver = DummySolver()

        with assert_warning(DeprecationWarning, msg):
            solver = model.nl_solver

        self.assertTrue(isinstance(solver, DummySolver))

        # check ln_solver setter & getter
        msg = "The 'ln_solver' attribute provides backwards compatibility " \
              "with OpenMDAO 1.x ; use 'linear_solver' instead."

        with assert_warning(DeprecationWarning, msg):
            model.ln_solver = DummySolver()

        with assert_warning(DeprecationWarning, msg):
            solver = model.ln_solver

        self.assertTrue(isinstance(solver, DummySolver))
Example #3
0
    def test_deprecated_solver_names(self):
        class DummySolver():
            pass

        model = Group()

        # check nl_solver setter
        with warnings.catch_warnings(record=True) as w:
            model.nl_solver = DummySolver()

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'nl_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'nonlinear_solver' instead.")

        # check nl_solver getter
        with warnings.catch_warnings(record=True) as w:
            solver = model.nl_solver

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'nl_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'nonlinear_solver' instead.")

        self.assertTrue(isinstance(solver, DummySolver))

        # check ln_solver setter
        with warnings.catch_warnings(record=True) as w:
            model.ln_solver = DummySolver()

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'ln_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'linear_solver' instead.")

        # check ln_solver getter
        with warnings.catch_warnings(record=True) as w:
            solver = model.ln_solver

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'ln_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'linear_solver' instead.")

        self.assertTrue(isinstance(solver, DummySolver))
Example #4
0
    def test_deprecated_solver_names(self):
        class DummySolver():
            pass

        model = Group()

        # check nl_solver setter
        with warnings.catch_warnings(record=True) as w:
            model.nl_solver = DummySolver()

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'nl_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'nonlinear_solver' instead.")

        # check nl_solver getter
        with warnings.catch_warnings(record=True) as w:
            solver = model.nl_solver

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'nl_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'nonlinear_solver' instead.")

        self.assertTrue(isinstance(solver, DummySolver))

        # check ln_solver setter
        with warnings.catch_warnings(record=True) as w:
            model.ln_solver = DummySolver()

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'ln_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'linear_solver' instead.")

        # check ln_solver getter
        with warnings.catch_warnings(record=True) as w:
            solver = model.ln_solver

        self.assertEqual(len(w), 1)
        self.assertTrue(issubclass(w[0].category, DeprecationWarning))
        self.assertEqual(str(w[0].message),
                         "The 'ln_solver' attribute provides backwards compatibility "
                         "with OpenMDAO 1.x ; use 'linear_solver' instead.")

        self.assertTrue(isinstance(solver, DummySolver))
Example #5
0
    ## 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()
    coupled.vlmstates.ln_solver = LinearGaussSeidel()
    coupled.spatialbeamstates.ln_solver = LinearGaussSeidel()

    # adds the MDA to root (do not remove!)
    root.add('coupled', coupled, promotes=['*'])

    # Instantiate an OpenMDAO problem and all the root group that we just
    # created to the problem.
    prob = Problem()
    prob.root = root

    # Print OpenMDAO solver convergence data.
    # Uncomment this output more solver info during optimization.
    
    #Inner interpolation method
    mda_h.add('inter_h', Interpolation(na_h, ns, function = function_type, bias = bias_inter), promotes=['apoints_coord','node_coord'])

    #Define solver type and tolerance for MDA Lo-Fi
    mda_l.nl_solver = NLGaussSeidel()
    #The solver execution limit is used to control fidelity levels
    if fidelity == 'high':
        mda_l.nl_solver.options['maxiter'] = 0 #No Lo-Fi iterations
              
    mda_l.nl_solver.options['rutol'] = 1.e-1 
    mda_l.nl_solver.options['use_aitken'] = True
    mda_l.nl_solver.options['aitken_alpha_min'] = 0.1
    mda_l.nl_solver.options['aitken_alpha_max'] = 1.5

    mda_l.ln_solver = ScipyGMRES()
    
    #Define solver type and tolerance for MDA Hi-Fi
    mda_h.nl_solver = NLGaussSeidel()
    #The solver execution limit is used to control fidelity levels
    if fidelity == 'low':
        mda_h.nl_solver.options['maxiter'] = 0
        
    mda_h.nl_solver.options['rutol'] = 1.e-1
    mda_h.nl_solver.options['use_aitken'] = True
    mda_h.nl_solver.options['aitken_alpha_min'] = 0.1
    mda_h.nl_solver.options['aitken_alpha_max'] = 1.5

    mda_h.ln_solver = ScipyGMRES()

    root.add('mda_group_l', mda_l, promotes=['*'])
Example #7
0
    mda.add('aerodynamics', Panair(na, network_info), promotes=['*'])
    mda.add('load_transfer', LoadTransfer(na, ns), promotes=['*'])
    mda.add('structures',
            NastranStatic(node_id, node_id_all, n_stress, tn, mn),
            promotes=['*'])

    #Define solver type and tolerance for MDA
    mda.nl_solver = NLGaussSeidel()
    #    mda.nl_solver.options['rtol'] = 1.e-1
    mda.nl_solver.options['maxiter'] = 15
    mda.nl_solver.options['rutol'] = 1.e-2
    mda.nl_solver.options['use_aitken'] = True
    mda.nl_solver.options['aitken_alpha_min'] = 0.1
    mda.nl_solver.options['aitken_alpha_max'] = 1.5

    mda.ln_solver = ScipyGMRES()

    root.add('mda_group', mda, promotes=['*'])

    #    top.root.mda_group.deriv_options['type'] = 'fd'
    #    top.root.mda_group.deriv_options['step_size'] = 1.0e-1
    #Recorder
    recorder = SqliteRecorder('opti_g_30')
    recorder.options['record_params'] = False
    recorder.options['record_metadata'] = False
    recorder.options['record_resids'] = False
    recorder.options['record_derivs'] = False
    top.root.nl_solver.add_recorder(recorder)
    #    top.root.add_recorder(recorder)

    #Define solver type
Example #8
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 #9
0
# coupled.nl_solver.options['iprint'] = 1
# coupled.nl_solver.line_search.options['iprint'] = 1

## Hybrid NLGS-Newton on the coupled group
# coupled.nl_solver = HybridGSNewton()
# coupled.nl_solver.nlgs.options['iprint'] = 1
# coupled.nl_solver.nlgs.options['maxiter'] = 5
# coupled.nl_solver.newton.options['atol'] = 1e-7
# coupled.nl_solver.newton.options['rtol'] = 1e-7
# coupled.nl_solver.newton.options['iprint'] = 1

# Newton solver on the root group
root.nl_solver = Newton()
root.nl_solver.options['iprint'] = 1
root.nl_solver.line_search.options['iprint'] = 1
root.ln_solver = ScipyGMRES()
root.ln_solver.options['iprint'] = 1
root.ln_solver.preconditioner = LinearGaussSeidel()
coupled.vlmstates.ln_solver = LinearGaussSeidel()
coupled.spatialbeamstates.ln_solver = LinearGaussSeidel()

###############################################
# Don't change the linear solver confuguration
###############################################
# linear solver configuration
# coupled.ln_solver = ScipyGMRES()
# coupled.ln_solver.options['iprint'] = 1
# coupled.ln_solver.preconditioner = LinearGaussSeidel()
# coupled.vlmstates.ln_solver = LinearGaussSeidel()
# coupled.spatialbeamstates.ln_solver = LinearGaussSeidel()
Example #10
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 #11
0
    def setup_aerostruct(self):
        """
        Specific method to add the necessary components to the problem for an
        aerostructural problem.

        Because this code has been extended to work for multiple aerostructural
        surfaces, a good portion of it is spent doing the bookkeeping for parameter
        passing and ensuring that each component modifies the correct data.
        """

        # 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()

            # Strip the surface names from the desvars list and save this
            # modified list as self.desvars
            desvar_names = []
            for desvar in self.desvars.keys():

                # Check to make sure that the surface's name is in the design
                # variable and only add the desvar to the list if it corresponds
                # to this surface.
                if name[:-1] in desvar:
                    desvar_names.append(''.join(desvar.split('.')[1:]))

            # Add independent variables that do not belong to a specific component
            indep_vars = []
            for var in surface['geo_vars']:
                if var in desvar_names or var in surface['initial_geo'] or 'thickness' in var:
                    indep_vars.append((var, surface[var]))

            # Add components to include in the surface's group
            tmp_group.add('indep_vars',
                     IndepVarComp(indep_vars),
                     promotes=['*'])
            tmp_group.add('tube',
                     MaterialsTube(surface),
                     promotes=['*'])
            tmp_group.add('mesh',
                     GeometryMesh(surface, self.desvars),
                     promotes=['*'])
            tmp_group.add('struct_setup',
                     SpatialBeamSetup(surface),
                     promotes=['*'])

            # Add bspline components for active bspline geometric variables.
            # We only add the component if the corresponding variable is a desvar,
            # a special parameter (radius), or if the user or geometry provided
            # an initial distribution.
            for var in surface['bsp_vars']:
                if var in desvar_names or var in surface['initial_geo'] or 'thickness' in var:
                    n_pts = surface['num_y']
                    if var in ['thickness_cp', 'radius_cp']:
                        n_pts -= 1
                    trunc_var = var.split('_')[0]
                    tmp_group.add(trunc_var + '_bsp',
                             Bspline(var, trunc_var, surface['num_'+var], n_pts),
                             promotes=['*'])

            # Add monotonic constraints for selected variables
            if surface['monotonic_con'] is not None:
                if type(surface['monotonic_con']) is not list:
                    surface['monotonic_con'] = [surface['monotonic_con']]
                for var in surface['monotonic_con']:
                    tmp_group.add('monotonic_' + var,
                        MonotonicConstraint(var, surface), promotes=['*'])

            # Add tmp_group to the problem with the name of the surface.
            name_orig = name
            name = name[:-1]
            root.add(name, tmp_group, 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('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()
            tmp_group.struct_states.ln_solver.options['atol'] = 1e-20

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

            # Add a loads component to the coupled group
            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, self.prob_dict),
                     promotes=['*'])

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

            root.add_metadata(surface['name'] + 'yield_stress', surface['yield'])
            root.add_metadata(surface['name'] + 'fem_origin', surface['fem_origin'])

        # Add a single 'aero_states' component for the whole system within the
        # coupled group.
        coupled.add('aero_states',
                 VLMStates(self.surfaces),
                 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']

            root.connect(name[:-1] + '.K', 'coupled.' + name[:-1] + '.K')

            # 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')

            # 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 mesh to coupled group mesh
            root.connect(name[:-1] + '.mesh', 'coupled.' + name[:-1] + '.mesh')

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

            # Connection performance functional variables
            root.connect(name + 'perf.structural_weight', 'total_perf.' + name + 'structural_weight')
            root.connect(name + 'perf.L', 'total_perf.' + name + 'L')
            root.connect(name + 'perf.CL', 'total_perf.' + name + 'CL')
            root.connect(name + 'perf.CD', 'total_perf.' + name + 'CD')
            root.connect('coupled.aero_states.' + name + 'sec_forces', 'total_perf.' + name + 'sec_forces')

            # Connect parameters from the 'coupled' group to the performance
            # groups for the individual surfaces.
            root.connect(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')
            root.connect('coupled.' + name[:-1] + '.widths', name + 'perf.widths')
            root.connect('coupled.' + name[:-1] + '.lengths', name + 'perf.lengths')
            root.connect('coupled.' + name[:-1] + '.cos_sweep', name + 'perf.cos_sweep')

            # Connect parameters from the 'coupled' group to the total performance group.
            root.connect('coupled.' + name[:-1] + '.S_ref', 'total_perf.' + name + 'S_ref')
            root.connect('coupled.' + name[:-1] + '.widths', 'total_perf.' + name + 'widths')
            root.connect('coupled.' + name[:-1] + '.chords', 'total_perf.' + name + 'chords')
            root.connect('coupled.' + name[:-1] + '.b_pts', 'total_perf.' + name + 'b_pts')
            root.connect(name + 'perf.cg_location', 'total_perf.' + name + 'cg_location')

        # Set solver properties for the coupled group
        coupled.ln_solver = ScipyGMRES()
        coupled.ln_solver.preconditioner = LinearGaussSeidel()
        coupled.aero_states.ln_solver = LinearGaussSeidel()
        coupled.nl_solver = NLGaussSeidel()

        # This is only available in the most recent version of OpenMDAO.
        # It may help converge tightly coupled systems when using NLGS.
        try:
            coupled.nl_solver.options['use_aitken'] = True
            coupled.nl_solver.options['aitken_alpha_min'] = 0.01
            # coupled.nl_solver.options['aitken_alpha_max'] = 0.5
        except:
            pass

        if self.prob_dict['print_level'] == 2:
            coupled.ln_solver.options['iprint'] = 1
        if self.prob_dict['print_level']:
            coupled.nl_solver.options['iprint'] = 1

        # 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']/self.prob_dict['reynolds_length']),
            ('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('total_perf',
                 TotalPerformance(self.surfaces, self.prob_dict),
                 promotes=['L_equals_W', 'fuelburn', 'CM', 'CL', 'CD', 'v', 'rho', 'cg', 'weighted_obj', 'total_weight'])

        # Actually set up the system
        self.setup_prob()
Example #12
0
coupled.add('def_mesh', def_mesh_comp, promotes=["*"])
coupled.add('vlmstates', vlmstates_comp, promotes=["*"])
coupled.add('loads', loads_comp, promotes=["*"])

## Newton Solver
coupled.nl_solver = Newton()
coupled.nl_solver.options['iprint'] = 1
coupled.nl_solver.line_search.options['iprint'] = 1

############################################################
# Comment/uncomment these solver blocks to try different
# linear solvers
############################################################

## Linear Gauss Seidel Solver
coupled.ln_solver = LinearGaussSeidel()
coupled.ln_solver.options['maxiter'] = 100

## Krylov Solver - No preconditioning
# coupled.ln_solver = ScipyGMRES()
# coupled.ln_solver.options['iprint'] = 1

## Krylov Solver - LNGS preconditioning
# coupled.ln_solver = ScipyGMRES()
# coupled.ln_solver.options['iprint'] = 1
# coupled.ln_solver.preconditioner = LinearGaussSeidel()
# coupled.vlmstates.ln_solver = LinearGaussSeidel()
# coupled.spatialbeamstates.ln_solver = LinearGaussSeidel()

##Direct Solver
# coupled.ln_solver = DirectSolver()