def test_viewer_data_from_subgroup(self):
        """
        Test error message when asking for viewer data for a subgroup.
        """
        p = om.Problem(model=SellarStateConnection())
        p.setup()

        msg = "Viewer data is not available for sub-Group 'sub'."
        with assert_warning(UserWarning, msg):
            _get_viewer_data(p.model.sub)
    def test_viewer_data_from_None(self):
        """
        Test error message when asking for viewer data for an invalid source.
        """
        p = om.Problem(model=SellarStateConnection())
        p.setup()

        msg = "Viewer data is not available for 'None'." + \
              "The source must be a Problem, model or the filename of a recording."

        with self.assertRaises(TypeError) as cm:
            _get_viewer_data(None)

        self.assertEquals(str(cm.exception), msg)
    def test_model_viewer_has_correct_data_from_sqlite(self):
        """
        Verify that the correct data exists when a model structure is recorded
        and then pulled out of a sqlite db file and compared to the expected
        structure.  Uses the SellarStateConnection model.
        """
        p = om.Problem(model=SellarStateConnection())

        r = SqliteRecorder(self.sqlite_db_filename)
        p.driver.add_recorder(r)

        p.setup()
        p.final_setup()
        r.shutdown()

        model_viewer_data = _get_viewer_data(self.sqlite_db_filename)

        with open(os.path.join(self.parent_dir,
                               'sellar_tree.json')) as json_file:
            expected_tree = json.load(json_file)

        # check expected model tree
        self.check_model_viewer_data(
            model_viewer_data, expected_tree, self.expected_pathnames,
            self.expected_conns, self.expected_abs2prom,
            self.expected_declare_partials, self.expected_driver_name,
            self.expected_design_vars_names, self.expected_responses_names)
def record_viewer_data(problem):
    """
    Record model viewer data for all recorders that have that option enabled.

    We don't want to collect the viewer data if it's not needed though,
    so first we'll find all recorders that need the data (if any) and
    then record it for those recorders.

    Parameters
    ----------
    problem : Problem
        The problem for which model viewer data is to be recorded.
    """
    # get all recorders that need to record the viewer data
    recorders = set(_get_all_viewer_data_recorders(problem))

    # if any recorders were found, get the viewer data and record it
    if recorders:
        from openmdao.visualization.n2_viewer.n2_viewer import _get_viewer_data
        viewer_data = _get_viewer_data(problem)
        viewer_data['md5_hash'] = problem.model._generate_md5_hash()
        viewer_data.pop('abs2prom',
                        None)  # abs2prom already recorded in metadata table
        for recorder in recorders:
            recorder.record_viewer_data(viewer_data)
Beispiel #5
0
    def test_index_number(self):
        prob = om.Problem()
        model = prob.model

        model.add_subsystem('p1', om.IndepVarComp('x', 0.0), promotes=['x'])
        model.add_subsystem('p2', om.IndepVarComp('y', 0.0), promotes=['y'])
        model.add_subsystem('comp', Paraboloid(), promotes=['x', 'y', 'f_xy'])

        model.add_design_var('x', lower=0.0, upper=1.0)
        model.add_design_var('y', lower=0.0, upper=1.0)
        model.add_objective('f_xy')

        prob.driver = om.DOEDriver(om.PlackettBurmanGenerator())
        prob.driver.add_recorder(self.recorder)

        prob.setup()
        prob.run_driver()
        prob.cleanup()

        data_dict = _get_viewer_data(self.filename, case_id=3)

        vals = data_dict['tree']['children'][2]['children']
        x_val = vals[0]['value']
        y_val = vals[1]['value']
        f_xy_val = vals[2]['value']

        self.assertEqual(x_val, "N/A")
        self.assertEqual(y_val, "N/A")
        self.assertEqual(f_xy_val, np.array([27.]))
