def plot(n, *args, **kwargs): import dufte from matplotlib import pyplot as plt plt.style.use(dufte.style) x = numpy.linspace(-1.0, 1.0, 100) evaluator = Eval(x, *args, **kwargs) for k in range(n + 1): plt.plot(x, next(evaluator), label=f"n={k}") plt.grid(axis="x") dufte.legend() ax = plt.gca() alpha, beta, scaling = args if alpha == beta: if alpha == 0: plt.title(f"Legendre polynomials (scaling={scaling})") elif alpha == -0.5: plt.title(f"Chebyshev 1 polynomials (scaling={scaling})") elif alpha == +0.5: plt.title(f"Chebyshev 2 polynomials (scaling={scaling})") else: plt.title(f"Gegenbauer polynomials (λ={alpha}, scaling={scaling})") else: plt.title( f"Jacobi polynomials (α={alpha}, β={beta}, scaling={scaling})") ax.spines["right"].set_visible(True) ax.spines["left"].set_visible(True)
def plot(n, *args, **kwargs): import dufte from matplotlib import pyplot as plt plt.style.use(dufte.style) x = numpy.linspace(-1.0, 1.0, 200) for k, level in enumerate(itertools.islice(Eval(x, *args, **kwargs), n + 1)): # Choose all colors in each level approximately equal, around the reference # color. ref_color = plt.rcParams["axes.prop_cycle"].by_key()["color"][k] ref_rgb = numpy.array( list(int(ref_color[1:][i : i + 2], 16) / 255 for i in (0, 2, 4)) ) for l, entry in enumerate(level): col = ref_rgb * (1 + (l - k) / (2 * (k + 1))) col[col < 0.0] = 0.0 col[col > 1.0] = 1.0 plt.plot(x, entry, label=f"n={k}, r={l - k}", color=col) plt.grid(axis="x") dufte.legend() ax = plt.gca() ax.spines["top"].set_visible(False) ax.spines["bottom"].set_visible(False) (scaling,) = args plt.title(f'Associated Legendre "polynomials" (scaling={scaling})') ax.spines["right"].set_visible(True) ax.spines["left"].set_visible(True) plt.xlim(-1.0, 1.0)
def test_accuracy_comparison_illcond(filename=None, target_conds=None): plt.style.use(dufte.style) if target_conds is None: target_conds = [10 ** k for k in range(1, 2)] kernels = [ sum, numpy.sum, accupy.kahan_sum, lambda p: accupy.ksum(p, K=2), lambda p: accupy.ksum(p, K=3), accupy.fsum, ] labels = [ "sum", "numpy.sum", "accupy.kahan_sum", "accupy.ksum[2]", "accupy.ksum[3]", "accupy.fsum", ] colors = plt.rcParams["axes.prop_cycle"].by_key()["color"][: len(labels)] data = numpy.empty((len(target_conds), len(kernels))) condition_numbers = numpy.empty(len(target_conds)) numpy.random.seed(0) for k, target_cond in enumerate(target_conds): p, ref, C = accupy.generate_ill_conditioned_sum(1000, target_cond) condition_numbers[k] = C data[k] = [abs(kernel(p) - ref) / abs(ref) for kernel in kernels] # sort s = numpy.argsort(condition_numbers) condition_numbers = condition_numbers[s] data = data[s] for label, color, d in zip(labels, colors, data.T): plt.loglog(condition_numbers, d, label=label, color=color) dufte.legend() plt.xlabel("condition number") plt.ylabel("relative error") # plt.gca().set_aspect(1.3) # plt.show() # <https://stackoverflow.com/a/10154763/353337> if filename: plt.savefig(filename, transparent=True, bbox_inches="tight")
def plot(n, *args, **kwargs): import dufte from matplotlib import pyplot as plt plt.style.use(dufte.style) x = numpy.linspace(-2.2, 2.2, 100) for k, level in enumerate(itertools.islice(Eval(x, *args, **kwargs), n + 1)): plt.plot(x, level, label=f"n={k}") plt.grid(axis="x") dufte.legend() variant, scaling = args plt.title(f"Hermite polynomials ({variant}, scaling={scaling})")
def plot(filenames, sort=True, cut=None, max_num=20): # read data data = [] for filename in filenames: with open(filename) as f: data.append(json.load(f)) if sort: # sort them such that the largest at the last time step gets plotted first and # the colors are in a nice order last_vals = [list(content["data"].values())[-1] for content in data] data = [data[i] for i in _argsort(last_vals)[::-1]] if cut is not None: # cut those files where the max data is less than cut*max_overall max_vals = [max(list(content["data"].values())) for content in data] max_overall = max(max_vals) data = [ content for content, max_val in zip(data, max_vals) if max_val > cut * max_overall ] if max_num is not None: # show only max_num repos data = data[:max_num] n = len(data) for k, content in enumerate(data): data = content["data"] data = { datetime.fromisoformat(key): value for key, value in data.items() } times = list(data.keys()) values = list(data.values()) label = content["name"] plt.plot(times, values, label=label, zorder=n - k) dufte.legend() if "creator" in content: _add_license_statement(content)
def test_accuracy_comparison_illcond(filename=None, target_cond=None): plt.style.use(dufte.style) if target_cond is None: target_cond = [10**k for k in range(2)] kernels = [ numpy.dot, lambda x, y: accupy.kdot(x, y, K=2), lambda x, y: accupy.kdot(x, y, K=3), accupy.fdot, ] labels = ["numpy.dot", "accupy.kdot[2]", "accupy.kdot[3]", "accupy.fdot"] data = numpy.empty((len(target_cond), len(kernels))) condition_numbers = numpy.empty(len(target_cond)) numpy.random.seed(0) for k, tc in enumerate(target_cond): x, y, ref, C = accupy.generate_ill_conditioned_dot_product(1000, tc) condition_numbers[k] = C data[k] = [abs(kernel(x, y) - ref) / abs(ref) for kernel in kernels] # sort s = numpy.argsort(condition_numbers) condition_numbers = condition_numbers[s] data = data[s] for label, d in zip(labels, data.T): plt.loglog(condition_numbers, d, label=label) dufte.legend() plt.xlabel("condition number") plt.ylabel("relative error") # plt.show() # <https://stackoverflow.com/a/10154763/353337> if filename: plt.savefig(filename, transparent=True, bbox_inches="tight")
def test_comparison(): plt.style.use(dufte.style) X, cells = circle_random(40, 1.0) # Do a few steps of a robust method to avoid too crazy meshes. tol = 0.0 n = 10 # X, cells = optimesh.cpt.fixed_point_uniform(X, cells, tol, n) # X, cells = optimesh.odt.fixed_point_uniform(X, cells, tol, n) X, cells = optimesh.optimize_points_cells(X, cells, "lloyd", tol, n, omega=2.0) # from meshplex import MeshTri # mesh = MeshTri(X, cells) # mesh.write("out.vtk") # exit(1) num_steps = 50 names = [ "cpt-fixed-point", "cpt-quasi-newton", # "lloyd", "lloyd(2.0)", "cvt-block-diagonal", "cvt-full", # "odt-fixed-point", "odt-bfgs", ] avg_quality = np.empty((len(names), num_steps + 1)) for i, name in enumerate(names): def callback(k, mesh): avg_quality[i, k] = np.average(mesh.q_radius_ratio) return X_in = X.copy() cells_in = cells.copy() if name == "lloyd(2.0)": optimesh.optimize_points_cells(X_in, cells_in, "lloyd", 0.0, num_steps, omega=2.0, callback=callback) else: optimesh.optimize_points_cells(X_in, cells_in, name, 0.0, num_steps, callback=callback) # sort by best final quality idx = np.argsort(avg_quality[:, -1])[::-1] sorted_labels = [names[i] for i in idx] for i, label, values in zip(idx, sorted_labels, avg_quality[idx]): plt.plot(values, "-", label=label, zorder=i) plt.xlim(0, num_steps) plt.ylim(0.93, 1.0) plt.xlabel("step") plt.title("average cell quality") dufte.legend() plt.savefig("comparison.svg", transparent=True, bbox_inches="tight")
def plot_per_day(filenames, sort=True, cut=None): if sort: # sort them such that the largest at the last time step gets plotted first and # the colors are in a nice order last_vals = [] for filename in filenames: with open(filename) as f: content = json.load(f) vals = list(content["data"].values()) last_vals.append(vals[-1] - vals[-2]) filenames = [filenames[i] for i in _argsort(last_vals)[::-1]] if cut is not None: # cut those files where the max data is less than cut*max_overall max_vals = [] for filename in filenames: with open(filename) as f: content = json.load(f) vals = list(content["data"].values()) vals = [vals[k + 1] - vals[k] for k in range(len(vals) - 1)] max_vals.append(max(vals)) max_overall = max(max_vals) filenames = [ filename for filename, max_val in zip(filenames, max_vals) if max_val > cut * max_overall ] times = [] values = [] labels = [] for filename in filenames: filename = pathlib.Path(filename) assert filename.is_file(), f"{filename} not found." with open(filename) as f: content = json.load(f) data = content["data"] data = { datetime.fromisoformat(key): value for key, value in data.items() } t = list(data.keys()) v = list(data.values()) times.append(_get_middle_times(t)) values.append(_get_avg_per_day(t, v)) labels.append(content["name"]) # start plotting from the 0 before the first value for j, (tm, val) in enumerate(zip(times, values)): for i, x in enumerate(val): if x > 0: k = max(i - 1, 0) break times[j] = tm[k:] values[j] = val[k:] n = len(times) for k, (time, vals, label) in enumerate(zip(times, values, labels)): plt.plot(time, vals, label=label, zorder=n - k) dufte.legend() if "creator" in content: _add_license_statement(content)
def plot( # noqa: C901 self, time_unit: str = "s", relative_to: Optional[int] = None, logx: Union[str, bool] = "auto", logy: Union[str, bool] = "auto", ): if logx == "auto": # Check if the x values are approximately equally spaced in log if np.any(self.n_range <= 0): logx = False else: log_n_range = np.log(self.n_range) diff = log_n_range - np.linspace( log_n_range[0], log_n_range[-1], len(log_n_range) ) logx = np.all(np.abs(diff) < 1.0e-5) if logy == "auto": if relative_to is not None: logy = False elif self.flop is not None: logy = False else: logy = logx if logx and logy: plotfun = plt.loglog elif logx: plotfun = plt.semilogx elif logy: plotfun = plt.semilogy else: plotfun = plt.plot if self.flop is None: if relative_to is None: # Set time unit of plots. # Allowed values: ("s", "ms", "us", "ns", "auto") if time_unit == "auto": time_unit = _auto_time_unit(np.min(self.timings_s)) else: assert time_unit in si_time, "Provided `time_unit` is not valid" scaled_timings = self.timings_s / si_time[time_unit] ylabel = f"Runtime [{time_unit}]" else: scaled_timings = self.timings_s / self.timings_s[relative_to] ylabel = f"Runtime\nrelative to {self.labels[relative_to]}" # plt.title(ylabel) ylabel = plt.ylabel(ylabel, ha="center", ma="left") plt.gca().yaxis.set_label_coords(-0.1, 1.0) ylabel.set_rotation(0) for t, label in zip(scaled_timings, self.labels): plotfun(self.n_range, t, label=label) else: if relative_to is None: flops = self.flop / self.timings_s plt.title("FLOPS") else: flops = self.timings_s[relative_to] / self.timings_s plt.title(f"FLOPS relative to {self.labels[relative_to]}") for fl, label in zip(flops, self.labels): plotfun(self.n_range, fl, label=label) if self.xlabel: plt.xlabel(self.xlabel) if relative_to is not None and not logy: plt.gca().set_ylim(bottom=0) dufte.legend()
def plot( # noqa: C901 self, time_unit="s", relative_to=None, logx="auto", logy="auto", style='dufte', ): if logx == "auto": # Check if the x values are approximately equally spaced in log log_n_range = numpy.log(self.n_range) diff = log_n_range - numpy.linspace( log_n_range[0], log_n_range[-1], len(log_n_range)) logx = numpy.all(numpy.abs(diff) < 1.0e-5) if logy == "auto": if relative_to is not None: logy = False elif self.flop is not None: logy = False else: logy = logx if logx and logy: plotfun = plt.loglog elif logx: plotfun = plt.semilogx elif logy: plotfun = plt.semilogy else: plotfun = plt.plot if self.flop is None: if relative_to is None: # Set time unit of plots. # Allowed values: ("s", "ms", "us", "ns", "auto") if time_unit == "auto": time_unit = _auto_time_unit(numpy.min(self.timings)) else: assert time_unit in si_time, "Provided `time_unit` is not valid" scaled_timings = self.timings * (si_time["ns"] / si_time[time_unit]) plt.title(f"Runtime [{time_unit}]") else: scaled_timings = self.timings / self.timings[relative_to] plt.title(f"Runtime relative to {self.labels[relative_to]}()") for t, label in zip(scaled_timings, self.labels): plotfun(self.n_range, t, label=label) else: if relative_to is None: flops = self.flop / self.timings / si_time["ns"] plt.title("FLOPS") else: flops = self.timings[relative_to] / self.timings plt.title(f"FLOPS relative to {self.labels[relative_to]}") for fl, label in zip(flops, self.labels): plotfun(self.n_range, fl, label=label) if self.xlabel: plt.xlabel(self.xlabel) if relative_to is not None and not logy: plt.gca().set_ylim(bottom=0) dufte.legend()
def create_plots(prefix, functions, H, time_limit=60): times = [] quality_min = [] quality_avg = [] num_poisson_steps = [] num_points = [] poisson_tol = 1.0e-10 with Progress() as progress: task1 = progress.add_task("Overall", total=len(H)) task2 = progress.add_task("Functions", total=len(functions)) for h in H: times.append([]) quality_min.append([]) quality_avg.append([]) num_poisson_steps.append([]) num_points.append([]) progress.update(task2, completed=0) for fun in functions: try: with time_limiter(time_limit): tic = time.time() points, cells = fun(h) toc = time.time() except TimeoutException: times[-1].append(numpy.nan) quality_min[-1].append(numpy.nan) quality_avg[-1].append(numpy.nan) num_points[-1].append(numpy.nan) num_poisson_steps[-1].append(numpy.nan) else: if cells.shape[1] == 3: mesh = meshplex.MeshTri(points, cells) else: assert cells.shape[1] == 4 mesh = meshplex.MeshTetra(points, cells) times[-1].append(toc - tic) quality_min[-1].append(numpy.min(mesh.q_radius_ratio)) quality_avg[-1].append(numpy.average(mesh.q_radius_ratio)) num_points[-1].append(mesh.node_coords.shape[0]) if numpy.min(mesh.q_radius_ratio) < 1.0e-5: num_poisson_steps[-1].append(numpy.nan) else: num_steps = get_poisson_steps(points, cells, poisson_tol) num_poisson_steps[-1].append(num_steps) progress.update(task2, advance=1) progress.update(task1, advance=1) times = numpy.array(times) quality_min = numpy.array(quality_min) quality_avg = numpy.array(quality_avg) num_poisson_steps = numpy.array(num_poisson_steps) num_points = numpy.array(num_points) names = [inspect.getmodule(fun).desc for fun in functions] colors = [inspect.getmodule(fun).colors for fun in functions] # plot the data plt.style.use(dufte.style) for name, num_pts, t, cols in zip(names, num_points.T, times.T, colors): plt.loglog(num_pts, t, color=cols[0], label=name) dufte.legend() plt.xlabel("num points") plt.title("mesh creation times [s]") plt.savefig(f"{prefix}-times.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close() for name, num_pts, qa, qm, cols in zip( names, num_points.T, quality_avg.T, quality_min.T, colors ): plt.semilogx(num_pts, qa, color=cols[0], linestyle="-", label=f"{name}") plt.semilogx(num_pts, qm, color=cols[1], linestyle="--", label="") plt.ylim(0.0, 1.0) dufte.legend() plt.xlabel("num points") plt.title("cell quality, avg and min (dashed)") plt.savefig(f"{prefix}-quality.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close() for name, num_pts, np, cols in zip( names, num_points.T, num_poisson_steps.T, colors ): plt.semilogx(num_pts, np, color=cols[0], label=f"{name}") dufte.legend() plt.xlabel("num points") plt.title(f"number of CG steps for the Poisson problem (tol={poisson_tol:.1e})") plt.savefig(f"{prefix}-poisson.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close()
def create_plots(domain): # plot the data plt.style.use(dufte.style) # num nodes vs. time for module in modules: name = module.packages[0][0] json_filename = name.lower() + ".json" with open(json_filename) as f: data = json.load(f) label = ", ".join(" ".join(package) for package in module.packages) if domain in data["data"]: x = numpy.array(data["data"][domain]["num_nodes"]) y = numpy.array(data["data"][domain]["time"]) idx = numpy.argsort(x) plt.loglog(x[idx], y[idx], color=module.colors[0], label=label) dufte.legend() plt.xlabel("num points") plt.title("mesh creation times [s]") plt.savefig(f"{domain}-times.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close() # num nodes vs. cell quality for module in modules: name = module.packages[0][0] json_filename = name.lower() + ".json" with open(json_filename) as f: data = json.load(f) label = ", ".join(" ".join(package) for package in module.packages) if domain in data["data"]: x = numpy.array(data["data"][domain]["num_nodes"]) y0 = numpy.array(data["data"][domain]["quality_avg"]) y1 = numpy.array(data["data"][domain]["quality_min"]) idx = numpy.argsort(x) plt.semilogx( x[idx], y0[idx], linestyle="-", color=module.colors[0], label=label ) plt.semilogx(x[idx], y1[idx], linestyle="--", color=module.colors[1]) dufte.legend() plt.xlabel("num points") plt.title("cell quality, avg and min (dashed)") plt.ylim(0.0, 1.0) plt.savefig(f"{domain}-quality.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close() # num nodes vs. energy for module in modules: name = module.packages[0][0] json_filename = name.lower() + ".json" with open(json_filename) as f: data = json.load(f) label = ", ".join(" ".join(package) for package in module.packages) if domain in data["data"]: x = numpy.array(data["data"][domain]["num_nodes"]) idx = numpy.argsort(x) try: y = numpy.array(data["data"][domain]["energy"]) except KeyError: pass else: plt.loglog( x[idx], y[idx], linestyle="-", color=module.colors[0], label=label ) dufte.legend() plt.xlabel("num points") plt.title("energy (lower is better)") plt.savefig(f"{domain}-energy.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close() # num nodes vs. CG iterations for Poisson for module in modules: name = module.packages[0][0] json_filename = name.lower() + ".json" with open(json_filename) as f: data = json.load(f) label = ", ".join(" ".join(package) for package in module.packages) if domain in data["data"]: x = numpy.array(data["data"][domain]["num_nodes"]) y = numpy.array(data["data"][domain]["num_poisson_steps"]) idx = numpy.argsort(x) plt.semilogx(x[idx], y[idx], color=module.colors[0], label=label) dufte.legend() plt.xlabel("num points") poisson_tol = 1.0e-10 plt.title(f"number of CG steps for the Poisson problem (tol={poisson_tol:.1e})") plt.ylim(0.0) plt.savefig(f"{domain}-poisson.svg", transparent=True, bbox_inches="tight") # plt.show() plt.close()
def plot(argv=None): import dufte import matplotlib.pyplot as plt plt.style.use(dufte.style) parser = _get_parser_plot() args = parser.parse_args(argv) data = [yaml.load(f, Loader=yaml.SafeLoader) for f in args.infiles] # actually plot it fig = plt.figure() ax1 = fig.add_subplot(1, 1, 1) for d in data: temperature_data = d["temperature"] if args.delta_t: temperature_data = [] zip_object = zip(d["temperature"], d["ambient"]) for d["temperature"], d["ambient"] in zip_object: temperature_data.append(d["temperature"] - d["ambient"]) plt.plot(d["time"], temperature_data, label=d["name"]) dufte.legend() if args.delta_t: plot_yaxis_label = "Δ temperature [°C over ambient]" else: plot_yaxis_label = "temperature [°C]" plt.xlabel("time [s]") plt.ylabel(plot_yaxis_label) if args.temp_lims: ax1.set_ylim(*args.temp_lims) # Only plot frequencies when using a single input file if len(data) == 1 and args.frequency: ax2 = plt.twinx() ax2.set_ylabel("core frequency (MHz)") if args.freq_lims: ax2.set_ylim(*args.freq_lims) try: for d in data: ax2.plot( d["time"], d["cpu frequency"], label=d["name"], color="C1", alpha=0.9, ) ax1.set_zorder(ax2.get_zorder() + 1) # put ax1 plot in front of ax2 ax1.patch.set_visible(False) # hide the 'canvas' except KeyError(): print("Source data does not contain CPU frequency data.") if args.outfile is not None: plt.savefig( args.outfile, transparent=args.transparent, bbox_inches="tight", dpi=args.dpi, ) else: plt.show() return