def get_sparsity(problem, mode='fwd', repeats=1, tol=1.e-15, show_jac=False, setup=False, run_model=False, stream=sys.stdout): """ Compute derivative sparsity for the given problem. Parameters ---------- problem : Problem The Problem being analyzed. mode : str Derivative direction. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualization of the final total jacobian used to compute the coloring. stream : file-like or None Stream where output coloring info will be written. setup : bool If True, run setup before calling compute_totals. run_model : bool If True, run run_model before calling compute_totals. Returns ------- dict A nested dict specifying subjac sparsity for each total deriv, e.g., sparsity[resp][dv]. """ driver = problem.driver J = _get_bool_jac(problem, mode=mode, repeats=repeats, tol=tol, setup=setup, run_model=run_model) of = driver._get_ordered_nl_responses() wrt = list(driver._designvars) sparsity = _sparsity_from_jac(J, of, wrt, driver) driver._total_jac = None if stream is not None: _write_sparsity(sparsity, stream) stream.write("\n") if show_jac and stream is not None: stream.write("\n\n") array_viz(J, problem, of, wrt, stream) return sparsity
def show(self, stream=sys.stdout): array_viz(self.J) maxdeg_fwd = np.max(np.count_nonzero(self.J, axis=1)) maxdeg_rev = np.max(np.count_nonzero(self.J, axis=0)) print("Shape:", self.J.shape, file=stream) print("Density:", np.count_nonzero(self.J) / self.J.size) print("Max degree (fwd, rev):", maxdeg_fwd, maxdeg_rev) simul_coloring_summary(self.J, self.coloring, stream=stream)
def get_sparsity(problem, mode='fwd', repeats=1, tol=1.e-15, show_jac=False, setup=False, run_model=False, stream=sys.stdout): """ Compute derivative sparsity for the given problem. Parameters ---------- problem : Problem The Problem being analyzed. mode : str Derivative direction. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualization of the final total jacobian used to compute the coloring. stream : file-like or None Stream where output coloring info will be written. setup : bool If True, run setup before calling compute_totals. run_model : bool If True, run run_model before calling compute_totals. Returns ------- dict A nested dict specifying subjac sparsity for each total deriv, e.g., sparsity[resp][dv]. """ driver = problem.driver J = _get_bool_jac(problem, repeats=repeats, tol=tol, setup=setup, run_model=run_model) of = driver._get_ordered_nl_responses() wrt = list(driver._designvars) sparsity = _sparsity_from_jac(J, of, wrt, driver) driver._total_jac = None if stream is not None: _write_sparsity(sparsity, stream) stream.write("\n") if show_jac and stream is not None: stream.write("\n\n") array_viz(J, problem, of, wrt, stream) return sparsity
def show(self, stream=sys.stdout): array_viz(self.J) print("Shape:", self.J.shape, file=stream) print("Density:", np.count_nonzero(self.J) / self.J.size) tup = _solves_info(self.coloring) dominant_mode = tup[-1] if dominant_mode == 'fwd': if 'rev' in self.coloring: opp_rows = self.coloring['rev'][0][0] Jcopy = self.J.copy() Jcopy[opp_rows] = False else: Jcopy = self.J maxdeg = np.max(np.count_nonzero(Jcopy, axis=1)) else: if 'fwd' in self.coloring: opp_cols = self.coloring['fwd'][0][0] Jcopy = self.J.copy() Jcopy[:, opp_cols] = False else: Jcopy = self.J maxdeg = np.max(np.count_nonzero(Jcopy, axis=0)) print("Max degree:", maxdeg) simul_coloring_summary(self.coloring, stream=stream)
def get_simul_meta(problem, mode='fwd', repeats=1, tol=1.e-15, show_jac=False, include_sparsity=True, setup=False, run_model=False, stream=sys.stdout): """ Compute simultaneous derivative colorings for the given problem. Parameters ---------- problem : Problem The Problem being analyzed. mode : str Derivative direction. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualiation of the final total jacobian used to compute the coloring. include_sparsity : bool If True, include the sparsity structure of the total jacobian mapped to design vars and responses. (This info is used by pyOptSparseDriver). setup : bool If True, run setup before calling compute_totals. run_model : bool If True, run run_model before calling compute_totals. stream : file-like or None Stream where output coloring info will be written. Returns ------- tuple of the form (col_lists, row_maps, sparsity) col_lists is a list of column lists, where the first list is the list of uncolored columns. row_maps is a list of nonzero rows for each column, or None for uncolored columns. sparsity is a nested dict specifying subjac sparsity for each total derivative, or None. """ driver = problem.driver # TODO: fix this to work in rev mode as well assert mode == 'fwd', "Simultaneous derivatives are currently supported only in fwd mode." J = _get_bool_jac(problem, mode=mode, repeats=repeats, tol=tol, setup=setup, run_model=run_model) full_disjoint, rows = _find_global_disjoint(problem, J) uncolored_cols = [i for i, r in enumerate(rows) if r is None] # the first col_list entry corresponds to all uncolored columns (columns that are not disjoint # wrt any other columns). The other entries are groups of columns that do not share any # nonzero row entries in common. col_lists = [uncolored_cols] col_lists.extend(full_disjoint) sparsity = None if include_sparsity or (show_jac and stream is not None): of = driver._get_ordered_nl_responses() wrt = list(driver._designvars) if include_sparsity: sparsity = _sparsity_from_jac(J, of, wrt, driver) driver._total_jac = None if stream is not None: if stream.isatty(): stream.write( "\n########### BEGIN COLORING DATA ################\n") _write_coloring(col_lists, rows, sparsity, stream) stream.write("\n########### END COLORING DATA ############\n") else: _write_coloring(col_lists, rows, sparsity, stream) if show_jac: s = stream if stream.isatty() else sys.stdout s.write("\n\n") array_viz(J, problem, of, wrt, s) return col_lists, rows, sparsity
def get_simul_meta(problem, mode='fwd', repeats=1, tol=1.e-30, show_jac=False, stream=sys.stdout): """ Compute simultaneous derivative colorings for the given problem. Parameters ---------- problem : Problem The Problem being analyzed. mode : str Derivative direction. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualiation of the final total jacobian used to compute the coloring. stream : file-like or None Stream where output coloring info will be written. Returns ------- tuple of the form (simul_colorings, simul_maps) Where simul_colorings is a dict of the form {dvname1: coloring_array, ...} and simul_maps is a dict of the form {resp_name: {dvname: {color: (row_idxs, col_idxs), ...}, ...}, ...} """ driver = problem.driver dv_idxs, res_idxs, J = _find_disjoint(problem, mode=mode, tol=tol, repeats=repeats) all_colors = set() simul_colorings = {} simul_maps = {} for dv in dv_idxs: # negative colors will be iterated over individually, so start by filling the coloring array # with -1. We then replace specific entries with positive colors which will be iterated # over as a group. coloring = np.full(driver._designvars[dv]['size'], -1, dtype=int) for color in dv_idxs[dv]: coloring[np.array(dv_idxs[dv][color], dtype=int)] = color all_colors.add(color) if np.any(coloring != -1): # need int conversion to avoid JSON serialization error simul_colorings[dv] = [int(c) for c in coloring] simul_colorings = OrderedDict(sorted(simul_colorings.items())) for res in res_idxs: simul_map = {} for dv in res_idxs[res]: simul_map[dv] = { c: v for c, v in iteritems(res_idxs[res][dv]) if c in all_colors } if not simul_map[dv]: del simul_map[dv] if simul_map: simul_maps[res] = OrderedDict(sorted(simul_map.items())) simul_maps = OrderedDict(sorted(simul_maps.items())) if stream is not None: if stream.isatty(): stream.write("\n({\n") for n, coloring in iteritems(simul_colorings): stream.write(" '%s': %s,\n" % (n, coloring)) stream.write("},") stream.write("\n{\n") for res, dvdict in iteritems(simul_maps): stream.write(" '%s': {\n" % res) for dv, coldict in iteritems(dvdict): stream.write(" '%s': {\n" % dv) for color, idxs in iteritems(coldict): stream.write(" %s: %s,\n" % (color, idxs)) stream.write(" },\n") stream.write(" },\n") stream.write("})") else: # output json format to a file s = json.dumps((simul_colorings, simul_maps)) # do a little pretty printing since the built-in json pretty printing stretches # the output vertically WAY too much. s = s.replace(',"', ',\n"') s = s.replace(', "', ',\n"') s = s.replace('{"', '{\n"') s = s.replace(', {', ',\n{') s = s.replace(']}', ']\n}') s = s.replace('{}', '{\n}') s = s.replace('}}', '}\n}') s = s.replace('[{', '[\n{') s = s.replace(' {', '\n{') lines = [] indent = 0 for line in s.split('\n'): start = line[0] if len(line) > 0 else '' if start in ('{', '['): tab = ' ' * indent indent += 3 elif start in ('}', ']'): indent -= 3 tab = ' ' * indent else: tab = ' ' * indent lines.append("%s%s" % (tab, line)) stream.write('\n'.join(lines)) stream.write("\n") if show_jac and stream is not None: of = list(driver._objs) of.extend([ c for c, meta in iteritems(driver._cons) if not ('linear' in meta and meta['linear']) ]) wrt = list(driver._designvars) stream.write("\n\n") array_viz(J, problem, of, wrt, stream) return simul_colorings, simul_maps
def get_simul_meta(problem, mode='fwd', repeats=1, tol=1.e-30, show_jac=False, stream=sys.stdout): """ Compute simultaneous derivative colorings for the given problem. Parameters ---------- problem : Problem The Problem being analyzed. mode : str Derivative direction. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualiation of the final total jacobian used to compute the coloring. stream : file-like or None Stream where output coloring info will be written. Returns ------- tuple of the form (simul_colorings, simul_maps) Where simul_colorings is a dict of the form {dvname1: coloring_array, ...} and simul_maps is a dict of the form {resp_name: {dvname: {color: (row_idxs, col_idxs), ...}, ...}, ...} """ driver = problem.driver dv_idxs, res_idxs, J = _find_disjoint(problem, mode=mode, tol=tol, repeats=repeats) all_colors = set() simul_colorings = {} simul_maps = {} for dv in dv_idxs: # negative colors will be iterated over individually, so start by filling the coloring array # with -1. We then replace specific entries with positive colors which will be iterated # over as a group. coloring = np.full(driver._designvars[dv]['size'], -1) for color in dv_idxs[dv]: coloring[np.array(dv_idxs[dv][color], dtype=int)] = color all_colors.add(color) if np.any(coloring != -1): simul_colorings[dv] = list(coloring) simul_colorings = OrderedDict(sorted(simul_colorings.items())) for res in res_idxs: simul_map = {} for dv in res_idxs[res]: simul_map[dv] = {c: v for c, v in iteritems(res_idxs[res][dv]) if c in all_colors} if not simul_map[dv]: del simul_map[dv] if simul_map: simul_maps[res] = OrderedDict(sorted(simul_map.items())) simul_maps = OrderedDict(sorted(simul_maps.items())) if stream is not None: if stream.isatty(): stream.write("\n({\n") for n, coloring in iteritems(simul_colorings): stream.write(" '%s': %s,\n" % (n, coloring)) stream.write("},") stream.write("\n{\n") for res, dvdict in iteritems(simul_maps): stream.write(" '%s': {\n" % res) for dv, coldict in iteritems(dvdict): stream.write(" '%s': {\n" % dv) for color, idxs in iteritems(coldict): stream.write(" %s: %s,\n" % (color, idxs)) stream.write(" },\n") stream.write(" },\n") stream.write("})") else: # output json format to a file s = json.dumps((simul_colorings, simul_maps)) # do a little pretty printing since the built-in json pretty printing stretches # the output vertically WAY too much. s = s.replace(',"', ',\n"') s = s.replace(', "', ',\n"') s = s.replace('{"', '{\n"') s = s.replace(', {', ',\n{') s = s.replace(']}', ']\n}') s = s.replace('{}', '{\n}') s = s.replace('}}', '}\n}') s = s.replace('[{', '[\n{') s = s.replace(' {', '\n{') lines = [] indent = 0 for line in s.split('\n'): start = line[0] if len(line) > 0 else '' if start in ('{', '['): tab = ' ' * indent indent += 3 elif start in ('}', ']'): indent -= 3 tab = ' ' * indent else: tab = ' ' * indent lines.append("%s%s" % (tab, line)) stream.write('\n'.join(lines)) stream.write("\n") if show_jac and stream is not None: of = list(driver._objs) of.extend([c for c, meta in iteritems(driver._cons) if not ('linear' in meta and meta['linear'])]) wrt = list(driver._designvars) stream.write("\n\n") array_viz(J, problem, of, wrt, stream) return simul_colorings, simul_maps
def get_simul_meta(problem, mode='fwd', repeats=1, tol=1.e-15, show_jac=False, include_sparsity=True, setup=False, run_model=False, stream=sys.stdout): """ Compute simultaneous derivative colorings for the given problem. Parameters ---------- problem : Problem The Problem being analyzed. mode : str Derivative direction. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualiation of the final total jacobian used to compute the coloring. include_sparsity : bool If True, include the sparsity structure of the total jacobian mapped to design vars and responses. (This info is used by pyOptSparseDriver). setup : bool If True, run setup before calling compute_totals. run_model : bool If True, run run_model before calling compute_totals. stream : file-like or None Stream where output coloring info will be written. Returns ------- tuple of the form (col_lists, row_maps, sparsity) col_lists is a list of column lists, where the first list is the list of uncolored columns. row_maps is a list of nonzero rows for each column, or None for uncolored columns. sparsity is a nested dict specifying subjac sparsity for each total derivative, or None. """ driver = problem.driver J = _get_bool_jac(problem, mode=mode, repeats=repeats, tol=tol, setup=setup, run_model=run_model) if mode == 'fwd': full_disjoint, rows = _get_full_disjoint_cols(J, 0, J.shape[1] - 1) uncolored_cols = [i for i, r in enumerate(rows) if r is None] print("%d uncolored columns" % len(uncolored_cols)) for color, cols in enumerate(full_disjoint): print("%d columns in color %d" % (len(cols), color + 1)) # the first col_list entry corresponds to all uncolored columns (columns that are not # disjoint wrt any other columns). The other entries are groups of columns that do not # share any nonzero row entries in common. col_lists = [uncolored_cols] col_lists.extend(full_disjoint) lists = col_lists other = rows elif mode == 'rev': full_disjoint, cols = _get_full_disjoint_rows(J, 0, J.shape[0] - 1) uncolored_rows = [i for i, r in enumerate(cols) if r is None] print("%d uncolored rows" % len(uncolored_rows)) for color, rows in enumerate(full_disjoint): print("%d rows in color %d" % (len(rows), color + 1)) # the first row_list entry corresponds to all uncolored rows (rows that are not disjoint # wrt any other rows). The other entries are groups of rows that do not share any # nonzero column entries in common. row_lists = [uncolored_rows] row_lists.extend(full_disjoint) lists = row_lists other = cols else: raise RuntimeError("get_simul_meta: invalid mode: '%s'" % mode) sparsity = None if include_sparsity or (show_jac and stream is not None): of = driver._get_ordered_nl_responses() wrt = list(driver._designvars) if include_sparsity: sparsity = _sparsity_from_jac(J, of, wrt, driver) driver._total_jac = None if stream is not None: if stream.isatty(): stream.write("\n########### BEGIN COLORING DATA ################\n") if mode == 'fwd': _write_coloring(mode, col_lists, rows, sparsity, stream) else: _write_coloring(mode, row_lists, cols, sparsity, stream) stream.write("\n########### END COLORING DATA ############\n") else: if mode == 'fwd': _write_coloring(mode, col_lists, rows, sparsity, stream) else: _write_coloring(mode, row_lists, cols, sparsity, stream) if show_jac: s = stream if stream.isatty() else sys.stdout s.write("\n\n") array_viz(J, problem, of, wrt, s) return lists, other, sparsity
def get_simul_meta(problem, mode=None, repeats=1, tol=1.e-15, show_jac=False, include_sparsity=True, setup=False, run_model=False, bool_jac=None, bidirectional=True, simul_coloring_excludes=None, stream=sys.stdout): """ Compute simultaneous derivative colorings for the given problem. Parameters ---------- problem : Problem or None The Problem being analyzed. mode : str or None The direction for computing derivatives. If None, use problem._mode. repeats : int Number of times to repeat total jacobian computation. tol : float Tolerance used to determine if an array entry is nonzero. show_jac : bool If True, display a visualiation of the final total jacobian used to compute the coloring. include_sparsity : bool If True, include the sparsity structure of the total jacobian mapped to design vars and responses. (This info is used by pyOptSparseDriver). setup : bool If True, run setup before calling compute_totals. run_model : bool If True, run run_model before calling compute_totals. bool_jac : ndarray If problem is not supplied, a previously computed boolean jacobian can be used. bidirectional : bool If True, compute a bidirectional coloring. simul_coloring_excludes : iter of int A collection of rows (fwd) or cols (rev) that are to be excluded from the coloring and solved in the opposite direction. Used only if problem is None. Otherwise, problem driver will supply exclude information gathered from design vars or responses. stream : file-like or None Stream where output coloring info will be written. Returns ------- dict dict['fwd'] = (col_lists, row_maps) col_lists is a list of column lists, the first being a list of uncolored columns. row_maps is a list of nonzero rows for each column, or None for uncolored columns. dict['rev'] = (row_lists, col_maps) row_lists is a list of row lists, the first being a list of uncolored rows. col_maps is a list of nonzero cols for each row, or None for uncolored rows. dict['sparsity'] = a nested dict specifying subjac sparsity for each total derivative. dict['J'] = ndarray, the computed boolean jacobian. """ if problem is not None: J = _get_bool_jac(problem, repeats=repeats, tol=tol, setup=setup, run_model=run_model) elif bool_jac is not None: J = bool_jac else: raise RuntimeError("You must supply either problem or bool_jac to get_simul_meta().") if mode is None: mode = problem._mode if problem is not None: simul_coloring_excludes = _get_simul_excludes(problem) coloring = _compute_coloring(J, mode, bidirectional, simul_coloring_excludes) modes = [m for m in ('fwd', 'rev') if m in coloring] sparsity = None if problem is not None: driver = problem.driver else: driver = None if driver is not None: if include_sparsity or (show_jac and stream is not None): of = driver._get_ordered_nl_responses() wrt = list(driver._designvars) if include_sparsity: sparsity = _sparsity_from_jac(J, of, wrt, driver) coloring['sparsity'] = sparsity driver._total_jac = None if stream is not None: if stream.isatty(): stream.write("\n########### BEGIN COLORING DATA ################\n") _write_coloring(modes, coloring, stream) stream.write("\n########### END COLORING DATA ############\n") else: _write_coloring(modes, coloring, stream) if show_jac: s = stream if stream.isatty() else sys.stdout s.write("\n\n") array_viz(J, problem, of, wrt, s) return coloring