def test_solve_subsystems_basic_csc(self): prob = Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = NewtonSolver(rtol=1.0e-5) g1.options['assembled_jac_type'] = 'dense' g1.linear_solver = DirectSolver(assemble_jac=True) g2 = model.g2 g2.nonlinear_solver = NewtonSolver(rtol=1.0e-5) g2.linear_solver = DirectSolver(assemble_jac=True) g2.options['assembled_jac_type'] = 'dense' model.nonlinear_solver = NewtonSolver(solve_subsystems=True) model.linear_solver = ScipyKrylov(assemble_jac=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_list_residuals_with_tol(self): from openmdao.test_suite.components.sellar import SellarImplicitDis1, SellarImplicitDis2 from openmdao.api import Problem, Group, IndepVarComp, NewtonSolver, ScipyKrylov, LinearBlockGS 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.linear_solver = ScipyKrylov() model.linear_solver.precon = LinearBlockGS() prob.setup(check=False) prob.set_solver_print(level=-1) prob.run_model() outputs = model.list_outputs(residuals_tol=0.01, residuals=True) print(outputs)
def test_implicit_component(self): class TestImplCompArrayDense(TestImplCompArray): def setup(self): super(TestImplCompArrayDense, self).setup() self.declare_partials('*', '*', method='cs') prob = self.prob = Problem() model = prob.model = Group() model.add_subsystem('p_rhs', IndepVarComp('rhs', val=np.ones(2))) sub = model.add_subsystem('sub', Group()) comp = sub.add_subsystem('comp', TestImplCompArrayDense()) model.connect('p_rhs.rhs', 'sub.comp.rhs') model.linear_solver = ScipyKrylov() prob.setup(check=False) prob.run_model() model.run_linearize() Jfd = comp.jacobian._subjacs assert_rel_error(self, Jfd['sub.comp.x', 'sub.comp.rhs'], -np.eye(2), 1e-6) assert_rel_error(self, Jfd['sub.comp.x', 'sub.comp.x'], comp.mtx, 1e-6)
def runs_successfully(use_scal, coeffs): prob = Problem(model=Group()) prob.model.add_subsystem( 'row1', ScalingTestComp(row=1, coeffs=coeffs, use_scal=use_scal)) prob.model.add_subsystem( 'row2', ScalingTestComp(row=2, coeffs=coeffs, use_scal=use_scal)) prob.model.connect('row1.y', 'row2.x') prob.model.connect('row2.y', 'row1.x') prob.model.nonlinear_solver = NewtonSolver(maxiter=2, atol=1e-5, rtol=0) prob.model.nonlinear_solver.linear_solver = ScipyKrylov(maxiter=1) prob.set_solver_print(level=0) prob.setup(check=False) result = prob.run_model() success = not result[0] return success
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(CountDS, 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)
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() sub.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)
def configure(self): # This will solve it. self.sub.nonlinear_solver = NewtonSolver() self.sub.linear_solver = ScipyKrylov()
def test_guess_nonlinear_feature(self): from openmdao.api import Problem, Group, ImplicitComponent, IndepVarComp, NewtonSolver, ScipyKrylov class ImpWithInitial(ImplicitComponent): def setup(self): self.add_input('a', val=1.) self.add_input('b', val=1.) self.add_input('c', val=1.) 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 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 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 self.inv_jac = 1.0 / (2 * a * x + b) def solve_nonlinear(self, inputs, outputs): """ Do nothing. """ pass def guess_nonlinear(self, inputs, outputs, resids): # Solution at 1 and 3. Default value takes us to -1 solution. Here # we set it to a value that will tke us to the 3 solution. outputs['x'] = 5.0 prob = Problem() model = prob.model = Group() model.add_subsystem('pa', IndepVarComp('a', 1.0)) model.add_subsystem('pb', IndepVarComp('b', 1.0)) model.add_subsystem('pc', IndepVarComp('c', 1.0)) model.add_subsystem('comp2', ImpWithInitial()) model.connect('pa.a', 'comp2.a') model.connect('pb.b', 'comp2.b') model.connect('pc.c', 'comp2.c') model.nonlinear_solver = NewtonSolver() model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 1 model.linear_solver = ScipyKrylov() prob.setup(check=False) prob['pa.a'] = 1. prob['pb.b'] = -4. prob['pc.c'] = 3. prob.run_model() assert_rel_error(self, prob['comp2.x'], 3.)
class demoComp(ImplicitComponent): """ x + y + xy = 2 """ def setup(self): self.add_input('x', val=1.0) self.add_output('y', val=0.) self.declare_partials('*', '*', method='fd') def apply_nonlinear(self, inputs, outputs, residuals): x = inputs['x'] y = outputs['y'] residuals['y'] = 2 * x + y - 2 from openmdao.api import Problem, Group, IndepVarComp, NewtonSolver, ScipyKrylov problem = Problem() model = problem.model = Group() model.add_subsystem('x', IndepVarComp('x', 1.0)) model.add_subsystem('demoComp', demoComp()) model.connect('x.x', 'demoComp.x') model.nonlinear_solver = NewtonSolver() model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 1 model.linear_solver = ScipyKrylov() problem.setup(check=True) totals = problem.compute_totals(['demoComp.y'], ['x.x']) print(totals)
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_hierarchy_list_vars_options(self): prob = Problem() model = prob.model model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0]))) sub1 = model.add_subsystem('sub1', Group()) sub2 = sub1.add_subsystem('sub2', Group()) g1 = sub2.add_subsystem('g1', SubSellar()) g2 = model.add_subsystem('g2', SubSellar()) model.connect('pz.z', 'sub1.sub2.g1.z') model.connect('sub1.sub2.g1.y2', 'g2.x') model.connect('g2.y2', 'sub1.sub2.g1.x') model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 0 g1.nonlinear_solver = NewtonSolver() g1.linear_solver = LinearBlockGS() g2.nonlinear_solver = NewtonSolver() g2.linear_solver = ScipyKrylov() g2.linear_solver.precon = LinearBlockGS() g2.linear_solver.precon.options['maxiter'] = 2 prob.setup(check=False) prob.run_driver() # logging inputs # out_stream - not hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_inputs(values=True, units=True, hierarchical=False, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("10 Input(s) in 'model'")) # make sure they are in the correct order self.assertTrue(text.find("sub1.sub2.g1.d1.z") < text.find('sub1.sub2.g1.d1.x') < text.find('sub1.sub2.g1.d1.y2') < text.find('sub1.sub2.g1.d2.z') < text.find('sub1.sub2.g1.d2.y1') < text.find('g2.d1.z') < text.find('g2.d1.x') < text.find('g2.d1.y2') < text.find('g2.d2.z') < text.find('g2.d2.y1')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(14, num_non_empty_lines) # out_stream - hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_inputs(values=True, units=True, hierarchical=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("10 Input(s) in 'model'")) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(23, num_non_empty_lines) self.assertEqual(1, text.count('top')) self.assertEqual(1, text.count(' sub1')) self.assertEqual(1, text.count(' sub2')) self.assertEqual(1, text.count(' g1')) self.assertEqual(1, text.count(' d1')) self.assertEqual(2, text.count(' z')) # logging outputs # out_stream - not hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('5 Explicit Output'), 1) # make sure they are in the correct order self.assertTrue(text.find("pz.z") < text.find('sub1.sub2.g1.d1.y1') < text.find('sub1.sub2.g1.d2.y2') < text.find('g2.d1.y1') < text.find('g2.d2.y2')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(11, num_non_empty_lines) # Hierarchical stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('top'), 1) self.assertEqual(text.count(' y1'), 1) self.assertEqual(text.count(' g2'), 1) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(num_non_empty_lines, 21)
def test_simple_implicit(self): prob = Problem(Group()) prob.model.add_subsystem('p1', IndepVarComp('x', 0.5)) prob.model.add_subsystem('comp', SimpleImplicitComp()) prob.model.linear_solver = ScipyKrylov() prob.model.nonlinear_solver = NewtonSolver() prob.set_solver_print(level=0) prob.model.connect('p1.x', 'comp.x') # fwd mode prob.setup(check=False, mode='fwd') prob.run_model() assert_rel_error(self, prob['comp.z'], 2.666, 1e-3) self.assertLess(prob.model.nonlinear_solver._iter_count, 5) J = prob.compute_totals(of=['comp.y', 'comp.z'], wrt=['p1.x']) assert_rel_error(self, J[('comp.y', 'p1.x')][0][0], -2.5555511, 1e-5) assert_rel_error(self, J[('comp.z', 'p1.x')][0][0], -1.77777777, 1e-5) # rev mode prob.setup(check=False, mode='rev') prob.run_model() assert_rel_error(self, prob['comp.z'], 2.666, 1e-3) self.assertLess(prob.model.nonlinear_solver._iter_count, 5) J = prob.compute_totals(of=['comp.y', 'comp.z'], wrt=['p1.x']) assert_rel_error(self, J[('comp.y', 'p1.x')][0][0], -2.5555511, 1e-5) assert_rel_error(self, J[('comp.z', 'p1.x')][0][0], -1.77777777, 1e-5) # Check partials data = prob.check_partials() for key1, val1 in iteritems(data): for key2, val2 in iteritems(val1): assert_rel_error(self, val2['abs error'][0], 0.0, 1e-5) assert_rel_error(self, val2['abs error'][1], 0.0, 1e-5) assert_rel_error(self, val2['abs error'][2], 0.0, 1e-5) assert_rel_error(self, data['comp'][('y', 'x')]['J_fwd'][0][0], 1.0, 1e-6) assert_rel_error(self, data['comp'][('y', 'z')]['J_fwd'][0][0], 2.0, 1e-6) assert_rel_error(self, data['comp'][('z', 'x')]['J_fwd'][0][0], 2.66666667, 1e-6) assert_rel_error(self, data['comp'][('z', 'z')]['J_fwd'][0][0], 1.5, 1e-6) # list inputs inputs = prob.model.list_inputs(out_stream=None) self.assertEqual(sorted(inputs), [('comp.x', [0.5])]) # list explicit outputs outputs = sorted( prob.model.list_outputs(implicit=False, out_stream=None)) self.assertEqual(len(outputs), 2) self.assertEqual(outputs[0][0], 'comp.y') assert_rel_error(self, outputs[0][1], 5.8333333, 1e-6) self.assertEqual(outputs[1][0], 'p1.x') assert_rel_error(self, outputs[1][1], 0.5, 1e-6) # list states states = prob.model.list_outputs(explicit=False, out_stream=None) self.assertEqual(len(states), 1) self.assertEqual(states[0][0], 'comp.z') assert_rel_error(self, states[0][1], 2.6666667, 1e-6) # list residuals resids = sorted(prob.model.list_residuals(out_stream=None)) self.assertEqual(len(resids), 3) self.assertEqual(resids[0][0], 'comp.y') assert_rel_error(self, resids[0][1], 0., 1e-6) self.assertEqual(resids[1][0], 'comp.z') assert_rel_error(self, resids[1][1], 0., 1e-6) self.assertEqual(resids[2][0], 'p1.x') assert_rel_error(self, resids[2][1], 0., 1e-6)
def __init__(self, **kwargs): super(Sellar, self).__init__(**kwargs) self.nonlinear_solver = RecklessNonlinearBlockGS() self.linear_solver = ScipyKrylov()