Пример #1
0
    def setup(self):
        surfaces = self.options['surfaces']

        for surface in surfaces:
            name = surface['name']

            self.connect(name + '.normals', 'aero_states.' + name + '_normals')
            # self.connect(name + '.b_pts', 'aero_states.' + name + '_b_pts')
            # self.connect(name + '.c_pts', 'aero_states.' + name + '_c_pts')
            # self.connect(name + '.cos_sweep', 'aero_states.' + name + '_cos_sweep')
            # self.connect(name + '.widths', 'aero_states.' + name + '_widths')

            # Connect the results from 'aero_states' to the performance groups
            self.connect('aero_states.' + name + '_sec_forces', name + '_perf' + '.sec_forces')

            # Connect S_ref for performance calcs
            self.connect(name + '.S_ref', name + '_perf.S_ref')
            self.connect(name + '.widths', name + '_perf.widths')
            self.connect(name + '.chords', name + '_perf.chords')
            self.connect(name + '.lengths', name + '_perf.lengths')
            self.connect(name + '.cos_sweep', name + '_perf.cos_sweep')

            # Connect S_ref for performance calcs
            self.connect(name + '.S_ref', 'total_perf.' + name + '_S_ref')
            self.connect(name + '.widths', 'total_perf.' + name + '_widths')
            self.connect(name + '.chords', 'total_perf.' + name + '_chords')
            self.connect(name + '.b_pts', 'total_perf.' + name + '_b_pts')
            self.connect(name + '_perf' + '.CL', 'total_perf.' + name + '_CL')
            self.connect(name + '_perf' + '.CD', 'total_perf.' + name + '_CD')
            self.connect('aero_states.' + name + '_sec_forces', 'total_perf.' + name + '_sec_forces')

            self.add_subsystem(name, VLMGeometry(surface=surface))

        # Add a single 'aero_states' component that solves for the circulations
        # and forces from all the surfaces.
        # While other components only depends on a single surface,
        # this component requires information from all surfaces because
        # each surface interacts with the others.
        aero_states = VLMStates(surfaces=surfaces)
        aero_states.linear_solver = LinearRunOnce()

        self.add_subsystem('aero_states',
                 aero_states,
                 promotes_inputs=['v', 'alpha', 'rho'],
                 promotes_outputs=['circulations'])

        # Explicitly connect parameters from each surface's group and the common
        # 'aero_states' group.
        # This is necessary because the VLMStates component requires information
        # from each surface, but this information is stored within each
        # surface's group.
        for surface in surfaces:
            self.add_subsystem(surface['name'] +'_perf', VLMFunctionals(surface=surface),
                    promotes_inputs=["v", "alpha", "M", "re", "rho"])

        self.add_subsystem('total_perf',
            TotalAeroPerformance(surfaces=surfaces),
            promotes_inputs=['v', 'rho', 'cg', 'S_ref_total'],
            promotes_outputs=['CM', 'CL', 'CD'])