Beispiel #6
0
    def test_model_viewer_has_correct_data_from_problem(self):
        """
        Verify that the correct model structure data exists when stored as compared
        to the expected structure, using the SellarStateConnection model.
        """
        p = om.Problem(model=SellarStateConnection())
        p.setup()
        p.final_setup()

        model_viewer_data = _get_viewer_data(p)

        with open(os.path.join(self.parent_dir, 'sellar_tree.json')) as json_file:
            expected_tree = json.load(json_file)

        # check expected model tree
        self.check_model_viewer_data(
            model_viewer_data,
            expected_tree,
            self.expected_pathnames,
            self.expected_conns,
            self.expected_abs2prom,
            self.expected_declare_partials,
            self.expected_driver_name,
            self.expected_design_vars_names,
            self.expected_responses_names
        )
    def test_initial_value(self):
        E = 1.
        L = 1.
        b = 0.1
        volume = 0.01

        num_cp = 5
        num_elements = 50
        num_load_cases = 2

        prob = om.Problem(
            model=MultipointBeamGroup(E=E,
                                      L=L,
                                      b=b,
                                      volume=volume,
                                      num_elements=num_elements,
                                      num_cp=num_cp,
                                      num_load_cases=num_load_cases))

        prob.driver = om.ScipyOptimizeDriver(optimizer='SLSQP', tol=1e-9)
        prob.setup()
        prob.run_driver()

        h = prob['interp.h']
        expected = np.array([
            0.14122705, 0.14130706, 0.14154096, 0.1419107, 0.14238706,
            0.14293095, 0.14349514, 0.14402636, 0.1444677, 0.14476123,
            0.14485062, 0.14468388, 0.14421589, 0.1434107, 0.14224356,
            0.14070252, 0.13878952, 0.13652104, 0.13392808, 0.13105565,
            0.1279617, 0.12471547, 0.1213954, 0.11808665, 0.11487828,
            0.11185599, 0.10900669, 0.10621949, 0.10338308, 0.10039485,
            0.09716531, 0.09362202, 0.08971275, 0.08540785, 0.08070168,
            0.07561313, 0.0701851, 0.06448311, 0.05859294, 0.05261756,
            0.0466733, 0.04088557, 0.03538417, 0.03029845, 0.02575245,
            0.02186027, 0.01872173, 0.01641869, 0.0150119, 0.01453876
        ])

        assert np.linalg.norm(h - expected) < 1e-6

        def check_initial_value(subsys, parallel=False):
            """
            check that 'initial_value' is indicated for variables under a parallel group
            """
            if subsys['type'] == 'subsystem':
                # Group or Component, recurse to children
                parallel = parallel or subsys['class'] == 'ParallelGroup'
                for child in subsys['children']:
                    check_initial_value(child, parallel)
            else:
                # input or output, check for 'initial_value' flag
                if parallel:
                    assert ('initial_value' in subsys
                            and subsys['initial_value'] is True)
                else:
                    assert ('initial_value' not in subsys)

        model_data = _get_viewer_data(prob)
        for subsys in model_data['tree']['children']:
            check_initial_value(subsys)
Beispiel #8
0
 def __init__(self, problem, depth, scalar):
     data = _get_viewer_data(problem)
     self.problem = problem
     self.depth = depth
     self.scalar = scalar
     self.tree = data["tree"]
     self.connections = data["connections_list"]
     self.vars = {"in": {}, "out": {}}
     self.vardescs = {}
     self.discmap = {}
     self.mdas = {}
    def test_model_viewer_has_correct_data_from_problem(self):
        """
        Verify that the correct model structure data exists when stored as compared
        to the expected structure, using the SellarStateConnection model.
        """
        p = Problem(model=SellarStateConnection())
        p.setup()
        p.final_setup()

        model_viewer_data = _get_viewer_data(p)

        # check expected model tree
        self.check_model_viewer_data(
            model_viewer_data, self.expected_tree, self.expected_pathnames,
            self.expected_conns, self.expected_abs2prom,
            self.expected_declare_partials, self.expected_driver_name,
            self.expected_design_vars_names, self.expected_responses_names)
