Skip to content

Commit 2077b11

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 2077b11

1 file changed

Lines changed: 110 additions & 1 deletion

File tree

sumpy/expansion/local.py

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

168277
class VolumeTaylorLocalExpansionBase(VolumeTaylorExpansionMixin, LocalExpansionBase):

0 commit comments

Comments
 (0)