Source code for openmdao.recorders.base_recorder

""" Class definition for BaseRecorder, the base class for all recorders."""

from fnmatch import fnmatch
import sys

from six.moves import filter
from six import StringIO

from openmdao.util.options import OptionsDictionary


[docs]class BaseRecorder(object): """ Base class for all case recorders. """ def __init__(self): self.options = OptionsDictionary() self.options.add_option('includes', ['*'], desc='Patterns for variables to include in recording') self.options.add_option('excludes', [], desc='Patterns for variables to exclude from recording ' '(processed after includes)') self.out = None # This is for drivers to determine if a recorder supports # real parallel recording (recording on each process), because # if it doesn't, the driver figures out what variables must # be gathered to rank 0 if running under MPI. # # By default, this is False, but it should be set to True # if the recorder will record data on each process to avoid # unnecessary gathering. self._parallel = False self._filtered = {} # TODO: System specific includes/excludes
[docs] def startup(self, group): """ Prepare for a new run. Args ---- group : `Group` Group that owns this recorder. """ # Compute the inclusion lists for recording params = list(filter(self._check_path, group.params)) unknowns = list(filter(self._check_path, group.unknowns)) resids = list(filter(self._check_path, group.resids)) self._filtered[group.pathname] = (params, unknowns, resids)
def _check_path(self, path): """ Return True if `path` should be recorded. """ includes = self.options['includes'] excludes = self.options['excludes'] # First see if it's included for pattern in includes: if fnmatch(path, pattern): # We found a match. Check to see if it is excluded. for ex_pattern in excludes: if fnmatch(path, ex_pattern): return False return True # Did not match anything in includes. return False def _get_pathname(self, iteration_coordinate): ''' Converts an iteration coordinate to key to index `_filtered` to retrieve names of variables to be recorder ''' return '.'.join(iteration_coordinate[4::2]) def _filter_vectors(self, params, unknowns, resids, iteration_coordinate): ''' Returns subset of `params`, `unknowns` and `resids` to be recoder ''' pathname = self._get_pathname(iteration_coordinate) pnames, unames, rnames = self._filtered[pathname] params = {key: params[key] for key in pnames} unknowns = {key: unknowns[key] for key in unames} resids = {key: resids[key] for key in rnames} return params, unknowns, resids
[docs] def record(self, params, unknowns, resids, metadata): """ Records the requested variables. This method must be defined in all recorders. Args ---- params : `VecWrapper` `VecWrapper` containing parameters. (p) unknowns : `VecWrapper` `VecWrapper` containing outputs and states. (u) resids : `VecWrapper` `VecWrapper` containing residuals. (r) metadata : dict Dictionary containing execution metadata (e.g. iteration coordinate). """ raise NotImplementedError("record")
[docs] def close(self): """Closes `out` unless it's ``sys.stdout``, ``sys.stderr``, or StringIO. Note that a closed recorder will do nothing in :meth:`record`.""" # Closing a StringIO deletes its contents. if self.out not in (None, sys.stdout, sys.stderr): if not isinstance(self.out, StringIO): self.out.close() self.out = None