Esempio n. 1
0
    def setup(self):
        surface = self.options['surface']

        promotes = []
        if surface['struct_weight_relief']:
            promotes = promotes + list(set(['nodes', 'element_weights', 'load_factor']))
        if surface['distributed_fuel_weight']:
            promotes = promotes + list(set(['nodes', 'load_factor']))

        self.add_subsystem('struct_states',
            SpatialBeamStates(surface=surface),
            promotes_inputs=['local_stiff_transformed', 'forces', 'loads'] + promotes, promotes_outputs=['disp'])

        self.add_subsystem('def_mesh',
            DisplacementTransferGroup(surface=surface),
            promotes_inputs=['nodes', 'mesh', 'disp'], promotes_outputs=['def_mesh'])

        self.add_subsystem('aero_geom',
            VLMGeometry(surface=surface),
            promotes_inputs=['def_mesh'], promotes_outputs=['b_pts', 'widths', 'cos_sweep', 'lengths', 'chords', 'normals', 'S_ref'])

        self.linear_solver = LinearRunOnce()
Esempio n. 2
0
    def coupled_group(self):
        # type: () -> Optional[Group]
        """:obj:`Group`, optional: Group wrapping the coupled blocks with a converger specified in the CMDOWS file.

        If no coupled blocks are specified in the CMDOWS file this property is `None`.
        """
        if self.coupled_blocks:
            coupled_group = Group()
            for uid in self.coupled_blocks:
                # Get the correct DisciplineComponent
                discipline_component = self.discipline_components[uid]

                # Change input variable names if they are provided as copies of coupling variables
                promotes = ['*']  # type: List[Union[str, Tuple[str, str]]]
                if not self.has_converger:
                    for i in discipline_component.inputs_from_xml.keys():
                        if i in self.coupling_vars:
                            promotes.append((i, self.coupling_vars[i]['copy']))

                # Add the DisciplineComponent to the group
                coupled_group.add_subsystem(uid, self.discipline_components[uid], promotes)

            # Find the convergence type of the coupled group
            if self.has_converger:
                conv_type = self.elem_problem_def.find('problemFormulation/convergerType').text
                if conv_type == 'Gauss-Seidel':
                    coupled_group.linear_solver = LinearBlockGS()
                    coupled_group.nonlinear_solver = NonlinearBlockGS()
                elif conv_type == 'Jacobi':
                    coupled_group.linear_solver = LinearBlockJac()
                    coupled_group.nonlinear_solver = NonlinearBlockJac()
                else:
                    raise RuntimeError('Specified convergerType "%s" is not supported.' % conv_type)
            else:
                coupled_group.linear_solver = LinearRunOnce()
                coupled_group.nonlinear_solver = NonLinearRunOnce()
            return coupled_group
        return None
    def test_record_solver_linear_linear_run_once(self, m):
        self.setup_endpoints(m)
        recorder = WebRecorder(self._accepted_token, suppress_output=True)
        # raise unittest.SkipTest("Linear Solver recording not working yet")
        self.setup_sellar_model()

        self.prob.model.nonlinear_solver = NewtonSolver()
        # used for analytic derivatives
        self.prob.model.nonlinear_solver.linear_solver = LinearRunOnce()

        linear_solver = self.prob.model.nonlinear_solver.linear_solver
        linear_solver.recording_options['record_abs_error'] = True
        linear_solver.recording_options['record_rel_error'] = True
        linear_solver.recording_options['record_solver_residuals'] = True
        self.prob.model.nonlinear_solver.linear_solver.add_recorder(recorder)

        self.prob.setup(check=False)
        t0, t1 = run_driver(self.prob)

        solver_iteration = json.loads(self.solver_iterations)
        expected_abs_error = 0.0
        expected_rel_error = 0.0

        expected_solver_output = [
            {'name': 'px.x', 'values': [0.0]},
            {'name': 'pz.z', 'values': [0.0, 0.0]},
            {'name': 'd1.y1', 'values': [-4.15366975e-05]},
            {'name': 'd2.y2', 'values': [-4.10568454e-06]},
            {'name': 'obj_cmp.obj', 'values': [-4.15366737e-05]},
            {'name': 'con_cmp1.con1', 'values': [4.15366975e-05]},
            {'name': 'con_cmp2.con2', 'values': [-4.10568454e-06]},
        ]

        self.assertAlmostEqual(expected_abs_error, solver_iteration['abs_err'])
        self.assertAlmostEqual(expected_rel_error, solver_iteration['rel_err'])

        for o in expected_solver_output:
            self.assert_array_close(o, solver_iteration['solver_output'])