Пример #2
0
    def setup(self):
        surfaces = self.options['surfaces']

        coupled = Group()

        for surface in surfaces:

            name = surface['name']

            # 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.
            coupled.connect(name + '_loads.loads', name + '.loads')

            # Perform the connections with the modified names within the
            # 'aero_states' group.
            coupled.connect(name + '.normals', 'aero_states.' + name + '_normals')
            coupled.connect(name + '.def_mesh', 'aero_states.' + name + '_def_mesh')

            # Connect the results from 'coupled' to the performance groups
            coupled.connect(name + '.def_mesh', name + '_loads.def_mesh')
            coupled.connect('aero_states.' + name + '_sec_forces', name + '_loads.sec_forces')

            # Connect the results from 'aero_states' to the performance groups
            self.connect('coupled.aero_states.' + name + '_sec_forces', name + '_perf' + '.sec_forces')

            # Connection performance functional variables
            self.connect(name + '_perf.CL', 'total_perf.' + name + '_CL')
            self.connect(name + '_perf.CD', 'total_perf.' + name + '_CD')
            self.connect('coupled.aero_states.' + name + '_sec_forces', 'total_perf.' + name + '_sec_forces')
            self.connect('coupled.' + name + '.chords', name + '_perf.aero_funcs.chords')

            # Connect parameters from the 'coupled' group to the performance
            # groups for the individual surfaces.
            self.connect('coupled.' + name + '.disp', name + '_perf.disp')
            self.connect('coupled.' + name + '.S_ref', name + '_perf.S_ref')
            self.connect('coupled.' + name + '.widths', name + '_perf.widths')
            # self.connect('coupled.' + name + '.chords', name + '_perf.chords')
            self.connect('coupled.' + name + '.lengths', name + '_perf.lengths')
            self.connect('coupled.' + name + '.cos_sweep', name + '_perf.cos_sweep')

            # Connect parameters from the 'coupled' group to the total performance group.
            self.connect('coupled.' + name + '.S_ref', 'total_perf.' + name + '_S_ref')
            self.connect('coupled.' + name + '.widths', 'total_perf.' + name + '_widths')
            self.connect('coupled.' + name + '.chords', 'total_perf.' + name + '_chords')
            self.connect('coupled.' + name + '.b_pts', 'total_perf.' + name + '_b_pts')

            # Add components to the 'coupled' group for each surface.
            # The 'coupled' group must contain all components and parameters
            # needed to converge the aerostructural system.
            coupled_AS_group = CoupledAS(surface=surface)

            if surface['distributed_fuel_weight']:
                promotes = ['load_factor']
            else:
                promotes = []

            coupled.add_subsystem(name, coupled_AS_group, promotes_inputs=promotes)

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

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

            # Add a loads component to the coupled group
            coupled.add_subsystem(name + '_loads', LoadTransfer(surface=surface))

        """
        ### Change the solver settings here ###
        """

        # Set solver properties for the coupled group
        # coupled.linear_solver = ScipyIterativeSolver()
        # coupled.linear_solver.precon = LinearRunOnce()

        coupled.nonlinear_solver = NonlinearBlockGS(use_aitken=True)
        coupled.nonlinear_solver.options['maxiter'] = 100
        coupled.nonlinear_solver.options['atol'] = 1e-7
        coupled.nonlinear_solver.options['rtol'] = 1e-30

        # coupled.linear_solver = DirectSolver()

        coupled.linear_solver = DirectSolver(assemble_jac=True)
        coupled.options['assembled_jac_type'] = 'csc'

        # coupled.nonlinear_solver = NewtonSolver(solve_subsystems=True)
        # coupled.nonlinear_solver.options['maxiter'] = 50
        coupled.nonlinear_solver.options['iprint'] = 2

        """
        ### End change of solver settings ###
        """

        # Add the coupled group to the model problem
        self.add_subsystem('coupled', coupled, promotes_inputs=['v', 'alpha', 'rho'])

        for surface in surfaces:
            name = surface['name']

            # Add a performance group which evaluates the data after solving
            # the coupled system
            perf_group = CoupledPerformance(surface=surface)

            self.add_subsystem(name + '_perf', perf_group, promotes_inputs=['rho', 'v', 'alpha', 're', 'Mach_number'])

        # Add functionals to evaluate performance of the system.
        # Note that only the interesting results are promoted here; not all
        # of the parameters.
        self.add_subsystem('total_perf',
                 TotalPerformance(surfaces=surfaces,
                 user_specified_Sref=self.options['user_specified_Sref'],
                 internally_connect_fuelburn=self.options['internally_connect_fuelburn']),
                 promotes_inputs=['v', 'rho', 'empty_cg', 'total_weight', 'CT', 'speed_of_sound', 'R', 'Mach_number', 'W0', 'load_factor', 'S_ref_total'],
                 promotes_outputs=['L_equals_W', 'fuelburn', 'CL', 'CD', 'CM', 'cg'])
