Skip to content
Merged
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
30 changes: 13 additions & 17 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,31 @@ sumpy: n-body kernels and translation operators
:target: https://gitlab.tiker.net/inducer/sumpy/commits/main
.. image:: https://github.com/inducer/sumpy/actions/workflows/ci.yml/badge.svg
:alt: Github Build Status
:target: https://github.com/inducer/sumpy/actions?query=branch%3Amain+workflow%3ACI
.. image:: https://badge.fury.io/py/sumpy.png
:target: https://github.com/inducer/sumpy/actions/workflows/ci.yml
.. image:: https://badge.fury.io/py/sumpy.svg
:alt: Python Package Index Release Page
:target: https://pypi.org/project/sumpy/
.. image:: https://zenodo.org/badge/1856097.svg
:alt: Zenodo DOI for latest release
:target: https://zenodo.org/badge/latestdoi/1856097

Sumpy is mainly a 'scaffolding' package for Fast Multipole and quadrature methods.
If you're building one of those and need code generation for the required Multipole
and local expansions, come right on in. Together with boxtree, there is a full,
sumpy is mainly a 'scaffolding' package for Fast Multipole and quadrature methods.
If you're building one of those and need code generation for the required multipole
and local expansions, come right on in. Together with ``boxtree``, there is a full,
symbolically kernel-independent FMM implementation here.

Sumpy relies on
It relies on

* `numpy <https://pypi.org/project/numpy>`_ for arrays
* `boxtree <https://pypi.org/project/boxtree>`_ for FMM tree building
* `loopy <https://pypi.org/project/loopy>`_ for fast array operations
* `pytest <https://pypi.org/project/pytest>`_ for automated testing
* `boxtree <https://pypi.org/project/boxtree>`__ for FMM tree building
* `loopy <https://pypi.org/project/loopy>`__ for fast array operations
* `pytest <https://pypi.org/project/pytest>`__ for automated testing

and, indirectly,

* `PyOpenCL <https://pypi.org/project/pyopencl>`_ as computational infrastructure

PyOpenCL is likely the only package you'll have to install
by hand, all the others will be installed automatically.
* `PyOpenCL <https://pypi.org/project/pyopencl>`__ as computational infrastructure

Resources:

