New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation for POEM_022 - Determining variable shape at runtime based on connections #1671
Conversation
…ch during dyn shape determination
…cally sized variables
p = om.Problem() | ||
indep = p.model.add_subsystem('indep', om.IndepVarComp('x1', val=np.ones((2,3)))) | ||
indep.add_output('x2', val=np.ones((4,2))) | ||
p.model.add_subsystem('Gdyn', DynShapeGroupSeries(3, 2, DynShapeComp)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tested what happens if you accidentally set shape_by_conn
to your own name? I imagine you will just get a 'cannot resolve shape' exception, so probably fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, doing a copy_shape
using your own name will either result in a failure to resolve, or if that variable happens to be connected to other variables by some other means (shape_by_conn or a resolvable variable connects to it by its own shape_by_conn or copy_shape) then it'll just work anyway. Your comment also reminded me that I didn't have a test for when copy_shape is set to a non-existent variable, so I added that.
…ices with dynamic shape variables
@joanibal I added a 'view_dyn_shapes' command to the openmdao command line tool that will display the shape dependency graph using matplotlib, basically like you showed in your example. At some point when I have more time I'd like to replace the matplotlib stuff with a better graph viewing library, but for now, it's at least better than nothing. |
def add_input(self, name, val=1.0, shape=None, src_indices=None, flat_src_indices=None, | ||
units=None, desc='', tags=None): | ||
def add_input(self, name, val=None, shape=None, src_indices=None, flat_src_indices=None, | ||
units=None, desc='', tags=None, shape_by_conn=False, copy_shape=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: changing the default value is a backward incompatibility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reverted this back to 1.0. So now, val is allowed to be set but it must be a scalar, and once the shape is known, that scalar is used to fill the array.
declared here since this is called after all size/shape information is known for | ||
all variables. | ||
""" | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: changing the API for where partials are declared is a backward incompatibility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not backwardly incompatible. Doing it in the old way still works, although we recommend that people do it now in setup_partials for consistency sake.
openmdao/core/system.py
Outdated
@@ -1346,6 +1364,7 @@ def _setup_global_shapes(self): | |||
""" | |||
meta = self._var_allprocs_abs2meta | |||
loc_meta = self._var_abs2meta | |||
myrank = self.comm.rank |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
self.add_output('out', shape=3) | ||
|
||
def compute(self, inputs, outputs): | ||
outputs['out'] *= self.comm.rank |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is strange, could you explain what's going on here (computing output based on itself)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated this so the output now depends upon the input.
@@ -22,7 +22,7 @@ Here is an example, based on the :ref:`Betz Limit Example <betz_limit_tutorial>` | |||
|
|||
|
|||
The calls to :code:`declare_partials` tell OpenMDAO which partial derivatives to expect. | |||
This is always done inside the :code:`setup` method. | |||
This should always be done inside the :code:`setup_partials` method. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should
or must
?
if should
then more explanation is probably required...
if must
then we do we need a deprecation or exception when it's done the old way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added more explanation about why setup_partials is the recommended way.
Summary
Implementation PR for POEM_022. Adds the ability to determine variable shapes at runtime based on what those variables are connected to. Also adds a new function hook,
setup_partials
, that is used to allow a component to compute its partials after all shape information is known.Backwards incompatibilities
None
New Dependencies
None