def plot_graphs(obj, recurse=True, fmt='pdf', pseudos=True, workflow=False, sysdone=False, prefix=''): if IAssembly.providedBy(obj): name = 'top' if obj.get_pathname()=='' else obj.get_pathname() try: plot_graph(obj._depgraph.get_pruned(), fmt=fmt, outfile=prefix+name+'_depgraph'+'.'+fmt, pseudos=pseudos) except Exception as err: print "Can't plot depgraph of '%s': %s" % (name, str(err)) try: plot_graph(obj._reduced_graph, fmt=fmt, outfile=prefix+name+'_reduced'+'.'+fmt, pseudos=pseudos) except Exception as err: print "Can't plot reduced graph of '%s': %s" % (name, str(err)) if not sysdone: try: plot_system_tree(obj._system, fmt=fmt, outfile=prefix+name+'_system_tree'+'.'+fmt) except Exception as err: print "Can't plot system graph of '%s': %s" % (name, str(err)) try: plot_graph(obj._reduced_graph.component_graph(), fmt=fmt, outfile=prefix+name+'_compgraph'+'.'+fmt, pseudos=pseudos, workflow=workflow, scope=obj) except Exception as err: print "Can't plot component_graph of '%s': %s" % (name, str(err)) _driver_plots(obj._top_driver, recurse=recurse, fmt=fmt, pseudos=pseudos, workflow=workflow, sysdone=True, prefix=prefix)
def _driver_plots(obj, recurse=True, fmt='pdf', pseudos=True, workflow=False, sysdone=False, prefix=''): # driver graph try: plot_graph(obj.get_reduced_graph(), fmt=fmt, outfile=prefix+obj.get_pathname()+'_reduced'+'.'+fmt, pseudos=pseudos) except Exception as err: print "Can't plot reduced graph of '%s': %s" % (obj.get_pathname(), str(err)) # workflow graph try: plot_graph(obj.workflow._reduced_graph, fmt=fmt, outfile=prefix+obj.get_pathname()+'_wflow_reduced'+'.'+fmt, pseudos=pseudos) except Exception as err: print "Can't plot reduced graph of '%s' workflow: %s" % (obj.get_pathname(), str(err)) if recurse: for comp in obj.workflow: if IAssembly.providedBy(comp): plot_graphs(comp, recurse, fmt=fmt, pseudos=pseudos, workflow=workflow, sysdone=True, prefix=prefix) elif IDriver.providedBy(comp): _driver_plots(comp, recurse, fmt=fmt, pseudos=pseudos, workflow=workflow, sysdone=True, prefix=prefix)
def applyJ(system, variables): """Multiply an input vector by the Jacobian. For an Explicit Component, this automatically forms the "fake" residual, and calls into the function hook "apply_deriv". """ J = system.J obj = system.inner() scope = system.scope is_sys = ISystem.providedBy(obj) arg = {} for item in system.list_states(): collapsed = scope.name2collapsed.get(item) if collapsed not in variables: continue key = item if not is_sys: key = item.partition('.')[-1] parent = system while True: if item in parent.vec['du']: arg[key] = parent.vec['du'][item] break parent = parent._parent_system for item in system.list_inputs(): collapsed = scope.name2collapsed.get(item) if collapsed not in variables: continue key = item if not is_sys: key = item.partition('.')[-1] parent = system while True: parent = parent._parent_system if item in parent.vec['dp']: arg[key] = parent.vec['dp'][item] break result = {} for item in system.list_outputs(): collapsed = scope.name2collapsed.get(item) if collapsed not in variables: continue key = item if not is_sys: key = item.partition('.')[-1] result[key] = system.rhs_vec[item] for item in system.list_residuals(): key = item if not is_sys: key = item.partition('.')[-1] result[key] = system.rhs_vec[item] # Bail if this component is not connected in the graph if len(arg) == 0 or len(result) == 0: return # Speedhack, don't call component's derivatives if incoming vector is zero. nonzero = False for key, value in arg.iteritems(): if any(value != 0): nonzero = True break if nonzero is False: #print 'applyJ', obj.name, arg, result return # If storage of the local Jacobian is a problem, the user can specify the # 'apply_deriv' function instead of provideJ. if J is None and hasattr(obj, 'apply_deriv'): # TODO - We shouldn't need to calculate the size of the full arrays, # so the cache shouldn't be needed. Cache is None for now. shape_cache = {} # The apply_deriv function expects the argument and result dicts for # each input and output to have the same shape as the input/output. resultkeys = sorted(result.keys()) for key in resultkeys: pre_process_dicts(obj, key, result, shape_cache, scope, is_sys) argkeys = arg.keys() for key in sorted(argkeys): pre_process_dicts(obj, key, arg, shape_cache, scope, is_sys) obj.apply_deriv(arg, result) # Result vector needs to be flattened. for key in reversed(resultkeys): post_process_dicts(key, result) # Arg is still called afterwards, so flatten it back. for key in argkeys: value = arg[key] if hasattr(value, 'flatten'): arg[key] = value.flatten() #print 'applyJ', obj.name, arg, result return if is_sys: input_keys = system.list_inputs() + system.list_states() output_keys = system.list_outputs() + system.list_residuals() elif IAssembly.providedBy(obj): input_keys = [item.partition('.')[-1] \ for item in system.list_inputs()] output_keys = [item.partition('.')[-1] \ for item in system.list_outputs()] else: input_keys, output_keys = list_deriv_vars(obj) #print 'J', input_keys, output_keys, J # The Jacobian from provideJ is a 2D array containing the derivatives of # the flattened output_keys with respect to the flattened input keys. We # need to find the start and end index of each input and output. if obj._provideJ_bounds is None: obj._provideJ_bounds = get_bounds(obj, input_keys, output_keys, J) ibounds, obounds = obj._provideJ_bounds for okey in result: odx = None if okey in obounds: o1, o2, osh = obounds[okey] else: basekey, _, odx = okey.partition('[') try: o1, o2, osh = obounds[basekey] except KeyError: if obj.missing_deriv_policy == 'error': msg = "does not provide analytical derivatives" + \ " for %s" % okey obj.raise_exception(msg, KeyError) continue tmp = result[okey] used = set() for ikey in arg: idx = None if ikey in ibounds: i1, i2, ish = ibounds[ikey] if (i1, i2) in used: continue used.add((i1, i2)) else: basekey, _, idx = ikey.partition('[') try: i1, i2, ish = ibounds[basekey] except KeyError: if obj.missing_deriv_policy == 'error': msg = "does not provide analytical derivatives" + \ " for %s" % ikey obj.raise_exception(msg, KeyError) continue if (i1, i2, idx) in used or (i1, i2) in used: continue used.add((i1, i2, idx)) Jsub = reduce_jacobian(J, i1, i2, idx, ish, o1, o2, odx, osh) #print ikey, okey, Jsub tmp += Jsub.dot(arg[ikey])
def print_vars(comp, list_type="inputs", prefix="", astable=False): comp_reserved = ["driver"] reserved = ["missing_deriv_policy", "force_execute", "directory", "force_fd", "printvars", "exec_count"] # recursively search for subassemblies if IAssembly.providedBy(comp): # outer needs to be an assembly subcomp = comp.list_components() for subc_name in subcomp: if subc_name in comp_reserved: continue subc = getattr(comp, subc_name) if IAssembly.providedBy(subc): # inner must be an subassembly if prefix is not None: newprefix = prefix + "." + subc_name else: newprefix = subc_name print_vars(subc, list_type, newprefix, astable) continue if list_type == "inputs": thelist = comp.list_inputs(connected=False) elif list_type == "outputs": thelist = comp.list_outputs(connected=False) elif list_type == "vars": thelist = comp.list_vars() for name in thelist: if name in reserved: continue trait = comp.get_trait(name) thetype = trait.trait_type.__str__().split()[0].split(".")[-1] if thetype == "VarTree": vartree = getattr(comp, name) if prefix is not None: newprefix = prefix + "." + name else: newprefix = name print_vars(vartree, "vars", newprefix, astable) continue units = trait.units desc = trait.desc default = trait.default # print trait.category if units is None: description = "(" + thetype + ")" else: description = "(" + thetype + ", " + units + ")" if desc is not None: description += ": " + desc if prefix is not "": name = prefix + "." + name if not astable: name = name + " = " + str(default) print name + " # " + description else: if not units: units = "" if not desc: desc = "" strdefault = str(default) if strdefault == "<undefined>": strdefault = "" print "{0:15}\t{1:10}\t{2:15}\t{3:10}\t{4}".format(name, thetype, strdefault, units, desc)
def print_vars(comp, list_type='inputs', prefix='', astable=False): comp_reserved = ['driver'] reserved = ['missing_deriv_policy', 'force_execute', 'directory', 'force_fd', 'printvars', 'exec_count'] # recursively search for subassemblies if IAssembly.providedBy(comp): # outer needs to be an assembly subcomp = comp.list_components() for subc_name in subcomp: if subc_name in comp_reserved: continue subc = getattr(comp, subc_name) if IAssembly.providedBy(subc): # inner must be an subassembly if prefix is not None: newprefix = prefix + '.' + subc_name else: newprefix = subc_name print_vars(subc, list_type, newprefix, astable) continue if list_type == 'inputs': thelist = comp.list_inputs(connected=False) elif list_type == 'outputs': thelist = comp.list_outputs(connected=False) elif list_type == 'vars': thelist = comp.list_vars() for name in thelist: if name in reserved: continue trait = comp.get_trait(name) thetype = trait.trait_type.__str__().split()[0].split('.')[-1] if thetype == 'VarTree': vartree = getattr(comp, name) if prefix is not None: newprefix = prefix + '.' + name else: newprefix = name print_vars(vartree, 'vars', newprefix, astable) continue units = trait.units desc = trait.desc default = trait.default # print trait.category if units is None: description = '(' + thetype + ')' else: description = '(' + thetype + ', ' + units + ')' if desc is not None: description += ': ' + desc if prefix is not '': name = prefix + '.' + name if not astable: name = name + ' = ' + str(default) print name + ' # ' + description else: if not units: units = '' if not desc: desc = '' strdefault = str(default) if strdefault == '<undefined>': strdefault = '' print '{0:15}\t{1:10}\t{2:15}\t{3:10}\t{4}'.format(name, thetype, strdefault, units, desc)