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)
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.]))
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)
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)
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)
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))
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)
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.]))
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)
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, )
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, )