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))
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))
def test_deprecated_methods(self): p1 = np.linspace(0, 100, 5) p2 = np.linspace(-10, 10, 3) p3 = np.linspace(0, 1, 3) # can use meshgrid to create a 3D array of test data P1, P2, P3 = np.meshgrid(p1, p2, p3, indexing='ij') f_p = np.sqrt(P1) + P2 * P3 x1 = np.linspace(-2, 101, 5) x2 = np.linspace(-10.5, 11, 5) x3 = np.linspace(-0.2, 1.1, 5) X1, X2, X3 = np.meshgrid(x1, x2, x3, indexing='ij') x = np.zeros((125, 3)) x[:, 0] = X1.ravel() x[:, 1] = X2.ravel() x[:, 2] = X3.ravel() msg = "The 'trilinear' method has been renamed to '3D-slinear'." with assert_warning(OMDeprecationWarning, msg): InterpND(points=(p1, p2, p3), values=f_p, method='trilinear', extrapolate=True) msg = "The 'akima1D' method has been renamed to '1D-akima'." with assert_warning(OMDeprecationWarning, msg): InterpND(points=p1, values=p1, method='akima1D')
def test_ivc_deprecations(self): msg = "IndepVarComp (p1): The '{}' argument was used when adding output '{}'. " + \ "This argument has been deprecated and will be removed in a future version." prob = om.Problem() indep = prob.model.add_subsystem('p1', om.IndepVarComp()) # ref, ref0 with assert_warnings([(DeprecationWarning, msg.format('ref', 'a')), (DeprecationWarning, msg.format('ref0', 'a'))]): indep.add_output('a', 12., ref=0.0, ref0=1.) # res_units with assert_warning(DeprecationWarning, msg.format('res_units', 'b')): indep.add_output('b', 12., res_units='m') # upper with assert_warning(DeprecationWarning, msg.format('upper', 'c')): indep.add_output('c', 12., upper=1.) # lower with assert_warning(DeprecationWarning, msg.format('lower', 'd')): indep.add_output('d', 12., lower=1.) # res_ref with assert_warning(DeprecationWarning, msg.format('res_ref', 'e')): indep.add_output('e', 12., res_ref=1.) # res_ref with assert_warning(DeprecationWarning, msg.format('ref', 'f')): indep.add_output('f', 12., ref=2.)
def test_recording_options_deprecated(self): prob = Problem() msg = "The recording option, record_model_metadata, on System is deprecated. " \ "Recording of model metadata will always be done" with assert_warning(OMDeprecationWarning, msg): prob.model.recording_options['record_model_metadata'] = True msg = "The recording option, record_metadata, on System is deprecated. " \ "Recording of metadata will always be done" with assert_warning(OMDeprecationWarning, msg): prob.model.recording_options['record_metadata'] = True
def test_preconditioner_deprecation(self): group = TestImplicitGroup(lnSolverClass=self.linear_solver_class) msg = "The 'preconditioner' property provides backwards compatibility " \ + "with OpenMDAO <= 1.x ; use 'precon' instead." # check deprecation on setter & getter with assert_warning(DeprecationWarning, msg): group.linear_solver.preconditioner = LinearBlockGS() with assert_warning(DeprecationWarning, msg): group.linear_solver.preconditioner
def test_duplicate_timeseries_glob_name(self): """ Test that the user gets a warning about multiple timeseries with the same name. """ msg = "The timeseries variable name rho is duplicated in these variables: atmos.rho, " \ "foo.rho. Disambiguate by using the add_timeseries_output output_name option." with assert_warning(UserWarning, msg): p = min_time_climb(num_seg=12, transcription_class=dm.Radau, transcription_order=3) with assert_warning(UserWarning, msg): p = min_time_climb(num_seg=12, transcription_class=dm.GaussLobatto, transcription_order=3)
def test_list_inputs_outputs_val_deprecation(self): p = Problem() p.model.add_subsystem('comp', ExecComp('b=2*a'), promotes=['a', 'b']) p.setup() p.run_model() msg = "<model> <class Group>: The 'values' argument to 'list_inputs()' " \ "is deprecated and will be removed in 4.0. Please use 'val' instead." with assert_warning(OMDeprecationWarning, msg): inputs = p.model.list_inputs(values=False, out_stream=None) self.assertEqual(inputs, [('comp.a', {})]) with assert_warning(OMDeprecationWarning, msg): inputs = p.model.list_inputs(values=True, out_stream=None) self.assertEqual(inputs, [('comp.a', {'val': 1})]) msg = "The metadata key 'value' will be deprecated in 4.0. Please use 'val'." with assert_warning(OMDeprecationWarning, msg): self.assertEqual(inputs[0][1]['value'], 1) msg = "<model> <class Group>: The 'values' argument to 'list_outputs()' " \ "is deprecated and will be removed in 4.0. Please use 'val' instead." with assert_warning(OMDeprecationWarning, msg): outputs = p.model.list_outputs(values=False, out_stream=None) self.assertEqual(outputs, [('comp.b', {})]) with assert_warning(OMDeprecationWarning, msg): outputs = p.model.list_outputs(values=True, out_stream=None) self.assertEqual(outputs, [('comp.b', {'val': 2})]) msg = "The metadata key 'value' will be deprecated in 4.0. Please use 'val'." with assert_warning(OMDeprecationWarning, msg): self.assertEqual(outputs[0][1]['value'], 2) meta = p.model.get_io_metadata(metadata_keys=('val',)) with assert_warning(OMDeprecationWarning, msg): self.assertEqual(meta['comp.a']['value'], 1) with assert_warning(OMDeprecationWarning, msg): meta = p.model.get_io_metadata(metadata_keys=('value',)) self.assertEqual(meta['comp.a']['val'], 1) with assert_warning(OMDeprecationWarning, msg): meta = p.model.get_io_metadata(metadata_keys=('value',)) with assert_warning(OMDeprecationWarning, msg): self.assertEqual(meta['comp.a']['value'], 1)
def test_solve_linear_scipy(self): """Solve implicit system with ScipyKrylov.""" # use ScipyIterativeSolver here to check for deprecation warning and verify that the deprecated # class still gets the right answer without duplicating this test. msg = "ScipyIterativeSolver is deprecated. Use ScipyKrylov instead." with assert_warning(DeprecationWarning, msg): group = TestImplicitGroup(lnSolverClass=lambda : ScipyIterativeSolver(solver=self.linear_solver_name)) p = Problem(group) p.setup(check=False) p.set_solver_print(level=0) # Conclude setup but don't run model. p.final_setup() d_inputs, d_outputs, d_residuals = group.get_linear_vectors() # forward d_residuals.set_const(1.0) d_outputs.set_const(0.0) group.run_solve_linear(['linear'], 'fwd') output = d_outputs._data assert_rel_error(self, output, group.expected_solution, 1e-15) # reverse d_outputs.set_const(1.0) d_residuals.set_const(0.0) group.run_solve_linear(['linear'], 'rev') output = d_residuals._data assert_rel_error(self, output, group.expected_solution, 1e-15)
def test_distrib_idx_in_full_out(self): size = 11 p = om.Problem() top = p.model C1 = top.add_subsystem("C1", InOutArrayComp(arr_size=size)) C2 = top.add_subsystem("C2", DistribInputComp(arr_size=size)) top.connect('C1.outvec', 'C2.invec') msg = "The 'distributed' option is set to True for Component C2, " \ "but there is no distributed vector implementation (MPI/PETSc) " \ "available. The default non-distributed vectors will be used." with assert_warning(UserWarning, msg): p.setup() # Conclude setup but don't run model. p.final_setup() C1._inputs['invec'] = np.array(range(size, 0, -1), float) p.run_model() self.assertTrue( all(C2._outputs['outvec'] == np.array(range(size, 0, -1), float) * 4))
def test_n2_connection_error(self): """ Test that an n2 html file is generated from a Problem even if it has connection errors. """ from openmdao.test_suite.scripts.bad_connection import BadConnectionModel p = Problem(BadConnectionModel()) # this would be set by the command line hook p.model._raise_connection_errors = False expected = "Group (sub): Attempted to connect from 'tgt.x' to 'cmp.x', but " + \ "'tgt.x' is an input. All connections must be from an output to an input." with assert_warning(UserWarning, expected): p.setup() n2(p, outfile=self.conn_html_filename, show_browser=DEBUG_BROWSER, title="Bad Connection") # Check that the html file has been created and has something in it. self.assertTrue(os.path.isfile(self.conn_html_filename), (self.conn_html_filename + " is not a valid file.")) self.assertTrue( 'OpenMDAO Model Hierarchy and N2 diagram: Bad Connection' in open( self.conn_html_filename).read())
def test_xdsmjs_right_outputs(self): """Makes XDSM for the Sellar problem""" filename = 'xdsmjs_outputs_on_the_right' prob = om.Problem() prob.model = model = SellarNoDerivatives() model.add_design_var('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0]), indices=np.arange(2, dtype=int)) model.add_design_var('x', lower=0.0, upper=10.0) model.add_objective('obj') model.add_constraint('con1', equals=np.zeros(1)) model.add_constraint('con2', upper=0.0) prob.setup() prob.final_setup() msg = 'Right side outputs not implemented for XDSMjs.' # Write output with assert_warning(Warning, msg): om.write_xdsm(prob, filename=filename, out_format='html', show_browser=SHOW, quiet=QUIET, output_side='right') # Check if file was created self.assertTrue(os.path.isfile('.'.join([filename, 'html'])))
def test_connect_incompatible_shapes(self): p = om.Problem() p.model.add_subsystem( 'indep', om.IndepVarComp('x', val=np.arange(10)[np.newaxis, :, np.newaxis, np.newaxis])) p.model.add_subsystem( 'C1', om.ExecComp('y=5*x', x={'value': np.zeros((5, 2))}, y={'value': np.zeros((5, 2))})) p.model.connect('indep.x', 'C1.x') expected = "<model> <class Group>: The source and target shapes do not match or are " + \ "ambiguous for the connection 'indep.x' to 'C1.x'. The source shape is " + \ "(1, 10, 1, 1) but the target shape is (5, 2)." with self.assertRaises(Exception) as context: p.setup() self.assertEqual(str(context.exception), expected) p.model._raise_connection_errors = False with assert_warning(UserWarning, expected): p.setup()
def test_single_parallel_group_order(self): prob = om.Problem() model = prob.model model.add_subsystem('p1', om.IndepVarComp('x', 1.0)) model.add_subsystem('p2', om.IndepVarComp('x', 1.0)) parallel = model.add_subsystem('parallel', om.ParallelGroup()) parallel.add_subsystem('c1', om.ExecComp(['y=-2.0*x'])) parallel.add_subsystem('c2', om.ExecComp(['y=5.0*x'])) parallel.connect('c1.y', 'c2.x') model.add_subsystem('c3', om.ExecComp(['y=3.0*x1+7.0*x2'])) model.connect("parallel.c1.y", "c3.x1") model.connect("parallel.c2.y", "c3.x2") model.connect("p1.x", "parallel.c1.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_warning(UserWarning, msg): prob.run_model() expected_warning = ( "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" ) testlogger.find_in('warning', expected_warning)
def test_mult_conns(self): class SubGroup(Group): def setup(self): self.add_subsystem('c1', ExecComp('y = 2*x', x=np.ones(4), y=2*np.ones(4)), promotes=['y', 'x']) self.add_subsystem('c2', ExecComp('z = 2*y', y=np.ones(4), z=2*np.ones(4)), promotes=['z', 'y']) prob = Problem() indeps = prob.model.add_subsystem('indeps', IndepVarComp(), promotes=['*']) indeps.add_output('x', 10*np.ones(4)) indeps.add_output('y', np.ones(4)) prob.model.add_subsystem('sub', SubGroup()) prob.model.connect('x', 'sub.x') prob.model.connect('y', 'sub.y') expected = "Group (<model>): The following inputs have multiple connections: " + \ "sub.c2.y from ['indeps.y', 'sub.c1.y']" with self.assertRaises(Exception) as context: prob.setup() self.assertEqual(str(context.exception), expected) prob.model._raise_connection_errors = False with assert_warning(UserWarning, expected): prob.setup()
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_deprecated_ks_component(self): # run same test as above, only with the deprecated component, # to ensure we get the warning and the correct answer. # self-contained, to be removed when class name goes away. from openmdao.components.ks_comp import KSComponent # deprecated prob = Problem() prob.model = model = Group() model.add_subsystem('px', IndepVarComp(name="x", val=np.ones((2, )))) model.add_subsystem('comp', DoubleArrayComp()) msg = "'KSComponent' has been deprecated. Use 'KSComp' instead." with assert_warning(DeprecationWarning, msg): model.add_subsystem('ks', KSComponent(width=2)) model.connect('px.x', 'comp.x1') model.connect('comp.y2', 'ks.g') model.add_design_var('px.x') model.add_objective('comp.y1') model.add_constraint('ks.KS', upper=0.0) prob.setup(check=False) prob.run_driver() assert_rel_error(self, max(prob['comp.y2']), prob['ks.KS'][0])
def test_mixed_conns_same_level(self): prob = om.Problem() indeps = prob.model.add_subsystem('indeps', om.IndepVarComp()) indeps.add_output('x', 10 * np.ones(4)) # c2.y is implicitly connected to c1.y prob.model.add_subsystem('c1', om.ExecComp('y = 2*x', x=np.ones(4), y=2 * np.ones(4)), promotes=['y']) prob.model.add_subsystem('c2', om.ExecComp('z = 2*y', y=np.ones(4), z=2 * np.ones(4)), promotes=['y']) # make a second, explicit, connection to y (which is c2.y promoted) prob.model.connect('indeps.x', 'y') expected = "<model> <class Group>: Input 'c2.y' cannot be connected to 'indeps.x' " + \ "because it's already connected to 'c1.y'" with self.assertRaises(Exception) as context: prob.setup() prob.final_setup() self.assertEqual(str(context.exception), expected) prob.model._raise_connection_errors = False with assert_warning(UserWarning, expected): prob.setup()
def test_deprecated_ks_component(self): # run same test as above, only with the deprecated component, # to ensure we get the warning and the correct answer. # self-contained, to be removed when class name goes away. from openmdao.components.ks_comp import KSComponent # deprecated prob = Problem() prob.model = model = Group() model.add_subsystem('px', IndepVarComp(name="x", val=np.ones((2,)))) model.add_subsystem('comp', DoubleArrayComp()) msg = "'KSComponent' has been deprecated. Use 'KSComp' instead." with assert_warning(DeprecationWarning, msg): model.add_subsystem('ks', KSComponent(width=2)) model.connect('px.x', 'comp.x1') model.connect('comp.y2', 'ks.g') model.add_design_var('px.x') model.add_objective('comp.y1') model.add_constraint('ks.KS', upper=0.0) prob.setup(check=False) prob.run_driver() assert_rel_error(self, max(prob['comp.y2']), prob['ks.KS'][0])
def test_solve_linear_ksp_default(self): """Solve implicit system with PETScKrylov using default method.""" # use PetscKSP here to check for deprecation warning and verify that the deprecated # class still gets the right answer without duplicating this test. msg = "PetscKSP is deprecated. Use PETScKrylov instead." with assert_warning(DeprecationWarning, msg): group = TestImplicitGroup(lnSolverClass=om.PetscKSP) p = om.Problem(group) p.setup() p.set_solver_print(level=0) # Conclude setup but don't run model. p.final_setup() d_inputs, d_outputs, d_residuals = group.get_linear_vectors() # forward d_residuals.set_const(1.0) d_outputs.set_const(0.0) group.run_solve_linear(['linear'], 'fwd') output = d_outputs._data assert_rel_error(self, output, group.expected_solution, 1e-15) # reverse d_outputs.set_const(1.0) d_residuals.set_const(0.0) group.run_solve_linear(['linear'], 'rev') output = d_residuals._data assert_rel_error(self, output, group.expected_solution, 1e-15)
def test_simul_coloring_fwd(self): # first, run w/o coloring p = run_opt(ScipyOptimizeDriver, 'fwd', optimizer='SLSQP', disp=False) p_color = run_opt(ScipyOptimizeDriver, 'fwd', color_info=self.color_info, optimizer='SLSQP', disp=False) assert_almost_equal(p['circle.area'], np.pi, decimal=7) assert_almost_equal(p_color['circle.area'], np.pi, decimal=7) # - coloring saves 16 solves per driver iter (5 vs 21) # - initial solve for linear constraints takes 21 in both cases (only done once) # - (total_solves - 21) / (solves_per_iter) should be equal between the two cases self.assertEqual((p.model._solve_count - 21) / 21, (p_color.model._solve_count - 21) / 5) # check for proper handling if someone calls compute_totals on Problem with different set or different order # of desvars/responses than were used to define the coloring. Behavior should be that coloring is turned off # and a warning is issued. msg = "compute_totals called using a different list of design vars and/or responses than those used " \ "to define coloring, so coloring will be turned off.\ncoloring design vars: " \ "['indeps.x', 'indeps.y', 'indeps.r'], current design vars: ['indeps.x', 'indeps.y', 'indeps.r']\n" \ "coloring responses: ['circle.area', 'r_con.g', 'theta_con.g', 'delta_theta_con.g', 'l_conx.g'], " \ "current responses: ['delta_theta_con.g', 'circle.area', 'r_con.g', 'theta_con.g', 'l_conx.g']." with assert_warning(UserWarning, msg): p_color.compute_totals(of=['delta_theta_con.g', 'circle.area', 'r_con.g', 'theta_con.g', 'l_conx.g'], wrt=['x', 'y', 'r'])
def test_simul_coloring_fwd(self): # first, run w/o coloring p = run_opt(ScipyOptimizeDriver, 'fwd', optimizer='SLSQP', disp=False) p_color = run_opt(ScipyOptimizeDriver, 'fwd', color_info=self.color_info, optimizer='SLSQP', disp=False) assert_almost_equal(p['circle.area'], np.pi, decimal=7) assert_almost_equal(p_color['circle.area'], np.pi, decimal=7) # - coloring saves 16 solves per driver iter (5 vs 21) # - initial solve for linear constraints takes 21 in both cases (only done once) # - (total_solves - 21) / (solves_per_iter) should be equal between the two cases self.assertEqual((p.model._solve_count - 21) / 21, (p_color.model._solve_count - 21) / 5) # check for proper handling if someone calls compute_totals on Problem with different set or different order # of desvars/responses than were used to define the coloring. Behavior should be that coloring is turned off # and a warning is issued. msg = "compute_totals called using a different list of design vars and/or responses than those used " \ "to define coloring, so coloring will be turned off.\ncoloring design vars: " \ "['indeps.x', 'indeps.y', 'indeps.r'], current design vars: ['indeps.x', 'indeps.y', 'indeps.r']\n" \ "coloring responses: ['circle.area', 'r_con.g', 'theta_con.g', 'delta_theta_con.g', 'l_conx.g'], " \ "current responses: ['delta_theta_con.g', 'circle.area', 'r_con.g', 'theta_con.g', 'l_conx.g']." with assert_warning(UserWarning, msg): p_color.compute_totals(of=['delta_theta_con.g', 'circle.area', 'r_con.g', 'theta_con.g', 'l_conx.g'], wrt=['x', 'y', 'r'])
def test_err_on_maxiter_deprecated(self): # Raise AnalysisError when it fails to converge prob = om.Problem() nlsolver = om.NewtonSolver() prob.model = SellarDerivatives(nonlinear_solver=nlsolver, linear_solver=om.LinearBlockGS()) nlsolver.options['err_on_maxiter'] = True nlsolver.options['maxiter'] = 1 prob.setup() prob.set_solver_print(level=0) msg = "The 'err_on_maxiter' option provides backwards compatibility " + \ "with earlier version of OpenMDAO; use options['err_on_non_converge'] " + \ "instead." #prob.final_setup() with assert_warning(DeprecationWarning, msg): prob.final_setup() with self.assertRaises(om.AnalysisError) as context: prob.run_model() msg = "Solver 'NL: Newton' on system '' failed to converge in 1 iterations." self.assertEqual(str(context.exception), msg)
def test_compute_and_list(self): prob = om.Problem(RectangleGroup()) prob.setup() # list explicit outputs outputs = prob.model.list_outputs(implicit=False, out_stream=None) expected = { 'comp1.area': {'val': np.array([1.])}, 'comp2.area': {'val': np.array([1.])} } self.assertEqual(dict(outputs), expected) # list states states = prob.model.list_outputs(explicit=False, out_stream=None) self.assertEqual(states, []) prob.set_val('length', 3.) prob.set_val('width', 2.) with assert_warning(UserWarning, "'comp2' <class RectangleJacVec>: matrix free component has declared the following partials: [('comp2.area', 'comp2.length'), ('comp2.area', 'comp2.width')], which will allocate (possibly unnecessary) memory for each of those sub-jacobians."): prob.run_model() assert_near_equal(prob['comp1.area'], 6.) assert_near_equal(prob['comp2.area'], 6.) # total derivs total_derivs = prob.compute_totals( wrt=['length', 'width'], of=['comp1.area', 'comp2.area'] ) assert_near_equal(total_derivs['comp1.area', 'length'], [[2.]]) assert_near_equal(total_derivs['comp2.area', 'length'], [[2.]]) assert_near_equal(total_derivs['comp1.area', 'width'], [[3.]]) assert_near_equal(total_derivs['comp2.area', 'width'], [[3.]]) # list inputs inputs = prob.model.list_inputs(out_stream=None) self.assertEqual(sorted(inputs), [ ('comp1.length', {'val': [3.]}), ('comp1.width', {'val': [2.]}), ('comp2.length', {'val': [3.]}), ('comp2.width', {'val': [2.]}), ]) # list explicit outputs outputs = prob.model.list_outputs(implicit=False, out_stream=None) self.assertEqual(sorted(outputs), [ ('comp1.area', {'val': [6.]}), ('comp2.area', {'val': [6.]}), ]) # list states states = prob.model.list_outputs(explicit=False, out_stream=None) self.assertEqual(states, []) # list excluding both explicit and implicit components raises error msg = "You have excluded both Explicit and Implicit components." with self.assertRaisesRegex(RuntimeError, msg): prob.model.list_outputs(explicit=False, implicit=False)
def test_total_no_mpi(self): msg = "Group (<model>): MPI is not active but num_par_fd = 3. No parallel finite difference will be performed." with assert_warning(UserWarning, msg): _setup_problem(self.mat, total_method='fd', total_num_par_fd=3, approx_totals=True)
def test_return_metadata_value_deprecation(self): prob = Problem() idv = prob.model.add_subsystem('idv', IndepVarComp()) meta = idv.add_output('x', 1.0) msg = ("The metadata key 'value' will be deprecated in 4.0. Please use 'val'.") with assert_warning(OMDeprecationWarning, msg): meta['value']
def test_range_partials(self): class RangePartialsComp(ExplicitComponent): def __init__(self, size=4): super().__init__() self.size = size def setup(self): # verify that both iterable and array types are valid # for val and src_indices arguments to add_input self.add_input('v1', val=range(self.size), src_indices=range(self.size)) self.add_input('v2', val=2 * np.ones(self.size), src_indices=np.array(range(self.size))) # verify that both iterable and array types are valid # for val, upper and lower arguments to add_output self.add_output('vSum', val=range(self.size), lower=np.zeros(self.size), upper=range(self.size)) self.add_output('vProd', val=np.zeros(self.size), lower=range(self.size), upper=np.ones(self.size)) # verify that both iterable and list types are valid # for rows and cols arguments to declare_partials rows = range(self.size) cols = list(range(self.size)) self.declare_partials(of='vProd', wrt='v1', val=np.ones(self.size), rows=rows, cols=cols) def compute(self, inputs, outputs): outputs['vSum'] = inputs['v1'] + inputs['v2'] outputs['vProd'] = inputs['v1'] * inputs['v2'] comp = RangePartialsComp() prob = Problem(model=comp) with assert_warning( OMDeprecationWarning, f"<model> <class RangePartialsComp>: Passing `src_indices` as an arg to `add_input` is" "deprecated and will become an error in a future release. Add " "`src_indices` to a `promotes` or `connect` call instead."): prob.setup() prob.run_model() assert_near_equal(prob['vSum'], np.array([2., 3., 4., 5.]), 0.00001) assert_near_equal(prob['vProd'], np.array([0., 2., 4., 6.]), 0.00001)
def test_missing_state_warning(self): # Testing Broyden on a 5 state case split among 3 vars. prob = Problem() model = prob.model model.add_subsystem('p1', IndepVarComp('c', 0.01)) model.add_subsystem('mixed', MixedEquation()) model.connect('p1.c', 'mixed.c') model.nonlinear_solver = BroydenSolver() model.nonlinear_solver.options['state_vars'] = ['mixed.x12'] model.nonlinear_solver.options['maxiter'] = 15 model.nonlinear_solver.options['compute_jacobian'] = False prob.setup(check=False) msg = "The following states are not covered by a solver, and may have been " \ "omitted from the BroydenSolver 'state_vars': mixed.x3, mixed.x45" with assert_warning(UserWarning, msg): prob.run_model() # Try again with promoted names. prob = Problem() model = prob.model model.add_subsystem('p1', IndepVarComp('c', 0.01)) model.add_subsystem('mixed', MixedEquation(), promotes=['*']) model.connect('p1.c', 'c') model.nonlinear_solver = BroydenSolver() model.nonlinear_solver.options['state_vars'] = ['x12'] model.nonlinear_solver.options['maxiter'] = 15 model.nonlinear_solver.options['compute_jacobian'] = False prob.setup(check=False) msg = "The following states are not covered by a solver, and may have been " \ "omitted from the BroydenSolver 'state_vars': x3, x45" with assert_warning(UserWarning, msg): prob.run_model()
def test_missing_state_warning(self): # Testing Broyden on a 5 state case split among 3 vars. prob = Problem() model = prob.model model.add_subsystem('p1', IndepVarComp('c', 0.01)) model.add_subsystem('mixed', MixedEquation()) model.connect('p1.c', 'mixed.c') model.nonlinear_solver = BroydenSolver() model.nonlinear_solver.options['state_vars'] = ['mixed.x12'] model.nonlinear_solver.options['maxiter'] = 15 model.nonlinear_solver.options['compute_jacobian'] = False prob.setup(check=False) msg = "The following states are not covered by a solver, and may have been " \ "omitted from the BroydenSolver 'state_vars': mixed.x3, mixed.x45" with assert_warning(UserWarning, msg): prob.run_model() # Try again with promoted names. prob = Problem() model = prob.model model.add_subsystem('p1', IndepVarComp('c', 0.01)) model.add_subsystem('mixed', MixedEquation(), promotes=['*']) model.connect('p1.c', 'c') model.nonlinear_solver = BroydenSolver() model.nonlinear_solver.options['state_vars'] = ['x12'] model.nonlinear_solver.options['maxiter'] = 15 model.nonlinear_solver.options['compute_jacobian'] = False prob.setup(check=False) msg = "The following states are not covered by a solver, and may have been " \ "omitted from the BroydenSolver 'state_vars': x3, x45" with assert_warning(UserWarning, msg): prob.run_model()
def test_deprecated_runonce(self): p = Problem() p.model.add_subsystem('indep', IndepVarComp('x', 5.0)) p.model.add_subsystem('comp', ExecComp('b=2*a')) msg = "NonLinearRunOnce is deprecated. Use NonlinearRunOnce instead." with assert_warning(DeprecationWarning, msg): p.model.nonlinear_solver = NonLinearRunOnce()
def test_deprecated_runonce(self): p = Problem() p.model.add_subsystem('indep', IndepVarComp('x', 5.0)) p.model.add_subsystem('comp', ExecComp('b=2*a')) msg = "NonLinearRunOnce is deprecated. Use NonlinearRunOnce instead." with assert_warning(DeprecationWarning, msg): p.model.nonlinear_solver = NonLinearRunOnce()
def test_viewer_data_from_subgroup(self): """ Test error message when asking for viewer data for a subgroup. """ p = om.Problem(model=SellarStateConnection()) p.setup() msg = "Viewer data is not available for sub-Group 'sub'." with assert_warning(UserWarning, msg): _get_viewer_data(p.model.sub)
def test_value_getitem_deprecation(self): comp = TestExplCompSimple() prob = Problem(comp).setup() # check optional metadata (desc) msg = ("The metadata key 'value' will be deprecated in 4.0. Please use 'val'.") prob.setup() with assert_warning(OMDeprecationWarning, msg): comp._var_rel2meta['length']['value']
def test_add_unitless_input(self): prob = Problem(model=Group()) prob.model.add_subsystem('C1', ExecComp('y=x', x={'units': 'unitless'})) msg = "Input 'x' has units='unitless' but 'unitless' has been deprecated. " \ "Use units=None instead. Note that connecting a unitless variable to " \ "one with units is no longer an error, but will issue a warning instead." with assert_warning(DeprecationWarning, msg): prob.setup(check=False)
def test_linsearch_3_deprecation(self): 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.' with assert_warning(DeprecationWarning, msg): prob.final_setup()
def test_group_add(self): model = Group() ecomp = ExecComp('b=2.0*a', a=3.0, b=6.0) msg = "The 'add' method provides backwards compatibility with OpenMDAO <= 1.x ; " \ "use 'add_subsystem' instead." with assert_warning(DeprecationWarning, msg): comp1 = model.add('comp1', ecomp) self.assertTrue(ecomp is comp1)
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']
def test_incompatible_units(self): """Test error handling when only one of src and tgt have units.""" prob = Problem(model=Group()) prob.model.add_subsystem('px1', IndepVarComp('x1', 100.0), promotes_outputs=['x1']) prob.model.add_subsystem('src', SrcComp(), promotes_inputs=['x1']) prob.model.add_subsystem('tgt', ExecComp('yy=xx', xx={'value': 0.0, 'units': 'unitless'})) prob.model.connect('src.x2', 'tgt.xx') msg = "Output 'src.x2' with units of 'degC' is connected to input 'tgt.xx' which has no units." with assert_warning(UserWarning, msg): prob.setup()
def test_connect_units_with_unitless(self): prob = Problem(Group()) prob.model.add_subsystem('px1', IndepVarComp('x1', 100.0)) prob.model.add_subsystem('src', ExecComp('x2 = 2 * x1', x2={'units': 'degC'})) prob.model.add_subsystem('tgt', ExecComp('y = 3 * x', x={'units': 'unitless'})) prob.model.connect('px1.x1', 'src.x1') prob.model.connect('src.x2', 'tgt.x') msg = "Output 'src.x2' with units of 'degC' is connected " \ "to input 'tgt.x' which has no units." with assert_warning(UserWarning, msg): prob.setup(check=False)
def test_line_search_deprecated(self): top = Problem() top.model.add_subsystem('px', IndepVarComp('x', 1.0)) top.model.add_subsystem('comp', ImplCompTwoStates()) top.model.connect('px.x', 'comp.x') top.model.nonlinear_solver = NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = ScipyKrylov() msg = "The 'line_search' attribute provides backwards compatibility with OpenMDAO 1.x ; " \ "use 'linesearch' instead." with assert_warning(DeprecationWarning, msg): top.model.nonlinear_solver.line_search = ArmijoGoldsteinLS(bound_enforcement='vector') with assert_warning(DeprecationWarning, msg): ls = top.model.nonlinear_solver.line_search ls.options['maxiter'] = 10 ls.options['alpha'] = 1.0 top.setup(check=False) # Test lower bound: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0.0 top['comp.z'] = 1.6 top.run_model() assert_rel_error(self, top['comp.z'], 1.5, 1e-8) # Test upper bound: should go to the upper bound and stall top['px.x'] = 0.5 top['comp.y'] = 0.0 top['comp.z'] = 2.4 top.run_model() assert_rel_error(self, top['comp.z'], 2.5, 1e-8)
def setUp(self): self.startdir = os.getcwd() self.tempdir = tempfile.mkdtemp(prefix='test_extcode-') os.chdir(self.tempdir) shutil.copy(os.path.join(DIRECTORY, 'extcode_example.py'), os.path.join(self.tempdir, 'extcode_example.py')) msg = "'ExternalCode' has been deprecated. Use 'ExternalCodeComp' instead." with assert_warning(DeprecationWarning, msg): self.extcode = DeprecatedExternalCodeForTesting() self.prob = Problem() self.prob.model.add_subsystem('extcode', self.extcode)
def test_isvalid_deprecated_type(self): msg = "In declaration of option 'even_test' the '_type' arg is deprecated. Use 'types' instead." with assert_warning(DeprecationWarning, msg): self.dict.declare('even_test', type_=int, check_valid=check_even) self.dict['even_test'] = 2 self.dict['even_test'] = 4 with self.assertRaises(ValueError) as context: self.dict['even_test'] = 3 expected_msg = "Option 'even_test' with value 3 is not an even number." self.assertEqual(expected_msg, str(context.exception))
def test_connect_units_with_nounits_prom(self): prob = Problem(Group()) prob.model.add_subsystem('px1', IndepVarComp('x', 100.0), promotes_outputs=['x']) prob.model.add_subsystem('src', ExecComp('y = 2 * x'), promotes=['x', 'y']) prob.model.add_subsystem('tgt', ExecComp('z = 3 * y', y={'units': 'degC'}), promotes=['y']) prob.set_solver_print(level=0) msg = "Input 'tgt.y' with units of 'degC' is " \ "connected to output 'src.y' which has no units." with assert_warning(UserWarning, msg): prob.setup(check=False) prob.run_model() assert_rel_error(self, prob['tgt.z'], 600.)
def test_connect_units_with_nounits(self): prob = Problem(Group()) prob.model.add_subsystem('px1', IndepVarComp('x1', 100.0)) prob.model.add_subsystem('src', ExecComp('x2 = 2 * x1')) prob.model.add_subsystem('tgt', ExecComp('y = 3 * x', x={'units': 'degC'})) prob.model.connect('px1.x1', 'src.x1') prob.model.connect('src.x2', 'tgt.x') prob.set_solver_print(level=0) msg = "Input 'tgt.x' with units of 'degC' is " \ "connected to output 'src.x2' which has no units." with assert_warning(UserWarning, msg): prob.setup(check=False) prob.run_model() assert_rel_error(self, prob['tgt.y'], 600.)
def test_deprecated_metadata(self): from openmdao.api import Problem, IndepVarComp from openmdao.test_suite.components.options_feature_vector import VectorDoublingComp prob = Problem() prob.model.add_subsystem('inputs', IndepVarComp('x', shape=3)) prob.model.add_subsystem('double', VectorDoublingComp()) msg = "The 'metadata' attribute provides backwards compatibility " \ "with earlier version of OpenMDAO; use 'options' instead." with assert_warning(DeprecationWarning, msg): prob.model.double.metadata['size'] = 3 prob.model.connect('inputs.x', 'double.x') prob.setup() prob['inputs.x'] = [1., 2., 3.] prob.run_model() assert_rel_error(self, prob['double.y'], [2., 4., 6.])
def test_multifi_meta_model_deprecated(self): # run same test as above, only with the deprecated component, # to ensure we get the warning and the correct answer. # self-contained, to be removed when class name goes away. from openmdao.components.multifi_meta_model_unstructured_comp import MultiFiMetaModel # deprecated msg = "'MultiFiMetaModel' component has been deprecated. Use 'MultiFiMetaModelUnStructuredComp' instead." with assert_warning(DeprecationWarning, msg): mm = MultiFiMetaModel(nfi=3) mm.add_input('x', 0.) mm.add_output('y', 0.) prob = Problem(Group()) prob.model.add_subsystem('mm', mm) prob.setup(check=False) self.assertEqual(mm.options['train:x'], None) self.assertEqual(mm.options['train:x_fi2'], None) self.assertEqual(mm.options['train:x_fi3'], None) self.assertEqual(mm.options['train:y'], None) self.assertEqual(mm.options['train:y_fi2'], None) self.assertEqual(mm.options['train:y_fi3'], None)
def test_distrib_idx_in_full_out(self): size = 11 p = Problem(model=Group()) top = p.model C1 = top.add_subsystem("C1", InOutArrayComp(size)) C2 = top.add_subsystem("C2", DistribInputComp(size)) top.connect('C1.outvec', 'C2.invec') msg = "The 'distributed' option is set to True for Component C2, " \ "but there is no distributed vector implementation (MPI/PETSc) " \ "available. The default non-distributed vectors will be used." with assert_warning(UserWarning, msg): p.setup(check=False) # Conclude setup but don't run model. p.final_setup() C1._inputs['invec'] = np.array(range(size, 0, -1), float) p.run_model() self.assertTrue(all(C2._outputs['outvec'] == np.array(range(size, 0, -1), float)*4))
def test_partial_no_mpi(self): msg = "'comp': MPI is not active but num_par_fd = 3. No parallel finite difference will be performed." with assert_warning(UserWarning, msg): _setup_problem(self.mat, partial_method='fd', partial_num_par_fd = 3)
def test_distrib_idx_in_full_out_deprecated(self): class DeprecatedDistribInputComp(ExplicitComponent): """Deprecated version of DistribInputComp, uses attribute instead of option.""" def __init__(self, arr_size=11): super(DeprecatedDistribInputComp, self).__init__() self.arr_size = arr_size self.distributed = True def compute(self, inputs, outputs): if MPI: self.comm.Allgatherv(inputs['invec']*2.0, [outputs['outvec'], self.sizes, self.offsets, MPI.DOUBLE]) else: outputs['outvec'] = inputs['invec'] * 2.0 def setup(self): comm = self.comm rank = comm.rank self.sizes, self.offsets = evenly_distrib_idxs(comm.size, self.arr_size) start = self.offsets[rank] end = start + self.sizes[rank] self.add_input('invec', np.ones(self.sizes[rank], float), src_indices=np.arange(start, end, dtype=int)) self.add_output('outvec', np.ones(self.arr_size, float), shape=np.int32(self.arr_size)) size = 11 p = Problem() top = p.model C1 = top.add_subsystem("C1", InOutArrayComp(size)) # check deprecation on setter & getter msg = "The 'distributed' property provides backwards compatibility " \ "with OpenMDAO <= 2.4.0 ; use the 'distributed' option instead." with assert_warning(DeprecationWarning, msg): C2 = top.add_subsystem("C2", DeprecatedDistribInputComp(size)) with assert_warning(DeprecationWarning, msg): C2.distributed # continue to make sure everything still works with the deprecation top.connect('C1.outvec', 'C2.invec') # Conclude setup but don't run model. msg = "The 'distributed' option is set to True for Component C2, " \ "but there is no distributed vector implementation (MPI/PETSc) " \ "available. The default non-distributed vectors will be used." if PETScVector is None: with assert_warning(UserWarning, msg): p.setup(check=False) else: p.setup(check=False) p.final_setup() C1._inputs['invec'] = np.array(range(size, 0, -1), float) p.run_model() self.assertTrue(all(C2._outputs['outvec'] == np.array(range(size, 0, -1), float)*4))