Beispiel #10
0
    def test_model_viewer_has_correct_data_from_sqlite(self):
        """
        Verify that the correct data exists when a model structure is recorded
        and then pulled out of a sqlite db file and compared to the expected
        structure.  Uses the SellarStateConnection model.
        """
        p = Problem(model=SellarStateConnection())

        r = SqliteRecorder(self.sqlite_db_filename)
        p.driver.add_recorder(r)

        p.setup()
        p.final_setup()
        r.shutdown()

        model_viewer_data = _get_viewer_data(self.sqlite_db_filename)
        print(model_viewer_data['tree'])

        # check expected model tree
        self.assertDictEqual(model_viewer_data['tree'], self.expected_tree)

        # check expected system pathnames
        pathnames = model_viewer_data['sys_pathnames_list']
        self.assertListEqual(sorted(pathnames), self.expected_pathnames)

        # check expected connections, after mapping cycle_arrows indices back to pathnames
        connections = sorted(model_viewer_data['connections_list'],
                             key=lambda x: (x['tgt'], x['src']))
        for conn in connections:
            if 'cycle_arrows' in conn:
                cycle_arrows = []
                for src, tgt in conn['cycle_arrows']:
                    cycle_arrows.append(' '.join(
                        [pathnames[src], pathnames[tgt]]))
                conn['cycle_arrows'] = sorted(cycle_arrows)
        self.assertEqual(len(connections), len(self.expected_conns))
        for c, ex in zip(connections, self.expected_conns):
            self.assertEqual(c['src'], ex['src'])
            self.assertEqual(c['tgt'], ex['tgt'])
            self.assertEqual(c.get('cycle_arrows', []),
                             ex.get('cycle_arrows', []))

        # check expected abs2prom map
        self.assertDictEqual(model_viewer_data['abs2prom'],
                             self.expected_abs2prom)
Beispiel #11
0
    def test_handle_ndarray_system_option(self):
        class SystemWithNdArrayOption(om.ExplicitComponent):
            def initialize(self):
                self.options.declare('arr', types=(np.ndarray,))

            def setup(self):
                self.add_input('x', val=0.0)
                self.add_output('f_x', val=0.0)

            def compute(self, inputs, outputs):
                x = inputs['x']
                outputs['f_x'] = (x - 3.0) ** 2

        prob = om.Problem()
        prob.model.add_subsystem('comp', SystemWithNdArrayOption(arr=np.ones(2)))
        prob.setup()
        model_viewer_data = _get_viewer_data(prob)
        np.testing.assert_equal(model_viewer_data['tree']['children'][1]['options']['arr'],
                                np.ones(2))
Beispiel #12
0
def record_viewer_data(problem):
    """
    Record model viewer data for all recorders that have that option enabled.

    We don't want to collect the viewer data if it's not needed though,
    so first we'll find all recorders that need the data (if any) and
    then record it for those recorders.

    Parameters
    ----------
    problem : Problem
        The problem for which model viewer data is to be recorded.
    """
    # assemble list of all objects that may have recorders
    systems = [
        system for system in problem.model.system_iter(include_self=True,
                                                       recurse=True)
    ]
    nl_solv = [
        system._nonlinear_solver for system in systems
        if system._nonlinear_solver
    ]
    ls_solv = [
        nl.linesearch for nl in nl_solv
        if hasattr(nl, 'linesearch') and nl.linesearch
    ]
    rec_obj = [problem, problem.driver] + systems + nl_solv + ls_solv

    # get all recorders that need to record the viewer data
    recorders = set()
    for obj in rec_obj:
        for recorder in obj._rec_mgr._recorders:
            if recorder._record_viewer_data:
                recorders.add(recorder)

    # if any recorders were found, get the viewer data and record it
    if recorders:
        from openmdao.visualization.n2_viewer.n2_viewer import _get_viewer_data
        viewer_data = _get_viewer_data(problem)
        for recorder in recorders:
            recorder.record_viewer_data(viewer_data)
Beispiel #13
0
    def test_auto_ivc_case(self):
        prob = SellarProblem(SellarDerivativesGrouped)

        prob.driver = om.ScipyOptimizeDriver(tol=1e-9, disp=False)
        prob.driver.add_recorder(self.recorder)

        prob.setup()
        prob.run_driver()
        prob.cleanup()

        cr = om.CaseReader(self.filename)
        first_case = cr.list_cases()[0]

        data_dict = _get_viewer_data(self.filename, case_id=first_case)

        vals = data_dict['tree']['children'][0]['children']
        ivc_0_val = vals[0]['value']
        ivc_1_val = vals[1]['value']

        self.assertEqual(ivc_0_val, [5., 2])
        self.assertEqual(ivc_1_val, np.array([1.]))
