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
19 changes: 0 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,6 @@ jobs:
pip install ruff
ruff check

pylint:
name: Pylint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "Main Script"
run: |
export EXTRA_INSTALL="pyvisfile matplotlib"

curl -L -O https://tiker.net/ci-support-v0
. ci-support-v0

# pylint seems unable to find the cython bits if not installed
# editable. -AK, 2023-11-01
PROJECT_INSTALL_FLAGS="--editable"

build_py_project_in_conda_env
run_pylint "$(get_proj_name)" examples/*.py test/*.py

mypy:
name: Mypy
runs-on: ubuntu-latest
Expand Down
17 changes: 0 additions & 17 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,23 +90,6 @@ Documentation:
tags:
- python3

Pylint:
script: |
export EXTRA_INSTALL="Cython pybind11 numpy scipy mako matplotlib"
curl -L -O https://tiker.net/ci-support-v0
. ci-support-v0

# pylint seems unable to find the cython bits if not installed
# editable. -AK, 2023-11-01
PROJECT_INSTALL_FLAGS="--editable"

build_py_project
run_pylint "$(get_proj_name)" examples/*.py test/*.py
tags:
- python3
except:
- tags

Mypy:
script: |
curl -L -O https://tiker.net/ci-support-v0
Expand Down
10 changes: 0 additions & 10 deletions .pylintrc-local.yml

This file was deleted.

19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
find_package(
Python
COMPONENTS Interpreter Development.Module
REQUIRED)
include(UseCython)

cython_transpile(pytential/qbx/target_specific/impl.pyx LANGUAGE C OUTPUT_VARIABLE pytential_c)

python_add_library(impl
MODULE
"${pytential_c}"
pytential/qbx/target_specific/helmholtz_utils.c
WITH_SOABI)

target_compile_options(impl PRIVATE -Wall -Ofast -fopenmp)
target_link_options(impl PRIVATE -fopenmp)
target_include_directories(impl PRIVATE ${CMAKE_SOURCE_DIR}/pytential/qbx/target_specific)

install(TARGETS impl DESTINATION pytential/qbx/target_specific)
2 changes: 2 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@
# Sphinx started complaining about these in 8.2.1(-ish)
# -AK, 2025-02-24
["py:class", r"TypeAliasForwardRef"],
["py:class", r"arraycontext.container._UserDefinedArrayContainer"],
["py:class", r"arraycontext.container._UserDefinedArithArrayContainer"],
]
34 changes: 29 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
[build-system]
build-backend = "setuptools.build_meta"
requires = [
"cython>=0.25",
"setuptools>=63",
]
requires = ["scikit-build-core", "cython", "cython-cmake"]
build-backend = "scikit_build_core.build"

[project]
name = "pytential"
Expand Down Expand Up @@ -164,3 +161,30 @@ module = [
"sympy.*",
]
ignore_missing_imports = true

[tool.basedpyright]
reportImplicitStringConcatenation = "none"
reportUnnecessaryIsInstance = "none"
reportUnusedCallResult = "none"
reportExplicitAny = "none"
reportUnusedParameter = "hint"

# This reports even cycles that are qualified by 'if TYPE_CHECKING'. Not what
# we care about at this moment.
# https://github.com/microsoft/pyright/issues/746
reportImportCycles = "none"

pythonVersion = "3.10"
pythonPlatform = "All"

[[tool.basedpyright.executionEnvironments]]
root = "test"
reportUnknownArgumentType = "hint"
reportAttributeAccessIssue = "hint"
reportOperatorIssue = "hint"
reportIndexIssue = "hint"
reportCallIssue = "hint"
reportArgumentType = "hint"
reportPossiblyUnboundVariable = "hint"
reportGeneralTypeIssues = "hint"
reportOptionalSubscript = "hint"
31 changes: 16 additions & 15 deletions pytential/linalg/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@

from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from typing import Any, cast

import numpy as np
import numpy.linalg as la

from arraycontext import PyOpenCLArrayContext, flatten
from arraycontext import Array, ArrayContainer, PyOpenCLArrayContext, flatten
from meshmode.discretization import Discretization
from meshmode.dof_array import DOFArray

from numpy.typing import NDArray
from pytools import memoize_in
from pytential import GeometryCollection, bind, sym
from pytential.symbolic.dof_desc import DOFDescriptorLike
Expand Down Expand Up @@ -151,7 +152,7 @@ class ProxyPointSource(PointPotentialSource):

def __init__(self,
lpot_source: QBXLayerPotentialSource,
proxies: np.ndarray) -> None:
proxies: Array) -> None:
"""
:arg lpot_source: the layer potential for which the proxy are constructed.
:arg proxies: an array of shape ``(ambient_dim, nproxies)`` containing
Expand All @@ -174,7 +175,7 @@ def get_expansion_for_qbx_direct_eval(self, base_kernel, target_kernels):
class ProxyPointTarget(PointsTarget):
def __init__(self,
lpot_source: QBXLayerPotentialSource,
proxies: np.ndarray) -> None:
proxies: Array) -> None:
"""
:arg lpot_source: the layer potential for which the proxy are constructed.
This argument is kept for symmetry with :class:`ProxyPointSource`.
Expand Down Expand Up @@ -227,9 +228,9 @@ class ProxyClusterGeometryData:
srcindex: IndexList
pxyindex: IndexList

points: np.ndarray
centers: np.ndarray
radii: np.ndarray
points: NDArray[Any]
centers: NDArray[Any]
radii: NDArray[Any]

_cluster_radii: np.ndarray | None = None

Expand Down Expand Up @@ -260,13 +261,13 @@ def as_sources(self) -> ProxyPointSource:
lpot_source = self.places.get_geometry(self.dofdesc.geometry)
assert isinstance(lpot_source, QBXLayerPotentialSource)

return ProxyPointSource(lpot_source, self.points)
return ProxyPointSource(lpot_source, cast("Array", self.points))

def as_targets(self) -> ProxyPointTarget:
lpot_source = self.places.get_geometry(self.dofdesc.geometry)
assert isinstance(lpot_source, QBXLayerPotentialSource)

return ProxyPointTarget(lpot_source, self.points)
return ProxyPointTarget(lpot_source, cast("Array", self.points))

# }}}

Expand Down Expand Up @@ -632,12 +633,12 @@ def __call__(self,
source_dd = self.places.auto_source
source_dd = sym.as_dofdesc(source_dd)

radii = bind(self.places, sym.expansion_radii(
self.ambient_dim, dofdesc=source_dd))(actx)
center_int = bind(self.places, sym.expansion_centers(
self.ambient_dim, -1, dofdesc=source_dd))(actx)
center_ext = bind(self.places, sym.expansion_centers(
self.ambient_dim, +1, dofdesc=source_dd))(actx)
radii = cast(ArrayContainer, bind(self.places, sym.expansion_radii(
self.ambient_dim, dofdesc=source_dd))(actx))
center_int = cast(ArrayContainer, bind(self.places, sym.expansion_centers(
self.ambient_dim, -1, dofdesc=source_dd))(actx))
center_ext = cast(ArrayContainer, bind(self.places, sym.expansion_centers(
self.ambient_dim, +1, dofdesc=source_dd))(actx))

return super().__call__(actx, source_dd, dof_index,
expansion_radii=flatten(radii, actx),
Expand Down
7 changes: 5 additions & 2 deletions pytential/qbx/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
THE SOFTWARE.
"""

from typing import cast
import numpy as np

from pytools import memoize_method, memoize_in, log_process
Expand Down Expand Up @@ -327,7 +328,8 @@ def _make_centers(discr):

# Build tree with sources and centers. Split boxes
# only because of sources.
refine_weights = actx.np.zeros(nparticles, np.int32)
import pyopencl.array as cl_array
refine_weights = cast("cl_array.Array", actx.np.zeros(nparticles, np.int32))
refine_weights[:nsources].fill(1)

refine_weights.finish()
Expand Down Expand Up @@ -363,7 +365,8 @@ def _make_centers(discr):
del box_to_class

# Compute element => source relation
qbx_element_to_source_starts = actx.np.zeros(nelements + 1, tree.particle_id_dtype)
qbx_element_to_source_starts = cast("cl_array.Array",
actx.np.zeros(nelements + 1, tree.particle_id_dtype))
el_offset = 0
node_nr_base = 0
for group in density_discr.groups:
Expand Down
6 changes: 3 additions & 3 deletions pytential/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from pytools import T, memoize_in
from sumpy.fmm import UnableToCollectTimingData
from sumpy.kernel import Kernel
from sumpy.p2p import P2PBase
from sumpy.p2p import P2P, P2PBase

from pytential import sym

Expand Down Expand Up @@ -112,10 +112,10 @@ class _SumpyP2PMixin:
def get_p2p(self,
actx: PyOpenCLArrayContext,
target_kernels: tuple[Kernel, ...],
source_kernels: tuple[Kernel, ...] | None = None) -> P2PBase:
source_kernels: tuple[Kernel, ...] | None = None) -> P2P:
@memoize_in(actx, (_SumpyP2PMixin, "p2p"))
def p2p(target_kernels: tuple[Kernel, ...],
source_kernels: tuple[Kernel, ...] | None) -> P2PBase:
source_kernels: tuple[Kernel, ...] | None) -> P2P:
if any(knl.is_complex_valued for knl in target_kernels):
value_dtype = self.complex_dtype # type: ignore[attr-defined]
else:
Expand Down
40 changes: 26 additions & 14 deletions pytential/symbolic/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
THE SOFTWARE.
"""

from collections.abc import Callable, Iterable
from collections.abc import Callable, Iterable, Sequence
from dataclasses import field
from warnings import warn
from functools import partial
Expand Down Expand Up @@ -400,17 +400,16 @@ def make_stringifier(self, originating_stringifier=None):


Operand: TypeAlias = (
ArithmeticExpression | np.ndarray[Any, np.dtype[Any]] | MultiVector)
QBXForcedLimit: TypeAlias = int | Literal["avg"] | None
ArithmeticExpression
| np.ndarray[Any, np.dtype[Any]]
| MultiVector[ArithmeticExpression])

QBXForcedLimit: TypeAlias = Literal[-2, -1, 1, 1, "avg"] | None

# NOTE: this will likely live in pymbolic at some point, but for now we take it!
ArithmeticExpressionT = TypeVar("ArithmeticExpressionT", bound=ArithmeticExpression)


class _NoArgSentinel:
pass


class cse_scope(cse_scope_base): # noqa: N801
DISCRETIZATION = "pytential_discretization"

Expand Down Expand Up @@ -457,7 +456,7 @@ class ErrorExpression(Expression):
"""The error message to raise when this expression is encountered."""


def make_sym_mv(name: str, num_components: int) -> MultiVector[Expression]:
def make_sym_mv(name: str, num_components: int) -> MultiVector[ArithmeticExpression]:
return MultiVector(make_sym_vector(name, num_components))


Expand Down Expand Up @@ -637,7 +636,7 @@ def make_op(operand_i):
# different..
def __init__(self,
ref_axes: tuple[tuple[int, int], ...],
operand: ArithmeticExpression,
operand: Operand | None,
dofdesc: DOFDescriptorLike) -> None:
if isinstance(ref_axes, int):
warn(f"Passing an 'int' as 'ref_axes' to {type(self).__name__!r} "
Expand Down Expand Up @@ -682,7 +681,11 @@ def num_reference_derivative(
return NumReferenceDerivative(ref_axes, expr, as_dofdesc(dofdesc))


def reference_jacobian(func, output_dim, dim, dofdesc=None):
def reference_jacobian(
func: Sequence[ArithmeticExpression],
output_dim: int,
dim: int,
dofdesc: DOFDescriptorLike = None):
"""Return a :class:`numpy.ndarray` representing the Jacobian of a vector function
with respect to the reference coordinates.
"""
Expand All @@ -697,7 +700,10 @@ def reference_jacobian(func, output_dim, dim, dofdesc=None):
return jac


def parametrization_derivative_matrix(ambient_dim, dim, dofdesc=None):
def parametrization_derivative_matrix(
ambient_dim: int,
dim: int,
dofdesc: DOFDescriptorLike = None):
"""Return a :class:`numpy.ndarray` representing the derivative of the
reference-to-global parametrization.
"""
Expand All @@ -710,18 +716,24 @@ def parametrization_derivative_matrix(ambient_dim, dim, dofdesc=None):
"pd_matrix", cse_scope.DISCRETIZATION)


def parametrization_derivative(ambient_dim, dim, dofdesc=None):
def parametrization_derivative(
ambient_dim: int,
dim: int,
dofdesc: DOFDescriptorLike = None):
"""Return a :class:`pymbolic.geometric_algebra.MultiVector` representing
the derivative of the reference-to-global parametrization.
"""

par_grad = parametrization_derivative_matrix(ambient_dim, dim, dofdesc)

from pytools import product
return product(MultiVector(vec) for vec in par_grad.T)
return product(MultiVector[ArithmeticExpression](vec) for vec in par_grad.T)


def pseudoscalar(ambient_dim, dim=None, dofdesc=None):
def pseudoscalar(
ambient_dim: int,
dim: int | None = None,
dofdesc: DOFDescriptorLike = None):
"""
Same as the outer product of all parametrization derivative columns.
"""
Expand Down
4 changes: 3 additions & 1 deletion pytential/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ def __init__(self, nodes: Array, normals: Array | None = None) -> None:

@property
def ambient_dim(self) -> int:
return self._nodes.shape[0]
adim = self._nodes.shape[0]
assert isinstance(adim, int)
return adim

@property
def ndofs(self) -> int:
Expand Down
Loading
Loading