Skip to content

Fix target derivative taking in line Taylor #229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions examples/curve-pot.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ def process_kernel(knl, what_operator):
elif what_operator == "D":
from sumpy.kernel import DirectionalSourceDerivative
source_knl = DirectionalSourceDerivative(knl)
# DirectionalTargetDerivative (temporarily?) removed
# elif what_operator == "S'":
# from sumpy.kernel import DirectionalTargetDerivative
# knl = DirectionalTargetDerivative(knl)
else:
raise RuntimeError(f"unrecognized operator '{what_operator}'")

Expand Down
9 changes: 6 additions & 3 deletions sumpy/expansion/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,12 @@ def coefficients_from_source(self, kernel, avec, bvec, rscale, sac=None):

def evaluate(self, tgt_kernel, coeffs, bvec, rscale, sac=None):
# no point in heeding rscale here--just ignore it
return sym.Add(*(
coeffs[self.get_storage_index(i)] / math.factorial(i)
for i in self.get_coefficient_identifiers()))

# NOTE: We can't meaningfully apply target derivatives here.
# Instead, this is handled in LayerPotentialBase._evaluate.
return sym.Add(*(
coeffs[self.get_storage_index(i)] / math.factorial(i)
for i in self.get_coefficient_identifiers()))

def translate_from(self, src_expansion, src_coeff_exprs, src_rscale,
dvec, tgt_rscale, sac=None, m2l_translation_classes_dependent_data=None):
Expand Down
7 changes: 3 additions & 4 deletions sumpy/expansion/multipole.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ def evaluate(self, kernel, coeffs, bvec, rscale, sac=None):
rscale = 1

base_taker = kernel.get_derivative_taker(bvec, rscale, sac)
# Following is a no-op, but AxisTargetDerivative.postprocess_at_target and
# DirectionalTargetDerivative.postprocess_at_target only handles
# DifferentiatedExprDerivativeTaker and sympy expressions, so we need to
# make the taker a DifferentitatedExprDerivativeTaker instance.
# Following is a no-op, but AxisTargetDerivative.postprocess_at_target
# only handles DifferentiatedExprDerivativeTaker and sympy expressions,
# so we need to make the taker a DifferentitatedExprDerivativeTaker instance.
base_taker = DifferentiatedExprDerivativeTaker(base_taker,
{tuple([0]*self.dim): 1})
taker = kernel.postprocess_at_target(base_taker, bvec)
Expand Down
69 changes: 0 additions & 69 deletions sumpy/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
.. autoclass:: AxisTargetDerivative
.. autoclass:: AxisSourceDerivative
.. autoclass:: DirectionalSourceDerivative
.. autoclass:: DirectionalTargetDerivative

Transforming kernels
--------------------
Expand Down Expand Up @@ -1143,74 +1142,6 @@ def __repr__(self):
return f"{type(self).__name__}({self.inner_kernel!r}, {self.dir_vec_name})"


class DirectionalTargetDerivative(DirectionalDerivative):
directional_kind = "tgt"
target_array_name = "targets"

def get_code_transformer(self):
from sumpy.codegen import VectorComponentRewriter
vcr = VectorComponentRewriter([self.dir_vec_name])
from pymbolic.primitives import Variable
via = _VectorIndexAdder(self.dir_vec_name, (Variable("itgt"),))

inner_transform = self.inner_kernel.get_code_transformer()

def transform(expr):
return via(vcr(inner_transform(expr)))

return transform

def postprocess_at_target(self, expr, bvec):
from sumpy.derivative_taker import (
DifferentiatedExprDerivativeTaker,
diff_derivative_coeff_dict,
)
from sumpy.symbolic import make_sym_vector as make_sympy_vector
dir_vec = make_sympy_vector(self.dir_vec_name, self.dim)
target_vec = make_sympy_vector(self.target_array_name, self.dim)

expr = self.inner_kernel.postprocess_at_target(expr, bvec)

# bvec = tgt - center
if not isinstance(expr, DifferentiatedExprDerivativeTaker):
result = 0
for axis in range(self.dim):
# Since `bvec` and `tgt` are two different symbolic variables
# need to differentiate by both to get the correct answer
result += (expr.diff(bvec[axis]) + expr.diff(target_vec[axis])) \
* dir_vec[axis]
return result

new_transformation = defaultdict(lambda: 0)
for axis in range(self.dim):
axis_transformation = diff_derivative_coeff_dict(
expr.derivative_coeff_dict, axis, target_vec)
for mi, coeff in axis_transformation.items():
new_transformation[mi] += coeff * dir_vec[axis]

return DifferentiatedExprDerivativeTaker(expr.taker,
dict(new_transformation))

def get_args(self):
return [
KernelArgument(
loopy_arg=lp.GlobalArg(
self.dir_vec_name,
None,
shape=(self.dim, "ntargets"),
offset=lp.auto
),
),
*self.inner_kernel.get_args()
]

def prepare_loopy_kernel(self, loopy_knl):
loopy_knl = self.inner_kernel.prepare_loopy_kernel(loopy_knl)
return lp.tag_array_axes(loopy_knl, self.dir_vec_name, "sep,C")

mapper_method = "map_directional_target_derivative"


class DirectionalSourceDerivative(DirectionalDerivative):
directional_kind = "src"

Expand Down
8 changes: 2 additions & 6 deletions sumpy/qbx.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ def _expand(self, sac, avec, bvec, rscale, isrc):
def _evaluate(self, sac, avec, bvec, rscale, expansion_nr, coefficients):
from sumpy.expansion.local import LineTaylorLocalExpansion
tgt_knl = self.target_kernels[expansion_nr]
if isinstance(tgt_knl, LineTaylorLocalExpansion):
if isinstance(self.expansion, LineTaylorLocalExpansion):
# In LineTaylorLocalExpansion.evaluate, we can't run
# postprocess_at_target because the coefficients are assigned
# symbols and postprocess with a derivative will make them zero.
# Instead run postprocess here before the coefficients are assigned.
coefficients = [tgt_knl.postprocess_at_target(coeff, bvec) for
coefficients = [tgt_knl.postprocess_at_target(coeff, avec) for
coeff in coefficients]

assigned_coeffs = [
Expand Down Expand Up @@ -512,7 +512,6 @@ def find_jump_term(kernel, arg_provider):
AxisTargetDerivative,
DerivativeBase,
DirectionalSourceDerivative,
DirectionalTargetDerivative,
)

tgt_derivatives = []
Expand All @@ -522,9 +521,6 @@ def find_jump_term(kernel, arg_provider):
if isinstance(kernel, AxisTargetDerivative):
tgt_derivatives.append(kernel.axis)
kernel = kernel.kernel
elif isinstance(kernel, DirectionalTargetDerivative):
tgt_derivatives.append(kernel.dir_vec_name)
kernel = kernel.kernel
elif isinstance(kernel, AxisSourceDerivative):
src_derivatives.append(kernel.axis)
kernel = kernel.kernel
Expand Down
2 changes: 1 addition & 1 deletion sumpy/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def __init__(self, ctx: Any,
device: Any | None = None) -> None:
"""
:arg target_kernels: list of :class:`~sumpy.kernel.Kernel` instances,
with :class:`sumpy.kernel.DirectionalTargetDerivative` as
with :class:`sumpy.kernel.AxisTargetDerivative` as
the outermost kernel wrappers, if present.
:arg source_kernels: list of :class:`~sumpy.kernel.Kernel` instances
with :class:`~sumpy.kernel.DirectionalSourceDerivative` as the
Expand Down
Loading