From 09fbd8980525ca060e430996b33256f2aff87acb Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Fri, 23 Dec 2016 15:48:43 -0600 Subject: [PATCH 1/3] Cache derivative taking so that we start from the nearest available derivative (apparently, sympy doesn't do this). This lets translation operators with big derivative expressions (order 20ish) finish compiling in a reasonable amount of time, even without symengine. --- sumpy/expansion/local.py | 12 ++++++------ sumpy/expansion/multipole.py | 5 +++-- sumpy/tools.py | 31 +++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/sumpy/expansion/local.py b/sumpy/expansion/local.py index 6c1fd28a..e3219933 100644 --- a/sumpy/expansion/local.py +++ b/sumpy/expansion/local.py @@ -91,11 +91,11 @@ class VolumeTaylorLocalExpansionBase(LocalExpansionBase): """ def coefficients_from_source(self, avec, bvec): - from sumpy.tools import mi_derivative + from sumpy.tools import MiDerivativeTaker ppkernel = self.kernel.postprocess_at_source( self.kernel.get_expression(avec), avec) - return [mi_derivative(ppkernel, avec, mi) - for mi in self.get_coefficient_identifiers()] + taker = MiDerivativeTaker(ppkernel, avec) + return [taker.diff(mi) for mi in self.get_coefficient_identifiers()] def evaluate(self, coeffs, bvec): from sumpy.tools import mi_power, mi_factorial @@ -115,10 +115,10 @@ class VolumeTaylorLocalExpansionBase(LocalExpansionBase): type(self).__name__, self.order)) - from sumpy.tools import mi_derivative + from sumpy.tools import MiDerivativeTaker expr = src_expansion.evaluate(src_coeff_exprs, dvec) - result = [mi_derivative(expr, dvec, mi) - for mi in self.get_coefficient_identifiers()] + taker = MiDerivativeTaker(expr, dvec) + result = [taker.diff(mi) for mi in self.get_coefficient_identifiers()] logger.info("building translation operator: done") return result diff --git a/sumpy/expansion/multipole.py b/sumpy/expansion/multipole.py index f579bd30..79412e17 100644 --- a/sumpy/expansion/multipole.py +++ b/sumpy/expansion/multipole.py @@ -92,9 +92,10 @@ class VolumeTaylorMultipoleExpansionBase(MultipoleExpansionBase): ppkernel = self.kernel.postprocess_at_target( self.kernel.get_expression(bvec), bvec) - from sumpy.tools import mi_derivative + from sumpy.tools import MiDerivativeTaker + taker = MiDerivativeTaker(ppkernel, bvec) result = sum( - coeff * mi_derivative(ppkernel, bvec, mi) + coeff * taker.diff(mi) for coeff, mi in zip(coeffs, self.get_coefficient_identifiers())) return result diff --git a/sumpy/tools.py b/sumpy/tools.py index d2d3a711..aaaeae7b 100644 --- a/sumpy/tools.py +++ b/sumpy/tools.py @@ -54,10 +54,33 @@ def mi_power(vector, mi): return result -def mi_derivative(expr, vector, mi): - for mi_i, vec_i in zip(mi, vector): - expr = expr.diff(vec_i, mi_i) - return expr +class MiDerivativeTaker(object): + + def __init__(self, expr, var_list): + self.var_list = var_list + empty_mi = (0,) * len(var_list) + self.cache_by_mi = {empty_mi: expr} + + def mi_dist(self, a, b): + return np.array(a, dtype=int) - np.array(b, dtype=int) + + def diff(self, mi): + closest_mi = min( + (other_mi + for other_mi in self.cache_by_mi.keys() + if (np.array(mi) >= np.array(other_mi)).all()), + key = lambda other_mi: sum(self.mi_dist(mi, other_mi))) + + expr = self.cache_by_mi[closest_mi] + current_mi = np.array(closest_mi, dtype=int) + for idx, (mi_i, vec_i) in enumerate( + zip(self.mi_distvec(mi, closest_mi), self.var_list)): + for i in range(1, 1 + mi_i): + current_mi[idx] += 1 + expr = expr.diff(vec_i) + self.cache_by_mi[tuple(current_mi)] = expr + + return expr # }}} -- GitLab From cdd993f91f1b3a58c461e01ea4544525cbca27b8 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Fri, 23 Dec 2016 16:11:40 -0600 Subject: [PATCH 2/3] Fix flake8 warning. --- sumpy/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sumpy/tools.py b/sumpy/tools.py index aaaeae7b..b0cd2322 100644 --- a/sumpy/tools.py +++ b/sumpy/tools.py @@ -69,7 +69,7 @@ class MiDerivativeTaker(object): (other_mi for other_mi in self.cache_by_mi.keys() if (np.array(mi) >= np.array(other_mi)).all()), - key = lambda other_mi: sum(self.mi_dist(mi, other_mi))) + key=lambda other_mi: sum(self.mi_dist(mi, other_mi))) expr = self.cache_by_mi[closest_mi] current_mi = np.array(closest_mi, dtype=int) -- GitLab From 5573aa9b2de39018d91162d77a212df654b2e2d5 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Fri, 23 Dec 2016 16:17:32 -0600 Subject: [PATCH 3/3] Fix called method name. --- sumpy/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sumpy/tools.py b/sumpy/tools.py index aaaeae7b..ce6c8c9b 100644 --- a/sumpy/tools.py +++ b/sumpy/tools.py @@ -74,7 +74,7 @@ class MiDerivativeTaker(object): expr = self.cache_by_mi[closest_mi] current_mi = np.array(closest_mi, dtype=int) for idx, (mi_i, vec_i) in enumerate( - zip(self.mi_distvec(mi, closest_mi), self.var_list)): + zip(self.mi_dist(mi, closest_mi), self.var_list)): for i in range(1, 1 + mi_i): current_mi[idx] += 1 expr = expr.diff(vec_i) -- GitLab