Skip to content

Commit

Permalink
Merge pull request #1671 from naylor-b/dyn_shape
Browse files Browse the repository at this point in the history
Implementation for POEM_022 - Determining variable shape at runtime based on connections
  • Loading branch information
swryan committed Sep 14, 2020
2 parents b51a213 + cd543fa commit c03985f
Show file tree
Hide file tree
Showing 74 changed files with 1,778 additions and 371 deletions.
12 changes: 9 additions & 3 deletions openmdao/components/exec_comp.py
Expand Up @@ -15,7 +15,7 @@
# Names of metadata entries allowed for ExecComp variables.
_allowed_meta = {'value', 'shape', 'units', 'res_units', 'desc',
'ref', 'ref0', 'res_ref', 'lower', 'upper', 'src_indices',
'flat_src_indices', 'tags'}
'flat_src_indices', 'tags', 'shape_by_conn', 'copy_shape'}

# Names that are not allowed for input or output variables (keywords for options)
_disallowed_names = {'has_diag_partials', 'units', 'shape'}
Expand Down Expand Up @@ -289,6 +289,12 @@ def setup(self):
init_vals[arg] = val['value']
del kwargs2[arg]['value']

if 'shape_by_conn' in val or 'copy_shape' in val:
if val.get('shape') is not None or val.get('value') is not None:
raise RuntimeError(f"{self.msginfo}: Can't set 'shape' or 'value' for "
f"variable '{arg}' along with 'copy_shape' or "
"'shape_by_conn'.")

if 'shape' in val:
if arg not in init_vals:
init_vals[arg] = np.ones(val['shape'])
Expand All @@ -302,14 +308,14 @@ def setup(self):
init_vals[arg] = val

for var in sorted(allvars):
meta = kwargs2.get(var, {'units': units, 'shape': shape})

# if user supplied an initial value, use it, otherwise set to 1.0
if var in init_vals:
val = init_vals[var]
else:
init_vals[var] = val = 1.0

meta = kwargs2.get(var, {'units': units, 'shape': shape})

if var in outs:
self.add_output(var, val, **meta)
else:
Expand Down
13 changes: 10 additions & 3 deletions openmdao/components/linear_system_comp.py
Expand Up @@ -49,8 +49,6 @@ def setup(self):
vec_size = self.options['vec_size']
vec_size_A = self.vec_size_A = vec_size if self.options['vectorize_A'] else 1
size = self.options['size']
mat_size = size * size
full_size = size * vec_size

self._lup = []
shape = (vec_size, size) if vec_size > 1 else (size, )
Expand All @@ -64,7 +62,16 @@ def setup(self):
self.add_input("b", val=np.ones(shape))
self.add_output("x", shape=shape, val=.1)

# Set up the derivatives.
def setup_partials(self):
"""
Set up the derivatives.
"""
vec_size = self.options['vec_size']
vec_size_A = self.vec_size_A = vec_size if self.options['vectorize_A'] else 1
size = self.options['size']
mat_size = size * size
full_size = size * vec_size

row_col = np.arange(full_size, dtype="int")

self.declare_partials('x', 'b', val=np.full(full_size, -1.0), rows=row_col, cols=row_col)
Expand Down
2 changes: 1 addition & 1 deletion openmdao/components/meta_model_structured_comp.py
Expand Up @@ -166,7 +166,7 @@ def _setup_partials(self):
'dependent': True,
}

for name in self._outputs:
for name in self._var_rel_names['output']:
self._declare_partials(of=name, wrt=pnames, dct=dct)
if self.options['training_data_gradients']:
self._declare_partials(of=name, wrt="%s_train" % name, dct={'dependent': True})
Expand Down
15 changes: 13 additions & 2 deletions openmdao/components/multifi_meta_model_unstructured_comp.py
Expand Up @@ -188,7 +188,8 @@ def add_input(self, name, val=1.0, shape=None, src_indices=None, flat_src_indice
self._input_sizes[fi] += input_size

def add_output(self, name, val=1.0, surrogate=None, shape=None, units=None, res_units=None,
desc='', lower=None, upper=None, ref=1.0, ref0=0.0, res_ref=1.0):
desc='', lower=None, upper=None, ref=1.0, ref0=0.0, res_ref=1.0, tags=None,
shape_by_conn=False, copy_shape=None):
"""
Add an output variable to the component.
Expand Down Expand Up @@ -230,13 +231,23 @@ def add_output(self, name, val=1.0, surrogate=None, shape=None, units=None, res_
res_ref : float
Scaling parameter. The value in the user-defined res_units of this output's residual
when the scaled value is 1. Default is 1.
tags : str or list of strs or set of strs
User defined tags that can be used to filter what gets listed when calling
list_inputs and list_outputs.
shape_by_conn : bool
If True, shape this output to match its connected input(s).
copy_shape : str or None
If a str, that str is the name of a variable. Shape this output to match that of
the named variable.
"""
super(MultiFiMetaModelUnStructuredComp, self).add_output(name, val, shape=shape,
units=units, res_units=res_units,
desc=desc, lower=lower,
upper=upper, ref=ref,
ref0=ref0, res_ref=res_ref,
surrogate=surrogate)
surrogate=surrogate, tags=tags,
shape_by_conn=shape_by_conn,
copy_shape=copy_shape)
self._training_output[name] = self._nfi * [np.empty(0)]

# Add train:<outvar>_fi<n>
Expand Down
6 changes: 5 additions & 1 deletion openmdao/components/tests/test_external_code_comp.py
Expand Up @@ -315,6 +315,7 @@ def setup(self):
sys.executable, 'extcode_paraboloid.py', self.input_file, self.output_file
]

def setup_partials(self):
# this external code does not provide derivatives, use finite difference
self.declare_partials(of='*', wrt='*', method='fd')

Expand Down Expand Up @@ -357,6 +358,7 @@ def setup(self):
self.input_file, self.output_file, self.derivs_file
]

def setup_partials(self):
# this external code does provide derivatives
self.declare_partials(of='*', wrt='*')

Expand Down Expand Up @@ -549,7 +551,6 @@ def initialize(self):
def setup(self):
self.add_input('area_ratio', val=1.0, units=None)
self.add_output('mach', val=1., units=None)
self.declare_partials(of='mach', wrt='area_ratio', method='fd')

self.input_file = 'mach_input.dat'
self.output_file = 'mach_output.dat'
Expand All @@ -570,6 +571,9 @@ def setup(self):
# If you want to write your own string command, the code below will also work.
# self.options['command_apply'] = ('python extcode_mach.py {} {}').format(self.input_file, self.output_file)

def setup_partials(self):
self.declare_partials(of='mach', wrt='area_ratio', method='fd')

def apply_nonlinear(self, inputs, outputs, residuals):
with open(self.input_file, 'w') as input_file:
input_file.write('residuals\n')
Expand Down
Expand Up @@ -890,6 +890,8 @@ def setup(self):
surrogate = SinSurrogate()
self.add_input('x', 0.)
self.add_output('sin_x', 0., surrogate=surrogate)

def setup_partials(self):
self.declare_partials('sin_x', 'x', method='fd',
form='backward', step=1e-7, step_calc='rel')

Expand Down

0 comments on commit c03985f

Please sign in to comment.