def test_specify_subgroup_solvers(self): import openmdao.api as om from openmdao.test_suite.components.double_sellar import DoubleSellar prob = om.Problem() model = prob.model = DoubleSellar() # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g1.linear_solver = om.DirectSolver() # used for derivatives g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g2.linear_solver = om.DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = om.NonlinearBlockGS(rtol=1.0e-5) model.linear_solver = om.ScipyKrylov() model.linear_solver.precon = om.LinearBlockGS() prob.setup() prob.run_model() assert_near_equal(prob.get_val('g1.y1'), 0.64, .00001) assert_near_equal(prob.get_val('g1.y2'), 0.80, .00001) assert_near_equal(prob.get_val('g2.y1'), 0.64, .00001) assert_near_equal(prob.get_val('g2.y2'), 0.80, .00001)
def test_specify_precon(self): import numpy as np from openmdao.api import Problem, ScipyKrylov, NewtonSolver, LinearBlockGS, \ DirectSolver from openmdao.test_suite.components.double_sellar import DoubleSellar prob = Problem(model=DoubleSellar()) model = prob.model model.nonlinear_solver = NewtonSolver() model.nonlinear_solver.linesearch = BoundsEnforceLS() model.linear_solver = ScipyKrylov() model.g1.linear_solver = DirectSolver() model.g2.linear_solver = DirectSolver() model.linear_solver.precon = LinearBlockGS() # TODO: This should work with 1 iteration. #model.linear_solver.precon.options['maxiter'] = 1 prob.setup() prob.set_solver_print(level=2) 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_solve_subsystems_assembled_jac_top(self): prob = Problem() model = prob.model = DoubleSellar() model.jacobian = DenseJacobian() g1 = model.get_subsystem('g1') g1.nonlinear_solver = NewtonSolver() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = ScipyIterativeSolver() g2 = model.get_subsystem('g2') g2.nonlinear_solver = NewtonSolver() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = ScipyIterativeSolver() model.nonlinear_solver = NewtonSolver() model.linear_solver = DirectSolver() 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_solve_subsystems_basic_dense_jac_units_scaling(self): prob = Problem(model=DoubleSellar(units=True, scaling=True)) model = prob.model model.jacobian = DenseJacobian() 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.0533333333, .00001) assert_rel_error(self, prob['g1.y2'], 0.80, .00001) assert_rel_error(self, prob['g2.y1'], 0.0533333333, .00001) assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
def test_with_subsolves(self): prob = Problem() model = prob.model = DoubleSellar() 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 model.nonlinear_solver.options['max_sub_solves'] = 4 ls = model.nonlinear_solver.linesearch = ArmijoGoldsteinLS( bound_enforcement='vector') # This is pretty bogus, but it ensures that we get a few LS iterations. ls.options['c'] = 100.0 prob.set_solver_print(level=0) 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 _masking_case(mode): p = Problem() dv = p.model.add_subsystem('dv', IndepVarComp(), promotes=['*']) dv.add_output('z', [1., 1.]) p.model.add_subsystem('double_sellar', DoubleSellar()) p.model.connect('z', ['double_sellar.g1.z', 'double_sellar.g2.z']) p.model.add_design_var('z', lower=-10, upper=10) p.model.add_objective('double_sellar.g1.y1') p.setup(mode=mode) p.model.double_sellar.g1.jacobian = CSCJacobian() p.model.double_sellar.g1.linear_solver = DirectSolver() p.model.double_sellar.g1.nonlinear_solver = NewtonSolver() p.model.double_sellar.g2.jacobian = CSCJacobian() p.model.double_sellar.g2.linear_solver = DirectSolver() p.model.double_sellar.g2.nonlinear_solver = NewtonSolver() p.model.nonlinear_solver = NewtonSolver() p.model.nonlinear_solver.options['solve_subsystems'] = True p.model.linear_solver = ScipyKrylov() p.model.linear_solver.precon = LinearRunOnce() p.run_model() objective = p['double_sellar.g1.y1'] jac = p.compute_totals() return objective, jac
def test_solve_subsystems_assembled_jac_subgroup(self): prob = om.Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, rtol=1.0e-5) g1.linear_solver = om.DirectSolver(assemble_jac=True) model.options['assembled_jac_type'] = 'dense' g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, rtol=1.0e-5) g2.linear_solver = om.DirectSolver() model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) model.linear_solver = om.ScipyKrylov() 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_reraise_child_analysiserror(self): # Raise AnalysisError when it fails to converge prob = om.Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver() g1.nonlinear_solver.options['maxiter'] = 1 g1.nonlinear_solver.options['err_on_non_converge'] = True g1.nonlinear_solver.options['solve_subsystems'] = True g1.linear_solver = om.DirectSolver(assemble_jac=True) g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver() g2.nonlinear_solver.options['maxiter'] = 1 g2.nonlinear_solver.options['err_on_non_converge'] = True g2.nonlinear_solver.options['solve_subsystems'] = True g2.linear_solver = om.DirectSolver(assemble_jac=True) model.nonlinear_solver = om.NewtonSolver() model.linear_solver = om.ScipyKrylov(assemble_jac=True) model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['err_on_non_converge'] = True model.nonlinear_solver.options['reraise_child_analysiserror'] = True prob.setup() with self.assertRaises(om.AnalysisError) as context: prob.run_model() msg = "Solver 'NL: Newton' on system 'g1' failed to converge in 1 iterations." self.assertEqual(str(context.exception), msg)
def test_serial_in_mpi(self): # Tests that we can take an MPI model with a DirectSolver and run it in mpi with more # procs. This verifies fix of a bug. prob = om.Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = om.DirectSolver(assemble_jac=True) g1.options['assembled_jac_type'] = 'dense' g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = om.DirectSolver(assemble_jac=True) g2.options['assembled_jac_type'] = 'dense' model.nonlinear_solver = om.NewtonSolver() model.linear_solver = om.ScipyKrylov(assemble_jac=True) model.options['assembled_jac_type'] = 'dense' model.nonlinear_solver.options['solve_subsystems'] = True prob.set_solver_print(level=0) prob.setup() prob.run_model() assert_near_equal(prob['g1.y1'], 0.64, 1.0e-5) assert_near_equal(prob['g1.y2'], 0.80, 1.0e-5) assert_near_equal(prob['g2.y1'], 0.64, 1.0e-5) assert_near_equal(prob['g2.y2'], 0.80, 1.0e-5)
def test_solve_subsystems_basic_dense_jac_units_scaling(self): prob = om.Problem(model=DoubleSellar(units=True, scaling=True)) model = prob.model g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, rtol=1.0e-5) g1.nonlinear_solver.linesearch = None g1.linear_solver = om.DirectSolver() g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, rtol=1.0e-5) g2.nonlinear_solver.linesearch = None g2.linear_solver = om.DirectSolver() model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) model.nonlinear_solver.linesearch = None model.linear_solver = om.ScipyKrylov(assemble_jac=True) model.options['assembled_jac_type'] = 'dense' prob.setup() prob.run_model() assert_rel_error(self, prob['g1.y1'], 0.0533333333, .00001) assert_rel_error(self, prob['g1.y2'], 0.80, .00001) assert_rel_error(self, prob['g2.y1'], 0.0533333333, .00001) assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
def test_solve_subsystems_basic(self): import openmdao.api as om from openmdao.test_suite.components.double_sellar import DoubleSellar prob = om.Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = om.DirectSolver() g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = om.DirectSolver() model.nonlinear_solver = om.NewtonSolver() model.linear_solver = om.ScipyKrylov() model.nonlinear_solver.options['solve_subsystems'] = True prob.setup() prob.run_model() assert_near_equal(prob.get_val('g1.y1'), 0.64, .00001) assert_near_equal(prob.get_val('g1.y2'), 0.80, .00001) assert_near_equal(prob.get_val('g2.y1'), 0.64, .00001) assert_near_equal(prob.get_val('g2.y2'), 0.80, .00001)
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_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_solve_subsystems_assembled_jac_subgroup(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() g1.jacobian = DenseJacobian() 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() 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, ScipyIterativeSolver, 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.get_subsystem('g1') g1.nonlinear_solver = NewtonSolver() g1.linear_solver = DirectSolver() # used for derivatives g2 = model.get_subsystem('g2') g2.nonlinear_solver = NewtonSolver() g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NonlinearBlockGS() model.nonlinear_solver.options['rtol'] = 1.0e-5 model.linear_solver = ScipyIterativeSolver() 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_assert_no_approx_partials_exception_not_expected(self): prob = Problem() prob.model = DoubleSellar() prob.setup(check=False) assert_no_approx_partials(prob.model, include_self=True, recurse=True)
def _build_model(mode, implicit=False): p = Problem() dv = p.model.add_subsystem('dv', IndepVarComp(), promotes=['*']) dv.add_output('z', [1.,1.]) if implicit: p.model.add_subsystem('double_sellar', DoubleSellarImplicit()) else: p.model.add_subsystem('double_sellar', DoubleSellar()) p.model.connect('z', ['double_sellar.g1.z', 'double_sellar.g2.z']) p.model.add_design_var('z', lower=-10, upper=10) p.model.add_objective('double_sellar.g1.y1') p.setup(mode=mode) p.model.nonlinear_solver = NewtonSolver() return p
def test_solve_subsystems_assembled_jac_top_csc(self): prob = Problem(model=DoubleSellar()) model = prob.model g1 = model.g1 g1.nonlinear_solver = NewtonSolver(rtol=1.0e-5) g1.linear_solver = DirectSolver() g2 = model.g2 g2.nonlinear_solver = NewtonSolver(rtol=1.0e-5) g2.linear_solver = DirectSolver() 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 _baseline(mode): p = Problem() dv = p.model.add_subsystem('dv', IndepVarComp(), promotes=['*']) dv.add_output('z', [1., 1.]) p.model.add_subsystem('double_sellar', DoubleSellar()) p.model.connect('z', ['double_sellar.g1.z', 'double_sellar.g2.z']) p.model.add_design_var('z', lower=-10, upper=10) p.model.add_objective('double_sellar.g1.y1') p.setup(mode=mode) p.model.nonlinear_solver = NewtonSolver() p.model.nonlinear_solver.options['solve_subsystems'] = True p.run_model() objective = p['double_sellar.g1.y1'] jac = p.compute_totals() return objective, jac
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)
import openmdao.api as om from openmdao.test_suite.components.double_sellar import DoubleSellar prob = om.Problem() model = prob.model = DoubleSellar() # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver() g1.linear_solver = om.DirectSolver() # used for derivatives g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver() g2.linear_solver = om.DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = om.NonlinearBlockGS(rtol=1.0e-5) model.linear_solver = om.ScipyKrylov() model.linear_solver.precon = om.LinearBlockGS() prob.setup() prob.run_model()
def setUp(self): # override notebook flag for system, variable table and sqlite_reader from openmdao.core import system from openmdao.utils import variable_table from openmdao.recorders import sqlite_reader system.notebook = variable_table.notebook = sqlite_reader.notebook = True # capture HTML output from variable_table self.html_stream = StringIO() variable_table.HTML = lambda x: self.html_stream.write(x) sqlite_reader.HTML = lambda x: self.html_stream.write(x) # create recorder self.filename = "cases.sql" self.recorder = om.SqliteRecorder(self.filename, record_viewer_data=False) # create & run problem, generate case prob = om.Problem(model=DoubleSellar()) prob.model.add_recorder(self.recorder) prob.setup() prob.set_solver_print(level=0) prob.run_model() prob.cleanup() # expected results self.prob = prob self.expected_inputs = [('g1.d1.x', { 'val': [0.80000] }), ('g1.d1.y2', { 'val': [0.80000] }), ('g1.d1.z', { 'val': [0., 0.] }), ('g1.d2.y1', { 'val': [0.64000] }), ('g1.d2.z', { 'val': [0., 0.] }), ('g2.d1.x', { 'val': [0.80000] }), ('g2.d1.y2', { 'val': [0.80000] }), ('g2.d1.z', { 'val': [0., 0.] }), ('g2.d2.y1', { 'val': [0.64000] }), ('g2.d2.z', { 'val': [0., 0.] })] self.expected_outputs = [('g1.d1.y1', { 'val': [0.64000] }), ('g1.d2.y2', { 'val': [0.80000] }), ('g2.d1.y1', { 'val': [0.64000] }), ('g2.d2.y2', { 'val': [0.80000] })]