From ca9f117fcca2b887484a334b0668e6a5a4db70f8 Mon Sep 17 00:00:00 2001 From: Ted Wright Date: Thu, 17 Sep 2020 13:41:24 -0400 Subject: [PATCH 1/2] add equivalent unit conversion check and tests --- openmdao/core/group.py | 10 +++++++-- openmdao/core/tests/test_units.py | 37 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/openmdao/core/group.py b/openmdao/core/group.py index 69309c844d..72a02cd423 100644 --- a/openmdao/core/group.py +++ b/openmdao/core/group.py @@ -3196,8 +3196,14 @@ def _resolve_ambiguous_input_meta(self): tmeta = abs2meta[tgt] if tgt in abs2meta else all_abs2meta[tgt] tunits = tmeta['units'] if 'units' in tmeta else None if 'units' not in gmeta and sunits != tunits: - errs.add('units') - metadata.add('units') + try: + test_conv = unit_conversion(sunits, tunits) + if abs(test_conv[0] - 1.0) > 1e-9 or abs(test_conv[1] - 0.0) > 1e-9: + errs.add('units') + metadata.add('units') + except TypeError: + errs.add('units') + metadata.add('units') if 'value' not in gmeta: if tval.shape == sval.shape: if _has_val_mismatch(tunits, tval, sunits, sval): diff --git a/openmdao/core/tests/test_units.py b/openmdao/core/tests/test_units.py index 3462050ac1..9567265f80 100644 --- a/openmdao/core/tests/test_units.py +++ b/openmdao/core/tests/test_units.py @@ -880,6 +880,43 @@ def setup(self): #self.assertTrue(iter_count < 20) #self.assertTrue(not np.isnan(prob['sub.cc2.y'])) + def test_promotes_equivalent_units(self): + # multiple Group.set_input_defaults calls at same tree level with conflicting units args + p = om.Problem() + + g1 = p.model.add_subsystem("G1", om.Group(), promotes_inputs=['x']) + g1.add_subsystem("C1", om.ExecComp("y = 2. * x * z", + x={'value': 5.0, 'units': 'm/s/s'}, + y={'value': 1.0, 'units': None}, + z={'value': 1.0, 'units': 'W'}), + promotes_inputs=['x', 'z']) + g1.add_subsystem("C2", om.ExecComp("y = 3. * x * z", + x={'value': 5.0, 'units': 'm/s**2'}, + y={'value': 1.0, 'units': None}, + z={'value': 1.0, 'units': 'J/s'}), + promotes_inputs=['x', 'z']) + # converting m/s/s to m/s**2 is allowed + p.setup() + + def test_promotes_non_equivalent_units(self): + # multiple Group.set_input_defaults calls at same tree level with conflicting units args + p = om.Problem() + + g1 = p.model.add_subsystem("G1", om.Group(), promotes_inputs=['x']) + g1.add_subsystem("C1", om.ExecComp("y = 2. * x * z", + x={'value': 5.0, 'units': 'J/s/s'}, + y={'value': 1.0, 'units': None}, + z={'value': 1.0, 'units': 'W'}), + promotes_inputs=['x', 'z']) + g1.add_subsystem("C2", om.ExecComp("y = 3. * x * z", + x={'value': 5.0, 'units': 'm/s**2'}, + y={'value': 1.0, 'units': None}, + z={'value': 1.0, 'units': 'J/s'}), + promotes_inputs=['x', 'z']) + # trying to convert J/s/s to m/s**2 should cause Incompatible units TypeError exception + with self.assertRaises(TypeError): + p.setup() + if __name__ == "__main__": unittest.main() From 7b121f50e0e2097472f822422873e461c4efd183 Mon Sep 17 00:00:00 2001 From: Ted Wright Date: Thu, 17 Sep 2020 16:15:38 -0400 Subject: [PATCH 2/2] code review updates --- openmdao/core/group.py | 9 ++------- openmdao/core/tests/test_units.py | 3 ++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/openmdao/core/group.py b/openmdao/core/group.py index 72a02cd423..8096754ccd 100644 --- a/openmdao/core/group.py +++ b/openmdao/core/group.py @@ -25,7 +25,7 @@ _flatten_src_indices from openmdao.utils.general_utils import ContainsAll, all_ancestors, simple_warning, \ common_subpath, conditional_error, _is_slicer_op, _slice_indices -from openmdao.utils.units import is_compatible, unit_conversion, _has_val_mismatch +from openmdao.utils.units import is_compatible, unit_conversion, _has_val_mismatch, _find_unit from openmdao.utils.mpi import MPI, check_mpi_exceptions, multi_proc_exception_check from openmdao.utils.coloring import Coloring, _STD_COLORING_FNAME import openmdao.utils.coloring as coloring_mod @@ -3196,12 +3196,7 @@ def _resolve_ambiguous_input_meta(self): tmeta = abs2meta[tgt] if tgt in abs2meta else all_abs2meta[tgt] tunits = tmeta['units'] if 'units' in tmeta else None if 'units' not in gmeta and sunits != tunits: - try: - test_conv = unit_conversion(sunits, tunits) - if abs(test_conv[0] - 1.0) > 1e-9 or abs(test_conv[1] - 0.0) > 1e-9: - errs.add('units') - metadata.add('units') - except TypeError: + if _find_unit(sunits) != _find_unit(tunits): errs.add('units') metadata.add('units') if 'value' not in gmeta: diff --git a/openmdao/core/tests/test_units.py b/openmdao/core/tests/test_units.py index 9567265f80..854fa598cb 100644 --- a/openmdao/core/tests/test_units.py +++ b/openmdao/core/tests/test_units.py @@ -914,8 +914,9 @@ def test_promotes_non_equivalent_units(self): z={'value': 1.0, 'units': 'J/s'}), promotes_inputs=['x', 'z']) # trying to convert J/s/s to m/s**2 should cause Incompatible units TypeError exception - with self.assertRaises(TypeError): + with self.assertRaises(TypeError) as e: p.setup() + self.assertEqual(str(e.exception), 'Incompatible units') if __name__ == "__main__":