* `documentation <https://documen.tician.de/sumpy>`_
* `source code via git <https://github.com/inducer/sumpy>`_
* `benchmarks <https://documen.tician.de/sumpy/benchmarks>`_
* `documentation <https://documen.tician.de/sumpy>`__
* `source code via git <https://github.com/inducer/sumpy>`__
* `benchmarks <https://documen.tician.de/sumpy/benchmarks>`__
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ classifiers = [
dependencies = [
"arraycontext>=2021.1",
"boxtree>=2023.1",
"immutabledict",
"constantdict>=2024.4",
"loopy>=2024.1",
"numpy",
"pyopencl>=2022.1",
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
numpy
sympy
immutabledict
constantdict
pyvkfft

# used in mpi-based tests
Expand Down
10 changes: 5 additions & 5 deletions sumpy/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import re

import numpy as np
from immutabledict import immutabledict
from constantdict import constantdict

import loopy as lp
import pymbolic.primitives as prim
Expand Down Expand Up @@ -142,7 +142,7 @@ def with_types(self, arg_id_to_dtype, clbl_inf_ctx):

if z_dtype.numpy_dtype.kind == "c":
return (self.copy(name_in_target="bessel_jv_two_complex",
arg_id_to_dtype=immutabledict({
arg_id_to_dtype=constantdict({
-2: NumpyType(np.complex128),
-1: NumpyType(np.complex128),
0: NumpyType(np.int32),
Expand All @@ -151,7 +151,7 @@ def with_types(self, arg_id_to_dtype, clbl_inf_ctx):
clbl_inf_ctx)
else:
return (self.copy(name_in_target="bessel_jv_two",
arg_id_to_dtype=immutabledict({
arg_id_to_dtype=constantdict({
-2: NumpyType(np.float64),
-1: NumpyType(np.float64),
0: NumpyType(np.int32),
Expand Down Expand Up @@ -184,15 +184,15 @@ def with_types(self, arg_id_to_dtype, clbl_inf_ctx):

if z_dtype.numpy_dtype.kind == "c":
return (self.copy(name_in_target="hank1_01_complex",
arg_id_to_dtype=immutabledict({
arg_id_to_dtype=constantdict({
-2: NumpyType(np.complex128),
-1: NumpyType(np.complex128),
0: NumpyType(np.complex128),
})),
clbl_inf_ctx)
else:
return (self.copy(name_in_target="hank1_01",
arg_id_to_dtype=immutabledict({
arg_id_to_dtype=constantdict({
-2: NumpyType(np.complex128),
-1: NumpyType(np.complex128),
0: NumpyType(np.float64),
Expand Down
28 changes: 17 additions & 11 deletions sumpy/expansion/diff_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import numpy as np
import sympy as sp
import sympy.polys.agca.modules as sp_modules
from immutabledict import immutabledict
from constantdict import constantdict

from pytools import memoize

Expand Down Expand Up @@ -115,7 +115,8 @@ def __mul__(self, param: Number_ish) -> LinearPDESystemOperator:
deriv_ident_to_coeff = {}
for k, v in eq.items():
deriv_ident_to_coeff[k] = v * param
eqs.append(immutabledict(deriv_ident_to_coeff))
eqs.append(constantdict(deriv_ident_to_coeff))

return LinearPDESystemOperator(self.dim, tuple(eqs))

__rmul__ = __mul__
Expand All @@ -125,6 +126,7 @@ def __add__(
) -> LinearPDESystemOperator:
assert self.dim == other_diff_op.dim
assert len(self.eqs) == len(other_diff_op.eqs)

eqs: list[Mapping[DerivativeIdentifier, sp.Expr]] = []
for eq, other_eq in zip(self.eqs, other_diff_op.eqs, strict=True):
res = dict(eq)
Expand All @@ -133,7 +135,8 @@ def __add__(
res[k] += v
else:
res[k] = v
eqs.append(immutabledict(res))
eqs.append(constantdict(res))

return LinearPDESystemOperator(self.dim, tuple(eqs))

__radd__ = __add__
Expand Down Expand Up @@ -269,7 +272,7 @@ def intersect(
DerivativeIdentifier(mi, 0): sym.sympify(coeff.as_expr().simplify()) for
(mi, coeff) in zip(scalar_pde.monoms(), scalar_pde.coeffs(), strict=True)
}
results.append(LinearPDESystemOperator(pde.dim, (immutabledict(pde_dict),)))
results.append(LinearPDESystemOperator(pde.dim, (constantdict(pde_dict),)))

return results

Expand Down Expand Up @@ -347,8 +350,8 @@ def as_scalar_pde(pde: LinearPDESystemOperator, comp_idx: int) \

def laplacian(diff_op: LinearPDESystemOperator) -> LinearPDESystemOperator:
dim = diff_op.dim
empty: tuple[Mapping[DerivativeIdentifier, sp.Expr], ...] = \
(immutabledict(),) * len(diff_op.eqs)
empty: tuple[Mapping[DerivativeIdentifier, sp.Expr], ...] = (
(constantdict(),) * len(diff_op.eqs))
res = LinearPDESystemOperator(dim, empty)
for j in range(dim):
mi = [0]*diff_op.total_dims
Expand All @@ -366,17 +369,20 @@ def diff(
for deriv_ident, v in eq.items():
new_mi = add_mi(deriv_ident.mi, mi)
res[DerivativeIdentifier(new_mi, deriv_ident.vec_idx)] = v
eqs.append(immutabledict(res))
eqs.append(constantdict(res))

return LinearPDESystemOperator(diff_op.dim, tuple(eqs))


def divergence(diff_op: LinearPDESystemOperator) -> LinearPDESystemOperator:
assert len(diff_op.eqs) == diff_op.dim
res = LinearPDESystemOperator(diff_op.dim, (immutabledict(),))

res = LinearPDESystemOperator(diff_op.dim, (constantdict(),))
for i in range(diff_op.dim):
mi = [0]*diff_op.total_dims
mi[i] = 1
res += diff(diff_op[i], tuple(mi))

return res


Expand Down Expand Up @@ -436,6 +442,6 @@ def make_identity_diff_op(
mi = tuple([0]*(ninput + 1))
else:
mi = tuple([0]*ninput)
return LinearPDESystemOperator(ninput, tuple(immutabledict(
{DerivativeIdentifier(mi, i): sp.sympify(1)})
for i in range(noutput)))
return LinearPDESystemOperator(ninput, tuple(
constantdict({DerivativeIdentifier(mi, i): sp.sympify(1)})
for i in range(noutput)))
Loading