diff --git a/pytools/convergence.py b/pytools/convergence.py index 6dd87b8b7e3faf5459ac6d469212e1d2b9e5fac2..cdedc83641e148f2dc23c6c5b83fe2296bdecc3c 100644 --- a/pytools/convergence.py +++ b/pytools/convergence.py @@ -80,4 +80,36 @@ class EOCRecorder(object): # }}} +# {{{ p convergence verifier + +class PConvergenceVerifier(object): + def __init__(self): + self.orders = [] + self.errors = [] + + def add_data_point(self, order, error): + self.orders.append(order) + self.errors.append(error) + + def __str__(self): + from pytools import Table + tbl = Table() + tbl.add_row(("p", "error")) + + for p, err in zip(self.orders, self.errors): + tbl.add_row((str(p), str(err))) + + return str(tbl) + + def __call__(self): + orders = np.array(self.orders, np.float64) + errors = np.abs(np.array(self.errors, np.float64)) + + rel_change = np.diff(1e-20 + np.log10(errors)) / np.diff(orders) + + assert (rel_change < -0.2).all() + +# }}} + + # vim: foldmethod=marker diff --git a/test/test_pytools.py b/test/test_pytools.py index f8d0109c11fb44801a4401642687222a400be626..7f0e3f4cea414a7fa575aa47459d7d6c440ec859 100644 --- a/test/test_pytools.py +++ b/test/test_pytools.py @@ -45,3 +45,23 @@ def test_memoize_method_clear(): assert sc.run_count == 1 sc.f.clear_cache(sc) + + +def test_p_convergence_verifier(): + from pytools.convergence import PConvergenceVerifier + + pconv_verifier = PConvergenceVerifier() + for order in [2, 3, 4, 5]: + pconv_verifier.add_data_point(order, 0.1**order) + pconv_verifier() + + pconv_verifier = PConvergenceVerifier() + for order in [2, 3, 4, 5]: + pconv_verifier.add_data_point(order, 0.5**order) + pconv_verifier() + + pconv_verifier = PConvergenceVerifier() + for order in [2, 3, 4, 5]: + pconv_verifier.add_data_point(order, 2) + with pytest.raises(AssertionError): + pconv_verifier()