MetaModelUnStructuredComp lets you quickly create a component with surrogate models
used to compute the outputs based on unstructured training data. Generally, this is
used to construct a low-computational-cost replacement for computationally
You can define
MetaModelUnStructuredComp with as many inputs and outputs as you like,
and you can also use a different surrogate model for each output.
What’s the difference between
MetaModelUnStructuredComp and a surrogate model? In
OpenMDAO, “surrogate model” refers to the model for a single response, and
MetaModelUnStructuredComp represents a collection of surrogate models trained at the
same locations in the design space.
|Option||Default||Acceptable Values||Acceptable Types||Description||Deprecation|
|default_surrogate||N/A||N/A||['SurrogateModel', 'NoneType']||Surrogate that will be used for all outputs that don't have a specific surrogate assigned to them.||N/A|
|distributed||False||[True, False]||['bool']||True if ALL variables in this component are distributed across multiple processes.||The 'distributed' option has been deprecated. Individual inputs and outputs should be set as distributed instead, using calls to add_input() or add_output().|
|run_root_only||False||[True, False]||['bool']||If True, call compute/compute_partials/linearize/apply_linear/apply_nonlinear/compute_jacvec_product only on rank 0 and broadcast the results to the other ranks.||N/A|
|vec_size||1||N/A||['int']||Number of points that will be simultaneously predicted by the surrogate.||N/A|
The call signature for the
MetaModelUnStructuredComp constructor is:
The following example demonstrates a simple
Problem in which a
MetaModelUnStructuredComp uses surrogates to mimic the sine and cosine functions.
In this example, the
trig has a single input,
x, and two outputs,
KrigingSurrogate is given as the surrogate for the
Although no surrogate has been given for the
cos_x output, a
default_surrogate is specified for the component. Any output which has
not had a surrogate assigned will use one of the default type.
default_surrogate is not specified, then a surrogate must be
given for all outputs.
The first time a
MetaModelUnStructuredComp runs, it will train the surrogates using the
training data that has been provided, and then it will predict the output
values. This training step only occurs on the first run.
# create a MetaModelUnStructuredComp, specifying surrogates for the outputs import numpy as np import openmdao.api as om trig = om.MetaModelUnStructuredComp() x_train = np.linspace(0,10,20) trig.add_input('x', 0., training_data=x_train) trig.add_output('sin_x', 0., training_data=.5*np.sin(x_train), surrogate=om.KrigingSurrogate()) trig.add_output('cos_x', 0., training_data=.5*np.cos(x_train)) trig.options['default_surrogate'] = om.KrigingSurrogate() # add it to a Problem, run and check the predicted values prob = om.Problem() prob.model.add_subsystem('trig', trig) prob.setup() prob.set_val('trig.x', 2.1) prob.run_model() print(prob.get_val('trig.sin_x')) print(prob.get_val('trig.cos_x'))
The following surrogates are available to use with
Description: Based on Kriging interpolation; prediction returns mean predicted value, optionally returns RMSE.
Description: Based on the N-Dimensional Interpolation library by Stephen Marone.
Description: Based on second order response surface equations.
You can specify the training data after instantiation if you like, by setting the component’s
options. Training data is provided in the options to the
component using the variable names prefixed with
train:. This can be done anytime before
MetaModelUnStructuredComp runs for the first time.
The inputs and outputs of a
MetaModelUnStructuredComp are not limited to scalar values. The
following modified version of the example uses an array to predict sine and
cosine as a single output array of two values. You will also note that the default
surrogate can be passed as an argument to the
MetaModelUnStructuredComp constructor, as an
alternative to specifying it later.
# create a MetaModelUnStructuredComp that predicts sine and cosine as an array trig = om.MetaModelUnStructuredComp(default_surrogate=om.KrigingSurrogate()) trig.add_input('x', 0) trig.add_output('y', np.zeros(2)) # add it to a Problem prob = om.Problem() prob.model.add_subsystem('trig', trig) prob.setup() # provide training data trig.options['train:x'] = np.linspace(0, 10, 20) trig.options['train:y'] = np.column_stack(( .5*np.sin(trig.options['train:x']), .5*np.cos(trig.options['train:x']) )) # train the surrogate and check predicted value prob.set_val('trig.x', 2.1) prob.run_model() print(prob.get_val('trig.y'))
[ 0.43161089 -0.25241615]
In addition, it’s possible to vectorize the input and output variables so that you can
make multiple predictions for the inputs and outputs in a single execution of the
MetaModelUnStructuredComp component. This is done by setting the
vec_size argument when
MetaModelUnStructuredComp component and giving it the number of predictions to make. The following example vectorizes the
component so that it makes three predictions at a time. In this case, the input is
three independent values of
x and the output is the corresponding predicted values
for the sine and cosine functions at those three points. Note that a vectorized
MetaModelUnStructuredComp component requires the first dimension of all input and output variables
to be the same size as specified in the
size = 3 # create a vectorized MetaModelUnStructuredComp for sine and cosine trig = om.MetaModelUnStructuredComp(vec_size=size, default_surrogate=om.KrigingSurrogate()) trig.add_input('x', np.zeros(size)) trig.add_output('y', np.zeros((size, 2))) # add it to a Problem prob = om.Problem() prob.model.add_subsystem('trig', trig) prob.setup() # provide training data trig.options['train:x'] = np.linspace(0, 10, 20) trig.options['train:y'] = np.column_stack(( .5*np.sin(trig.options['train:x']), .5*np.cos(trig.options['train:x']) )) # train the surrogate and check predicted value prob.set_val('trig.x', np.array([2.1, 3.2, 4.3])) prob.run_model() print(prob.get_val('trig.y'))
[[ 0.43161089 -0.25241615] [-0.0291842 -0.4991407 ] [-0.45808581 -0.20039903]]
Using Surrogates That Do Not Define Linearize Method¶
In some cases, you might define surrogates but not define a
linearize method. In this case, the
MetaModelUnStructuredComp derivatives will be computed using finite differences for the output variables that use that
surrogate. By default, the default options for the finite differencing method will be used.
If you would like to specify finite differencing options, you can do so by calling the
method in the component’s
setup_partials or in a parent group’s configure method.
This example, which uses a surrogate with no
linearize method and no training for simplicity, shows
declare_partials called in
from math import sin class SinSurrogate(om.SurrogateModel): def train(self, x, y): pass def predict(self, x): return sin(x) class TrigWithFdInSetup(om.MetaModelUnStructuredComp): 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') # Testing explicitly setting fd inside of setup prob = om.Problem() trig = TrigWithFdInSetup() prob.model.add_subsystem('trig', trig, promotes_inputs=['x']) prob.setup(check=True) prob.set_val('x', 5.) trig.train = False prob.run_model() J = prob.compute_totals(of=['trig.sin_x'], wrt=['x']) deriv_using_fd = J[('trig.sin_x', 'x')]
INFO: checking out_of_order
INFO: checking system
INFO: checking solvers
INFO: checking dup_inputs
INFO: checking missing_recorders
WARNING: The Problem has no recorder of any kind attached
INFO: checking unserializable_options
INFO: checking comp_has_no_outputs
INFO: checking auto_ivc_warnings
/usr/share/miniconda/envs/test/lib/python3.8/site-packages/openmdao/approximation_schemes/finite_difference.py:135: OMDeprecationWarning:When using 'rel' as the step_calc, the fd stepsize is currently scaled by the norm of the vector variable. This is not ideal for larger vectors, and this behavior is being changed in OpenMDAO 3.12.0. To preserve the older way of doing this calculation, set step_calc to 'rel_legacy'.
Complex step has not been tested with
MetaModelUnStructuredComp and will result in an exception if used.