Beispiel #14
0
    def test_model_viewer_has_correct_data_from_problem(self):
        """
        Verify that the correct model structure data exists when stored as compared
        to the expected structure, using the SellarStateConnection model.
        """
        p = Problem(model=SellarStateConnection())
        p.setup()

        model_viewer_data = _get_viewer_data(p)

        # check expected model tree
        self.assertDictEqual(model_viewer_data['tree'], self.expected_tree)

        # check expected system pathnames
        pathnames = model_viewer_data['sys_pathnames_list']
        self.assertListEqual(sorted(pathnames), self.expected_pathnames)

        # check expected connections, after mapping cycle_arrows indices back to pathnames
        connections = sorted(model_viewer_data['connections_list'],
                             key=lambda x: (x['tgt'], x['src']))
        for conn in connections:
            if 'cycle_arrows' in conn and conn['cycle_arrows']:
                cycle_arrows = []
                for src, tgt in conn['cycle_arrows']:
                    cycle_arrows.append(' '.join(
                        [pathnames[src], pathnames[tgt]]))
                conn['cycle_arrows'] = sorted(cycle_arrows)
        self.assertEqual(len(connections), len(self.expected_conns))
        for c, ex in zip(connections, self.expected_conns):
            self.assertEqual(c['src'], ex['src'])
            self.assertEqual(c['tgt'], ex['tgt'])
            self.assertEqual(c.get('cycle_arrows', []),
                             ex.get('cycle_arrows', []))

        # check expected abs2prom map
        self.assertDictEqual(model_viewer_data['abs2prom'],
                             self.expected_abs2prom)
