Skip to content

Commit

Permalink
Merge pull request #181 from naylor-b/poem87
Browse files Browse the repository at this point in the history
Poem87 - expanding the functionality of dynamic shaping
  • Loading branch information
robfalck authored Oct 5, 2023
2 parents dc2a363 + ddb3bab commit 2da7668
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions POEM_087.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
POEM ID: 087
Title: Expand functionality of dynamic shaping.
authors: naylor-b (Bret Naylor)
Competing POEMs:
Related POEMs:
Associated implementation PR: [OpenMDAO/OpenMDAO#3000 : Implementation branch for POEM 87 Expand Functionality of Dynamic Shaping](https://github.com/OpenMDAO/OpenMDAO/pull/3000)

Status:

- [ ] Active
- [ ] Requesting decision
- [x] Accepted
- [ ] Rejected
- [ ] Integrated


## Motivation

Currently, the shape of a dynamically shaped variable can be determined either by the shape of
the variable it connects to, via 'shape_by_conn', or by the shape of a variable residing in the
same component, via 'copy_shape'. Both cases only work if the desired shape happens to be the
same as the shape of the connected or named variable.

In the case of 'copy_shape' there are situations where the desired shape of an output will not
be the same as the shape of a single input but will instead be some function of the shapes of
one or more of the component's input variables.


## Proposed solution

Since `copy_shape` doesn't properly describe the process of computing the shape based on the
shapes of other variables, a new argument called `compute_shape` will be added to `add_output` and
`add_input`. The value of `compute_shape` will be a function taking a single argument of the form
`{'var1': shape1, 'var2': shape2, ...}`. The argument will be populated with shapes of
all input variables in the component. This will allow the final shape to be computed based on the
shapes of multiple variables if necessary.


## Example

A component has two dynamically shaped input matrices, 'M1' and 'M2', and an output matrix 'M3'
that is the result of the matrix multiplication M1 @ M2. If 'M1' is shape (m, n) and 'M2' is
shape (n, p), then the desired shape of 'M3' is (m, p). This can be computed using the function

```
def shapefunc(shapes):
return (shapes['M1'][0], shapes['M2'][1])
```

or

```
lambda shapes: (shapes['M1'][0], shapes['M2'][1])
```


So, when adding output 'M3' to its parent component, the add_output call would look something
like this:

```
self.add_output('M3', compute_shape=shapefunc)
```

or

```
self.add_output('M3', compute_shape=lambda shapes: (shapes['M1'][0], shapes['M2'][1]))
```

0 comments on commit 2da7668

Please sign in to comment.