Skip to content

Commit a24d6fa

Browse files
committed
AsymptoticDividingLineTaylorExpansion
1 parent 01ba686 commit a24d6fa

1 file changed

Lines changed: 119 additions & 84 deletions

File tree

sumpy/expansion/local.py

Lines changed: 119 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from collections.abc import Sequence
4949

5050
import loopy as lp
51+
from pymbolic.typing import Expression
5152

5253
from sumpy.assignment_collection import SymbolicAssignmentCollection
5354
from sumpy.expansion.diff_op import MultiIndex
@@ -67,6 +68,7 @@
6768
.. autoclass:: H2DLocalExpansion
6869
.. autoclass:: Y2DLocalExpansion
6970
.. autoclass:: LineTaylorLocalExpansion
71+
.. autoclass:: AsymptoticDividingLineTaylorExpansion
7072
"""
7173

7274

@@ -145,6 +147,8 @@ def coefficients_from_source(self,
145147
"formation")
146148

147149
tau = sym.Symbol("tau")
150+
# In the LineTaylor expansion, bvec is the expansion line.
151+
# It is not necessarily the target-center vector.
148152
expansion_line = bvec
149153
avec_line = avec + tau*expansion_line
150154
line_kernel = kernel.get_expression(avec_line)
@@ -216,90 +220,121 @@ def translate_from(self,
216220

217221
# {{{ Asymptotic dividing line Taylor expansion
218222

219-
# @dataclass(frozen=True)
220-
# class AsymptoticDividingLineTaylorExpansion(LineTaylorLocalExpansion):
221-
# r"""
222-
# A target-specific modified line Taylor expansion.
223-
#
224-
# The expansion line is defined as :math:`l(\tau) = \text{avec} + \tau \cdot
225-
# \text{bvec}` at a target point :math:`x`. The modified line Taylor expansion
226-
# takes the form:
227-
#
228-
# .. math::
229-
#
230-
# \sum_{k=0}^{\text{order}} \frac{g_k}{k!} \tau^k,
231-
#
232-
# where:
233-
#
234-
# .. math::
235-
#
236-
# g_k := \frac{d^k}{d\tau^k} \left(
237-
# \frac{\text{kernel}(l(\tau))}{\text{asymptotic}(l(\tau))}
238-
# \right) \bigg|_{\tau=0}
239-
#
240-
# .. automethod:: get_asymptotic_expression
241-
# """
242-
#
243-
# asymptotic: Any = field(kw_only=True)
244-
#
245-
# def get_asymptotic_expression(self, scaled_dist_vec: sym.Matrix) -> sym.Expr:
246-
# from sumpy.symbolic import PymbolicToSympyMapperWithSymbols, Symbol
247-
#
248-
# expr = PymbolicToSympyMapperWithSymbols()(self.asymptotic)
249-
# expr = expr.xreplace({Symbol(f"d{i}"): dist_vec_i
250-
# for i, dist_vec_i in enumerate(scaled_dist_vec)})
251-
#
252-
# tau = sym.Symbol("tau")
253-
#
254-
# b = scaled_dist_vec.applyfunc(lambda expr: expr.coeff(tau))
255-
# a = scaled_dist_vec - tau*b
256-
# expr = expr.subs({Symbol(f"a{i}"): a_i for i, a_i in enumerate(a)})
257-
# expr = expr.subs({Symbol(f"b{i}"): b_i for i, b_i in enumerate(b)})
258-
#
259-
# return expr
260-
#
261-
# @override
262-
# def coefficients_from_source(self,
263-
# kernel: Kernel,
264-
# avec: sym.Matrix,
265-
# bvec: sym.Matrix | None,
266-
# rscale: sym.Expr,
267-
# sac: SymbolicAssignmentCollection | None = None
268-
# ) -> Sequence[sym.Expr]:
269-
# # no point in heeding rscale here--just ignore it
270-
# if bvec is None:
271-
# raise RuntimeError("cannot use line-Taylor expansions in a setting "
272-
# "where the center-target vector is not known at coefficient "
273-
# "formation")
274-
#
275-
# tau = sym.Symbol("tau")
276-
#
277-
# line_vec = bvec
278-
# avec_line = avec + tau*line_vec
279-
# line_kernel = (
280-
# kernel.get_expression(avec_line)
281-
# / self.get_asymptotic_expression(avec_line))
282-
#
283-
# from sumpy.symbolic import USE_SYMENGINE
284-
# if USE_SYMENGINE:
285-
# from sumpy.derivative_taker import ExprDerivativeTaker
286-
# deriv_taker = ExprDerivativeTaker(line_kernel, (tau,), sac=sac,
287-
# rscale=sym.sympify(1))
288-
#
289-
# return [kernel.postprocess_at_source(deriv_taker.diff(i), avec)
290-
# .subs(tau, 0)
291-
# for i in self.get_coefficient_identifiers()]
292-
# else:
293-
# # Workaround for sympy. The automatic distribution after
294-
# # single-variable diff makes the expressions very large
295-
# # (https://github.com/sympy/sympy/issues/4596), so avoid doing
296-
# # single variable diff.
297-
# #
298-
# # See also https://gitlab.tiker.net/inducer/pytential/merge_requests/12
299-
#
300-
# return [kernel.postprocess_at_source(line_kernel.diff(tau, i), avec)
301-
# .subs(tau, 0)
302-
# for i, in self.get_coefficient_identifiers()]
223+
@dataclass(frozen=True)
224+
class AsymptoticDividingLineTaylorExpansion(LineTaylorLocalExpansion):
225+
r"""
226+
A target-specific asymptotic-dividing line Taylor expansion.
227+
228+
The asymptotic-dividing line Taylor expansion takes the form:
229+
230+
.. math::
231+
232+
\text{asymptotic}(\tau \cdot \text{expansion}\_\text{vec}) \,
233+
\sum_{k=0}^{\text{order}} \frac{g_k}{k!} \tau^k,
234+
235+
where:
236+
237+
.. math::
238+
239+
g_k := \frac{d^k}{d\tau^k} \left(
240+
\frac{\text{kernel}(\text{avec}
241+
+ \tau \cdot \text{expansion}\_\text{vec})}
242+
{\text{asymptotic}(\tau \cdot \text{expansion}\_\text{vec})}
243+
\right) \bigg|_{\tau=0}
244+
245+
.. attribute:: asymptotic
246+
247+
A :mod:`pymbolic` expression for the asymptotic factor along the
248+
expansion line. May reference ``tau`` and ``b0, b1, ...`` (components
249+
of ``expansion_vec``).
250+
251+
.. automethod:: get_asymptotic_expression
252+
"""
253+
254+
asymptotic: Expression
255+
256+
def get_asymptotic_expression(self,
257+
asymptotic_line: sym.Matrix,
258+
tau: sym.Symbol | None = None
259+
) -> sym.Expr:
260+
from sumpy.symbolic import PymbolicToSympyMapperWithSymbols, Symbol
261+
262+
if tau is None:
263+
tau = sym.Symbol("tau")
264+
265+
expansion_vec = asymptotic_line.applyfunc(lambda expr: expr.coeff(tau))
266+
267+
expr = PymbolicToSympyMapperWithSymbols()(self.asymptotic)
268+
expr = expr.subs({Symbol("tau"): tau})
269+
expr = expr.subs({Symbol(f"b{i}"): b_i
270+
for i, b_i in enumerate(expansion_vec)})
271+
272+
return cast("sym.Expr", expr)
273+
274+
@override
275+
def coefficients_from_source(self,
276+
kernel: Kernel,
277+
avec: sym.Matrix,
278+
bvec: sym.Matrix | None,
279+
rscale: sym.Expr,
280+
sac: SymbolicAssignmentCollection | None = None
281+
) -> Sequence[sym.Expr]:
282+
# no point in heeding rscale here--just ignore it
283+
if bvec is None:
284+
raise RuntimeError("cannot use line-Taylor expansions in a setting "
285+
"where the center-target vector is not known at coefficient "
286+
"formation")
287+
288+
tau = sym.Symbol("tau")
289+
290+
expansion_vec = bvec
291+
# Here, we assume the asymptotic expansion is independent of the source.
292+
asymptotic_line = expansion_vec*tau
293+
avec_line = avec + asymptotic_line
294+
line_kernel = (
295+
kernel.get_expression(avec_line)
296+
/ self.get_asymptotic_expression(asymptotic_line, tau=tau))
297+
298+
from sumpy.symbolic import USE_SYMENGINE
299+
if USE_SYMENGINE:
300+
from sumpy.derivative_taker import ExprDerivativeTaker
301+
deriv_taker = ExprDerivativeTaker(line_kernel, (tau,), sac=sac,
302+
rscale=sym.sympify(1))
303+
304+
return [kernel.postprocess_at_source(deriv_taker.diff(i), avec)
305+
.subs(tau, 0)
306+
for i in self.get_coefficient_identifiers()]
307+
else:
308+
# Workaround for sympy. The automatic distribution after
309+
# single-variable diff makes the expressions very large
310+
# (https://github.com/sympy/sympy/issues/4596), so avoid doing
311+
# single variable diff.
312+
#
313+
# See also https://gitlab.tiker.net/inducer/pytential/merge_requests/12
314+
315+
return [kernel.postprocess_at_source(line_kernel.diff(tau, i), avec)
316+
.subs(tau, 0)
317+
for i, in self.get_coefficient_identifiers()]
318+
319+
@override
320+
def evaluate(self,
321+
kernel: Kernel,
322+
coeffs: Sequence[sym.Expr],
323+
bvec: sym.Matrix,
324+
rscale: sym.Expr,
325+
sac: SymbolicAssignmentCollection | None = None,
326+
*,
327+
expansion_vec: sym.Matrix) -> sym.Expr:
328+
result = super().evaluate(kernel, coeffs, bvec, rscale, sac=sac,
329+
expansion_vec=expansion_vec)
330+
331+
tau = sym.Symbol("tau")
332+
eval_tau = ((bvec.T*expansion_vec)[0, 0]
333+
/ (expansion_vec.T*expansion_vec)[0, 0])
334+
return (
335+
result
336+
* self.get_asymptotic_expression(expansion_vec*tau, tau=tau)
337+
.subs(tau, eval_tau))
303338

304339
# }}}
305340

0 commit comments

Comments
 (0)