Skip to content

Commit 6490348

Browse files
ShawnL00inducer
authored andcommitted
add asymline expansion + support for different tau values
Add AsymptoticDividingLineTaylorExpansion class, todo: add test case documentaions + autoclass + rename
1 parent 2cd2f4f commit 6490348

1 file changed

Lines changed: 114 additions & 1 deletion

File tree

sumpy/expansion/local.py

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
.. autoclass:: H2DLocalExpansion
4949
.. autoclass:: Y2DLocalExpansion
5050
.. autoclass:: LineTaylorLocalExpansion
51+
.. autoclass:: AsymptoticDividingLineTaylorExpansion
5152
5253
"""
5354

@@ -106,6 +107,10 @@ def translate_from(self, src_expansion, src_coeff_exprs, src_rscale,
106107
# {{{ line taylor
107108

108109
class LineTaylorLocalExpansion(LocalExpansionBase):
110+
def __init__(self, kernel, order, tau=1, use_rscale=None, m2l_translation=None):
111+
super().__init__(kernel, order, use_rscale, m2l_translation)
112+
self.tau = tau
113+
109114
def get_storage_index(self, k):
110115
return k
111116

@@ -152,8 +157,9 @@ def evaluate(self, tgt_kernel, coeffs, bvec, rscale, sac=None):
152157

153158
# NOTE: We can't meaningfully apply target derivatives here.
154159
# Instead, this is handled in LayerPotentialBase._evaluate.
160+
155161
return sym.Add(*(
156-
coeffs[self.get_storage_index(i)] / math.factorial(i)
162+
coeffs[self.get_storage_index(i)] / math.factorial(i) * self.tau**i
157163
for i in self.get_coefficient_identifiers()))
158164

159165
def translate_from(self, src_expansion, src_coeff_exprs, src_rscale,
@@ -163,6 +169,113 @@ def translate_from(self, src_expansion, src_coeff_exprs, src_rscale,
163169
# }}}
164170

165171

172+
# {{{ Asymptotic dividing line Taylor expansion
173+
174+
class AsymptoticDividingLineTaylorExpansion(LocalExpansionBase):
175+
r"""
176+
A target-specific modified line Taylor expansion.
177+
178+
The expansion line is defined as :math:`l(\tau) = \text{avec} + \tau \cdot
179+
\text{bvec}` at a target point :math:`x`. The modified line Taylor expansion takes
180+
the form:
181+
182+
.. math::
183+
184+
\sum_{k=0}^{\text{order}} \frac{g_k}{k!} \tau^k,
185+
186+
where:
187+
188+
.. math::
189+
190+
g_k := \frac{d^k}{d\tau^k} \left(
191+
\frac{\text{kernel}(l(\tau))}{\text{asymptotic}(l(\tau))} \right) \bigg|_{\tau=0}
192+
193+
.. automethod:: get_asymptotic_expression
194+
"""
195+
196+
def __init__(self,
197+
kernel,
198+
asymptotic,
199+
order,
200+
tau=1,
201+
use_rscale=None,
202+
m2l_translation=None):
203+
super().__init__(kernel, order, use_rscale, m2l_translation)
204+
self.asymptotic = asymptotic
205+
self.tau = tau
206+
207+
def get_storage_index(self, k):
208+
return k
209+
210+
def get_coefficient_identifiers(self):
211+
return list(range(self.order+1))
212+
213+
def get_asymptotic_expression(self, scaled_dist_vec):
214+
from sumpy.symbolic import PymbolicToSympyMapperWithSymbols, Symbol
215+
216+
expr = PymbolicToSympyMapperWithSymbols()(self.asymptotic)
217+
expr = expr.xreplace({Symbol(f"d{i}"): dist_vec_i
218+
for i, dist_vec_i in enumerate(scaled_dist_vec)})
219+
220+
tau = sym.Symbol("tau")
221+
222+
b = scaled_dist_vec.applyfunc(lambda expr: expr.coeff(tau))
223+
a = scaled_dist_vec - tau*b
224+
expr = expr.subs({Symbol(f"a{i}"): a_i for i, a_i in enumerate(a)})
225+
expr = expr.subs({Symbol(f"b{i}"): b_i for i, b_i in enumerate(b)})
226+
227+
return expr
228+
229+
def coefficients_from_source(self, kernel, avec, bvec, rscale, sac=None):
230+
# no point in heeding rscale here--just ignore it
231+
if bvec is None:
232+
raise RuntimeError("cannot use line-Taylor expansions in a setting "
233+
"where the center-target vector is not known at coefficient "
234+
"formation")
235+
236+
tau = sym.Symbol("tau")
237+
238+
avec_line = avec + tau*bvec
239+
line_kernel = (
240+
kernel.get_expression(avec_line)
241+
/ self.get_asymptotic_expression(avec_line))
242+
243+
from sumpy.symbolic import USE_SYMENGINE
244+
if USE_SYMENGINE:
245+
246+
from sumpy.derivative_taker import ExprDerivativeTaker
247+
deriv_taker = ExprDerivativeTaker(line_kernel, (tau,), sac=sac, rscale=1)
248+
249+
return [kernel.postprocess_at_source(
250+
deriv_taker.diff(i), avec).subs(tau, 0)
251+
for i in self.get_coefficient_identifiers()]
252+
else:
253+
# Workaround for sympy. The automatic distribution after
254+
# single-variable diff makes the expressions very large
255+
# (https://github.com/sympy/sympy/issues/4596), so avoid doing
256+
# single variable diff.
257+
#
258+
# See also https://gitlab.tiker.net/inducer/pytential/merge_requests/12
259+
260+
return [kernel.postprocess_at_source(
261+
line_kernel.diff(tau, i), avec)
262+
.subs(tau, 0)
263+
for i in self.get_coefficient_identifiers()]
264+
265+
def evaluate(self, tgt_kernel, coeffs, bvec, rscale, sac=None):
266+
# no point in heeding rscale here--just ignore it
267+
268+
return sym.Add(*(
269+
coeffs[self.get_storage_index(i)] / math.factorial(i) * self.tau**i
270+
for i in self.get_coefficient_identifiers()))
271+
272+
def translate_from(self, src_expansion, src_coeff_exprs, src_rscale,
273+
dvec, tgt_rscale, sac=None, m2l_translation_classes_dependent_data=None):
274+
raise NotImplementedError
275+
276+
# }}}
277+
278+
166279
# {{{ volume taylor
167280

168281
class VolumeTaylorLocalExpansionBase(VolumeTaylorExpansionMixin, LocalExpansionBase):

0 commit comments

Comments
 (0)