From 20b41019e6b052ec2f278971839ed9caa54ba6c0 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Thu, 29 Dec 2016 19:31:32 -0600 Subject: [PATCH] M2L: Speed up derivative taking by borrowing the multipole expansion's derivative taker. --- sumpy/expansion/local.py | 34 ++++++++++++++++++++++++++++++---- sumpy/expansion/multipole.py | 13 ++++++++----- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/sumpy/expansion/local.py b/sumpy/expansion/local.py index e3219933..c20eaf20 100644 --- a/sumpy/expansion/local.py +++ b/sumpy/expansion/local.py @@ -115,10 +115,36 @@ class VolumeTaylorLocalExpansionBase(LocalExpansionBase): type(self).__name__, self.order)) - from sumpy.tools import MiDerivativeTaker - expr = src_expansion.evaluate(src_coeff_exprs, dvec) - taker = MiDerivativeTaker(expr, dvec) - result = [taker.diff(mi) for mi in self.get_coefficient_identifiers()] + from sumpy.expansion.multipole import VolumeTaylorMultipoleExpansionBase + if isinstance(src_expansion, VolumeTaylorMultipoleExpansionBase): + # We know the general form of the multipole expansion is: + # + # coeff0 * diff(kernel, mi0) + coeff1 * diff(kernel, mi1) + ... + # + # To get the local expansion coefficients, we take derivatives of + # the multipole expansion. + # + # This code speeds up derivative taking by caching all kernel + # derivatives. + taker = src_expansion.get_kernel_derivative_taker(dvec) + + def mi_sum(a, b): + return tuple(aval + bval for aval, bval in zip(a, b)) + + result = [] + for deriv in self.get_coefficient_identifiers(): + local_result = [] + for coeff, term in zip( + src_coeff_exprs, + src_expansion.get_coefficient_identifiers()): + kernel_deriv = taker.diff(mi_sum(deriv, term)) + local_result.append(coeff * kernel_deriv) + result.append(sp.Add(*local_result)) + else: + from sumpy.tools import MiDerivativeTaker + expr = src_expansion.evaluate(src_coeff_exprs, dvec) + 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 79412e17..04441795 100644 --- a/sumpy/expansion/multipole.py +++ b/sumpy/expansion/multipole.py @@ -89,16 +89,19 @@ class VolumeTaylorMultipoleExpansionBase(MultipoleExpansionBase): return self.full_to_stored(result) def evaluate(self, coeffs, bvec): - ppkernel = self.kernel.postprocess_at_target( - self.kernel.get_expression(bvec), bvec) - - from sumpy.tools import MiDerivativeTaker - taker = MiDerivativeTaker(ppkernel, bvec) + taker = self.get_kernel_derivative_taker(bvec) result = sum( coeff * taker.diff(mi) for coeff, mi in zip(coeffs, self.get_coefficient_identifiers())) return result + def get_kernel_derivative_taker(self, bvec): + ppkernel = self.kernel.postprocess_at_target( + self.kernel.get_expression(bvec), bvec) + + from sumpy.tools import MiDerivativeTaker + return MiDerivativeTaker(ppkernel, bvec) + def translate_from(self, src_expansion, src_coeff_exprs, dvec): if not isinstance(src_expansion, type(self)): raise RuntimeError("do not know how to translate %s to " -- GitLab