def test_base_var(self): self.assertEqual(base_var(self.dep, 'B.a'), 'B.a') self.assertEqual(base_var(self.dep, 'a'), 'a') self.assertEqual(base_var(self.dep, 'a.x'), 'a') self.assertEqual(base_var(self.dep, 'a.x.y'), 'a') self.assertEqual(base_var(self.dep, 'a.x[3].y'), 'a') self.assertEqual(base_var(self.dep, 'A.c[2]'), 'A.c')
def _filter_ignored(scope, lst): # Remove any vars that the user designates as 'deriv_ignore' unignored = [] topvars = scope._system.vector_vars for name in lst: collapsed_name = scope.name2collapsed[name] if collapsed_name in topvars and topvars[collapsed_name].get('deriv_ignore'): continue # The user sets 'deriv_ignore' in the basevar, so we have to check that for # subvars. base = base_var(scope._depgraph, name) if base != name: collname = scope.name2collapsed.get(base) if collname and collname in topvars and \ topvars[collname].get('deriv_ignore'): continue unignored.append(name) return unignored
def _update_graph_metadata(G, scope): nmeta = G.node conns = [] for node, data in G.nodes_iter(data=True): data = data.copy() # don't corrupt metadata of other subgraphs/parent graphs nmeta[node] = data if 'pseudo' in data: data['label'] = node.replace('_pseudo_', '_p_') # shorten all pseudocomp names data['shape'] = 'diamond' elif 'driver' in data: data['shape'] = 'invhouse' if scope: driver = getattr(scope, node) for pcomp in driver.list_pseudocomps(): conns.append((pcomp, node)) if hasattr(driver, 'list_param_targets'): conns.extend([(node, p) for p in driver.list_param_targets() if p in G]) elif 'comp' in data: data['shape'] = 'box' elif 'var' in data or 'basevar' in data: # var node try: parts = node.split('.', 1) except AttributeError: pass else: if hasattr(G, 'base_var'): base = base_var(G, node) if G.node[base].get('iotype') == 'state': data['shape'] = 'doubleoctagon' else: data['shape'] = 'ellipse' else: data['shape'] = 'ellipse' data['margin'] = '0.0' G.add_edges_from(conns, style='dotted')
def __init__(self, system, inputs, outputs, return_format='array'): """ Performs finite difference on the components in a given System. """ self.inputs = inputs self.outputs = outputs self.in_bounds = {} self.system = system self.scope = system.scope self.return_format = return_format options = system.options driver = options.parent self.fd_step = options.fd_step*ones((len(self.inputs))) self.low = [None] * len(self.inputs) self.high = [None] * len(self.inputs) self.form = options.fd_form self.form_custom = {} self.step_type = options.fd_step_type self.step_type_custom = {} self.relative_threshold = 1.0e-4 dgraph = self.scope._depgraph driver_params = [] driver_targets = [] if hasattr(driver, 'get_parameters'): driver_params = driver.get_parameters() driver_targets = driver.list_param_targets() in_size = 0 for j, srcs in enumerate(self.inputs): low = high = None # Support for parameter groups if isinstance(srcs, basestring): srcs = [srcs] # Local stepsize support meta = self.scope.get_metadata(base_var(dgraph, srcs[0])) if 'fd_step' in meta: self.fd_step[j] = meta['fd_step'] if 'low' in meta: low = meta['low'] if 'high' in meta: high = meta['high'] # Settings in the add_parameter call trump all others param_srcs = [item for item in srcs if item in driver_targets] if param_srcs: if param_srcs[0] in driver_params: param = driver_params[param_srcs[0]] if param.fd_step is not None: self.fd_step[j] = param.fd_step if param.low is not None: low = param.low if param.high is not None: high = param.high else: # have to check through all the param groups for param_group in driver_params: is_fd_step_not_set = is_low_not_set = \ is_high_not_set = True if not isinstance(param_group, str) and \ param_srcs[0] in param_group: param = driver_params[param_group] if is_fd_step_not_set and param.fd_step is not None: self.fd_step[j] = param.fd_step is_fd_step_not_set = False if is_low_not_set and param.low is not None: low = param.low is_low_not_set = False if is_high_not_set and param.high is not None: high = param.high is_high_not_set = False if 'fd_step_type' in meta: self.step_type_custom[j] = meta['fd_step_type'] step_type = self.step_type_custom[j] else: step_type = self.step_type # Bounds scaled if step_type == 'bounds_scaled': if low is None and high is None: raise RuntimeError("For variable '%s', a finite " "difference step type of bounds_scaled " "is used but required low and " "high values are not set" % srcs[0]) if low == - float_info.max: raise RuntimeError("For variable '%s', a finite " "difference step type of " "bounds_scaled is used but required " "low value is not set" % srcs[0]) if high == float_info.max: raise RuntimeError("For variable '%s', a finite " "difference step type of " "bounds_scaled is used but required " "high value is not set" % srcs[0]) self.fd_step[j] = (high - low) * self.fd_step[j] if 'fd_form' in meta: self.form_custom[j] = meta['fd_form'] val = self.scope.get(srcs[0]) width = flattened_size(srcs[0], val, self.scope) for src in srcs: self.in_bounds[src] = (in_size, in_size+width) in_size += width self.high[j] = high self.low[j] = low out_size = 0 for src in self.outputs: val = self.scope.get(src) width = flattened_size(src, val) out_size += width # Size our Jacobian if return_format == 'dict': self.J = {} for okey in outputs: self.J[okey] = {} for ikey in inputs: if isinstance(ikey, tuple): ikey = ikey[0] # If output not on this process, just allocate a dummy # array if MPI and okey not in self.system.vec['u']: osize = 0 else: osize = self.system.vec['u'][okey].size isize = self.system.vec['p'][ikey].size self.J[okey][ikey] = zeros((osize, isize)) else: self.J = zeros((out_size, in_size)) self.y_base = zeros((out_size,)) self.y = zeros((out_size,)) self.y2 = zeros((out_size,))