Skip to content

Commit

Permalink
Merge pull request #937 from naylor-b/promote_bug
Browse files Browse the repository at this point in the history
added a check to 'openmdao check' that will report any inputs that are explicitly connected and promoted at or above that group.
  • Loading branch information
swryan committed May 23, 2019
2 parents ab8e3fb + 7bb4609 commit 5ad7976
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 2 deletions.
2 changes: 1 addition & 1 deletion openmdao/core/group.py
Expand Up @@ -938,8 +938,8 @@ def _setup_connections(self, recurse=True):
elif not s.options['distributed']:
self._local_system_set.add(s.pathname)

path_len = len(pathname) + 1 if pathname else 0
path_dot = pathname + '.' if pathname else ''
path_len = len(path_dot)

allprocs_abs2meta = self._var_allprocs_abs2meta

Expand Down
2 changes: 1 addition & 1 deletion openmdao/core/system.py
Expand Up @@ -1911,7 +1911,7 @@ def resolve(to_match, io_types, matches, proms):
resolve(self._var_promotes['input'], ('input',), maps, prom_names)
resolve(self._var_promotes['output'], ('output',), maps, prom_names)
else:
resolve(self._var_promotes['any'], ('input', 'output',), maps, prom_names)
resolve(self._var_promotes['any'], ('input', 'output'), maps, prom_names)

return maps

Expand Down
39 changes: 39 additions & 0 deletions openmdao/core/tests/test_group.py
Expand Up @@ -143,6 +143,45 @@ def test_group_simple_promoted(self):
self.assertEqual(p['a'], 3.0)
self.assertEqual(p['comp1.b'], 6.0)

def test_inner_connect_w_extern_promote(self):
p = Problem()
g = p.model.add_subsystem('g', Group(), promotes_inputs=['c0.x'])
g.add_subsystem('ivc', IndepVarComp('x', 2.))
g.add_subsystem('c0', ExecComp('y = 2*x'))
g.connect('ivc.x', 'c0.x')

p.setup()
p.final_setup()

from openmdao.error_checking.check_config import _get_promoted_connected_ins
ins = _get_promoted_connected_ins(p.model)
self.assertEqual(len(ins), 1)
inp, tup = list(ins.items())[0]
in_proms, mans = tup
self.assertEqual(inp, 'g.c0.x')
self.assertEqual(in_proms, ['g'])
self.assertEqual(mans, [('c0.x', 'g')])

def test_inner_connect_w_2extern_promotes(self):
p = Problem()
g0 = p.model.add_subsystem('g0', Group(), promotes_inputs=['c0.x'])
g = g0.add_subsystem('g', Group(), promotes_inputs=['c0.x'])
g.add_subsystem('ivc', IndepVarComp('x', 2.))
g.add_subsystem('c0', ExecComp('y = 2*x'))
g.connect('ivc.x', 'c0.x')

p.setup()
p.final_setup()

from openmdao.error_checking.check_config import _get_promoted_connected_ins
ins = _get_promoted_connected_ins(p.model)
self.assertEqual(len(ins), 1)
inp, tup = list(ins.items())[0]
in_proms, mans = tup
self.assertEqual(inp, 'g0.g.c0.x')
self.assertEqual(list(sorted(in_proms)), ['g0', 'g0.g'])
self.assertEqual(mans, [('c0.x', 'g0.g')])

def test_group_rename_connect(self):
from openmdao.api import Problem, IndepVarComp, ExecComp

Expand Down
67 changes: 67 additions & 0 deletions openmdao/error_checking/check_config.py
Expand Up @@ -348,6 +348,72 @@ def _check_missing_recorders(problem, logger):
logger.warning(msg)


def _get_promoted_connected_ins(g):
"""
Find all inputs that are promoted above the level where they are explicitly connected.
Parameters
----------
g : Group
Starting Group.
Returns
-------
defaultdict
Absolute input name keyed to [promoting_groups, manually_connecting_groups]
"""
prom2abs_list = g._var_allprocs_prom2abs_list['input']
abs2prom_in = g._var_abs2prom['input']
prom_conn_ins = defaultdict(lambda: ([], []))
for prom_in in g._manual_connections:
for abs_in in prom2abs_list[prom_in]:
prom_conn_ins[abs_in][1].append((prom_in, g.pathname))

for subsys in g._subgroups_myproc:
sub_prom_conn_ins = _get_promoted_connected_ins(subsys)
for n, tup in iteritems(sub_prom_conn_ins):
proms, mans = tup
mytup = prom_conn_ins[n]
mytup[0].extend(proms)
mytup[1].extend(mans)

sub_abs2prom_in = subsys._var_abs2prom['input']

for inp, sub_prom_inp in iteritems(sub_abs2prom_in):
if abs2prom_in[inp] == sub_prom_inp: # inp is promoted up from sub
if inp in sub_prom_conn_ins and len(sub_prom_conn_ins[inp][1]) > 0:
prom_conn_ins[inp][0].append(subsys.pathname)

return prom_conn_ins


def _check_explicitly_connected_promoted_inputs(problem, logger):
"""
Check for any inputs that are explicitly connected AND promoted above their connection group.
Parameters
----------
problem : <Problem>
The problem being checked.
logger : object
The object that manages logging output.
"""
prom_conn_ins = _get_promoted_connected_ins(problem.model)

for inp, lst in iteritems(prom_conn_ins):
proms, mans = lst
if proms:
# there can only be one manual connection (else an exception would've been raised)
man_prom, man_group = mans[0]
if len(proms) > 1:
lst = [p for p in proms if p == man_group or man_group.startswith(p + '.')]
s = "groups %s" % sorted(lst)
else:
s = "group '%s'" % proms[0]
logger.warning("Input '%s' was explicitly connected in group '%s' as '%s', but was "
"promoted up from %s." % (inp, man_group, man_prom, s))


# Dict of all checks by name, mapped to the corresponding function that performs the check
# Each function must be of the form f(problem, logger).
_checks = {
Expand All @@ -358,6 +424,7 @@ def _check_missing_recorders(problem, logger):
'dup_inputs': _check_dup_comp_inputs,
'missing_recorders': _check_missing_recorders,
'comp_has_no_outputs': _check_comp_has_no_outputs,
'promoted_connected': _check_explicitly_connected_promoted_inputs,
}


Expand Down

0 comments on commit 5ad7976

Please sign in to comment.