Esempio n. 4
0
    def test_method_default(self):
        # Uses `solve_linear` by default
        p = Problem()

        p.model.add_subsystem('des_vars',
                              IndepVarComp('a', val=10., units='m'),
                              promotes=['*'])

        p.model.add_subsystem('icomp', DistribStateImplicit(), promotes=['*'])

        model = p.model

        model.linear_solver = PETScKrylov()
        model.linear_solver.precon = LinearRunOnce()

        p.setup(mode='rev', check=False)

        model.icomp.linear_solver.precon = LinearUserDefined()

        p.run_model()
        jac = p.compute_totals(of=['out_var'], wrt=['a'], return_format='dict')

        assert_rel_error(self, 15.0, jac['out_var']['a'][0][0])
    def setup(self):
        surface = self.options['surface']

        self.add_subsystem(
            'struct_states',
            SpatialBeamStates(surface=surface),
            promotes_inputs=['K', 'forces', 'loads', 'element_weights'],
            promotes_outputs=['disp'])

        self.add_subsystem('def_mesh',
                           DisplacementTransfer(surface=surface),
                           promotes_inputs=['mesh', 'disp'],
                           promotes_outputs=['def_mesh'])

        self.add_subsystem('aero_geom',
                           VLMGeometry(surface=surface),
                           promotes_inputs=['def_mesh'],
                           promotes_outputs=[
                               'b_pts', 'c_pts', 'widths', 'cos_sweep',
                               'lengths', 'chords', 'normals', 'S_ref'
                           ])

        self.linear_solver = LinearRunOnce()
Esempio n. 6
0
    def setUp(self):

        p = Problem()

        p.model.cite = "foobar model"
        p.model.nonlinear_solver.cite = "foobar nonlinear_solver"
        p.model.linear_solver.cite = "foobar linear_solver"

        indeps = p.model.add_subsystem('indeps',
                                       IndepVarComp('x', 10),
                                       promotes=['*'])
        indeps.linear_solver = LinearRunOnce()

        par = p.model.add_subsystem('par', ParallelGroup(), promotes=['*'])

        ec = par.add_subsystem('ec', ExecComp('y = 2+3*x'), promotes=['*'])
        # note using newton here makes no sense in reality, but its fine for this test since we never run the model
        ec.nonlinear_solver = NewtonSolver()
        ec.cite = "foobar exec comp"
        c2 = par.add_subsystem('c2', ExecComp('y2=x'), promotes=['*'])
        c2.cite = 'foobar exec comp'

        self.prob = p
