Exemple #1
0
    def test_serial_in_parallel(self):
        prob = om.Problem()
        model = prob.model

        model.add_subsystem('p1', om.IndepVarComp('x', 1.0))

        parallel = model.add_subsystem('parallel', om.ParallelGroup())
        parallel.add_subsystem('c1', om.ExecComp(['y=-2.0*x']))

        parallel2 = model.add_subsystem('parallel_copy', om.ParallelGroup())
        parallel2.add_subsystem('comp1', om.ExecComp(['y=-2.0*x']))

        model.add_subsystem('con', om.ExecComp('y = 3.0*x'))

        model.connect("p1.x", "parallel.c1.x")
        model.connect('parallel.c1.y', 'parallel_copy.comp1.x')
        model.connect('parallel_copy.comp1.y', 'con.x')

        prob.setup(check=True)

        msg = (
            "The following systems are executed out-of-order:\n"
            "   System 'parallel.c2' executes out-of-order with respect to its source systems ['parallel.c1']\n"
        )

        with assert_no_warning(UserWarning, msg):
            prob.run_model()
Exemple #2
0
    def test_discrete_input_dataframe(self):
        class OMDataFrame:
            def __dict__(self):
                pass

        class ModCompEx2(ModCompEx):
            def setup(self):
                super().setup()
                self.add_discrete_input('test', OMDataFrame())

        prob = om.Problem()
        model = prob.model

        indep = model.add_subsystem('indep', om.IndepVarComp(), promotes=['*'])
        indep.add_discrete_output('x', 11)
        model.add_subsystem('comp', ModCompEx2(3), promotes=['*'])

        rec = om.SqliteRecorder('test.db')
        prob.driver.add_recorder(rec)
        prob.add_recorder(rec)

        prob.setup()
        msg = (
            "DeprecationWarning: The truth value of an empty array is ambiguous. Returning"
            "False, but in future this will result in an error. Use `array.size > 0` to check "
            "that an array is not empty.")

        with assert_no_warning(DeprecationWarning, msg):
            prob.run_model()
    def test_nonlinear_solver_bounds_stall_warning(self):
        prob = om.Problem()

        prob.model.add_subsystem('comp', om.ExecComp('y=3*x+1'), promotes=['*'])

        balance = prob.model.add_subsystem('balance', om.BalanceComp(), promotes=['*'])
        balance.add_balance('x', lower=-.1, upper=10, rhs_val=0, lhs_name='y')

        newton = prob.model.nonlinear_solver = om.NewtonSolver()
        newton.options['solve_subsystems'] = True
        newton.options['stall_limit'] = 5
        newton.options['stall_tol'] = 1e-8
        newton.options['maxiter'] = 100
        newton.options['err_on_non_converge'] = False

        prob.model.linear_solver = om.DirectSolver()

        prob.setup()

        msg = (f"Your model has stalled three times and may be violating the bounds. "
                f"In the future, turn on print_bound_enforce in your solver options "
                f"here: \nnonlinear_solver.linesearch.options"
                f"['print_bound_enforce']=True. "
                f"\nThe bound(s) being violated now are:\n")
        with assert_warning(UserWarning, msg):
            prob.run_model()

        newton.linesearch.options['print_bound_enforce'] = True

        prob.setup()

        with assert_no_warning(UserWarning, msg):
            prob.run_model()
    def test_balance_comp_options_exclude_no_error(self):

        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', val=1.0)

        prob.model.add_subsystem(name='balance', subsys=bal)

        recorder = om.SqliteRecorder('cases.sql')

        prob.model.add_recorder(recorder)

        prob.model.recording_options['record_inputs'] = True
        prob.model.recording_options['record_outputs'] = True
        prob.model.recording_options['record_residuals'] = True
        bal.recording_options['record_metadata'] = False

        prob.setup()

        msg = (
            "Trying to record option 'guess_func' which cannot be pickled on system BalanceComp "
            "(balance). Set 'recordable' to False. Skipping recording options for this system."
        )

        with assert_no_warning(UserWarning, msg):
            prob.run_model()

        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', val=1.0)

        prob.model.add_subsystem(name='balance', subsys=bal)

        recorder = om.SqliteRecorder('cases.sql')

        prob.model.add_recorder(recorder)

        bal.recording_options['record_metadata'] = True
        bal.recording_options['options_excludes'] = ['guess_func']

        prob.setup()

        with assert_no_warning(UserWarning, msg):
            prob.run_model()