Пример #3
0
    def setup(self):
        surfaces = self.options['surfaces']
        rotational = self.options['rotational']

        # Loop through each surface and connect relevant parameters
        for surface in surfaces:
            name = surface['name']

            self.connect(name + '.normals', 'aero_states.' + name + '_normals')

            # Connect the results from 'aero_states' to the performance groups
            self.connect('aero_states.' + name + '_sec_forces',
                         name + '_perf' + '.sec_forces')

            # Connect S_ref for performance calcs
            self.connect(name + '.S_ref', name + '_perf.S_ref')
            self.connect(name + '.widths', name + '_perf.widths')
            self.connect(name + '.chords', name + '_perf.chords')
            self.connect(name + '.lengths', name + '_perf.lengths')
            self.connect(name + '.cos_sweep', name + '_perf.cos_sweep')

            # Connect S_ref for performance calcs
            self.connect(name + '.S_ref', 'total_perf.' + name + '_S_ref')
            self.connect(name + '.widths', 'total_perf.' + name + '_widths')
            self.connect(name + '.chords', 'total_perf.' + name + '_chords')
            self.connect(name + '.b_pts', 'total_perf.' + name + '_b_pts')
            self.connect(name + '_perf' + '.CL', 'total_perf.' + name + '_CL')
            self.connect(name + '_perf' + '.CD', 'total_perf.' + name + '_CD')
            self.connect('aero_states.' + name + '_sec_forces',
                         'total_perf.' + name + '_sec_forces')

            self.add_subsystem(name, VLMGeometry(surface=surface))

        # Add a single 'aero_states' component that solves for the circulations
        # and forces from all the surfaces.
        # While other components only depends on a single surface,
        # this component requires information from all surfaces because
        # each surface interacts with the others.
        if self.options['compressible'] == True:
            aero_states = CompressibleVLMStates(surfaces=surfaces,
                                                rotational=rotational)
            prom_in = ['v', 'alpha', 'beta', 'rho', 'Mach_number']
        else:
            aero_states = VLMStates(surfaces=surfaces, rotational=rotational)
            prom_in = ['v', 'alpha', 'beta', 'rho']

        aero_states.linear_solver = om.LinearRunOnce()

        if rotational:
            prom_in.extend(['omega', 'cg'])

        self.add_subsystem('aero_states',
                           aero_states,
                           promotes_inputs=prom_in,
                           promotes_outputs=['circulations'])

        # Explicitly connect parameters from each surface's group and the common
        # 'aero_states' group.
        # This is necessary because the VLMStates component requires information
        # from each surface, but this information is stored within each
        # surface's group.
        for surface in surfaces:
            self.add_subsystem(surface['name'] + '_perf',
                               VLMFunctionals(surface=surface),
                               promotes_inputs=[
                                   'v', 'alpha', 'beta', 'Mach_number', 're',
                                   'rho'
                               ])

        # Add the total aero performance group to compute the CL, CD, and CM
        # of the total aircraft. This accounts for all lifting surfaces.
        self.add_subsystem(
            'total_perf',
            TotalAeroPerformance(
                surfaces=surfaces,
                user_specified_Sref=self.options['user_specified_Sref']),
            promotes_inputs=['v', 'rho', 'cg', 'S_ref_total'],
            promotes_outputs=['CM', 'CL', 'CD'])
Пример #4
0
    def setup(self):
        surfaces = self.options['surfaces']

        # Loop through each surface and connect relevant parameters
        for surface in surfaces:
            name = surface['name']

            self.connect(name + '.normals', 'aero_states.' + name + '_normals')

            # Connect the results from 'aero_states' to the performance groups
            self.connect('aero_states.' + name + '_sec_forces',
                name + '_perf' + '.sec_forces')

            # Connect S_ref for performance calcs
            self.connect(name + '.S_ref', name + '_perf.S_ref')
            self.connect(name + '.widths', name + '_perf.widths')
            self.connect(name + '.chords', name + '_perf.chords')
            self.connect(name + '.lengths', name + '_perf.lengths')
            self.connect(name + '.cos_sweep', name + '_perf.cos_sweep')

            # Connect S_ref for performance calcs
            self.connect(name + '.S_ref', 'total_perf.' + name + '_S_ref')
            self.connect(name + '.widths', 'total_perf.' + name + '_widths')
            self.connect(name + '.chords', 'total_perf.' + name + '_chords')
            self.connect(name + '.b_pts', 'total_perf.' + name + '_b_pts')
            self.connect(name + '_perf' + '.CL', 'total_perf.' + name + '_CL')
            self.connect(name + '_perf' + '.CD', 'total_perf.' + name + '_CD')
            self.connect('aero_states.' + name + '_sec_forces',
                'total_perf.' + name + '_sec_forces')

            self.add_subsystem(name, VLMGeometry(surface=surface))

        # Add a single 'aero_states' component that solves for the circulations
        # and forces from all the surfaces.
        # While other components only depends on a single surface,
        # this component requires information from all surfaces because
        # each surface interacts with the others.
        aero_states = VLMStates(surfaces=surfaces)
        aero_states.linear_solver = LinearRunOnce()

        self.add_subsystem('aero_states',
                 aero_states,
                 promotes_inputs=['v', 'alpha', 'rho'],
                 promotes_outputs=['circulations'])

        # Explicitly connect parameters from each surface's group and the common
        # 'aero_states' group.
        # This is necessary because the VLMStates component requires information
        # from each surface, but this information is stored within each
        # surface's group.
        for surface in surfaces:
            self.add_subsystem(surface['name'] +'_perf',
                VLMFunctionals(surface=surface),
                promotes_inputs=["v", "alpha", "M", "re", "rho"])

        # Add the total aero performance group to compute the CL, CD, and CM
        # of the total aircraft. This accounts for all lifting surfaces.
        self.add_subsystem('total_perf',
            TotalAeroPerformance(surfaces=surfaces,
            user_specified_Sref=self.options['user_specified_Sref']),
            promotes_inputs=['v', 'rho', 'cg', 'S_ref_total'],
            promotes_outputs=['CM', 'CL', 'CD'])