Esempio n. 7
0
    def test_zero_src_indices(self):
        prob = Problem()
        model = prob.model
        model.nonlinear_solver = NonlinearRunOnce()
        model.linear_solver = LinearRunOnce()

        model.add_subsystem('comp1', Comp())
        model.add_subsystem('comp2', Comp())
        model.connect('comp1.y', 'comp2.x')
        model.connect('comp2.y', 'comp1.x')

        prob.setup()
        prob.run_model()

        if model.comm.rank == 1:
            np.testing.assert_almost_equal(model.comp1._outputs['y'],
                                           np.array([]))
            np.testing.assert_almost_equal(model.comp2._outputs['y'],
                                           np.array([]))
        else:
            np.testing.assert_almost_equal(model.comp1._outputs['y'],
                                           np.ones(3) * 2.)
            np.testing.assert_almost_equal(model.comp2._outputs['y'],
                                           np.ones(3) * 3.)
    def test_circuit_voltage_source(self):
        from openmdao.api import ArmijoGoldsteinLS, Problem, IndepVarComp, BalanceComp, ExecComp
        from openmdao.api import NewtonSolver, DirectSolver, NonlinearRunOnce, LinearRunOnce

        from openmdao.test_suite.scripts.circuit_analysis import Circuit

        p = Problem()
        model = p.model

        model.add_subsystem('ground', IndepVarComp('V', 0., units='V'))

        # replacing the fixed current source with a BalanceComp to represent a fixed Voltage source
        # model.add_subsystem('source', IndepVarComp('I', 0.1, units='A'))
        model.add_subsystem('batt', IndepVarComp('V', 1.5, units='V'))
        bal = model.add_subsystem('batt_balance', BalanceComp())
        bal.add_balance('I', units='A', eq_units='V')

        model.add_subsystem('circuit', Circuit())
        model.add_subsystem(
            'batt_deltaV',
            ExecComp('dV = V1 - V2',
                     V1={'units': 'V'},
                     V2={'units': 'V'},
                     dV={'units': 'V'}))

        # current into the circuit is now the output state from the batt_balance comp
        model.connect('batt_balance.I', 'circuit.I_in')
        model.connect('ground.V', ['circuit.Vg', 'batt_deltaV.V2'])
        model.connect('circuit.n1.V', 'batt_deltaV.V1')

        # set the lhs and rhs for the battery residual
        model.connect('batt.V', 'batt_balance.rhs:I')
        model.connect('batt_deltaV.dV', 'batt_balance.lhs:I')

        p.setup()

        ###################
        # Solver Setup
        ###################

        # change the circuit solver to RunOnce because we're
        # going to converge at the top level of the model with newton instead
        p.model.circuit.nonlinear_solver = NonlinearRunOnce()
        p.model.circuit.linear_solver = LinearRunOnce()

        # Put Newton at the top so it can also converge the new BalanceComp residual
        newton = p.model.nonlinear_solver = NewtonSolver()
        p.model.linear_solver = DirectSolver()
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 20
        newton.options['solve_subsystems'] = True
        newton.linesearch = ArmijoGoldsteinLS()
        newton.linesearch.options['maxiter'] = 10
        newton.linesearch.options['iprint'] = 2

        # set initial guesses from the current source problem
        p['circuit.n1.V'] = 9.8
        p['circuit.n2.V'] = .7

        p.run_model()

        assert_rel_error(self, p['circuit.n1.V'], 1.5, 1e-5)
        assert_rel_error(self, p['circuit.n2.V'], 0.676232, 1e-5)
        assert_rel_error(self, p['circuit.R1.I'], 0.015, 1e-5)
        assert_rel_error(self, p['circuit.R2.I'], 8.23767999e-05, 1e-5)
        assert_rel_error(self, p['circuit.D1.I'], 8.23767999e-05, 1e-5)