Exemple #5
0
    def test_deprecated_option(self):
        msg = 'Option "test1" is deprecated.'
        self.dict.declare('test1', deprecation=msg)

        # test double set
        with assert_warning(OMDeprecationWarning, msg):
            self.dict['test1'] = None
        # Should only generate warning first time
        with assert_no_warning(OMDeprecationWarning, msg):
            self.dict['test1'] = None

        # Also test set and then get
        msg = 'Option "test2" is deprecated.'
        self.dict.declare('test2', deprecation=msg)

        with assert_warning(OMDeprecationWarning, msg):
            self.dict['test2'] = None
        # Should only generate warning first time
        with assert_no_warning(OMDeprecationWarning, msg):
            option = self.dict['test2']
Exemple #6
0
    def test_deprecated_tuple_option(self):
        msg = 'Option "test1" is deprecated. Use "foo" instead.'
        self.dict.declare('test1', deprecation=(msg, 'foo'))
        self.dict.declare('foo')

        # test double set
        with assert_warning(OMDeprecationWarning, msg):
            self.dict['test1'] = 'xyz'
        # Should only generate warning first time
        with assert_no_warning(OMDeprecationWarning, msg):
            self.dict['test1'] = 'zzz'

        with assert_no_warning(OMDeprecationWarning, msg):
            option = self.dict['test1']
        with assert_no_warning(OMDeprecationWarning):
            option2 = self.dict['foo']
        self.assertEqual(option, option2)

        # Also test set and then get
        msg = 'Option "test2" is deprecated. Use "foo2" instead.'
        self.dict.declare('test2', deprecation=(msg, 'foo2'))
        self.dict.declare('foo2')

        with assert_warning(OMDeprecationWarning, msg):
            self.dict['test2'] = 'abcd'
        # Should only generate warning first time
        with assert_no_warning(OMDeprecationWarning, msg):
            option = self.dict['test2']
        with assert_no_warning(OMDeprecationWarning):
            option2 = self.dict['foo2']
        self.assertEqual(option, option2)

        # test bad alias
        msg = 'Option "test3" is deprecated. Use "foo3" instead.'
        self.dict.declare('test3', deprecation=(msg, 'foo3'))

        with self.assertRaises(KeyError) as context:
            self.dict['test3'] = 'abcd'

        expected_msg = "Can't find aliased option 'foo3' for deprecated option 'test3'."
        self.assertEqual(context.exception.args[0], expected_msg)
    def test_comm_warning(self):

        rank = MPI.COMM_WORLD.rank if MPI is not None else 0

        prob = om.Problem(model=SellarDerivatives(nonlinear_solver=om.NewtonSolver()))

        prob.setup()

        msg = 'Deprecation warning: In V 3.0, the default Newton solver setup will change ' + \
              'to use the BoundsEnforceLS line search.'
        if rank == 0:
            with assert_warning(DeprecationWarning, msg):
                prob.final_setup()
        else:
            with assert_no_warning(DeprecationWarning, msg):
                prob.final_setup()
Exemple #8
0
    def test_balance_comp_record_options(self):

        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', val=1.0)

        prob.model.add_subsystem(name='balance', subsys=bal)

        recorder = om.SqliteRecorder('cases.sql')

        prob.model.add_recorder(recorder)

        prob.model.recording_options['record_inputs'] = True
        prob.model.recording_options['record_outputs'] = True
        prob.model.recording_options['record_residuals'] = True

        prob.setup()

        # there should be no warnings wrt unpicklable 'guess_func' option,
        # since 'recordable' has been set to False
        with assert_no_warning(UserWarning):
            prob.run_model()
Exemple #9
0
    def test_no_connect_parallel_group(self):
        prob = om.Problem()
        model = prob.model

        traj = model.add_subsystem('traj', om.ParallelGroup())

        burn1 = traj.add_subsystem('burn1', om.Group())
        burn1.add_subsystem('p1', om.IndepVarComp('x', 1.0))
        burn1.add_subsystem('burn_eq1', om.ExecComp(['y=-2.0*x']))
        burn1.connect('p1.x', 'burn_eq1.x')

        burn2 = traj.add_subsystem('burn2', om.Group())
        burn2.add_subsystem('p2', om.IndepVarComp('x', 1.0))
        burn2.add_subsystem('burn_eq2', om.ExecComp(['y=5.0*x']))
        burn2.connect('p2.x', 'burn_eq2.x')

        testlogger = TestLogger()
        prob.setup(check=True, mode='fwd', logger=testlogger)

        msg = "Need to attach NonlinearBlockJac, NewtonSolver, or BroydenSolver to 'parallel' when " \
              "connecting components inside parallel groups"

        with assert_no_warning(UserWarning, msg):
            prob.run_model()
