def test_solve_subsystems_basic(self): from openmdao.api import Problem, NewtonSolver, DirectSolver, ScipyKrylov from openmdao.test_suite.components.double_sellar import DoubleSellar prob = Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = NewtonSolver() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = DirectSolver() g2 = model.g2 g2.nonlinear_solver = NewtonSolver() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() model.nonlinear_solver.options['solve_subsystems'] = True prob.setup() prob.run_model() assert_rel_error(self, prob['g1.y1'], 0.64, .00001) assert_rel_error(self, prob['g1.y2'], 0.80, .00001) assert_rel_error(self, prob['g2.y1'], 0.64, .00001) assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
def test_inp_inp_promoted_w_explicit_src(self): p = Problem(model=Group()) root = p.model G1 = root.add_subsystem("G1", Group()) G2 = G1.add_subsystem("G2", Group(), promotes=['x']) G2.add_subsystem("C1", ExecComp('y=x*2.0')) G2.add_subsystem("C2", IndepVarComp('x', 1.0), promotes=['x']) G3 = root.add_subsystem("G3", Group()) G4 = G3.add_subsystem("G4", Group(), promotes=['x']) C3 = G4.add_subsystem("C3", ExecComp('y=x*2.0'), promotes=['x']) C4 = G4.add_subsystem("C4", ExecComp('y=x*2.0'), promotes=['x']) p.model.connect('G1.x', 'G3.x') p.setup(check=False) p.set_solver_print(level=0) # setting promoted name will set the value into the outputs, but will # not propagate it to the inputs. That will happen during run_model(). p['G1.x'] = 999. p.run_model() self.assertEqual(C3._inputs['x'], 999.) self.assertEqual(C4._inputs['x'], 999.)
def test_basic(self): prob = Problem() model = prob.model n_cp = 80 n_point = 160 t = np.linspace(0, 3.0*np.pi, n_cp) x = np.sin(t) model.add_subsystem('px', IndepVarComp('x', val=x)) model.add_subsystem('interp', BsplinesComp(num_control_points=n_cp, num_points=n_point, in_name='h_cp', out_name='h', distribution='uniform')) model.connect('px.x', 'interp.h_cp') prob.setup(check=False) prob.run_model() xx = prob['interp.h'].flatten() tt = np.linspace(0, 3.0*np.pi, n_point) x_expected = np.sin(tt) delta = xx - x_expected # Here we test that we don't have crazy interpolation error. self.assertLess(max(delta), .15) # And that it gets middle points a little better. self.assertLess(max(delta[15:-15]), .06)
def test_solve_subsystems_basic(self): prob = Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = NewtonSolver() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = DirectSolver(assemble_jac=True) g1.options['assembled_jac_type'] = 'dense' g2 = model.g2 g2.nonlinear_solver = NewtonSolver() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver(assemble_jac=True) g2.options['assembled_jac_type'] = 'dense' model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov(assemble_jac=True) model.options['assembled_jac_type'] = 'dense' model.nonlinear_solver.options['solve_subsystems'] = True prob.setup() prob.run_model() assert_rel_error(self, prob['g1.y1'], 0.64, .00001) assert_rel_error(self, prob['g1.y2'], 0.80, .00001) assert_rel_error(self, prob['g2.y1'], 0.64, .00001) assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
def test_specify_subgroup_solvers(self): from openmdao.api import Problem, NewtonSolver, ScipyKrylov, DirectSolver, NonlinearBlockGS, LinearBlockGS from openmdao.test_suite.components.double_sellar import DoubleSellar prob = Problem() model = prob.model = DoubleSellar() # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = NewtonSolver() g1.linear_solver = DirectSolver() # used for derivatives g2 = model.g2 g2.nonlinear_solver = NewtonSolver() g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NonlinearBlockGS(rtol=1.0e-5) model.linear_solver = ScipyKrylov() model.linear_solver.precon = LinearBlockGS() prob.setup() prob.run_model() assert_rel_error(self, prob['g1.y1'], 0.64, .00001) assert_rel_error(self, prob['g1.y2'], 0.80, .00001) assert_rel_error(self, prob['g2.y1'], 0.64, .00001) assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
def test_converge_diverge_groups(self): # Test derivatives for converge-diverge-groups topology. prob = Problem() model = prob.model = ConvergeDivergeGroups() model.linear_solver = LinearRunOnce() model.g1.linear_solver = LinearRunOnce() model.g1.g2.linear_solver = LinearRunOnce() model.g3.linear_solver = LinearRunOnce() prob.set_solver_print(level=0) prob.setup(check=False, mode='fwd') prob.run_model() wrt = ['iv.x'] of = ['c7.y1'] # Make sure value is fine. assert_rel_error(self, prob['c7.y1'], -102.7, 1e-6) J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') assert_rel_error(self, J['c7.y1', 'iv.x'][0][0], -40.75, 1e-6) prob.setup(check=False, mode='rev') prob.run_model() J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') assert_rel_error(self, J['c7.y1', 'iv.x'][0][0], -40.75, 1e-6)
def test_linear_system(self): """Check against the scipy solver.""" model = Group() x = np.array([1, 2, -3]) A = np.array([[5.0, -3.0, 2.0], [1.0, 7.0, -4.0], [1.0, 0.0, 8.0]]) b = A.dot(x) model.add_subsystem('p1', IndepVarComp('A', A)) model.add_subsystem('p2', IndepVarComp('b', b)) lingrp = model.add_subsystem('lingrp', Group(), promotes=['*']) lingrp.add_subsystem('lin', LinearSystemComp(size=3, partial_type="matrix_free")) model.connect('p1.A', 'lin.A') model.connect('p2.b', 'lin.b') prob = Problem(model) prob.setup() lingrp.linear_solver = ScipyKrylov() prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob['lin.x'], x, .0001) assert_rel_error(self, prob.model._residuals.get_norm(), 0.0, 1e-10)
def test_fan_in_grouped(self): prob = Problem() prob.model = FanInGrouped2() prob.setup(vector_class=PETScVector, check=False, mode='fwd') prob.set_solver_print(level=0) prob.run_model() indep_list = ['p1.x', 'p2.x'] unknown_list = ['c3.y'] assert_rel_error(self, prob['c3.y'], 29.0, 1e-6) J = prob.compute_totals(of=unknown_list, wrt=indep_list) assert_rel_error(self, J['c3.y', 'p1.x'][0][0], -6.0, 1e-6) assert_rel_error(self, J['c3.y', 'p2.x'][0][0], 35.0, 1e-6) assert_rel_error(self, prob['c3.y'], 29.0, 1e-6) prob.setup(vector_class=PETScVector, check=False, mode='rev') prob.run_model() assert_rel_error(self, prob['c3.y'], 29.0, 1e-6) J = prob.compute_totals(of=unknown_list, wrt=indep_list) assert_rel_error(self, J['c3.y', 'p1.x'][0][0], -6.0, 1e-6) assert_rel_error(self, J['c3.y', 'p2.x'][0][0], 35.0, 1e-6) assert_rel_error(self, prob['c3.y'], 29.0, 1e-6)
def test_setup_bug1(self): # This tests a bug where, if you run setup more than once on a derived component class, # the list of var names continually gets prepended with the component global path. class NewBase(Component): def __init__(self, **kwargs): super(NewBase, self).__init__(**kwargs) class MyComp(NewBase): def __init__(self, **kwargs): super(MyComp, self).__init__(**kwargs) def setup(self): self.add_input('x', val=0.0) self.add_output('y', val=0.0) prob = Problem() model = prob.model = Group() comp = model.add_subsystem('comp', MyComp()) prob.setup(check=False) self.assertEqual(comp._var_abs_names['input'], ['comp.x']) self.assertEqual(comp._var_abs_names['output'], ['comp.y']) prob.run_model() prob.setup(check=False) self.assertEqual(comp._var_abs_names['input'], ['comp.x']) self.assertEqual(comp._var_abs_names['output'], ['comp.y'])
def test_converge_diverge(self): prob = Problem() prob.model = ConvergeDiverge() prob.setup(vector_class=PETScVector, check=False, mode='fwd') prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob['c7.y1'], -102.7, 1e-6) indep_list = ['iv.x'] unknown_list = ['c7.y1'] J = prob.compute_totals(of=unknown_list, wrt=indep_list) assert_rel_error(self, J['c7.y1', 'iv.x'][0][0], -40.75, 1e-6) prob.setup(vector_class=PETScVector, check=False, mode='rev') prob.run_model() assert_rel_error(self, prob['c7.y1'], -102.7, 1e-6) J = prob.compute_totals(of=unknown_list, wrt=indep_list) assert_rel_error(self, J['c7.y1', 'iv.x'][0][0], -40.75, 1e-6) assert_rel_error(self, prob['c7.y1'], -102.7, 1e-6)
def test_fan_out_grouped(self): prob = Problem(FanOutGrouped()) of=['c2.y', "c3.y"] wrt=['iv.x'] prob.setup(vector_class=PETScVector, check=False, mode='fwd') prob.set_solver_print(level=0) prob.run_model() J = prob.compute_totals(of=['c2.y', "c3.y"], wrt=['iv.x']) assert_rel_error(self, J['c2.y', 'iv.x'][0][0], -6.0, 1e-6) assert_rel_error(self, J['c3.y', 'iv.x'][0][0], 15.0, 1e-6) assert_rel_error(self, prob['c2.y'], -6.0, 1e-6) assert_rel_error(self, prob['c3.y'], 15.0, 1e-6) prob.setup(vector_class=PETScVector, check=False, mode='rev') prob.run_model() J = prob.compute_totals(of=['c2.y', "c3.y"], wrt=['iv.x']) assert_rel_error(self, J['c2.y', 'iv.x'][0][0], -6.0, 1e-6) assert_rel_error(self, J['c3.y', 'iv.x'][0][0], 15.0, 1e-6) assert_rel_error(self, prob['c2.y'], -6.0, 1e-6) assert_rel_error(self, prob['c3.y'], 15.0, 1e-6)
def test_fan_in_grouped_feature(self): from openmdao.api import Problem, IndepVarComp, ParallelGroup, ExecComp, PETScVector prob = Problem() model = prob.model model.add_subsystem('p1', IndepVarComp('x', 1.0)) model.add_subsystem('p2', IndepVarComp('x', 1.0)) parallel = model.add_subsystem('parallel', ParallelGroup()) parallel.add_subsystem('c1', ExecComp(['y=-2.0*x'])) parallel.add_subsystem('c2', ExecComp(['y=5.0*x'])) model.add_subsystem('c3', 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") model.connect("p2.x", "parallel.c2.x") prob.setup(vector_class=PETScVector, check=False, mode='fwd') prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob['c3.y'], 29.0, 1e-6)
def test_diamond(self): prob = Problem() prob.model = Diamond() prob.setup(vector_class=PETScVector, check=False, mode='fwd') prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob['c4.y1'], 46.0, 1e-6) assert_rel_error(self, prob['c4.y2'], -93.0, 1e-6) indep_list = ['iv.x'] unknown_list = ['c4.y1', 'c4.y2'] J = prob.compute_totals(of=unknown_list, wrt=indep_list) assert_rel_error(self, J['c4.y1', 'iv.x'][0][0], 25, 1e-6) assert_rel_error(self, J['c4.y2', 'iv.x'][0][0], -40.5, 1e-6) prob.setup(vector_class=PETScVector, check=False, mode='rev') prob.run_model() assert_rel_error(self, prob['c4.y1'], 46.0, 1e-6) assert_rel_error(self, prob['c4.y2'], -93.0, 1e-6) J = prob.compute_totals(of=unknown_list, wrt=indep_list) assert_rel_error(self, J['c4.y1', 'iv.x'][0][0], 25, 1e-6) assert_rel_error(self, J['c4.y2', 'iv.x'][0][0], -40.5, 1e-6)
class TestDeprecatedExternalCode(unittest.TestCase): 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 tearDown(self): os.chdir(self.startdir) try: shutil.rmtree(self.tempdir) except OSError: pass def test_normal(self): self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out' ] self.extcode.options['external_input_files'] = ['extcode_example.py'] self.extcode.options['external_output_files'] = ['extcode.out'] self.prob.setup(check=True) self.prob.run_model()
def test_feature_simple(self): """Tests feature for adding a Scipy GMRES solver and calculating the derivatives.""" from openmdao.api import Problem, Group, IndepVarComp, ScipyKrylov from openmdao.test_suite.components.expl_comp_simple import TestExplCompSimpleDense # Tests derivatives on a simple comp that defines compute_jacvec. prob = Problem() model = prob.model model.add_subsystem('x_param', IndepVarComp('length', 3.0), promotes=['length']) model.add_subsystem('mycomp', TestExplCompSimpleDense(), promotes=['length', 'width', 'area']) model.linear_solver = ScipyKrylov() prob.set_solver_print(level=0) prob.setup(check=False, mode='fwd') prob['width'] = 2.0 prob.run_model() of = ['area'] wrt = ['length'] J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') assert_rel_error(self, J['area', 'length'][0][0], 2.0, 1e-6)
def runO(x): p = Problem() p.model.add_subsystem('hs', HeatSink(num_nodes=1)) p.setup(check=False) p['hs.fin_gap'] = x[0] p['hs.fin_w'] = x[1] p.run_model() def printstuff(): print('=============') print('V_in (m/s) : %f' %p['hs.V_in']) print('V_fin (m/s) : %f' %p['hs.V_fin']) print('Nu : %f' %p['hs.Nu']) print('Pr : %f' %p['hs.Pr']) print('Re : %f' %p['hs.Re']) print('fin height: %f' %p['hs.fin_h']) print('# of fins : %f' %p['hs.n_fins']) print('-------------') print('fin thickness (m): %f' % p['hs.fin_w']) print('fin gap (m): %f' % p['hs.fin_gap']) print('Volumetric Flow Rate (m^3/s): %f' % p['hs.V_dot']) print('Maximum thermal resistance (K/W): %f' %p['hs.R_max']) print('Actual total thermal resistance (K/W): %f' % p['hs.R_tot']) #print('Actual total thermal resistance1 (K/W): %f' % p['hs.R_tot1']) #print('h %f' % p['hs.h']) print('Pressure Drop (Pa): %f' % p['hs.dP']) print() printstuff() return np.array([p['hs.R_tot']*10000 + p['hs.dP']*1.4])
def test_rk_with_time_invariant(self): np.random.seed(1) indeps = IndepVarComp() rktest = RKTest(NTIME) indeps.add_output('yi', np.random.random((2, 3))) indeps.add_output('yv', np.random.random((2, NTIME))) indeps.add_output('x0', np.random.random((2,))) prob = Problem() prob.model.add_subsystem('indeps', indeps, promotes=['*']) prob.model.add_subsystem('rktest', rktest, promotes=['*']) prob.setup() prob.run_model() # check partials partials = prob.check_partials(out_stream=None) assert_check_partials(partials, atol=6e-5, rtol=6e-5) # check totals inputs = ['yi', 'yv', 'x0'] outputs = ['x'] J = prob.check_totals(of=outputs, wrt=inputs, out_stream=None) for outp in outputs: for inp in inputs: Jn = J[outp, inp]['J_fd'] Jf = J[outp, inp]['J_fwd'] diff = abs(Jf - Jn) assert_rel_error(self, diff.max(), 0.0, 6e-5)
def test_globaljac_err(self): prob = Problem() model = prob.model = Group() model.add_subsystem('x_param', IndepVarComp('length', 3.0), promotes=['length']) model.add_subsystem('mycomp', TestExplCompSimpleDense(), promotes=['length', 'width', 'area']) model.linear_solver = LinearBlockJac() prob.set_solver_print(level=0) prob.model.jacobian = AssembledJacobian() prob.setup(check=False, mode='fwd') prob['width'] = 2.0 prob.run_model() of = ['area'] wrt = ['length'] with self.assertRaises(RuntimeError) as context: prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') self.assertEqual(str(context.exception), "A block linear solver 'LN: LNBJ' is being used with" " an AssembledJacobian in system ''")
def test_specify_solver(self): import numpy as np from openmdao.api import Problem, Group, IndepVarComp, ExecComp, LinearBlockJac, NonlinearBlockGS from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives prob = Problem() model = prob.model = Group() model.add_subsystem('px', IndepVarComp('x', 1.0), promotes=['x']) model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2']) model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2']) model.add_subsystem('obj_cmp', ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0), promotes=['obj', 'x', 'z', 'y1', 'y2']) model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) model.nonlinear_solver = NonlinearBlockGS() model.linear_solver = LinearBlockJac() prob.setup() prob.run_model() wrt = ['z'] of = ['obj'] J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') assert_rel_error(self, J['obj', 'z'][0][0], 9.61001056, .00001) assert_rel_error(self, J['obj', 'z'][0][1], 1.78448534, .00001)
def test_rhs_val(self): """ Test solution with a default RHS value and no connected RHS variable. """ n = 1 prob = Problem(model=Group(assembled_jac_type='dense')) bal = BalanceComp('x', rhs_val=4.0) exec_comp = ExecComp('y=x**2', x={'value': 1}, y={'value': 1}) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=bal) prob.model.connect('balance.x', 'exec.x') prob.model.connect('exec.y', 'balance.lhs:x') prob.model.linear_solver = DirectSolver(assemble_jac=True) prob.model.nonlinear_solver = NewtonSolver(maxiter=100, iprint=0) prob.setup() prob['balance.x'] = np.random.rand(n) prob.run_model() assert_almost_equal(prob['balance.x'], 2.0, decimal=7) cpd = prob.check_partials(out_stream=None) for (of, wrt) in cpd['balance']: assert_almost_equal(cpd['balance'][of, wrt]['abs error'], 0.0, decimal=5)
def test_feature_scalar_with_default_mult(self): from numpy.testing import assert_almost_equal from openmdao.api import Problem, Group, IndepVarComp, ExecComp, NewtonSolver, \ DirectSolver, BalanceComp prob = Problem() bal = BalanceComp() bal.add_balance('x', use_mult=True, mult_val=2.0) tgt = IndepVarComp(name='y_tgt', val=4) exec_comp = ExecComp('y=x**2', x={'value': 1}, y={'value': 1}) prob.model.add_subsystem(name='target', subsys=tgt, promotes_outputs=['y_tgt']) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=bal) prob.model.connect('y_tgt', 'balance.rhs:x') prob.model.connect('balance.x', 'exec.x') prob.model.connect('exec.y', 'balance.lhs:x') prob.model.linear_solver = DirectSolver(assemble_jac=True) prob.model.nonlinear_solver = NewtonSolver(maxiter=100, iprint=0) prob.setup(check=False) # A reasonable initial guess to find the positive root. prob['balance.x'] = 1.0 prob.run_model() assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)
def test_create_on_init_no_normalization(self): prob = Problem(model=Group()) bal = BalanceComp('x', val=1.0, normalize=False) tgt = IndepVarComp(name='y_tgt', val=1.5) exec_comp = ExecComp('y=x**2') prob.model.add_subsystem(name='target', subsys=tgt, promotes_outputs=['y_tgt']) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=bal) prob.model.connect('y_tgt', 'balance.rhs:x') prob.model.connect('balance.x', 'exec.x') prob.model.connect('exec.y', 'balance.lhs:x') prob.model.linear_solver = DirectSolver() prob.model.nonlinear_solver = NewtonSolver(iprint=0) prob.setup() prob.run_model() assert_almost_equal(prob['balance.x'], np.sqrt(1.5), decimal=7) assert_almost_equal(prob.model.balance._scale_factor, 1.0) cpd = prob.check_partials(out_stream=None) for (of, wrt) in cpd['balance']: assert_almost_equal(cpd['balance'][of, wrt]['abs error'], 0.0, decimal=5)
def test_noncontiguous_idxs(self): # take even input indices in 0 rank and odd ones in 1 rank size = 11 p = Problem(model=Group()) top = p.model C1 = top.add_subsystem("C1", InOutArrayComp(size)) C2 = top.add_subsystem("C2", DistribNoncontiguousComp(size)) C3 = top.add_subsystem("C3", DistribGatherComp(size)) top.connect('C1.outvec', 'C2.invec') top.connect('C2.outvec', 'C3.invec') p.setup(check=False) # Conclude setup but don't run model. p.final_setup() C1._inputs['invec'] = np.array(range(size), float) p.run_model() if MPI: if self.comm.rank == 0: self.assertTrue(all(C2._outputs['outvec'] == np.array(list(take_nth(0, 2, range(size))), 'f')*4)) else: self.assertTrue(all(C2._outputs['outvec'] == np.array(list(take_nth(1, 2, range(size))), 'f')*4)) full_list = list(take_nth(0, 2, range(size))) + list(take_nth(1, 2, range(size))) self.assertTrue(all(C3._outputs['outvec'] == np.array(full_list, 'f')*4)) else: self.assertTrue(all(C2._outputs['outvec'] == C1._outputs['outvec']*2.)) self.assertTrue(all(C3._outputs['outvec'] == C2._outputs['outvec']))
def test_obj_pass(self): prob = Problem() model = prob.model indep = model.add_subsystem('indep', IndepVarComp(), promotes_outputs=['x']) indep.add_discrete_output('x', _DiscreteVal(19)) G = model.add_subsystem('G', ParallelGroup(), promotes_inputs=['x']) G1 = G.add_subsystem('G1', Group(), promotes_inputs=['x'], promotes_outputs=['y']) G1.add_subsystem('C1_1', ObjAdderCompEx(_DiscreteVal(5)), promotes_inputs=['x']) G1.add_subsystem('C1_2', ObjAdderCompEx(_DiscreteVal(7)), promotes_outputs=['y']) G1.connect('C1_1.y', 'C1_2.x') G2 = G.add_subsystem('G2', Group(), promotes_inputs=['x']) G2.add_subsystem('C2_1', ObjAdderCompEx(_DiscreteVal(1)), promotes_inputs=['x']) G2.add_subsystem('C2_2', ObjAdderCompEx(_DiscreteVal(11)), promotes_outputs=['y']) G2.connect('C2_1.y', 'C2_2.x') model.add_subsystem('C3', ObjAdderCompEx(_DiscreteVal(9))) model.add_subsystem('C4', ObjAdderCompEx(_DiscreteVal(21))) model.connect('G.y', 'C3.x') model.connect('G.G2.y', 'C4.x') prob.setup() prob.run_model() self.assertEqual(prob['C3.y'].getval(), 40) self.assertEqual(prob['C4.y'].getval(), 52)
def test_implicit_cycle_precon(self): prob = Problem() model = prob.model = Group() model.add_subsystem('p1', IndepVarComp('x', 1.0)) model.add_subsystem('d1', SellarImplicitDis1()) model.add_subsystem('d2', SellarImplicitDis2()) model.connect('d1.y1', 'd2.y1') model.connect('d2.y2', 'd1.y2') model.nonlinear_solver = NewtonSolver() model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.linesearch = BoundsEnforceLS() model.linear_solver = ScipyKrylov() model.linear_solver.precon = self.linear_solver_class() prob.setup(check=False) prob['d1.y1'] = 4.0 prob.set_solver_print() prob.run_model() res = model._residuals.get_norm() # Newton is kinda slow on this for some reason, this is how far it gets with directsolver too. self.assertLess(res, 2.0e-2)
def test_scaling(self): # Make sure values are unscaled/dimensional. def custom_method(d_outputs, d_residuals, mode): if d_outputs['out_var'][0] != 12.0: raise ValueError('This value should be unscaled.') return False, 0, 0 class ScaledComp(ImplicitComponent): def setup(self): self.add_input('a', val=10., units='m') self.add_output('states', val=20.0, ref=3333.0) self.add_output('out_var', val=20.0, ref=12.0) p = Problem() p.model.add_subsystem('des_vars', IndepVarComp('a', val=10., units='m'), promotes=['*']) p.model.add_subsystem('icomp', ScaledComp(), promotes=['*']) model = p.model model.linear_solver = LinearUserDefined(custom_method) p.setup(vector_class=PETScVector, mode='rev', check=False) p.run_model() jac = p.compute_totals(of=['out_var'], wrt=['a'], return_format='dict')
def test_detailed(self): """ This is a longer version of the previous method, with plotting. """ # Load in default lifting surfaces to setup the comparison surfaces = get_default_surfaces() # Instantiate an OpenMDAO problem and add the component we want to test # as asubsystem, giving that component a default lifting surface prob = Problem() prob.model.add_subsystem('tube', SectionPropertiesTube(surface=surfaces[0])) # Set up the problem and ensure it uses complex arrays so we can check # the derivatives using complex step prob.setup(force_alloc_complex=True) # Actually run the model, which is just a component in this case, then # check the derivatives and store the results in the `check` dict prob.run_model() check = prob.check_partials(compact_print=False) # Loop through this `check` dictionary and visualize the approximated # and computed derivatives for key, subjac in iteritems(check[list(check.keys())[0]]): print() print(key) view_mat(subjac['J_fd'],subjac['J_fwd'],key) # Loop through the `check` dictionary and perform assert that the # approximated deriv must be very close to the computed deriv for key, subjac in iteritems(check[list(check.keys())[0]]): if subjac['magnitude'].fd > 1e-6: assert_almost_equal( subjac['rel error'].forward, 0., err_msg='deriv of %s wrt %s' % key) assert_almost_equal( subjac['rel error'].reverse, 0., err_msg='deriv of %s wrt %s' % key)
def test_overlapping_inputs_idxs(self): # distrib comp with src_indices that overlap, i.e. the same # entries are distributed to multiple processes size = 11 p = Problem(model=Group()) top = p.model C1 = top.add_subsystem("C1", InOutArrayComp(size)) C2 = top.add_subsystem("C2", DistribOverlappingInputComp(size)) top.connect('C1.outvec', 'C2.invec') 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'][:4] == np.array(range(size, 0, -1), float)[:4]*4)) self.assertTrue(all(C2._outputs['outvec'][8:] == np.array(range(size, 0, -1), float)[8:]*4)) # overlapping part should be double size of the rest self.assertTrue(all(C2._outputs['outvec'][4:8] == np.array(range(size, 0, -1), float)[4:8]*8))
def test_feature_atol(self): import numpy as np from openmdao.api import Problem, Group, IndepVarComp, NewtonSolver, LinearBlockGS, ExecComp, DirectSolver from openmdao.test_suite.components.sellar import SellarDis1withDerivatives, SellarDis2withDerivatives prob = Problem() model = prob.model model.add_subsystem('px', IndepVarComp('x', 1.0), promotes=['x']) model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2']) model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2']) model.add_subsystem('obj_cmp', ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0), promotes=['obj', 'x', 'z', 'y1', 'y2']) model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) model.linear_solver = DirectSolver() nlgbs = model.nonlinear_solver = NewtonSolver() nlgbs.options['atol'] = 1e-4 prob.setup() prob.run_model() assert_rel_error(self, prob['y1'], 25.5882856302, .00001) assert_rel_error(self, prob['y2'], 12.05848819, .00001)
def test_shape(self): n = 100 bal = BalanceComp() bal.add_balance('x', shape=(n,)) tgt = IndepVarComp(name='y_tgt', val=4*np.ones(n)) exe = ExecComp('y=x**2', x=np.zeros(n), y=np.zeros(n)) model = Group() model.add_subsystem('tgt', tgt, promotes_outputs=['y_tgt']) model.add_subsystem('exe', exe) model.add_subsystem('bal', bal) model.connect('y_tgt', 'bal.rhs:x') model.connect('bal.x', 'exe.x') model.connect('exe.y', 'bal.lhs:x') model.linear_solver = DirectSolver(assemble_jac=True) model.nonlinear_solver = NewtonSolver(maxiter=100, iprint=0) prob = Problem(model) prob.setup() prob['bal.x'] = np.random.rand(n) prob.run_model() assert_almost_equal(prob['bal.x'], 2.0*np.ones(n), decimal=7)
def main(): interp = ViternaAirfoil().create_akima('mh117', Re_scaling=False, extend_alpha=True) def ccblade_interp(alpha, Re, Mach): shape = alpha.shape x = np.concatenate( [alpha.flatten()[:, np.newaxis], Re.flatten()[:, np.newaxis]], axis=-1) y = interp(x) y.shape = shape + (2, ) return y[..., 0], y[..., 1] num_nodes = 1 num_blades = 3 num_radial = 15 num_cp = 6 chord = 10. theta = np.linspace(65., 25., num_cp) * np.pi / 180. pitch = 0. hub_diameter = 30. # cm prop_diameter = 150. # cm c0 = np.sqrt(1.4 * 287.058 * 300.) # meters/second rho0 = 1.4 * 98600. / (c0 * c0) # kg/m^3 omega = 236. prob = Problem() comp = IndepVarComp() comp.add_discrete_input('B', val=num_blades) comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3') comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s') comp.add_output('asound', val=c0, shape=num_nodes, units='m/s') comp.add_output('v', val=77.2, shape=num_nodes, units='m/s') comp.add_output('alpha', val=0., shape=num_nodes, units='rad') comp.add_output('incidence', val=0., shape=num_nodes, units='rad') comp.add_output('precone', val=0., units='deg') comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s') comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm') comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm') comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad') comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm') comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad') prob.model.add_subsystem('inputs_comp', comp, promotes=['*']) comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp, num_radial=num_radial) prob.model.add_subsystem( 'geometry_group', comp, promotes_inputs=[ 'hub_diameter', 'prop_diameter', 'chord_dv', 'theta_dv', 'pitch' ], promotes_outputs=['radii', 'dradii', 'chord', 'theta']) comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial, airfoil_interp=ccblade_interp, turbine=False, phi_residual_solve_nonlinear=False) prob.model.add_subsystem('ccblade_group', comp, promotes_inputs=[ 'B', 'radii', 'dradii', 'chord', 'theta', 'rho', 'mu', 'asound', 'v', 'precone', 'omega', 'hub_diameter', 'prop_diameter' ], promotes_outputs=[('Np', 'ccblade_normal_load'), ('Tp', 'ccblade_circum_load')]) prob.setup() prob.final_setup() eps = 1e-2 num_phi = 45 phi = np.linspace(-0.5 * np.pi + eps, 0.0 - eps, num_phi) phi = np.tile(phi[:, np.newaxis, np.newaxis], (1, num_nodes, num_radial)) phi_residual = np.zeros_like(phi) for i in range(num_phi): p = phi[i, :, :] prob.set_val('ccblade_group.ccblade_comp.phi', p, units='rad') prob.run_model() prob.model.run_apply_nonlinear() inputs, outputs, residuals = prob.model.get_nonlinear_vectors() phi_residual[i, :, :] = residuals['ccblade_group.ccblade_comp.phi'] make_individual_plots(prob, phi, phi_residual, 'phi_residual-r{:02d}.png')
def test_simple(self): prob = Problem(RectangleComp()) prob.setup(check=False) prob.run_model()
def support_design_model(self, TIs, depths): # Redefine method in subclass of AbstractSupportStructureDesign with specific model that has same inputs and outputs. pass if __name__ == '__main__': from openmdao.api import Problem, Group, IndepVarComp class TeamPlay(AbstractSupportStructureDesign): def compute(self, inputs, outputs): TI = inputs['TI'] depth = inputs['depth'] outputs['cost_support'] = TI * depth**3.0 model = Group() ivc = IndepVarComp() ivc.add_output('TI', 0.12) ivc.add_output('depth', 14.0) model.add_subsystem('indep', ivc) model.add_subsystem('teamplay', TeamPlay()) model.connect('indep.TI', 'teamplay.TI') model.connect('indep.depth', 'teamplay.depth') prob = Problem(model) prob.setup() prob.run_model() print(prob['teamplay.cost_support'])
def test_fan_out_grouped(self): size = 3 prob = Problem() prob.model = root = Group() root.add_subsystem('P', IndepVarComp('x', numpy.ones(size, dtype=float))) root.add_subsystem( 'C1', DistribExecComp(['y=3.0*x', 'y=2.0*x'], arr_size=size, x=numpy.zeros(size, dtype=float), y=numpy.zeros(size, dtype=float))) sub = root.add_subsystem('sub', ParallelGroup()) sub.add_subsystem( 'C2', ExecComp('y=1.5*x', x=numpy.zeros(size), y=numpy.zeros(size))) sub.add_subsystem( 'C3', ExecComp(['y=5.0*x'], x=numpy.zeros(size, dtype=float), y=numpy.zeros(size, dtype=float))) root.add_subsystem( 'C2', ExecComp(['y=x'], x=numpy.zeros(size, dtype=float), y=numpy.zeros(size, dtype=float))) root.add_subsystem( 'C3', ExecComp(['y=x'], x=numpy.zeros(size, dtype=float), y=numpy.zeros(size, dtype=float))) root.connect('sub.C2.y', 'C2.x') root.connect('sub.C3.y', 'C3.x') root.connect("C1.y", "sub.C2.x") root.connect("C1.y", "sub.C3.x") root.connect("P.x", "C1.x") prob.setup(check=False, mode='fwd') prob.run_model() diag1 = [4.5, 4.5, 3.0] diag2 = [15.0, 15.0, 10.0] assert_rel_error(self, prob['C2.y'], diag1) assert_rel_error(self, prob['C3.y'], diag2) diag1 = numpy.diag(diag1) diag2 = numpy.diag(diag2) J = prob.compute_totals(of=['C2.y', "C3.y"], wrt=['P.x']) assert_rel_error(self, J['C2.y', 'P.x'], diag1, 1e-6) assert_rel_error(self, J['C3.y', 'P.x'], diag2, 1e-6) prob.setup(check=False, mode='rev') prob.run_model() J = prob.compute_totals(of=['C2.y', "C3.y"], wrt=['P.x']) assert_rel_error(self, J['C2.y', 'P.x'], diag1, 1e-6) assert_rel_error(self, J['C3.y', 'P.x'], diag2, 1e-6)
def test(self): p = Problem() p.model = Group() p.model.add_subsystem('c1', IndepVarComp('x', 1.0), promotes_outputs=['x']) p.model.add_subsystem('c2', ReconfComp(), promotes_inputs=['x'], promotes_outputs=['y']) p.model.add_subsystem('c3', Comp(), promotes_inputs=['x'], promotes_outputs=['z']) # First run the usual setup method on Problem; size of y = 1 p.setup() p['x'] = 2 p.run_model() totals = p.compute_totals(wrt=['x'], of=['y']) assert_rel_error(self, p['x'], 2.0) assert_rel_error(self, p['y'], 4.0) assert_rel_error(self, p['z'], 6.0) assert_rel_error(self, totals['y', 'x'], [[2.0]]) # Now run the setup method on the root system; size of y = 2 p.model.resetup() p['x'] = 3 p.run_model() totals = p.compute_totals(wrt=['x'], of=['y']) assert_rel_error(self, p['x'], 3.0) assert_rel_error(self, p['y'], 6.0 * np.ones(2)) assert_rel_error(self, p['z'], 9.0) assert_rel_error(self, totals['y', 'x'], 2.0 * np.ones((2, 1))) # Now reconfigure from c2 and update in root; size of y = 3; the value of x is preserved p.model.get_subsystem('c2').resetup('reconf') p.model.resetup('update') p.run_model() totals = p.compute_totals(wrt=['x'], of=['y']) assert_rel_error(self, p['x'], 3.0) assert_rel_error(self, p['y'], 6.0 * np.ones(3)) assert_rel_error(self, p['z'], 9.0) assert_rel_error(self, totals['y', 'x'], 2.0 * np.ones((3, 1))) # Now reconfigure from c3 and update in root; size of y = 3; the value of x is preserved p.model.get_subsystem('c3').resetup('reconf') p.model.resetup('update') p.run_model() totals = p.compute_totals(wrt=['x'], of=['y']) assert_rel_error(self, p['x'], 3.0) assert_rel_error(self, p['y'], 6.0 * np.ones(3)) assert_rel_error(self, p['z'], 9.0) assert_rel_error(self, totals['y', 'x'], 2.0 * np.ones((3, 1))) # Finally, setup reconf from root; size of y = 4 # Since we are at the root, calling setup('full') and setup('reconf') have the same effect. # In both cases, variable values are lost so we have to set x=3 again. p.model.resetup('reconf') p['x'] = 3 p.run_model() totals = p.compute_totals(wrt=['x'], of=['y']) assert_rel_error(self, p['x'], 3.0) assert_rel_error(self, p['y'], 6.0 * np.ones(4)) assert_rel_error(self, p['z'], 9.0) assert_rel_error(self, totals['y', 'x'], 2.0 * np.ones((4, 1)))
def test_distribcomp_feature(self): import numpy as np from openmdao.api import Problem, ExplicitComponent, Group, IndepVarComp from openmdao.utils.mpi import MPI from openmdao.utils.array_utils import evenly_distrib_idxs if not MPI: raise unittest.SkipTest() rank = MPI.COMM_WORLD.rank size = 15 class DistribComp(ExplicitComponent): def __init__(self, size): super(DistribComp, self).__init__() self.size = size self.options['distributed'] = True def compute(self, inputs, outputs): if self.comm.rank == 0: outputs['outvec'] = inputs['invec'] * 2.0 else: outputs['outvec'] = inputs['invec'] * -3.0 def setup(self): comm = self.comm rank = comm.rank # results in 8 entries for proc 0 and 7 entries for proc 1 when using 2 processes. sizes, offsets = evenly_distrib_idxs(comm.size, self.size) start = offsets[rank] end = start + sizes[rank] self.add_input('invec', np.ones(sizes[rank], float), src_indices=np.arange(start, end, dtype=int)) self.add_output('outvec', np.ones(sizes[rank], float)) class Summer(ExplicitComponent): """Sums a distributed input.""" def __init__(self, size): super(Summer, self).__init__() self.size = size def setup(self): # this results in 8 entries for proc 0 and 7 entries for proc 1 # when using 2 processes. sizes, offsets = evenly_distrib_idxs(self.comm.size, self.size) start = offsets[rank] end = start + sizes[rank] # NOTE: you must specify src_indices here for the input. Otherwise, # you'll connect the input to [0:local_input_size] of the # full distributed output! self.add_input('invec', np.ones(sizes[self.comm.rank], float), src_indices=np.arange(start, end, dtype=int)) self.add_output('out', 0.0) def compute(self, inputs, outputs): data = np.zeros(1) data[0] = np.sum(self._inputs['invec']) total = np.zeros(1) self.comm.Allreduce(data, total, op=MPI.SUM) self._outputs['out'] = total[0] p = Problem(model=Group()) top = p.model top.add_subsystem("indep", IndepVarComp('x', np.zeros(size))) top.add_subsystem("C2", DistribComp(size)) top.add_subsystem("C3", Summer(size)) top.connect('indep.x', 'C2.invec') top.connect('C2.outvec', 'C3.invec') p.setup() p['indep.x'] = np.ones(size) p.run_model() assert_rel_error(self, p['C3.out'], -5.)
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 msg = "The 'distributed' property provides backwards compatibility " \ "with OpenMDAO <= 2.4.0 ; use the 'distributed' option instead." with warnings.catch_warnings(record=True) as w: C2 = top.add_subsystem("C2", DeprecatedDistribInputComp(size)) self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) self.assertEqual(str(w[0].message), msg) # check deprecation on getter with warnings.catch_warnings(record=True) as w: C2.distributed self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) self.assertEqual(str(w[0].message), msg) # continue to make sure everything still works with the deprecation top.connect('C1.outvec', 'C2.invec') # Conclude setup but don't run model. with warnings.catch_warnings(record=True) as w: p.setup(check=False) if PETScVector is None: self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[0].category, UserWarning)) self.assertEqual( str(w[0].message), "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.") 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_group_assembled_jac_with_ext_mat(self): class TwoSellarDis1(ExplicitComponent): """ Component containing Discipline 1 -- no derivatives version. """ def setup(self): self.add_input('z', val=np.zeros(2)) self.add_input('x', val=np.zeros(2)) self.add_input('y2', val=np.ones(2)) self.add_output('y1', val=np.ones(2)) self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): z1 = inputs['z'][0] z2 = inputs['z'][1] x1 = inputs['x'] y2 = inputs['y2'] outputs['y1'][0] = z1**2 + z2 + x1[0] - 0.2 * y2[0] outputs['y1'][1] = z1**2 + z2 + x1[0] - 0.2 * y2[0] def compute_partials(self, inputs, partials): """ Jacobian for Sellar discipline 1. """ partials['y1', 'y2'] = np.array([[-0.2, 0.], [0., -0.2]]) partials['y1', 'z'] = np.array([[2.0 * inputs['z'][0], 1.0], [2.0 * inputs['z'][0], 1.0]]) partials['y1', 'x'] = np.eye(2) class TwoSellarDis2(ExplicitComponent): def setup(self): self.add_input('z', val=np.zeros(2)) self.add_input('y1', val=np.ones(2)) self.add_output('y2', val=np.ones(2)) self.declare_partials('*', '*', method='fd') def compute(self, inputs, outputs): z1 = inputs['z'][0] z2 = inputs['z'][1] y1 = inputs['y1'] # Note: this may cause some issues. However, y1 is constrained to be # above 3.16, so lets just let it converge, and the optimizer will # throw it out if y1[0].real < 0.0: y1[0] *= -1 if y1[1].real < 0.0: y1[1] *= -1 outputs['y2'][0] = y1[0]**.5 + z1 + z2 outputs['y2'][1] = y1[1]**.5 + z1 + z2 def compute_partials(self, inputs, J): y1 = inputs['y1'] if y1[0].real < 0.0: y1[0] *= -1 if y1[1].real < 0.0: y1[1] *= -1 J['y2', 'y1'] = np.array([[.5 * y1[0]**-.5, 0.], [0., .5 * y1[1]**-.5]]) J['y2', 'z'] = np.array([[1.0, 1.0], [1.0, 1.0]]) prob = Problem() model = prob.model model.add_subsystem('px', IndepVarComp('x', np.array([1.0, 1.0])), promotes=['x']) model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) sup = model.add_subsystem('sup', Group(), promotes=['*']) sub1 = sup.add_subsystem('sub1', Group(), promotes=['*']) sub2 = sup.add_subsystem('sub2', Group(), promotes=['*']) d1 = sub1.add_subsystem('d1', TwoSellarDis1(), promotes=['x', 'z', 'y1', 'y2']) sub2.add_subsystem('d2', TwoSellarDis2(), promotes=['z', 'y1', 'y2']) model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1[0] - y1[1]', y1=np.array([0.0, 0.0])), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', ExecComp('con2 = y2[0] + y2[1] - 24.0', y2=np.array([0.0, 0.0])), promotes=['con2', 'y2']) model.linear_solver = LinearBlockGS() sup.linear_solver = LinearBlockGS() sub1.linear_solver = DirectSolver(assemble_jac=True) sub2.linear_solver = DirectSolver(assemble_jac=True) prob.set_solver_print(level=0) prob.setup(check=False, mode='rev') prob.run_model() of = ['con1', 'con2'] wrt = ['x', 'z'] # Make sure we don't get a size mismatch. derivs = prob.compute_totals(of=of, wrt=wrt)
def test_guess_nonlinear_complex_step(self): class ImpWithInitial(ImplicitComponent): """ An implicit component to solve the quadratic equation: x^2 - 4x + 3 (solutions at x=1 and x=3) """ def setup(self): self.add_input('a', val=1.) self.add_input('b', val=-4.) self.add_input('c', val=3.) self.add_output('x', val=0.) self.declare_partials(of='*', wrt='*') def apply_nonlinear(self, inputs, outputs, residuals): a = inputs['a'] b = inputs['b'] c = inputs['c'] x = outputs['x'] residuals['x'] = a * x**2 + b * x + c def linearize(self, inputs, outputs, partials): a = inputs['a'] b = inputs['b'] c = inputs['c'] x = outputs['x'] partials['x', 'a'] = x**2 partials['x', 'b'] = x partials['x', 'c'] = 1.0 partials['x', 'x'] = 2 * a * x + b def guess_nonlinear(self, inputs, outputs, resids): if outputs._data.dtype == np.complex: raise RuntimeError( 'Vector should not be complex when guess_nonlinear is called.' ) # Default initial state of zero for x takes us to x=1 solution. # Here we set it to a value that will take us to the x=3 solution. outputs['x'] = 5.0 prob = Problem() model = prob.model = Group() indep = IndepVarComp() indep.add_output('a', 1.0) indep.add_output('b', -4.0) indep.add_output('c', 3.0) model.add_subsystem('p', indep) model.add_subsystem('comp', ImpWithInitial()) model.add_subsystem('fn', ExecComp(['y = .03*a*x*x - .04*a*a*b*x - c'])) model.connect('p.a', 'comp.a') model.connect('p.a', 'fn.a') model.connect('p.b', 'fn.b') model.connect('p.c', 'fn.c') model.connect('comp.x', 'fn.x') model.nonlinear_solver = NewtonSolver() model.nonlinear_solver.options['rtol'] = 1e-12 model.nonlinear_solver.options['atol'] = 1e-12 model.nonlinear_solver.options['maxiter'] = 15 model.linear_solver = ScipyKrylov() prob.setup(force_alloc_complex=True) prob.run_model() assert_rel_error(self, prob['comp.x'], 3.) totals = prob.check_totals(of=['fn.y'], wrt=['p.a'], method='cs', out_stream=None) for key, val in iteritems(totals): assert_rel_error(self, val['rel error'][0], 0.0, 1e-9)
def test_assembled_jacobian_unsupported_cases(self): class ParaboloidApply(ImplicitComponent): def setup(self): self.add_input('x', val=0.0) self.add_input('y', val=0.0) self.add_output('f_xy', val=0.0) def linearize(self, inputs, outputs, jacobian): return def apply_linear(self, inputs, outputs, d_inputs, d_outputs, d_residuals, mode): d_residuals['x'] += ( np.exp(outputs['x']) - 2 * inputs['a']**2 * outputs['x']) * d_outputs['x'] d_residuals['x'] += (-2 * inputs['a'] * outputs['x']**2) * d_inputs['a'] # One level deep prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', ParaboloidApply()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model() # Nested prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) sub = model.add_subsystem('sub', Group()) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) sub.add_subsystem('comp', ParaboloidApply()) model.connect('p1.x', 'sub.comp.x') model.connect('p2.y', 'sub.comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model() # Try a component that is derived from a matrix-free one class FurtherDerived(ParaboloidApply): def do_nothing(self): pass prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', FurtherDerived()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model() # Make sure regular comps don't give an error. prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', Paraboloid()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() prob.final_setup() class ParaboloidJacVec(Paraboloid): def linearize(self, inputs, outputs, jacobian): return def compute_jacvec_product(self, inputs, d_inputs, d_outputs, d_residuals, mode): d_residuals['x'] += ( np.exp(outputs['x']) - 2 * inputs['a']**2 * outputs['x']) * d_outputs['x'] d_residuals['x'] += (-2 * inputs['a'] * outputs['x']**2) * d_inputs['a'] # One level deep prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', ParaboloidJacVec()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model()
def test_result(self): import numpy as np from numpy.testing import assert_almost_equal from openmdao.api import Problem, Group, IndepVarComp, BalanceComp, \ ExecComp, DirectSolver, NewtonSolver prob = Problem() ivc = IndepVarComp() ivc.add_output(name='M', val=0.0, units='deg', desc='Mean anomaly') ivc.add_output(name='ecc', val=0.0, units=None, desc='orbit eccentricity') bal = BalanceComp() bal.add_balance(name='E', val=0.0, units='rad', eq_units='rad', rhs_name='M') # Use M (mean anomaly) as the initial guess for E (eccentric anomaly) def guess_function(inputs, outputs, residuals): outputs['E'] = inputs['M'] bal.options['guess_func'] = guess_function # ExecComp used to compute the LHS of Kepler's equation. lhs_comp = ExecComp('lhs=E - ecc * sin(E)', lhs={ 'value': 0.0, 'units': 'rad' }, E={ 'value': 0.0, 'units': 'rad' }, ecc={'value': 0.0}) prob.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['M', 'ecc']) prob.model.add_subsystem(name='balance', subsys=bal, promotes_inputs=['M'], promotes_outputs=['E']) prob.model.add_subsystem(name='lhs_comp', subsys=lhs_comp, promotes_inputs=['E', 'ecc']) # Explicit connections prob.model.connect('lhs_comp.lhs', 'balance.lhs:E') # Set up solvers prob.model.linear_solver = DirectSolver() prob.model.nonlinear_solver = NewtonSolver(maxiter=100, iprint=0) prob.setup() prob['M'] = 85.0 prob['ecc'] = 0.6 prob.run_model() assert_almost_equal(np.degrees(prob['E']), 115.9, decimal=1)
def test_csc_masking(self): class CCBladeResidualComp(ImplicitComponent): def initialize(self): self.options.declare('num_nodes', types=int) self.options.declare('num_radial', types=int) def setup(self): num_nodes = self.options['num_nodes'] num_radial = self.options['num_radial'] self.add_input('chord', shape=(1, num_radial)) self.add_input('theta', shape=(1, num_radial)) self.add_output('phi', lower=-0.5 * np.pi, upper=0.0, shape=(num_nodes, num_radial)) self.add_output('Tp', shape=(num_nodes, num_radial)) of_names = ('phi', 'Tp') row_col = np.arange(num_radial) for name in of_names: self.declare_partials(name, 'chord', rows=row_col, cols=row_col) self.declare_partials(name, 'theta', rows=row_col, cols=row_col, val=0.0) self.declare_partials(name, 'phi', rows=row_col, cols=row_col) self.declare_partials('Tp', 'Tp', rows=row_col, cols=row_col, val=1.) def linearize(self, inputs, outputs, partials): partials['phi', 'chord'] = np.array([1., 2, 3, 4]) partials['phi', 'phi'] = np.array([5., 6, 7, 8]) partials['Tp', 'chord'] = np.array([9., 10, 11, 12]) partials['Tp', 'phi'] = np.array([13., 14, 15, 16]) prob = Problem() model = prob.model comp = IndepVarComp() comp.add_output('chord', val=np.ones((4, ))) model.add_subsystem('indep_var_comp', comp, promotes=['*']) comp = CCBladeResidualComp(num_nodes=1, num_radial=4, assembled_jac_type='csc') comp.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('ccblade_comp', comp, promotes_inputs=['chord'], promotes_outputs=['Tp']) prob.setup(mode='fwd') prob.run_model() totals = prob.compute_totals(of=['Tp'], wrt=['chord'], return_format='array') expected = np.array([[-6.4, 0., 0., 0.], [0., -5.33333333, 0., 0.], [0., 0., -4.57142857, 0.], [0., 0., 0., -4.]]) np.testing.assert_allclose(totals, expected)
super(EngUnitStaticProps, self).setup() if __name__ == "__main__": from openmdao.api import Problem, Group, IndepVarComp from pycycle.cea import species_data thermo = species_data.Thermo(species_data.co2_co_o2) p = Problem() model = p.model = Group() indep = model.add_subsystem('indep', IndepVarComp(), promotes=['*']) # indep.add_output('T', val=100., units='degK') # indep.add_output('P', val=1., units='bar') indep.add_output('T', val=100., units='degR') indep.add_output('P', val=1., units='psi') model.add_subsystem('units', EngUnitProps(thermo=thermo), promotes=['*']) p.setup() p.run_model() p.model.run_linearize() jac = p.model.get_subsystem('units').jacobian._subjacs for pair in jac: print(pair) print(jac[pair]) print()
def test_simple_list_vars_options(self): from openmdao.api import Group, Problem, IndepVarComp class QuadraticComp(ImplicitComponent): """ A Simple Implicit Component representing a Quadratic Equation. R(a, b, c, x) = ax^2 + bx + c Solution via Quadratic Formula: x = (-b + sqrt(b^2 - 4ac)) / 2a """ def setup(self): self.add_input('a', val=1., units='ft') self.add_input('b', val=1., units='inch') self.add_input('c', val=1., units='ft') self.add_output('x', val=0., lower=1.0, upper=100.0, ref=1.1, ref0=2.1, units='inch') self.declare_partials(of='*', wrt='*') def apply_nonlinear(self, inputs, outputs, residuals): a = inputs['a'] b = inputs['b'] c = inputs['c'] x = outputs['x'] residuals['x'] = a * x**2 + b * x + c def solve_nonlinear(self, inputs, outputs): a = inputs['a'] b = inputs['b'] c = inputs['c'] outputs['x'] = (-b + (b**2 - 4 * a * c)**0.5) / (2 * a) group = Group() comp1 = group.add_subsystem('comp1', IndepVarComp()) comp1.add_output('a', 1.0, units='ft') comp1.add_output('b', 1.0, units='inch') comp1.add_output('c', 1.0, units='ft') sub = group.add_subsystem('sub', Group()) sub.add_subsystem('comp2', QuadraticComp()) sub.add_subsystem('comp3', QuadraticComp()) group.connect('comp1.a', 'sub.comp2.a') group.connect('comp1.b', 'sub.comp2.b') group.connect('comp1.c', 'sub.comp2.c') group.connect('comp1.a', 'sub.comp3.a') group.connect('comp1.b', 'sub.comp3.b') group.connect('comp1.c', 'sub.comp3.c') global prob prob = Problem(model=group) prob.setup() prob['comp1.a'] = 1. prob['comp1.b'] = -4. prob['comp1.c'] = 3. prob.run_model() # list_inputs test stream = cStringIO() inputs = prob.model.list_inputs(values=False, out_stream=stream) text = stream.getvalue() self.assertEqual(sorted(inputs), [ ('sub.comp2.a', {}), ('sub.comp2.b', {}), ('sub.comp2.c', {}), ('sub.comp3.a', {}), ('sub.comp3.b', {}), ('sub.comp3.c', {}), ]) self.assertEqual(1, text.count("6 Input(s) in 'model'")) self.assertEqual(1, text.count("top")) self.assertEqual(1, text.count(" sub")) self.assertEqual(1, text.count(" comp2")) self.assertEqual(2, text.count(" a")) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(num_non_empty_lines, 14) # list_outputs tests # list implicit outputs outputs = prob.model.list_outputs(explicit=False, out_stream=None) text = stream.getvalue() self.assertEqual(sorted(outputs), [('sub.comp2.x', { 'value': [3.] }), ('sub.comp3.x', { 'value': [3.] })]) # list explicit outputs stream = cStringIO() outputs = prob.model.list_outputs(implicit=False, out_stream=None) self.assertEqual(sorted(outputs), [ ('comp1.a', { 'value': [1.] }), ('comp1.b', { 'value': [-4.] }), ('comp1.c', { 'value': [3.] }), ])
def test_turbine_cooling(self): """test the flow calculations and final temperatures for multiple rows""" p = Problem() # p = self.prob # n_init = np.array([3.23319258e-04, 1.00000000e-10, 1.10131241e-05, 1.00000000e-10, # 1.63212420e-10, 6.18813039e-09, 1.00000000e-10, 2.69578835e-02, # 1.00000000e-10, 7.23198770e-03]) # need ivc here, because b0 is shape_by_conn b0_air = [ 3.23319258e-04, 1.10132241e-05, 5.39157736e-02, 1.44860147e-02 ] b0_mix = [0.00031378, 0.00211278, 0.00420881, 0.05232509, 0.01405863] ivc = p.model.add_subsystem('ivc', IndepVarComp()) ivc.add_output('air_composition', b0_air) ivc.add_output('mix_composition', b0_mix) # p.model.set_input_defaults('turb_cool.Fl_cool:tot:composition', val=b0_air) # product ratios for clean air p.model.set_input_defaults('turb_cool.turb_pwr', val=24193.5, units='hp') p.model.set_input_defaults('turb_cool.Fl_turb_I:tot:P', val=616.736, units='psi') p.model.set_input_defaults('turb_cool.Fl_turb_O:tot:P', val=149.113, units='psi') p.model.set_input_defaults('turb_cool.Fl_turb_I:stat:W', val=62.15, units='lbm/s') p.model.set_input_defaults('turb_cool.Fl_turb_I:tot:T', val=3400.00, units='degR') p.model.set_input_defaults('turb_cool.Fl_cool:tot:T', val=1721.97, units='degR') p.model.set_input_defaults('turb_cool.Fl_turb_I:tot:h', val=250.097, units='Btu/lbm') p.model.set_input_defaults('turb_cool.Fl_cool:tot:h', val=298.48, units='Btu/lbm') cool_comp = p.model.add_subsystem( 'turb_cool', cooling.TurbineCooling(n_stages=2, T_metal=2460., T_safety=150., thermo_method='CEA', thermo_data=species_data.janaf)) cool_comp.Fl_I_data['Fl_turb_I'] = CEA_AIR_FUEL_COMPOSITION cool_comp.Fl_I_data['Fl_cool'] = CEA_AIR_COMPOSITION cool_comp.Fl_I_data['Fl_turb_O'] = CEA_AIR_FUEL_COMPOSITION cool_comp.pyc_setup_output_ports() p.model.connect('ivc.mix_composition', [ 'turb_cool.Fl_turb_I:tot:composition', 'turb_cool.Fl_turb_I:stat:composition' ]) p.model.connect('ivc.mix_composition', [ 'turb_cool.Fl_turb_O:tot:composition', 'turb_cool.Fl_turb_O:stat:composition' ]) p.model.connect('ivc.air_composition', [ 'turb_cool.Fl_cool:tot:composition', 'turb_cool.Fl_cool:stat:composition' ]) p.setup() p.set_solver_print(0) p.set_val('turb_cool.x_factor', .9) p.run_model() tol = 4e-4 assert_near_equal(p['turb_cool.row_0.Fl_O:tot:T'], 3299.28, tol) assert_near_equal(p['turb_cool.row_1.Fl_O:tot:T'], 2846.45, tol) assert_near_equal(p['turb_cool.row_2.Fl_O:tot:T'], 2821.58, tol) assert_near_equal(p['turb_cool.row_3.Fl_O:tot:T'], 2412.12, tol) assert_near_equal(p['turb_cool.row_0.W_cool'], 4.44635, tol) assert_near_equal(p['turb_cool.row_1.W_cool'][0], 2.2981, tol) assert_near_equal(p['turb_cool.row_2.W_cool'], 1.7079, tol) assert_near_equal(p['turb_cool.row_3.W_cool'][0], 0.91799, tol) np.set_printoptions(precision=5) check = p.check_partials(includes=[ 'turb_cool.row_0.cooling_calcs', 'turb_cool.row_1.cooling_calcs' ], out_stream=None) assert_check_partials(check, atol=1e-6, rtol=1e2)
def test_case_sanity_check(self): p = Problem() params = p.model.add_subsystem('params', IndepVarComp(), promotes=['*']) params.add_output('MN', val=0.8) params.add_output('alt', val=35000., units='ft') params.add_output('W', val=15., units='lbm/s') p.model.add_subsystem('fc', FlightConditions(), promotes_inputs=['MN', 'alt', 'W']) p.model.add_subsystem( 'cfd_start', CFDStart()) #, promotes_inputs=['Ps', 'V', 'area', 'W']) p.model.connect('fc.Fl_O:stat:P', 'cfd_start.Ps') p.model.connect('fc.Fl_O:stat:area', 'cfd_start.area') p.model.connect('fc.Fl_O:stat:V', 'cfd_start.V') p.model.connect('fc.Fl_O:stat:W', 'cfd_start.W') p.set_solver_print(level=-1) # p.set_solver_print(level=2, depth=1) p.setup(check=False) p.run_model() tol = 1e-6 assert_rel_error(self, p['cfd_start.Fl_O:tot:P'], p['fc.Fl_O:tot:P'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:T'], p['fc.Fl_O:tot:T'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:h'], p['fc.Fl_O:tot:h'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:S'], p['fc.Fl_O:tot:S'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:gamma'], p['fc.Fl_O:tot:gamma'], tol) p['MN'] = 1.2 p['alt'] = 50000. p['W'] = 125. p.run_model() tol = 1e-6 assert_rel_error(self, p['cfd_start.Fl_O:tot:P'], p['fc.Fl_O:tot:P'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:T'], p['fc.Fl_O:tot:T'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:h'], p['fc.Fl_O:tot:h'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:S'], p['fc.Fl_O:tot:S'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:gamma'], p['fc.Fl_O:tot:gamma'], tol) p['MN'] = 0.25 p['alt'] = 100. p['W'] = 12. # needs some initial guesses or it won't converge p['cfd_start.balance.P'] = 14 p['cfd_start.balance.T'] = 300 p['cfd_start.balance.MN'] = .2 p.run_model() tol = 5e-3 assert_rel_error(self, p['cfd_start.Fl_O:tot:P'], p['fc.Fl_O:tot:P'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:T'], p['fc.Fl_O:tot:T'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:h'], p['fc.Fl_O:tot:h'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:S'], p['fc.Fl_O:tot:S'], tol) assert_rel_error(self, p['cfd_start.Fl_O:tot:gamma'], p['fc.Fl_O:tot:gamma'], tol)
class ConditionalComponent(ExplicitComponent): def initialize(self): self.options.declare('out_name', types=str) self.options.declare('condition', types=Variable) self.options.declare('expr_true', types=Variable) self.options.declare('expr_false', types=Variable) self.options.declare('n2', types=bool, default=False) self.condition = Problem() self.condition.model = Group() self.ptrue = Problem() self.ptrue.model = Group() self.pfalse = Problem() self.pfalse.model = Group() # self.all_outputs: Set[str] = set() self.in_exprs_condition: Dict[Set[Input]] = dict() self.in_exprs_true: Dict[Set[Input]] = dict() self.in_exprs_false: Dict[Set[Input]] = dict() self.derivs = dict() # TODO: allow condition to be an input # TODO: check number of expressions for expr_true, expr_false def setup(self): out_name = self.options['out_name'] condition = self.options['condition'] if isinstance(condition, Input): raise TypeError("Condition must not be an Input object") expr_true = self.options['expr_true'] if isinstance(expr_true, Input): raise TypeError( "Variable object to evaluate when condition is TRUE must not be an Input object" ) expr_false = self.options['expr_false'] if isinstance(expr_false, Input): raise TypeError( "Variable object to evaluate when condition is FALSE must not be an Input object" ) if expr_true.shape != expr_false.shape: raise ValueError( "Variable shapes must be the same for Variable objects for both branches of execution" ) self.add_output( out_name, shape=expr_true.shape, val=expr_true.val, ) # collect input expressions for all three problems self.in_exprs_condition = set( collect_input_exprs([], condition, condition)) self.in_exprs_true = set(collect_input_exprs([], expr_true, expr_true)) self.in_exprs_false = set( collect_input_exprs([], expr_false, expr_false)) # TODO: enable multiple outputs # self.all_inputs[out_name] = in_exprs # self.all_outputs = self.all_outputs.union({out_name}) # add inputs, declare partials (out wrt in) for in_expr in set(self.in_exprs_condition, self.in_exprs_true, self.in_exprs_false): if in_expr.name != out_name: self.add_input( in_expr.name, shape=in_expr.shape, val=in_expr.val, ) self.declare_partials( of=out_name, wrt=in_expr.name, ) # setup response variables self.condition.model.add_constraint(condition.name) self.ptrue.model.add_constraint(expr_true.name) self.pfalse.model.add_constraint(expr_false.name) # setup input variables for in_expr in self.in_exprs_condition: in_name = in_expr.name if in_name in self.condition.model._design_vars or in_name in self.condition.model._static_design_vars: pass else: self.condition.model.add_design_var(in_name) for in_expr in self.in_exprs_true: in_name = in_expr.name if in_name in self.ptrue.model._design_vars or in_name in self.ptrue.model._static_design_vars: pass else: self.ptrue.model.add_design_var(in_name) for in_expr in self.in_exprs_false: in_name = in_expr.name if in_name in self.pfalse.model._design_vars or in_name in self.pfalse.model._static_design_vars: pass else: self.pfalse.model.add_design_var(in_name) # setup internal problems self.condition.model._root = deepcopy(condition) self.condition.setup() self.ptrue.model._root = deepcopy(expr_true) self.ptrue.setup() self.pfalse.model._root = deepcopy(expr_false) self.pfalse.setup() # create n2 diagram of internal model for debugging if self.options['n2'] == True: self.ptrue.run_model() self.ptrue.model.list_inputs() self.ptrue.model.list_outputs() self.pfalse.run_model() self.pfalse.model.list_inputs() self.pfalse.model.list_outputs() from openmdao.api import n2 # TODO: check that two n2 diagrams are created, make sure # both show up in docs n2(self.ptrue) n2(self.pfalse) def _set_values(self, inputs): for in_expr in self.in_exprs_condition: self.condition[in_expr.name] = inputs[in_expr.name] for in_expr in self.in_exprs_true: self.ptrue[in_expr.name] = inputs[in_expr.name] for in_expr in self.in_exprs_false: self.pfalse[in_expr.name] = inputs[in_expr.name] def compute(self, inputs, outputs): out_name = self.options['out_name'] condition = self.options['condition'] self.condition.run_model() prob = None if self.condition[condition.name] > 0: prob = self.ptrue else: prob = self.pfalse prob.run_model() outputs[out_name] = np.array(prob[out_name]) def compute_partials(self, inputs, partials): out_name = self.options['out_name'] condition = self.options['condition'] expr_true = self.options['expr_true'] expr_false = self.options['expr_false'] self._set_values(inputs) prob = None in_exprs = set() branch_expr_name = '' if self.condition[condition.name] > 0: prob = self.ptrue in_exprs = self.in_exprs_true branch_expr_name = expr_true.name else: prob = self.pfalse in_exprs = self.in_exprs_false branch_expr_name = expr_false.name jac = prob.compute_totals( of=branch_expr_name, wrt=[in_expr.name for in_expr in list(in_exprs)] + branch_expr_name, ) for in_expr in in_exprs: partials[out_name, in_expr.name] = jac[branch_expr_name, in_expr.name]
def test(self): # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 7, 'num_x': 2, 'wing_type': 'rect', 'symmetry': True } mesh = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name': 'wing', # name of the surface 'symmetry': True, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type': 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'fem_model_type': 'tube', 'mesh': mesh, # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0': 0.0, # CL of the surface at alpha=0 'CD0': 0.015, # CD of the surface at alpha=0 # Airfoil properties for viscous drag calculation 'k_lam': 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp': np.array([0.15]), # thickness over chord ratio (NACA0015) 'c_max_t': .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous': True, # if true, compute viscous drag 'with_wave': False, # if true, compute wave drag } # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 5, 'num_x': 3, 'wing_type': 'rect', 'symmetry': True, 'offset': np.array([50, 0., 0.]) } mesh = generate_mesh(mesh_dict) surf_dict2 = { # Wing definition 'name': 'tail', # name of the surface 'symmetry': True, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type': 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'mesh': mesh, # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0': 0.0, # CL of the surface at alpha=0 'CD0': 0.0, # CD of the surface at alpha=0 'fem_origin': 0.35, # Airfoil properties for viscous drag calculation 'k_lam': 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp': np.array([0.15]), # thickness over chord ratio (NACA0015) 'c_max_t': .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous': True, # if true, compute viscous drag 'with_wave': False, # if true, compute wave drag } surfaces = [surf_dict, surf_dict2] # Create the problem and the model group prob = Problem() indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=5., units='deg') indep_var_comp.add_output('Mach_number', val=0.84) indep_var_comp.add_output('re', val=1.e6, units='1/m') indep_var_comp.add_output('rho', val=0.38, units='kg/m**3') indep_var_comp.add_output('cg', val=np.zeros((3)), units='m') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Loop over each surface in the surfaces list for surface in surfaces: geom_group = Geometry(surface=surface) # Add tmp_group to the problem as the name of the surface. # Note that is a group and performance group for each # individual surface. prob.model.add_subsystem(surface['name'], geom_group) # Loop through and add a certain number of aero points for i in range(1): # Create the aero point group and add it to the model aero_group = AeroPoint(surfaces=surfaces) point_name = 'aero_point_{}'.format(i) prob.model.add_subsystem(point_name, aero_group) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v') prob.model.connect('alpha', point_name + '.alpha') prob.model.connect('Mach_number', point_name + '.Mach_number') prob.model.connect('re', point_name + '.re') prob.model.connect('rho', point_name + '.rho') prob.model.connect('cg', point_name + '.cg') # Connect the parameters within the model for each aero point for surface in surfaces: name = surface['name'] # Connect the mesh from the geometry component to the analysis point prob.model.connect(name + '.mesh', point_name + '.' + name + '.def_mesh') # Perform the connections with the modified names within the # 'aero_states' group. prob.model.connect( name + '.mesh', point_name + '.aero_states.' + name + '_def_mesh') prob.model.connect( name + '.t_over_c', point_name + '.' + name + '_perf.' + 't_over_c') # Set up the problem prob.setup() prob.run_model() assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0], 0.035076501750605345, 1e-6) assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.4523608754613204, 1e-6) assert_rel_error(self, prob['aero_point_0.CM'][1], -10.59426779178033, 1e-6)
class TestExternalCodeComp(unittest.TestCase): 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')) self.prob = Problem() self.extcode = self.prob.model.add_subsystem('extcode', ExternalCodeComp()) def tearDown(self): os.chdir(self.startdir) try: shutil.rmtree(self.tempdir) except OSError: pass def test_normal(self): self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out' ] self.extcode.options['external_input_files'] = [ 'extcode_example.py', ] self.extcode.options['external_output_files'] = [ 'extcode.out', ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) self.prob.run_model() def test_timeout_raise(self): self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out', '--delay', '3' ] self.extcode.options['timeout'] = 1.0 self.extcode.options['external_input_files'] = [ 'extcode_example.py', ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) try: self.prob.run_model() except AnalysisError as exc: self.assertEqual(str(exc), 'Timed out after 1.0 sec.') else: self.fail('Expected AnalysisError') def test_error_code_raise(self): self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out', '--delay', '-3' ] self.extcode.options['timeout'] = 1.0 self.extcode.options['external_input_files'] = [ 'extcode_example.py', ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) try: self.prob.run_model() except RuntimeError as exc: self.assertTrue('Traceback' in str(exc), "no traceback found in '%s'" % str(exc)) self.assertEqual(self.extcode.return_code, 1) else: self.fail('Expected RuntimeError') def test_error_code_soft(self): self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out', '--delay', '-3' ] self.extcode.options['timeout'] = 1.0 self.extcode.options['fail_hard'] = False self.extcode.options['external_input_files'] = [ 'extcode_example.py', ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) try: self.prob.run_model() except AnalysisError as err: self.assertTrue( "delay must be >= 0" in str(err), "expected 'delay must be >= 0' to be in '%s'" % str(err)) self.assertTrue('Traceback' in str(err), "no traceback found in '%s'" % str(err)) else: self.fail("AnalysisError expected") def test_allowed_return_code(self): self.extcode.options['allowed_return_codes'] = set(range(5)) self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out', '--return_code', '4' ] self.extcode.options['external_input_files'] = [ 'extcode_example.py', ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) self.prob.run_model() def test_disallowed_return_code(self): self.extcode.options['allowed_return_codes'] = list(range(5)) self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out', '--return_code', '7' ] self.extcode.options['external_input_files'] = [ 'extcode_example.py', ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) try: self.prob.run_model() except RuntimeError as err: self.assertTrue( "return_code = 7" in str(err), "expected 'return_code = 7' to be in '%s'" % str(err)) else: self.fail("RuntimeError expected") def test_badcmd(self): # Set command to nonexistant path. self.extcode.options['command'] = [ 'no-such-command', ] self.prob.setup(check=False) try: self.prob.run_model() except ValueError as exc: msg = "The command to be executed, 'no-such-command', cannot be found" self.assertEqual(str(exc), msg) self.assertEqual(self.extcode.return_code, -999999) else: self.fail('Expected ValueError') def test_nullcmd(self): self.extcode.stdout = 'nullcmd.out' self.extcode.stderr = STDOUT self.prob.setup(check=False) try: self.prob.run_model() except ValueError as exc: self.assertEqual(str(exc), 'Empty command list') else: self.fail('Expected ValueError') finally: if os.path.exists(self.extcode.stdout): os.remove(self.extcode.stdout) def test_env_vars(self): self.extcode.options['env_vars'] = { 'TEST_ENV_VAR': 'SOME_ENV_VAR_VALUE' } self.extcode.options['command'] = [ 'python', 'extcode_example.py', 'extcode.out', '--write_test_env_var' ] dev_null = open(os.devnull, 'w') self.prob.setup(check=True) self.prob.run_model() # Check to see if output file contains the env var value with open(os.path.join(self.tempdir, 'extcode.out'), 'r') as out: file_contents = out.read() self.assertTrue( 'SOME_ENV_VAR_VALUE' in file_contents, "'SOME_ENV_VAR_VALUE' missing from '%s'" % file_contents)
def test(self): from openaerostruct.geometry.utils import generate_mesh, write_FFD_file from openaerostruct.geometry.geometry_group import Geometry from openaerostruct.transfer.displacement_transfer import DisplacementTransfer from openaerostruct.aerodynamics.aero_groups import AeroPoint from openaerostruct.integration.multipoint_comps import MultiCD from openmdao.api import IndepVarComp, Problem, Group, NewtonSolver, ScipyIterativeSolver, LinearBlockGS, NonlinearBlockGS, DirectSolver, LinearBlockGS, PetscKSP, ScipyOptimizeDriver, ExplicitComponent # TODO, SqliteRecorder, CaseReader, profile from openmdao.devtools import iprofile from openmdao.api import view_model from openmdao.utils.assert_utils import assert_check_partials from pygeo import DVGeometry # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 5, 'num_x': 3, 'wing_type': 'CRM', 'symmetry': True, 'num_twist_cp': 5, 'span_cos_spacing': 0. } mesh, _ = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name': 'wing', # name of the surface 'symmetry': True, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type': 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'fem_model_type': 'tube', 'mesh': mesh, 'mx': 2, 'my': 3, 'geom_manipulator': 'FFD', # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0': 0.0, # CL of the surface at alpha=0 'CD0': 0.015, # CD of the surface at alpha=0 # Airfoil properties for viscous drag calculation 'k_lam': 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp': np.array([0.15]), # thickness over chord ratio (NACA0015) 'c_max_t': .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous': True, # if true, compute viscous drag 'with_wave': False, # if true, compute wave drag } surfaces = [surf_dict] n_points = 2 # Create the problem and the model group prob = Problem() indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=np.ones(n_points) * 6.64, units='deg') indep_var_comp.add_output('Mach_number', val=0.84) indep_var_comp.add_output('re', val=1.e6, units='1/m') indep_var_comp.add_output('rho', val=0.38, units='kg/m**3') indep_var_comp.add_output('cg', val=np.zeros((3)), units='m') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Loop through and add a certain number of aero points for i in range(n_points): # Create the aero point group and add it to the model aero_group = AeroPoint(surfaces=surfaces) point_name = 'aero_point_{}'.format(i) prob.model.add_subsystem(point_name, aero_group) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v') prob.model.connect('alpha', point_name + '.alpha', src_indices=[i]) prob.model.connect('Mach_number', point_name + '.Mach_number') prob.model.connect('re', point_name + '.re') prob.model.connect('rho', point_name + '.rho') prob.model.connect('cg', point_name + '.cg') # Connect the parameters within the model for each aero point for surface in surfaces: filename = write_FFD_file(surface, surface['mx'], surface['my']) DVGeo = DVGeometry(filename) geom_group = Geometry(surface=surface, DVGeo=DVGeo) # Add tmp_group to the problem as the name of the surface. # Note that is a group and performance group for each # individual surface. aero_group.add_subsystem(surface['name'] + '_geom', geom_group) name = surface['name'] prob.model.connect(point_name + '.CD', 'multi_CD.' + str(i) + '_CD') # Connect the mesh from the geometry component to the analysis point prob.model.connect(point_name + '.' + name + '_geom.mesh', point_name + '.' + name + '.def_mesh') # Perform the connections with the modified names within the # 'aero_states' group. prob.model.connect( point_name + '.' + name + '_geom.mesh', point_name + '.aero_states.' + name + '_def_mesh') prob.model.connect( point_name + '.' + name + '_geom.t_over_c', point_name + '.' + name + '_perf.' + 't_over_c') prob.model.add_subsystem('multi_CD', MultiCD(n_points=n_points), promotes_outputs=['CD']) from openmdao.api import pyOptSparseDriver prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = "SNOPT" prob.driver.opt_settings = { 'Major optimality tolerance': 1.0e-5, 'Major feasibility tolerance': 1.0e-5 } # # Setup problem and add design variables, constraint, and objective prob.model.add_design_var('alpha', lower=-15, upper=15) prob.model.add_design_var('aero_point_0.wing_geom.shape', lower=-3, upper=2) prob.model.add_constraint('aero_point_0.wing_perf.CL', equals=0.45) prob.model.add_design_var('aero_point_1.wing_geom.shape', lower=-3, upper=2) prob.model.add_constraint('aero_point_1.wing_perf.CL', equals=0.5) prob.model.add_objective('CD', scaler=1e4) # Set up the problem prob.setup() prob.run_model() # Check the partials at this point in the design space data = prob.check_partials(compact_print=True, out_stream=None, method='cs', step=1e-40) assert_check_partials(data, atol=1e20, rtol=1e-6)
def test_deep_analysis_error_iprint(self): class ImplCompTwoStatesAE(ImplicitComponent): def setup(self): self.add_input('x', 0.5) self.add_output('y', 0.0) self.add_output('z', 2.0, lower=1.5, upper=2.5) self.maxiter = 10 self.atol = 1.0e-12 self.declare_partials(of='*', wrt='*') self.counter = 0 def apply_nonlinear(self, inputs, outputs, residuals): """ Don't solve; just calculate the residual. """ x = inputs['x'] y = outputs['y'] z = outputs['z'] residuals['y'] = y - x - 2.0 * z residuals['z'] = x * z + z - 4.0 self.counter += 1 if self.counter > 5 and self.counter < 11: raise AnalysisError('catch me') def linearize(self, inputs, outputs, jac): """ Analytical derivatives. """ # Output equation jac[('y', 'x')] = -1.0 jac[('y', 'y')] = 1.0 jac[('y', 'z')] = -2.0 # State equation jac[('z', 'z')] = -inputs['x'] + 1.0 jac[('z', 'x')] = -outputs['z'] top = Problem() top.model = Group() top.model.add_subsystem('px', IndepVarComp('x', 7.0)) sub = top.model.add_subsystem('sub', Group()) sub.add_subsystem('comp', ImplCompTwoStatesAE()) top.model.connect('px.x', 'sub.comp.x') top.model.nonlinear_solver = NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 2 top.model.nonlinear_solver.options['solve_subsystems'] = True top.model.linear_solver = ScipyKrylov() sub.nonlinear_solver = NewtonSolver() sub.nonlinear_solver.options['maxiter'] = 2 sub.linear_solver = ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = ArmijoGoldsteinLS( bound_enforcement='wall') ls.options['maxiter'] = 5 ls.options['alpha'] = 10.0 ls.options['retry_on_analysis_error'] = True ls.options['c'] = 10000.0 top.setup(check=False) top.set_solver_print(level=2) stdout = sys.stdout strout = StringIO() sys.stdout = strout try: top.run_model() finally: sys.stdout = stdout output = strout.getvalue().split('\n') self.assertTrue(output[26].startswith('| LS: AG 5'))
def test_simple_external_code_implicit_comp(self): from openmdao.api import Group, NewtonSolver, Problem, IndepVarComp, DirectSolver, \ ExternalCodeImplicitComp class MachExternalCodeComp(ExternalCodeImplicitComp): def initialize(self): self.options.declare('super_sonic', types=bool) def setup(self): self.add_input('area_ratio', val=1.0, units=None) self.add_output('mach', val=1., units=None) self.declare_partials(of='mach', wrt='area_ratio', method='fd') self.input_file = 'mach_input.dat' self.output_file = 'mach_output.dat' # providing these are optional; the component will verify that any input # files exist before execution and that the output files exist after. self.options['external_input_files'] = [ self.input_file, ] self.options['external_output_files'] = [ self.output_file, ] self.options['command_apply'] = [ 'python', 'extcode_mach.py', self.input_file, self.output_file, ] self.options['command_solve'] = [ 'python', 'extcode_mach.py', self.input_file, self.output_file, ] def apply_nonlinear(self, inputs, outputs, residuals): with open(self.input_file, 'w') as input_file: input_file.write('residuals\n') input_file.write('{}\n'.format(inputs['area_ratio'][0])) input_file.write('{}\n'.format(outputs['mach'][0])) # the parent apply_nonlinear function actually runs the external code super(MachExternalCodeComp, self).apply_nonlinear(inputs, outputs, residuals) # parse the output file from the external code and set the value of mach with open(self.output_file, 'r') as output_file: mach = float(output_file.read()) residuals['mach'] = mach def solve_nonlinear(self, inputs, outputs): with open(self.input_file, 'w') as input_file: input_file.write('outputs\n') input_file.write('{}\n'.format(inputs['area_ratio'][0])) input_file.write('{}\n'.format( self.options['super_sonic'])) # the parent apply_nonlinear function actually runs the external code super(MachExternalCodeComp, self).solve_nonlinear(inputs, outputs) # parse the output file from the external code and set the value of mach with open(self.output_file, 'r') as output_file: mach = float(output_file.read()) outputs['mach'] = mach group = Group() group.add_subsystem('ar', IndepVarComp('area_ratio', 0.5)) mach_comp = group.add_subsystem('comp', MachExternalCodeComp(), promotes=['*']) prob = Problem(model=group) group.nonlinear_solver = NewtonSolver() group.nonlinear_solver.options['solve_subsystems'] = True group.nonlinear_solver.options['iprint'] = 0 group.nonlinear_solver.options['maxiter'] = 20 group.linear_solver = DirectSolver() prob.setup(check=False) area_ratio = 1.3 super_sonic = False prob['area_ratio'] = area_ratio mach_comp.options['super_sonic'] = super_sonic prob.run_model() assert_rel_error(self, prob['mach'], mach_solve(area_ratio, super_sonic=super_sonic), 1e-8) area_ratio = 1.3 super_sonic = True prob['area_ratio'] = area_ratio mach_comp.options['super_sonic'] = super_sonic prob.run_model() assert_rel_error(self, prob['mach'], mach_solve(area_ratio, super_sonic=super_sonic), 1e-8)
class CompressorTestCase(unittest.TestCase): def setUp(self): thermo = Thermo(janaf, constants.AIR_MIX) self.prob = Problem() self.prob.model.add_subsystem( 'flow_start', FlowStart(thermo_data=janaf, elements=AIR_MIX)) self.prob.model.add_subsystem( 'compressor', Compressor(design=True, elements=AIR_MIX)) self.prob.model.set_input_defaults('flow_start.P', 17., units='psi') self.prob.model.set_input_defaults('flow_start.T', 500., units='degR') self.prob.model.set_input_defaults('compressor.MN', 0.5) self.prob.model.set_input_defaults('flow_start.W', 10., units='lbm/s') self.prob.model.set_input_defaults('compressor.PR', 6.) self.prob.model.set_input_defaults('compressor.eff', 0.9) connect_flow(self.prob.model, "flow_start.Fl_O", "compressor.Fl_I") self.prob.set_solver_print(level=-1) self.prob.setup(check=False) def test_case1(self): np.seterr(divide='raise') # 6 cases to check against for i, data in enumerate(ref_data): self.prob['compressor.PR'] = data[h_map['comp.PRdes']] self.prob['compressor.eff'] = data[h_map['comp.effDes']] self.prob['compressor.MN'] = data[h_map['comp.Fl_O.MN']] # input flowstation self.prob['flow_start.P'] = data[h_map['start.Pt']] self.prob['flow_start.T'] = data[h_map['start.Tt']] self.prob['flow_start.W'] = data[h_map['start.W']] self.prob.run_model() tol = 1e-3 npss = data[h_map['comp.Fl_O.Pt']] pyc = self.prob['compressor.Fl_O:tot:P'][0] print('Pt out:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['comp.Fl_O.Tt']] pyc = self.prob['compressor.Fl_O:tot:T'][0] print('Tt out:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['comp.Fl_O.ht']] - data[h_map['start.Fl_O.ht']] pyc = self.prob['compressor.Fl_O:tot:h'] - self.prob[ 'flow_start.Fl_O:tot:h'] print('delta h:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['start.Fl_O.s']] pyc = self.prob['flow_start.Fl_O:tot:S'][0] print('S in:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['comp.Fl_O.s']] pyc = self.prob['compressor.Fl_O:tot:S'][0] print('S out:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['comp.pwr']] pyc = self.prob['compressor.power'][0] print('Power:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['Fl_O.Ps']] pyc = self.prob['compressor.Fl_O:stat:P'][0] print('Ps out:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['Fl_O.Ts']] pyc = self.prob['compressor.Fl_O:stat:T'][0] print('Ts out:', npss, pyc) assert_near_equal(pyc, npss, tol) npss = data[h_map['comp.effPoly']] pyc = self.prob['compressor.eff_poly'][0] print('effPoly:', npss, pyc) assert_near_equal(pyc, npss, tol) print("") check_element_partials(self, self.prob, tol=5e-5)
class TestControlEndpointDefectComp(unittest.TestCase): def setUp(self): gd = GridData(num_segments=2, segment_ends=np.array([0., 2., 4.]), transcription='radau-ps', transcription_order=3) self.gd = gd self.p = Problem(model=Group()) control_opts = { 'u': { 'units': 'm', 'shape': (1, ), 'dynamic': True, 'opt': True }, 'v': { 'units': 'm', 'shape': (3, 2), 'dynamic': True, 'opt': True } } indep_comp = IndepVarComp() self.p.model.add_subsystem('indep', indep_comp, promotes=['*']) indep_comp.add_output('controls:u', val=np.zeros((gd.subset_num_nodes['all'], 1)), units='m') indep_comp.add_output('controls:v', val=np.zeros((gd.subset_num_nodes['all'], 3, 2)), units='m') self.p.model.add_subsystem('endpoint_defect_comp', subsys=ControlEndpointDefectComp( grid_data=gd, control_options=control_opts)) self.p.model.connect('controls:u', 'endpoint_defect_comp.controls:u') self.p.model.connect('controls:v', 'endpoint_defect_comp.controls:v') self.p.setup(force_alloc_complex=True) self.p['controls:u'] = np.random.random( (gd.subset_num_nodes['all'], 1)) self.p['controls:v'] = np.random.random( (gd.subset_num_nodes['all'], 3, 2)) self.p.run_model() def test_results(self): u_coefs = np.polyfit(self.gd.node_ptau[-4:-1], self.p['controls:u'][-4:-1], deg=2) u_poly = np.poly1d(u_coefs.ravel()) u_interp = u_poly(1.0) u_given = self.p['controls:u'][-1] assert_rel_error( self, np.ravel( self.p['endpoint_defect_comp.control_endpoint_defects:u']), np.ravel(u_given - u_interp), tolerance=1.0E-12) def test_partials(self): cpd = self.p.check_partials(compact_print=False, method='cs') assert_check_partials(cpd)
# -*- coding: utf-8 -*- """ run_analysis.py generated by WhatsOpt 1.7.1 """ # DO NOT EDIT unless you know what you are doing # analysis_id: 77 from openmdao.api import Problem from run_parameters_init import initialize from lanceur_prop_solide import LanceurPropSolide pb = Problem(LanceurPropSolide()) pb.setup() initialize(pb) pb.run_model() pb.model.list_inputs(print_arrays=False) pb.model.list_outputs(print_arrays=False)
def test_analysis_error(self): class ParaboloidAE(ExplicitComponent): """ Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3 This version raises an analysis error if x < 2.0 The AE in ParaboloidAE stands for AnalysisError.""" def __init__(self): super(ParaboloidAE, self).__init__() self.fail_hard = False def setup(self): self.add_input('x', val=0.0) self.add_input('y', val=0.0) self.add_output('f_xy', val=0.0) self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): """f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3 Optimal solution (minimum): x = 6.6667; y = -7.3333 """ x = inputs['x'] y = inputs['y'] if x < 1.75: raise AnalysisError('Try Again.') outputs['f_xy'] = (x - 3.0)**2 + x * y + (y + 4.0)**2 - 3.0 def compute_partials(self, inputs, partials): """ Jacobian for our paraboloid.""" x = inputs['x'] y = inputs['y'] partials['f_xy', 'x'] = 2.0 * x - 6.0 + y partials['f_xy', 'y'] = 2.0 * y + 8.0 + x top = Problem() top.model = Group() top.model.add_subsystem('px', IndepVarComp('x', 1.0)) top.model.add_subsystem('comp', ImplCompTwoStates()) top.model.add_subsystem('par', ParaboloidAE()) top.model.connect('px.x', 'comp.x') top.model.connect('comp.z', 'par.x') top.model.nonlinear_solver = NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 1 top.model.linear_solver = ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = ArmijoGoldsteinLS( bound_enforcement='vector') ls.options['maxiter'] = 10 ls.options['alpha'] = 1.0 top.set_solver_print(level=0) top.setup(check=False) # Test lower bound: should go as far as it can without going past 1.75 and triggering an # AnalysisError. It doesn't do a great job, so ends up at 1.8 instead of 1.75 top['px.x'] = 2.0 top['comp.y'] = 0.0 top['comp.z'] = 2.1 top.run_model() assert_rel_error(self, top['comp.z'], 1.8, 1e-8) # Test the behavior with the switch turned off. top = Problem() top.model = Group() top.model.add_subsystem('px', IndepVarComp('x', 1.0)) top.model.add_subsystem('comp', ImplCompTwoStates()) top.model.add_subsystem('par', ParaboloidAE()) top.model.connect('px.x', 'comp.x') top.model.connect('comp.z', 'par.x') top.model.nonlinear_solver = NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 1 top.model.linear_solver = ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = ArmijoGoldsteinLS( bound_enforcement='vector') ls.options['maxiter'] = 10 ls.options['alpha'] = 1.0 ls.options['retry_on_analysis_error'] = False top.set_solver_print(level=0) top.setup(check=False) top['px.x'] = 2.0 top['comp.y'] = 0.0 top['comp.z'] = 2.1 with self.assertRaises(AnalysisError) as context: top.run_model() self.assertEqual(str(context.exception), 'Try Again.')
def test_sellar_specify_linear_direct_solver(self): prob = Problem() model = prob.model model.add_subsystem('px', IndepVarComp('x', 1.0), promotes=['x']) model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) proms = [ 'x', 'z', 'y1', 'state_eq.y2_actual', 'state_eq.y2_command', 'd1.y2', 'd2.y2' ] sub = model.add_subsystem('sub', Group(), promotes=proms) subgrp = sub.add_subsystem( 'state_eq_group', Group(), promotes=['state_eq.y2_actual', 'state_eq.y2_command']) subgrp.linear_solver = ScipyKrylov() subgrp.add_subsystem('state_eq', StateConnection()) sub.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1']) sub.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1']) model.connect('state_eq.y2_command', 'd1.y2') model.connect('d2.y2', 'state_eq.y2_actual') model.add_subsystem('obj_cmp', ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0, y1=0.0, y2=0.0), promotes=['x', 'z', 'y1', 'obj']) model.connect('d2.y2', 'obj_cmp.y2') model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['con2']) model.connect('d2.y2', 'con_cmp2.y2') model.nonlinear_solver = NewtonSolver() # Use bad settings for this one so that problem doesn't converge. # That way, we test that we are really using Newton's Lin Solver # instead. sub.linear_solver = ScipyKrylov() model.linear_solver.options['maxiter'] = 1 # The good solver model.nonlinear_solver.linear_solver = DirectSolver() prob.set_solver_print(level=0) prob.setup(check=False) prob.run_model() assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['state_eq.y2_command'], 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertLess(model.nonlinear_solver._iter_count, 8) self.assertEqual(model.linear_solver._iter_count, 0)
class CompressorTestCase(unittest.TestCase): def setUp(self): self.prob = Problem() des_vars = self.prob.model.add_subsystem('des_vars', IndepVarComp(), promotes=['*']) des_vars.add_output('P', 17., units='psi') des_vars.add_output('T', 500., units='degR') des_vars.add_output('MN', 0.5) des_vars.add_output('W', 10., units='lbm/s') des_vars.add_output('PR', 6.) des_vars.add_output('eff', 0.9) self.prob.model.connect("P", "flow_start.P") self.prob.model.connect("T", "flow_start.T") self.prob.model.connect("W", "flow_start.W") self.prob.model.connect("MN", "compressor.MN") self.prob.model.connect('PR', 'compressor.PR') self.prob.model.connect('eff', 'compressor.eff') self.prob.model.add_subsystem('flow_start', FlowStart(thermo_data=janaf, elements=AIR_MIX)) self.prob.model.add_subsystem('compressor', Compressor(design=True, elements=AIR_MIX)) connect_flow(self.prob.model, "flow_start.Fl_O", "compressor.Fl_I") self.prob.set_solver_print(level=-1) self.prob.setup(check=False) # from openmdao.api import view_model # view_model(self.prob) # exit() def test_case1(self): np.seterr(divide='raise') # 6 cases to check against for i, data in enumerate(ref_data): self.prob['PR'] = data[h_map['comp.PRdes']] self.prob['eff'] = data[h_map['comp.effDes']] self.prob['MN'] = data[h_map['comp.Fl_O.MN']] # input flowstation self.prob['P'] = data[h_map['start.Pt']] self.prob['T'] = data[h_map['start.Tt']] self.prob['W'] = data[h_map['start.W']] self.prob.run_model() # print(" mapPRdes : PRdes : PR : scalarsPRmapDes : scaledOutput.PR") # print(self.prob['PR'], data[h_map['comp.PRdes']], self.prob[ # 'PR'], self.prob['compressor.map.PRmap']) # print("s_PR", self.prob['compressor.s_PR']) # print(" mapeffDes : effDes : eff : scalars_effMapDes : scaledOutput.eff") # print(self.prob['compressor.map.effDes'], data[h_map['comp.effDes']], self.prob[ # 'compressor.eff'], self.prob['compressor.map.scalars.effMapDes']) # print("Rline", self.prob['compressor.map.RlineMap']) # print(self.prob.model.resids._dat.keys()) #print("errWc: ", self.prob.model.resids['compressor.map.RlineMap']) # quit() # check outputs tol = 1e-3 npss = data[h_map['comp.Fl_O.Pt']] pyc = self.prob['compressor.Fl_O:tot:P'][0] print('Pt out:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['comp.Fl_O.Tt']] pyc = self.prob['compressor.Fl_O:tot:T'][0] # print('foo test:', self.prob['compressor.enth_rise.ht_out'][0], data[h_map['start.Fl_O.ht']]) print('Tt out:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['comp.Fl_O.ht']] - data[h_map['start.Fl_O.ht']] pyc = self.prob['compressor.Fl_O:tot:h'] - self.prob['flow_start.Fl_O:tot:h'] print('delta h:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['start.Fl_O.s']] pyc = self.prob['flow_start.Fl_O:tot:S'][0] print('S in:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['comp.Fl_O.s']] pyc = self.prob['compressor.Fl_O:tot:S'][0] print('S out:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['comp.pwr']] pyc = self.prob['compressor.power'][0] print('Power:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['Fl_O.Ps']] pyc = self.prob['compressor.Fl_O:stat:P'][0] print('Ps out:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['Fl_O.Ts']] pyc = self.prob['compressor.Fl_O:stat:T'][0] print('Ts out:', npss, pyc) assert_rel_error(self, pyc, npss, tol) npss = data[h_map['comp.effPoly']] pyc = self.prob['compressor.eff_poly'][0] print('effPoly:', npss, pyc) assert_rel_error(self, pyc, npss, tol) print("") check_element_partials(self, self.prob,tol = 5e-5)
def test_multifidelity_warm_start(self): mm = MultiFiMetaModelUnStructured(nfi=2) surr = MockSurrogate() mm.add_input('x', 0.) mm.add_output('y', 0., surrogate=surr) mm.warm_restart = True prob = Problem(Group()) prob.model.add_subsystem('mm', mm) prob.setup(check=False) mm.metadata['train:x'] = [0.0, 0.4, 1.0] mm.metadata['train:x_fi2'] = [0.1, 0.2, 0.3, 0.5, 0.6] mm.metadata['train:y'] = [1.0, 1.4, 2.0] mm.metadata['train:y_fi2'] = [1.1, 1.2, 1.3, 1.5, 1.6] prob.run_model() expected_xtrain = [ np.array([[0.0], [0.4], [1.0]]), np.array([[0.1], [0.2], [0.3], [0.5], [0.6]]) ] expected_ytrain = [ np.array([[1.0], [1.4], [2.0]]), np.array([[1.1], [1.2], [1.3], [1.5], [1.6]]) ] np.testing.assert_array_equal(surr.xtrain[0], expected_xtrain[0]) np.testing.assert_array_equal(surr.xtrain[1], expected_xtrain[1]) np.testing.assert_array_equal(surr.ytrain[0], expected_ytrain[0]) np.testing.assert_array_equal(surr.ytrain[1], expected_ytrain[1]) # Test adding only one lowest fidelity sample mm.metadata['train:x'] = [] mm.metadata['train:y'] = [] mm.metadata['train:x_fi2'] = [2.0] mm.metadata['train:y_fi2'] = [1.0] mm.train = True prob.run_model() expected_xtrain = [ np.array([[0.0], [0.4], [1.0]]), np.array([[0.1], [0.2], [0.3], [0.5], [0.6], [2.0]]) ] expected_ytrain = [ np.array([[1.0], [1.4], [2.0]]), np.array([[1.1], [1.2], [1.3], [1.5], [1.6], [1.0]]) ] np.testing.assert_array_equal(surr.xtrain[0], expected_xtrain[0]) np.testing.assert_array_equal(surr.xtrain[1], expected_xtrain[1]) np.testing.assert_array_equal(surr.ytrain[0], expected_ytrain[0]) np.testing.assert_array_equal(surr.ytrain[1], expected_ytrain[1]) # Test adding high and low fidelity points mm.metadata['train:x'] = [3.0] mm.metadata['train:x_fi2'] = [3.0] mm.metadata['train:y'] = [4.0] mm.metadata['train:y_fi2'] = [4.0] mm.train = True prob.run_model() expected_xtrain = [ np.array([[0.0], [0.4], [1.0], [3.0]]), np.array([[0.1], [0.2], [0.3], [0.5], [0.6], [2.0], [3.0]]) ] expected_ytrain = [ np.array([[1.0], [1.4], [2.0], [4.0]]), np.array([[1.1], [1.2], [1.3], [1.5], [1.6], [1.0], [4.0]]) ] np.testing.assert_array_equal(surr.xtrain[0], expected_xtrain[0]) np.testing.assert_array_equal(surr.xtrain[1], expected_xtrain[1]) np.testing.assert_array_equal(surr.ytrain[0], expected_ytrain[0]) np.testing.assert_array_equal(surr.ytrain[1], expected_ytrain[1])
def test_solve_subsystems_internals(self): # Here we test that this feature is doing what it should do by counting the # number of calls in various places. class CountNewton(NewtonSolver): """ This version of Newton also counts how many times it runs in total.""" def __init__(self, **kwargs): super(CountNewton, self).__init__(**kwargs) self.total_count = 0 def _iter_execute(self): super(CountNewton, self)._iter_execute() self.total_count += 1 class CountDS(DirectSolver): """ This version of Newton also counts how many times it linearizes""" def __init__(self, **kwargs): super(DirectSolver, self).__init__(**kwargs) self.lin_count = 0 def _linearize(self): super(CountDS, self)._linearize() self.lin_count += 1 prob = Problem(model=DoubleSellar()) model = prob.model # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = CountNewton() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = CountDS() # used for derivatives g2 = model.g2 g2.nonlinear_solver = CountNewton() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() # Enfore behavior: max_sub_solves = 0 means we run once during init model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 0 prob.set_solver_print(level=0) prob.setup() prob.run_model() # Verifying subsolvers ran self.assertEqual(g1.nonlinear_solver.total_count, 2) self.assertEqual(g2.nonlinear_solver.total_count, 2) self.assertEqual(g1.linear_solver.lin_count, 2) prob = Problem(model=DoubleSellar()) model = prob.model # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = CountNewton() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = CountDS() # used for derivatives g2 = model.g2 g2.nonlinear_solver = CountNewton() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() # Enforce Behavior: baseline model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 5 prob.set_solver_print(level=0) prob.setup() prob.run_model() # Verifying subsolvers ran self.assertEqual(g1.nonlinear_solver.total_count, 5) self.assertEqual(g2.nonlinear_solver.total_count, 5) self.assertEqual(g1.linear_solver.lin_count, 5) prob = Problem(model=DoubleSellar()) model = prob.model # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = CountNewton() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = CountDS() # used for derivatives g2 = model.g2 g2.nonlinear_solver = CountNewton() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() # Enfore behavior: max_sub_solves = 1 means we run during init and first iteration of iter_execute model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 1 prob.set_solver_print(level=0) prob.setup() prob.run_model() # Verifying subsolvers ran self.assertEqual(g1.nonlinear_solver.total_count, 4) self.assertEqual(g2.nonlinear_solver.total_count, 4) self.assertEqual(g1.linear_solver.lin_count, 4)