Beispiel #15
0
    def test_model_viewer_has_correct_data_from_optimization_problem(self):
        """
        Verify that the correct model structure data exists when stored as compared
        to the expected structure, using the ActuatorDisc model.
        """

        # build the model
        prob = Problem()
        indeps = prob.model.add_subsystem('indeps',
                                          IndepVarComp(),
                                          promotes=['*'])
        indeps.add_output('a', .5)
        indeps.add_output('Area', 10.0, units='m**2')
        indeps.add_output('rho', 1.225, units='kg/m**3')
        indeps.add_output('Vu', 10.0, units='m/s')

        prob.model.add_subsystem('a_disk',
                                 ActuatorDisc(),
                                 promotes_inputs=['a', 'Area', 'rho', 'Vu'])

        # setup the optimization
        prob.driver = ScipyOptimizeDriver()
        prob.driver.options['optimizer'] = 'SLSQP'

        prob.model.add_design_var('a', lower=0., upper=1.)
        prob.model.add_design_var('Area', lower=0., upper=1.)

        # negative one so we maximize the objective
        prob.model.add_objective('a_disk.Cp', scaler=-1)

        prob.setup()
        prob.final_setup()

        model_viewer_data = _get_viewer_data(prob)

        expected_tree_betz = json.loads("""
                    {"name": "root", "type": "root", "class": "Group", "component_type": null,
                     "subsystem_type": "group", "is_parallel": false, "linear_solver": "LN: RUNONCE",
                     "nonlinear_solver": "NL: RUNONCE", "children": [
                        {"name": "indeps", "type": "subsystem", "class": "IndepVarComp",
                         "subsystem_type": "component", "is_parallel": false, "component_type": "indep",
                         "linear_solver": "", "nonlinear_solver": "", "children": [
                            {"name": "a", "type": "unknown", "implicit": false, "dtype": "ndarray"},
                            {"name": "Area", "type": "unknown", "implicit": false, "dtype": "ndarray"},
                            {"name": "rho", "type": "unknown", "implicit": false, "dtype": "ndarray"},
                            {"name": "Vu", "type": "unknown", "implicit": false, "dtype": "ndarray"}]},
                        {"name": "a_disk", "type": "subsystem", "class": "ActuatorDisc",
                         "subsystem_type": "component", "is_parallel": false, "component_type": "explicit",
                         "linear_solver": "", "nonlinear_solver": "",
                         "children": [{"name": "a", "type": "param", "dtype": "ndarray"},
                                      {"name": "Area", "type": "param", "dtype": "ndarray"},
                                      {"name": "rho", "type": "param", "dtype": "ndarray"},
                                      {"name": "Vu", "type": "param", "dtype": "ndarray"},
                                      {"name": "Vr", "type": "unknown", "implicit": false,
                                       "dtype": "ndarray"},
                                      {"name": "Vd", "type": "unknown", "implicit": false,
                                       "dtype": "ndarray"},
                                      {"name": "Ct", "type": "unknown", "implicit": false,
                                       "dtype": "ndarray"},
                                      {"name": "thrust", "type": "unknown", "implicit": false,
                                       "dtype": "ndarray"},
                                      {"name": "Cp", "type": "unknown", "implicit": false,
                                       "dtype": "ndarray"},
                                      {"name": "power", "type": "unknown", "implicit": false,
                                       "dtype": "ndarray"}]}]}
                    """)
        expected_pathnames_betz = json.loads('[]')
        expected_conns_betz = json.loads("""
                [{"src": "indeps.a", "tgt": "a_disk.a"}, {"src": "indeps.Area", "tgt": "a_disk.Area"},
                 {"src": "indeps.rho", "tgt": "a_disk.rho"}, {"src": "indeps.Vu", "tgt": "a_disk.Vu"}]
                """)
        expected_abs2prom_betz = json.loads("""
                    {"input": {"a_disk.a": "a", "a_disk.Area": "Area", "a_disk.rho": "rho", "a_disk.Vu": "Vu"},
                    "output": {"indeps.a": "a", "indeps.Area": "Area", "indeps.rho": "rho", "indeps.Vu": "Vu",
                    "a_disk.Vr": "a_disk.Vr", "a_disk.Vd": "a_disk.Vd", "a_disk.Ct": "a_disk.Ct",
                    "a_disk.thrust": "a_disk.thrust", "a_disk.Cp": "a_disk.Cp",
                    "a_disk.power": "a_disk.power"}}
                    """)
        expected_declare_partials_betz = json.loads("""
                ["indeps.a > indeps.a", "indeps.Area > indeps.Area", "indeps.rho > indeps.rho", "indeps.Vu > indeps.Vu", "a_disk.Vr > a_disk.a", "a_disk.Vr > a_disk.Vu", "a_disk.Vd > a_disk.a", "a_disk.Ct > a_disk.a", "a_disk.thrust > a_disk.a", "a_disk.thrust > a_disk.Area", "a_disk.thrust > a_disk.rho", "a_disk.thrust > a_disk.Vu", "a_disk.Cp > a_disk.a", "a_disk.power > a_disk.a", "a_disk.power > a_disk.Area", "a_disk.power > a_disk.rho", "a_disk.power > a_disk.Vu", "a_disk.Vr > a_disk.Vr", "a_disk.Vd > a_disk.Vd", "a_disk.Ct > a_disk.Ct", "a_disk.thrust > a_disk.thrust", "a_disk.Cp > a_disk.Cp", "a_disk.power > a_disk.power"]
        """)

        expected_driver_name = 'ScipyOptimizeDriver'
        expected_design_vars_names = ['indeps.a', 'indeps.Area']
        expected_responses_names = [
            'a_disk.Cp',
        ]

        # check expected model tree
        self.check_model_viewer_data(
            model_viewer_data,
            expected_tree_betz,
            expected_pathnames_betz,
            expected_conns_betz,
            expected_abs2prom_betz,
            expected_declare_partials_betz,
            expected_driver_name,
            expected_design_vars_names,
            expected_responses_names,
        )
