Example #1
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 #2
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()