Пример #5
0
    def setup(self):
        surfaces = self.options['surfaces']
        rotational = self.options['rotational']
        rollOnly = self.options['rollOnly']

        coupled = om.Group()

        for surface in surfaces:

            name = surface['name']

            # 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.
            coupled.connect(name + '_loads.loads', name + '.loads')

            # Perform the connections with the modified names within the
            # 'aero_states' group.
            coupled.connect(name + '.def_mesh',
                            'aero_states.' + name + '_def_mesh')

            # Connect the results from 'coupled' to the performance groups
            coupled.connect(name + '.def_mesh', name + '_loads.def_mesh')
            coupled.connect('aero_states.' + name + '_sec_forces',
                            name + '_loads.sec_forces')

            # Connect the results from 'aero_states' to the performance groups
            self.connect('coupled.aero_states.' + name + '_sec_forces',
                         name + '_perf' + '.sec_forces')

            # Connection performance functional variables
            self.connect(name + '_perf.CL', 'total_perf.' + name + '_CL')
            self.connect(name + '_perf.CD', 'total_perf.' + name + '_CD')
            self.connect('coupled.aero_states.' + name + '_sec_forces',
                         'total_perf.' + name + '_sec_forces')
            self.connect('coupled.' + name + '.chords',
                         name + '_perf.aero_funcs.chords')

            # Connect parameters from the 'coupled' group to the performance
            # groups for the individual surfaces.
            self.connect('coupled.' + name + '.disp', name + '_perf.disp')
            self.connect('coupled.' + name + '.S_ref', name + '_perf.S_ref')
            self.connect('coupled.' + name + '.widths', name + '_perf.widths')
            # self.connect('coupled.' + name + '.chords', name + '_perf.chords')
            self.connect('coupled.' + name + '.lengths',
                         name + '_perf.lengths')
            self.connect('coupled.' + name + '.cos_sweep',
                         name + '_perf.cos_sweep')

            # Connect parameters from the 'coupled' group to the total performance group.
            self.connect('coupled.' + name + '.S_ref',
                         'total_perf.' + name + '_S_ref')
            self.connect('coupled.' + name + '.widths',
                         'total_perf.' + name + '_widths')
            self.connect('coupled.' + name + '.chords',
                         'total_perf.' + name + '_chords')
            self.connect('coupled.' + name + '.b_pts',
                         'total_perf.' + name + '_b_pts')

            # Add components to the 'coupled' group for each surface.
            # The 'coupled' group must contain all components and parameters
            # needed to converge the aerostructural system.
            coupled_AS_group = _CoupledAS(surface=surface)

            if surface[
                    'distributed_fuel_weight'] or 'n_point_masses' in surface.keys(
                    ) or surface['struct_weight_relief']:
                prom_in = ['load_factor']
            else:
                prom_in = []

            coupled.add_subsystem(name,
                                  coupled_AS_group,
                                  promotes_inputs=prom_in)

        if self.options['compressible'] == True:
            aero_states = CompressibleVLMStates(surfaces=surfaces,
                                                rotational=rotational)
            prom_in = ['v', 'alpha', 'beta', 'rho', 'Mach_number']
        else:
            aero_states = VLMStates(surfaces=surfaces, rotational=rotational)
            prom_in = ['v', 'alpha', 'beta', 'rho']

        # If rotational, add in roll rate and cg
        if rotational:
            prom_in.extend(['omega', 'cg'])

        # Add a single 'aero_states' component for the whole system within the
        # coupled group.
        coupled.add_subsystem('aero_states',
                              aero_states,
                              promotes_inputs=prom_in)

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

            # Connect normals
            if 'control_surfaces' in surface:
                first = surface['control_surfaces'][0]['name']
                last = surface['control_surfaces'][-1]['name']
                coupled.connect(
                    f'{name}.aero_geom.normals',
                    f'{name}.control_surfaces.undeflected_normals')
                coupled.connect(f'{name}.control_surfaces.deflected_normals',
                                f'aero_states.{name}_normals')

            else:
                coupled.connect(f'{name}.aero_geom.normals',
                                f'aero_states.{name}_normals')

        # Add a loads component to the coupled group
        for surface in surfaces:
            name = surface['name']
            coupled.add_subsystem(name + '_loads',
                                  LoadTransfer(surface=surface))
        """
        ### Change the solver settings here ###
        """

        # Set solver properties for the coupled group
        # coupled.linear_solver = ScipyKrylov()
        # coupled.linear_solver.precon = om.LinearRunOnce()

        coupled.nonlinear_solver = om.NonlinearBlockGS(use_aitken=True)
        coupled.nonlinear_solver.options['maxiter'] = 100
        coupled.nonlinear_solver.options['atol'] = 1e-7
        coupled.nonlinear_solver.options['rtol'] = 1e-30
        coupled.nonlinear_solver.options['iprint'] = 2
        coupled.nonlinear_solver.options['err_on_non_converge'] = True

        # coupled.linear_solver = om.DirectSolver()

        coupled.linear_solver = om.DirectSolver(assemble_jac=True)
        coupled.options['assembled_jac_type'] = 'csc'

        # coupled.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)
        # coupled.nonlinear_solver.options['maxiter'] = 50
        """
        ### End change of solver settings ###
        """
        prom_in = ['v', 'alpha', 'rho']

        if self.options['compressible'] == True:
            prom_in.append('Mach_number')

        # If rotational, add in roll rate and cg
        if rotational:
            prom_in.extend(['omega', 'cg'])

        # Add the coupled group to the model problem
        self.add_subsystem('coupled', coupled, promotes_inputs=prom_in)

        for surface in surfaces:
            name = surface['name']

            # Add a performance group which evaluates the data after solving
            # the coupled system
            perf_group = CoupledPerformance(surface=surface)

            self.add_subsystem(
                name + '_perf',
                perf_group,
                promotes_inputs=['rho', 'v', 'alpha', 're', 'Mach_number'])

        # Add functionals to evaluate performance of the system.
        # Note that only the interesting results are promoted here; not all
        # of the parameters.
        if not rotational:
            self.add_subsystem(
                'total_perf',
                TotalPerformance(
                    surfaces=surfaces,
                    user_specified_Sref=self.options['user_specified_Sref'],
                    internally_connect_fuelburn=self.
                    options['internally_connect_fuelburn']),
                promotes_inputs=[
                    'v', 'rho', 'empty_cg', 'total_weight', 'CT',
                    'speed_of_sound', 'R', 'Mach_number', 'W0', 'load_factor',
                    'S_ref_total'
                ],
                promotes_outputs=[
                    'L_equals_W', 'fuelburn', 'CL', 'CD', 'CM', 'cg'
                ])

        elif rotational:
            # In rotational case cannot take in empty_cg and calculate cg.
            # Leads to a cycle between three groups (rotational aero needs
            # cg well before cg calculation)
            if rollOnly:
                self.add_subsystem(
                    'total_perf',
                    TotalRollPerformance(
                        surfaces=surfaces,
                        user_specified_Sref=self.
                        options['user_specified_Sref'],
                        internally_connect_fuelburn=self.
                        options['internally_connect_fuelburn'],
                        rotational=self.options['rotational']),
                    promotes_inputs=['v', 'rho', 'cg', 'S_ref_total'],
                    promotes_outputs=['CL', 'CD', 'CM'])
            else:
                self.add_subsystem(
                    'total_perf',
                    TotalPerformance(surfaces=surfaces,
                                     user_specified_Sref=self.
                                     options['user_specified_Sref'],
                                     internally_connect_fuelburn=self.
                                     options['internally_connect_fuelburn'],
                                     rotational=self.options['rotational']),
                    promotes_inputs=[
                        'v', 'rho', 'cg', 'CT', 'speed_of_sound', 'R',
                        'Mach_number', 'W0', 'load_factor', 'S_ref_total'
                    ],
                    promotes_outputs=[
                        'L_equals_W', 'fuelburn', 'CL', 'CD', 'CM'
                    ])