Beispiel #16
0
    def test_obj_pass(self):
        prob = om.Problem()
        model = prob.model

        G = model.add_subsystem('G', om.ParallelGroup(), promotes_inputs=['x'])

        G1 = G.add_subsystem('G1', om.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', om.Group(), promotes_inputs=['x'])
        G2.add_subsystem('C2_1', ObjAdderCompEx(_DiscreteVal(5)), 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['x'] =  _DiscreteVal(19)

        prob.run_model()

        self.assertEqual(prob['C3.y'].getval(), 40)
        self.assertEqual(prob['C4.y'].getval(), 56)

        def _var_iter(obj):
            name = obj['name']
            if 'children' in obj:
                for c in obj['children']:
                    for vname in _var_iter(c):
                        if name:
                            yield '.'.join((name, vname))
                        else:
                            yield vname
            else:
                yield name

        # add a test to see if discrete vars show up in n2
        data = _get_viewer_data(prob)
        findvars = [
            '_auto_ivc.v0',
            'G.G1.C1_1.x',
            'G.G1.C1_1.y',
            'G.G1.C1_2.x',
            'G.G1.C1_2.y',
            'G.G2.C2_1.x',
            'G.G2.C2_1.y',
            'G.G2.C2_2.x',
            'G.G2.C2_2.y',
            'C3.x',
            'C3.y',
            'C4.x',
            'C4.y',
        ]
        vnames = list(_var_iter(data['tree']))
        self.assertTrue(sorted(findvars), sorted(vnames))
    def test_model_viewer_has_correct_data_from_optimization_problem(self):
        """
        Verify that the correct model structure data exists when stored as compared
        to the expected structure, using the ActuatorDisc model.
        """

        # build the model
        prob = om.Problem()
        indeps = prob.model.add_subsystem('indeps',
                                          om.IndepVarComp(),
                                          promotes=['*'])
        indeps.add_output('a', .5)
        indeps.add_output('Area', 10.0, units='m**2')
        indeps.add_output('rho', 1.225, units='kg/m**3')
        indeps.add_output('Vu', 10.0, units='m/s')

        prob.model.add_subsystem('a_disk',
                                 ActuatorDisc(),
                                 promotes_inputs=['a', 'Area', 'rho', 'Vu'])

        # setup the optimization
        prob.driver = om.ScipyOptimizeDriver()
        prob.driver.options['optimizer'] = 'SLSQP'

        prob.model.add_design_var('a', lower=0., upper=1.)
        prob.model.add_design_var('Area', lower=0., upper=1.)

        # negative one so we maximize the objective
        prob.model.add_objective('a_disk.Cp', scaler=-1)

        prob.setup()
        prob.final_setup()

        model_viewer_data = _get_viewer_data(prob)

        # To generate the reference JSON file, use this code
        # from openmdao.utils.testing_utils import _ModelViewerDataTreeEncoder
        # with open('betz_tree_new.json', 'w') as outfile:
        #    json.dump(model_viewer_data['tree'], outfile,cls=_ModelViewerDataTreeEncoder, indent=4)

        with open(os.path.join(self.parent_dir,
                               'betz_tree.json')) as json_file:
            expected_tree_betz = json.load(json_file)

        expected_pathnames_betz = json.loads('[]')
        expected_conns_betz = json.loads("""
                [{"src": "indeps.a", "tgt": "a_disk.a"}, {"src": "indeps.Area", "tgt": "a_disk.Area"},
                 {"src": "indeps.rho", "tgt": "a_disk.rho"}, {"src": "indeps.Vu", "tgt": "a_disk.Vu"}]
                """)
        expected_abs2prom_betz = json.loads("""
                    {"input": {"a_disk.a": "a", "a_disk.Area": "Area", "a_disk.rho": "rho", "a_disk.Vu": "Vu"},
                    "output": {"indeps.a": "a", "indeps.Area": "Area", "indeps.rho": "rho", "indeps.Vu": "Vu",
                    "a_disk.Vr": "a_disk.Vr", "a_disk.Vd": "a_disk.Vd", "a_disk.Ct": "a_disk.Ct",
                    "a_disk.thrust": "a_disk.thrust", "a_disk.Cp": "a_disk.Cp",
                    "a_disk.power": "a_disk.power"}}
                    """)
        expected_declare_partials_betz = json.loads("""
                ["a_disk.Vr > a_disk.a", "a_disk.Vr > a_disk.Vu", "a_disk.Vd > a_disk.a", "a_disk.Ct > a_disk.a", "a_disk.thrust > a_disk.a", "a_disk.thrust > a_disk.Area", "a_disk.thrust > a_disk.rho", "a_disk.thrust > a_disk.Vu", "a_disk.Cp > a_disk.a", "a_disk.power > a_disk.a", "a_disk.power > a_disk.Area", "a_disk.power > a_disk.rho", "a_disk.power > a_disk.Vu"]
        """)

        expected_driver_name = 'ScipyOptimizeDriver'
        expected_design_vars_names = ['indeps.a', 'indeps.Area']
        expected_responses_names = [
            'a_disk.Cp',
        ]

        # check expected model tree
        self.check_model_viewer_data(
            model_viewer_data,
            expected_tree_betz,
            expected_pathnames_betz,
            expected_conns_betz,
            expected_abs2prom_betz,
            expected_declare_partials_betz,
            expected_driver_name,
            expected_design_vars_names,
            expected_responses_names,
        )