From a339e511f6fdbb9a45608d5be6b97a2c1ba166bc Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Mon, 4 Nov 2019 16:22:50 -0600 Subject: [PATCH 01/13] Make wave example more amenable to calling from scripts --- .../wave-accuracy.py | 9 + .../wave-equation.py | 179 +++++++++++++----- 2 files changed, 139 insertions(+), 49 deletions(-) create mode 100755 examples/variable-coeff-wave-equation/wave-accuracy.py diff --git a/examples/variable-coeff-wave-equation/wave-accuracy.py b/examples/variable-coeff-wave-equation/wave-accuracy.py new file mode 100755 index 0000000..595614f --- /dev/null +++ b/examples/variable-coeff-wave-equation/wave-accuracy.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +"""Runs a multirate accuracy experiment for the 1D wave equation.""" + +import os +import subprocess + + +if __name__ == "__main__": + subprocess.check_output(["./wave-equation.py", "-x", "accuracy"], cwd=os.path.dirname(__file__)) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index 547c7c5..ceed03c 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python """Solves the 1D wave equation u_tt - c(x)^2 u_xx = 0 @@ -6,15 +6,17 @@ u(0) = init with piecewise constant coefficients c(x) using a multirate multistep method. - """ +import argparse +import fnmatch import logging +import matplotlib import numpy as np import numpy.linalg as la +import os -import matplotlib from contextlib import contextmanager @@ -22,7 +24,8 @@ from contextlib import contextmanager logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -PAPER_OUTPUT = False +PAPER_OUTPUT = bool(os.environ.get("PAPER_OUTPUT")) +OUT_DIR = os.environ.get("OUT_DIR", ".") # {{{ matplotlib setup @@ -392,7 +395,7 @@ def plot_example(ngridpoints): axis.set_title("Solution to 1D Wave Equation with Variable Coefficients") suffix = "pgf" if PAPER_OUTPUT else "pdf" - filename = f"wave-problem.{suffix}" + filename = os.path.join(OUT_DIR, f"wave-problem.{suffix}") plt.savefig(filename, bbox_inches="tight") logger.info("wrote to '%s'" % filename) @@ -413,7 +416,7 @@ def timer(name): name=name, time=end - start)) -def generate_mrab_step_matrix(ngridpoints, coeffs, substep_ratio): +def generate_mrab_step_matrix(ngridpoints, coeffs, substep_ratio, filename): problem = VariableCoeffWaveEquationProblem(ngridpoints, coeffs) code, rhs_map = make_3_component_multirate_method( @@ -443,17 +446,11 @@ def generate_mrab_step_matrix(ngridpoints, coeffs, substep_ratio): shapes=component_sizes, sparse=True) - substep_ratio_suffix = "-".join(str(r) for r in substep_ratio) - - filename = f"mat{ngridpoints}-{substep_ratio_suffix}.pkl" - with open(filename, "wb") as outf: import pickle pickle.dump(mat, outf) - logging.info(f"{len(mat.data)} nnz, size {mat.shape}") - - return filename + logging.info(f"{filename}: {len(mat.data)} nnz, size {mat.shape}") def compute_all_stable_timesteps(filenames, stable_dts_outf): @@ -494,6 +491,9 @@ def compute_all_stable_timesteps(filenames, stable_dts_outf): print(tabulate(rows, col_fmt="cSc"), file=stable_dts_outf) + if hasattr(stable_dts_outf, "name"): + logger.info("Wrote '%s'", stable_dts_outf.name) + def compute_stable_timestep(step_matrix, tol=0, prec=1e-15): def as_dense(mat): @@ -593,6 +593,9 @@ def multirate_accuracy_experiment(errors_outf): tabulate(rows, col_fmt="S" * (1 + len(substep_ratios))), file=errors_outf) + if hasattr(errors_outf, "name"): + logger.info("Wrote '%s'", errors_outf.name) + # }}} @@ -629,59 +632,137 @@ else: tabulate = tabulate_ascii -@contextmanager def open_or_stdout(filename): if not PAPER_OUTPUT: import sys - yield sys.stdout + return sys.stdout else: - with open(filename, "w") as outf: - logger.info("opened '%s' for writing", filename) - yield outf + return open(filename, "w") -def main(): - if 0: - # Plot an example solution. - plot_example(1000) +# {{{ experimental drivers - elif 0: - # Generate stability results. - # Generating the step matrices takes a long time. +def run_plot_experiment(): + # Plot an example solution. + plot_example(1000) - step_ratios = ( - (1, 1, 1), - (1, 2, 2), - (1, 2, 4), - (1, 2, 6), - ) - filenames = [] +def run_accuracy_experiment(): + errors_outf = open_or_stdout("mrab-errors.tex") + multirate_accuracy_experiment(errors_outf) - ngridpoints = 100 - for step_ratio in step_ratios: - filename = "mat%d-%d-%d-%d.pkl" % ((ngridpoints,) + step_ratio) +def run_stability_experiment(): + # Generate stability results. + # Generating the step matrices takes a long time. + step_ratios = ( + (1, 1, 1), + (1, 2, 2), + (1, 2, 4), + (1, 2, 6), + ) - import os - if not os.path.exists(filename): - filename = generate_mrab_step_matrix( - ngridpoints, (16, 4, 1), step_ratio) - else: - logger.info("using saved step matrix '%s'" % filename) + filenames = [] + + ngridpoints = 100 + + for step_ratio in step_ratios: + filename = os.path.join( + OUT_DIR, + "mat%d-%d-%d-%d.pkl" % ((ngridpoints,) + step_ratio)) + + if not os.path.exists(filename): + generate_mrab_step_matrix( + ngridpoints, (16, 4, 1), step_ratio, filename) + else: + logger.info("using saved step matrix '%s'" % filename) + + filenames.append(filename) + + stable_dts_outf = open_or_stdout("mrab-stable-dts.tex") + compute_all_stable_timesteps(filenames, stable_dts_outf) + +# }}} + + +EXPERIMENTS = ("plot", "accuracy", "stability") + + +def parse_args(): + names = [" - '%s'" % name for name in EXPERIMENTS] + epilog = "\n".join(["experiment names:"] + names) + epilog += "\n".join([ + "\n\nenvironment variables:", + " - OUT_DIR: output path (default '.')", + " - PAPER_OUTPUT: if set to true, generate paperable outputs"]) + + parser = argparse.ArgumentParser( + description= "Runs one or more experiments.", + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter) + + parser.add_argument( + "-x", + metavar="experiment-name", + action="append", + dest="experiments", + default=[], + help="Adds an experiment to the list to be run " + "(accepts wildcards) (may be given multiple times)") + + parser.add_argument( + "--all", + action="store_true", + dest="run_all", + help="Runs all experiments") + + parser.add_argument( + "--except", + action="append", + metavar="experiment-name", + dest="run_except", + default=[], + help="Removes an experiment from the list to be run " + "(accepts wildcards) (may be given multiple times)") + + parse_result = parser.parse_args() + + result = set() + + if parse_result.run_all: + result = set(EXPERIMENTS) + + for experiment in EXPERIMENTS: + for pat in parse_result.experiments: + if fnmatch.fnmatch(experiment, pat): + result.add(experiment) + continue + + to_discard = set() + for experiment in EXPERIMENTS: + for pat in parse_result.run_except: + if fnmatch.fnmatch(experiment, pat): + to_discard.add(experiment) + continue + result -= to_discard + + return result + + +def main(): + experiments = parse_args() - filenames.append(filename) + if "plot" in experiments: + run_plot_experiment() - with open_or_stdout("mrab-stable-dts.tex") as stable_dts_outf: - compute_all_stable_timesteps(filenames, stable_dts_outf) + if "accuracy" in experiments: + run_accuracy_experiment() - elif 1: - # Accuracy results - with open_or_stdout("mrab-errors.tex") as errors_outf: - multirate_accuracy_experiment(errors_outf) + if "stability" in experiments: + run_stability_experiment() -if __name__ == '__main__': +if __name__ == "__main__": main() # vim: foldmethod=marker -- GitLab From 265a59aaaf081caded10c314bb1bf17bcb65c0e1 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Mon, 4 Nov 2019 16:25:23 -0600 Subject: [PATCH 02/13] flake8 fixes --- examples/variable-coeff-wave-equation/wave-accuracy.py | 4 +++- examples/variable-coeff-wave-equation/wave-equation.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/variable-coeff-wave-equation/wave-accuracy.py b/examples/variable-coeff-wave-equation/wave-accuracy.py index 595614f..4d15b1c 100755 --- a/examples/variable-coeff-wave-equation/wave-accuracy.py +++ b/examples/variable-coeff-wave-equation/wave-accuracy.py @@ -6,4 +6,6 @@ import subprocess if __name__ == "__main__": - subprocess.check_output(["./wave-equation.py", "-x", "accuracy"], cwd=os.path.dirname(__file__)) + subprocess.check_output( + ["./wave-equation.py", "-x", "accuracy"], + cwd=os.path.dirname(__file__)) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index ceed03c..1d97883 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -697,7 +697,7 @@ def parse_args(): " - PAPER_OUTPUT: if set to true, generate paperable outputs"]) parser = argparse.ArgumentParser( - description= "Runs one or more experiments.", + description="Runs one or more experiments.", epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter) -- GitLab From 9491d324f2fb08e78543741d293f66b246ac1508 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Mon, 4 Nov 2019 17:44:49 -0600 Subject: [PATCH 03/13] Fix (maybe) wave-accuracy.py --- examples/variable-coeff-wave-equation/wave-accuracy.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/variable-coeff-wave-equation/wave-accuracy.py b/examples/variable-coeff-wave-equation/wave-accuracy.py index 4d15b1c..b81a261 100755 --- a/examples/variable-coeff-wave-equation/wave-accuracy.py +++ b/examples/variable-coeff-wave-equation/wave-accuracy.py @@ -1,11 +1,13 @@ #!/usr/bin/env python -"""Runs a multirate accuracy experiment for the 1D wave equation.""" +"""Runs a multirate accuracy experiment for the 1D wave equation + +(This file is here to run the code as a CI job. See the file wave-equation.py +for more experiments.) +""" import os import subprocess if __name__ == "__main__": - subprocess.check_output( - ["./wave-equation.py", "-x", "accuracy"], - cwd=os.path.dirname(__file__)) + subprocess.check_output(["./wave-equation.py", "-x", "accuracy"]) -- GitLab From ce0baf446ebeb1df96cc7ec941097383f8ca4575 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Mon, 4 Nov 2019 17:55:32 -0600 Subject: [PATCH 04/13] Use subprocess.run --- examples/variable-coeff-wave-equation/wave-accuracy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-accuracy.py b/examples/variable-coeff-wave-equation/wave-accuracy.py index b81a261..acd6405 100755 --- a/examples/variable-coeff-wave-equation/wave-accuracy.py +++ b/examples/variable-coeff-wave-equation/wave-accuracy.py @@ -10,4 +10,4 @@ import subprocess if __name__ == "__main__": - subprocess.check_output(["./wave-equation.py", "-x", "accuracy"]) + subprocess.run(["./wave-equation.py", "-x", "accuracy"]) -- GitLab From ff6766c4fecf84680d54f39b3684338bd84cfd61 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Mon, 4 Nov 2019 20:31:30 -0600 Subject: [PATCH 05/13] Fix PAPER_OUTPUT environment variable --- examples/variable-coeff-wave-equation/wave-equation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index 1d97883..ac0ca75 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -24,7 +24,7 @@ from contextlib import contextmanager logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -PAPER_OUTPUT = bool(os.environ.get("PAPER_OUTPUT")) +PAPER_OUTPUT = int(os.environ.get("PAPER_OUTPUT", 0)) OUT_DIR = os.environ.get("OUT_DIR", ".") -- GitLab From 941141f4a1f969693aec52f51f4716f2ef588b25 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Mon, 4 Nov 2019 23:25:42 -0600 Subject: [PATCH 06/13] Use basename for matching saved matrix file --- examples/variable-coeff-wave-equation/wave-equation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index ac0ca75..f94a8c6 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -476,7 +476,9 @@ def compute_all_stable_timesteps(filenames, stable_dts_outf): intervals = tuple( int(i) for i in - re.match(r"mat\d+-(\d+)-(\d+)-(\d+)\.pkl", fname).groups()) + re.match( + r"mat\d+-(\d+)-(\d+)-(\d+)\.pkl", + os.path.basename(fname)).groups()) row = [str(intervals), f"{dt:.2e}"] -- GitLab From fc51eda6fdac3adbe5b6c1877d3412b49fe02037 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 01:13:31 -0600 Subject: [PATCH 07/13] Fix output path --- examples/variable-coeff-wave-equation/wave-equation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index f94a8c6..4e95532 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -639,7 +639,7 @@ def open_or_stdout(filename): import sys return sys.stdout else: - return open(filename, "w") + return open(os.path.join(OUT_DIR, filename), "w") # {{{ experimental drivers -- GitLab From 7d5461693951a420deb20665a6f4d8f3e7257c8c Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 01:20:44 -0600 Subject: [PATCH 08/13] Fix typo --- examples/variable-coeff-wave-equation/wave-equation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index 4e95532..865e212 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -580,7 +580,7 @@ def multirate_accuracy_experiment(errors_outf): rows.append(row) if PAPER_OUTPUT: - rows.append([r"\midrow"]) + rows.append([r"\midrule"]) row = [r"\multicolumn{1}{l}{Order}"] for s in substep_ratios: row.append(f"{eocs[s].order_estimate():.2f}") -- GitLab From 92a2bef530f1f52780c4835143b57173abf82d89 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 01:58:59 -0600 Subject: [PATCH 09/13] Set pgf.texsystem=pdflatex --- examples/variable-coeff-wave-equation/wave-equation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index ac0ca75..36c04ed 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -42,6 +42,7 @@ LINEWIDTH = 0.5 def initialize_matplotlib(): + plt.rc("pgf", texsystem="pdflatex") plt.rc("font", family="serif") plt.rc("text", usetex=False) plt.rc("xtick", labelsize=FONTSIZE) -- GitLab From 5094e15b52b60bd508371610205546a5ea6158a0 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 18:29:40 +0100 Subject: [PATCH 10/13] Restore interpreter to python3 --- examples/variable-coeff-wave-equation/wave-equation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index 99bf1bf..a3b66bd 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """Solves the 1D wave equation u_tt - c(x)^2 u_xx = 0 -- GitLab From 5c883938ead6379952987158be6ec7f231cb7863 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 18:29:55 +0100 Subject: [PATCH 11/13] Also use python3 in wave-accuracy.py --- examples/variable-coeff-wave-equation/wave-accuracy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-accuracy.py b/examples/variable-coeff-wave-equation/wave-accuracy.py index acd6405..c4efd70 100755 --- a/examples/variable-coeff-wave-equation/wave-accuracy.py +++ b/examples/variable-coeff-wave-equation/wave-accuracy.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """Runs a multirate accuracy experiment for the 1D wave equation (This file is here to run the code as a CI job. See the file wave-equation.py -- GitLab From aacd539609e188812e43a41d080a2edc31fb2349 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 18:30:10 +0100 Subject: [PATCH 12/13] Remove unused import. --- examples/variable-coeff-wave-equation/wave-accuracy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-accuracy.py b/examples/variable-coeff-wave-equation/wave-accuracy.py index c4efd70..b46cc23 100755 --- a/examples/variable-coeff-wave-equation/wave-accuracy.py +++ b/examples/variable-coeff-wave-equation/wave-accuracy.py @@ -5,7 +5,6 @@ for more experiments.) """ -import os import subprocess -- GitLab From 2ac043ac5e195c85bf1163ba6e5dabf37b1c7fb3 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 5 Nov 2019 20:36:53 +0100 Subject: [PATCH 13/13] Remove Docker workaround --- examples/variable-coeff-wave-equation/wave-equation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/variable-coeff-wave-equation/wave-equation.py b/examples/variable-coeff-wave-equation/wave-equation.py index a3b66bd..3efb600 100755 --- a/examples/variable-coeff-wave-equation/wave-equation.py +++ b/examples/variable-coeff-wave-equation/wave-equation.py @@ -42,7 +42,6 @@ LINEWIDTH = 0.5 def initialize_matplotlib(): - plt.rc("pgf", texsystem="pdflatex") plt.rc("font", family="serif") plt.rc("text", usetex=False) plt.rc("xtick", labelsize=FONTSIZE) -- GitLab