Exemple #10
0
    def test_errors_and_warnings(self):
        def func(a=7., opt='foo'):
            if opt == 'foo':
                x = a * 2.0
            else:
                x = a / 2.0
            return x

        f = omf.wrap(func)

        with self.assertRaises(Exception) as context:
            f.declare_option('opt', types=str, valuess=('foo', 'bar'), desc='an opt')

        self.assertEqual(context.exception.args[0],
                         "In declare_option, metadata names ['valuess'] are not allowed.")

        with self.assertRaises(Exception) as context:
            f.declare_partials(of='*', wrrt='*', method='cs')

        self.assertEqual(context.exception.args[0],
                         "In declare_partials, metadata names ['wrrt'] are not allowed.")

        with self.assertRaises(Exception) as context:
            f.declare_coloring(wrrt='*', method='cs')

        self.assertEqual(context.exception.args[0],
                         "In declare_coloring, metadata names ['wrrt'] are not allowed.")

        with self.assertRaises(Exception) as context:
            f.add_input('a', shepe=4, units='m')

        self.assertEqual(context.exception.args[0],
                         "In add_input, metadata names ['shepe'] are not allowed.")

        with self.assertRaises(Exception) as context:
            f.add_input('a', val=4, units='m')

        self.assertEqual(context.exception.args[0],
                         "In add_input, metadata 'val' has already been added to function for input 'a'.")

        with self.assertRaises(Exception) as context:
            f.add_output('x', shepe=4, val=3.)

        self.assertEqual(context.exception.args[0],
                         "In add_output, metadata names ['shepe'] are not allowed.")

        with self.assertRaises(Exception) as context:
            f.defaults(shepe=4, val=3.)

        self.assertEqual(context.exception.args[0],
                         "In defaults, metadata names ['shepe'] are not allowed.")

        with self.assertRaises(Exception) as context:
            f.add_input('aa', shape=4, val=3.)

        self.assertEqual(context.exception.args[0],
                         "In add_input, 'aa' is not an input to this function.")

        with self.assertRaises(Exception) as context:
            f.add_output('a', shape=4, val=3.)

        self.assertEqual(context.exception.args[0],
                         "In add_output, 'a' already registered as an input.")

        f.add_output('x', shape=4, val=3.)
        with self.assertRaises(Exception) as context:
            f.add_output('x', shape=4, val=3.)

        self.assertEqual(context.exception.args[0],
                         "In add_output, 'x' already registered as an output.")

        # multiple returns, but neither gives the name, so raise exception
        def func2(a):
            if a < 1.:
                return a + 1
            return None

        f = omf.wrap(func2)

        with self.assertRaises(Exception) as context:
            f._setup()

        self.assertEqual(context.exception.args[0],
                         "0 output names are specified in the metadata but there are 1 unnamed return values in the function.")

        # this func defines the same name in both returns, which is ok
        def func3(a):
            if a < 1.:
                bb = a + 1
                return bb
            bb = 8.
            return bb

        f = omf.wrap(func3)

        with assert_no_warning(UserWarning):
            f._setup()

        # this func defines the name in one return but not the other, which is ok
        def func4(a):
            if a < 1.:
                bb = a + 1
                return bb
            return a - 1

        f = omf.wrap(func4)

        with assert_no_warning(UserWarning):
            f._setup()

        # different numbers of return values, which isn't allowed
        def func5(a):
            if a < 1.:
                b = a + 1
                c = a * 2.
                return b, c
            return None

        f = omf.wrap(func5)

        with self.assertRaises(Exception) as context:
            f._setup()

        self.assertEqual(context.exception.args[0],
                         "During AST processing to determine the number and name of return values, the following error occurred: Function has multiple return statements with differing numbers of return values.")

        # different return value names. not allowed
        def func6(a):
            b = a + 1
            c = a * 2.
            x = c
            if a < 1.:
                return b, c
            return b, x

        f = omf.wrap(func6)

        with self.assertRaises(Exception) as context:
            f._setup()

        self.assertEqual(context.exception.args[0],
                         "During AST processing to determine the number and name of return values, the following error occurred: Function has multiple return statements with different return value names of ['c', 'x'] for return value 1.")

        def func7(a):
            b = a + 1
            c = a * 2.
            return b, c

        f = omf.wrap(func7).add_input('a', val=np.ones(2), shape=(2,2))

        with self.assertRaises(Exception) as context:
            f._setup()

        self.assertEqual(context.exception.args[0],
                         "Input 'a' value has shape (2,), but shape was specified as (2, 2).")