Source code for openmdao.lib.drivers.distributioncasedriver
"""
``distributioncasedriver.py`` -- Driver that executes
cases for distributions of points
in the neighborhood of a given point.
"""
# pylint: disable-msg=E0611,F0401,E1101
from zope.interface import Attribute, Interface
# E0611 - name cannot be found in a module
# F0401 - Unable to import module
# E1101 - Used when a variable is accessed for an unexistent member
from openmdao.main.numpy_fallback import zeros
from openmdao.lib.datatypes.api import List, Str, Slot, Int, Enum, Bool
from openmdao.lib.drivers.caseiterdriver import CaseIterDriverBase
from openmdao.main.api import Container
from openmdao.main.case import Case
from openmdao.util.decorators import add_delegate
from openmdao.main.hasparameters import HasParameters
from openmdao.main.interfaces import implements, IHasParameters
class IDistributionGenerator(Interface):
"""An iterator that returns lists of input
values that are mapped from a single design
point via some point distribution.
"""
num_parameters = Attribute("number of parameters")
def __iter__():
"""Return an iterator object where each iteration returns
a set of values.
"""
[docs]class FiniteDifferenceGenerator(Container):
"""
Generate the input cases for finite differences.
"""
implements(IDistributionGenerator)
num_parameters = Int(2, desc="Number of parameters, or dimensions")
order = Int(1, desc="Order of the finite differences")
form = Enum("CENTRAL", ["CENTRAL", "FORWARD", "BACKWARD"],
desc="Form of finite difference used")
skip_baseline = Bool(False,
desc="Set to True to skip running the baseline case.")
def __init__(self, driver):
super(FiniteDifferenceGenerator, self).__init__()
self.driver = driver
def __iter__(self):
"""Return an iterator over our sets of input values."""
return self._get_input_values()
def _get_input_values(self):
'''Generator for the values'''
params = self.driver.get_parameters().values()
baseline = zeros(self.num_parameters, 'd')
delta = zeros(self.num_parameters, 'd')
mask = zeros(self.num_parameters, 'd')
for i, param in enumerate(params):
baseline[i] = param.evaluate()
delta[i] = param.fd_step
# baseline case
if not self.skip_baseline:
if not (self.form == "CENTRAL" and self.order % 2 == 1):
yield baseline
if self.form == "FORWARD":
offset = 1
elif self.form == "BACKWARD":
offset = - self.order
elif self.form == "CENTRAL":
if self.order % 2 == 1:
offset = (0.5 - self.order)
else:
offset = 1 - self.order
# non-baseline cases for forward and backward
if self.form in ["BACKWARD", "FORWARD"]:
for iparam in range(self.num_parameters):
mask[iparam] = 1.0
for i in range(self.order):
var_val = baseline + (offset + i) * delta * mask
yield var_val
mask[iparam] = 0.0
else: # for central form
for iparam in range(self.num_parameters):
mask[iparam] = 1.0
if self.order % 2 == 1:
for i in range(self.order + 1):
var_val = baseline + (offset + i) * delta * mask
yield var_val
else:
for i in range(self.order + 1):
if (offset + i) != 0:
var_val = baseline + (offset + i) * delta * mask
yield var_val
mask[iparam] = 0.0
@add_delegate(HasParameters)
[docs]class DistributionCaseDriver(CaseIterDriverBase):
""" Driver for evaluating models at point distributions. """
implements(IHasParameters)
distribution_generator = Slot(IDistributionGenerator,
iotype='in', required=True,
desc='Iterator supplying values of point distribitions.')
case_outputs = List(Str, iotype='in',
desc='A list of outputs to be saved with each case.')
[docs] def get_case_iterator(self):
"""Returns a new iterator over the Case set."""
return self._get_cases()
def _get_cases(self):
"""Iterator over the cases"""
params = self.get_parameters().values()
self.distribution_generator.num_parameters = len(params)
for row in self.distribution_generator:
case = self.set_parameters(row, Case(parent_uuid=self._case_id))
case.add_outputs(self.case_outputs)
yield case