Esempio n. 9
0
    def test_feature(self):
        import numpy as np

        from openmdao.api import Problem, ImplicitComponent, IndepVarComp, LinearRunOnce, PETScKrylov, PETScVector, LinearUserDefined
        from openmdao.utils.array_utils import evenly_distrib_idxs

        class CustomSolveImplicit(ImplicitComponent):
            def setup(self):

                self.add_input('a', val=10., units='m')

                rank = self.comm.rank
                GLOBAL_SIZE = 15
                sizes, offsets = evenly_distrib_idxs(self.comm.size,
                                                     GLOBAL_SIZE)

                self.add_output('states', shape=int(sizes[rank]))

                self.add_output('out_var', shape=1)
                self.local_size = sizes[rank]

                self.linear_solver = PETScKrylov()
                self.linear_solver.precon = LinearUserDefined(
                    solve_function=self.mysolve)

            def solve_nonlinear(self, i, o):
                o['states'] = i['a']

                local_sum = np.zeros(1)
                local_sum[0] = np.sum(o['states'])
                tmp = np.zeros(1)

                o['out_var'] = tmp[0]

            def apply_nonlinear(self, i, o, r):
                r['states'] = o['states'] - i['a']

                local_sum = np.zeros(1)
                local_sum[0] = np.sum(o['states'])
                global_sum = np.zeros(1)

                r['out_var'] = o['out_var'] - tmp[0]

            def apply_linear(self, i, o, d_i, d_o, d_r, mode):
                if mode == 'fwd':
                    if 'states' in d_o:
                        d_r['states'] += d_o['states']

                        local_sum = np.array([np.sum(d_o['states'])])
                        global_sum = np.zeros(1)
                        self.comm.Allreduce(local_sum, global_sum, op=MPI.SUM)
                        d_r['out_var'] -= global_sum

                    if 'out_var' in d_o:
                        d_r['out_var'] += d_o['out_var']

                    if 'a' in d_i:
                        d_r['states'] -= d_i['a']

                elif mode == 'rev':
                    if 'states' in d_o:
                        d_o['states'] += d_r['states']

                        tmp = np.zeros(1)
                        if self.comm.rank == 0:
                            tmp[0] = d_r['out_var'].copy()
                        self.comm.Bcast(tmp, root=0)

                        d_o['states'] -= tmp

                    if 'out_var' in d_o:
                        d_o['out_var'] += d_r['out_var']

                    if 'a' in d_i:
                        d_i['a'] -= np.sum(d_r['states'])

            def mysolve(self, d_outputs, d_residuals, mode):
                r"""
                Apply inverse jac product. The model is assumed to be in an unscaled state.

                If mode is:
                    'fwd': d_residuals \|-> d_outputs

                    'rev': d_outputs \|-> d_residuals

                Parameters
                ----------
                d_outputs : Vector
                    unscaled, dimensional quantities read via d_outputs[key]
                d_residuals : Vector
                    unscaled, dimensional quantities read via d_residuals[key]
                mode : str
                    either 'fwd' or 'rev'

                Returns
                -------
                None or bool or (bool, float, float)
                    The bool is the failure flag; and the two floats are absolute and relative error.
                """
                # Note: we are just preconditioning with Identity as a proof of concept.
                if mode == 'fwd':
                    d_outputs.set_vec(d_residuals)
                elif mode == 'rev':
                    d_residuals.set_vec(d_outputs)

                return False, 0., 0.

        prob = Problem()

        prob.model.add_subsystem('des_vars',
                                 IndepVarComp('a', val=10., units='m'),
                                 promotes=['*'])
        prob.model.add_subsystem('icomp',
                                 CustomSolveImplicit(),
                                 promotes=['*'])

        model = prob.model

        model.linear_solver = PETScKrylov()
        model.linear_solver.precon = LinearRunOnce()

        prob.setup(mode='rev', check=False)
        prob.run_model()
        jac = prob.compute_totals(of=['out_var'],
                                  wrt=['a'],
                                  return_format='dict')

        assert_rel_error(self, 15.0, jac['out_var']['a'][0][0])
Esempio n. 10
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 = 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'])

class PlanesIntersection(Group):

    def setup(self):
        self.add_subsystem('p3', Plane3())
        self.add_subsystem('p1', Plane1())
        self.add_subsystem('p2', Plane2())

        self.connect('p1.y', 'p2.y')
        self.connect('p1.y', 'p3.y')
        self.connect('p2.x', 'p3.x')
        self.connect('p2.x', 'p1.x')
        self.connect('p3.z', 'p1.z')
        self.connect('p3.z', 'p2.z')


prob = Problem()
from openmdao.api import LinearRunOnce
prob.model = PlanesIntersection()
# a = prob.model.nonlinear_solver = NewtonSolver()
a = prob.model.linear_solver = LinearRunOnce()

a.options['maxiter'] = 10

prob.setup()
# view_model(prob)

prob.run_model()
print(prob['p1.y'], prob['p1.x'], prob['p1.z'])
Esempio n. 12
0
    model.connect('circuit.n1.V', 'batt_deltaV.V1')

    # set the lhs and rhs for the battery residual
    model.connect('batt.V', 'batt_balance.rhs:I')
    model.connect('batt_deltaV.dV', 'batt_balance.lhs:I')

    p.setup()

    ###################
    # Solver Setup
    ###################

    # change the circuit solver to RunOnce because we're
    # going to converge at the top level of the model with newton instead
    p.model.circuit.nonlinear_solver = NonlinearRunOnce()
    p.model.circuit.linear_solver = LinearRunOnce()

    # Put Newton at the top so it can also converge the new BalanceComp residual
    newton = p.model.nonlinear_solver = NewtonSolver()
    p.model.linear_solver = DirectSolver()
    newton.options['iprint'] = 2
    newton.options['maxiter'] = 20
    newton.options['solve_subsystems'] = True
    newton.linesearch = ArmijoGoldsteinLS()
    newton.linesearch.options['maxiter'] = 10
    newton.linesearch.options['iprint'] = 2

    # set initial guesses from the current source problem
    p['circuit.n1.V'] = 9.8
    p['circuit.n2.V'] = .7
Esempio n. 13
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'])