diff --git a/.basedpyright/baseline.json b/.basedpyright/baseline.json index cb82cdc4..84a6a751 100644 --- a/.basedpyright/baseline.json +++ b/.basedpyright/baseline.json @@ -10671,14 +10671,6 @@ "lineCount": 1 } }, - { - "code": "reportArgumentType", - "range": { - "startColumn": 35, - "endColumn": 50, - "lineCount": 1 - } - }, { "code": "reportArgumentType", "range": { @@ -10847,78 +10839,6 @@ "lineCount": 1 } }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 22, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 25, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 21, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 25, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 34, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 26, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 30, - "lineCount": 1 - } - }, { "code": "reportUnusedParameter", "range": { @@ -10927,70 +10847,6 @@ "lineCount": 1 } }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 22, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 25, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 21, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 34, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 26, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 30, - "lineCount": 1 - } - }, { "code": "reportUnannotatedClassAttribute", "range": { diff --git a/sumpy/kernel.py b/sumpy/kernel.py index 5fbb99d2..de6f3eeb 100644 --- a/sumpy/kernel.py +++ b/sumpy/kernel.py @@ -113,6 +113,18 @@ :show-inheritance: :members: mapper_method +.. [Pozrikidis1992] C. Pozrikidis, + *Boundary Integral and Singularity Methods for Linearized Viscous Flow*, + Cambridge University Press, 1992. + +.. [Hsiao2008] G. C. Hsiao, W. L. Wendland, + *Boundary Integral Equations*, + Springer, 2008. + +.. [Kress2013] R. Kress, + *Linear Integral Equations*, + Springer Science & Business Media, 2013. + Derivatives ----------- @@ -489,6 +501,13 @@ def is_complex_valued(self) -> bool: # {{{ PDE kernels class LaplaceKernel(ExpressionKernel): + r"""A kernel for the Laplace equation (see e.g. Theorem 6.2 from [Kress2013]_). + + .. math:: + + \Delta K(\mathbf{x}, \mathbf{y}) = \delta(\mathbf{x} - \mathbf{y}). + """ + mapper_method: ClassVar[str] = "map_laplace_kernel" def __init__(self, dim: int) -> None: @@ -537,6 +556,13 @@ def get_pde_as_diff_op(self) -> LinearPDESystemOperator: class BiharmonicKernel(ExpressionKernel): + r"""A kernel for the biharmonic equation. + + .. math:: + + \Delta^2 K(\mathbf{x}, \mathbf{y}) = \delta(\mathbf{x} - \mathbf{y}). + """ + mapper_method: ClassVar[str] = "map_biharmonic_kernel" def __init__(self, dim: int) -> None: @@ -591,7 +617,13 @@ def get_pde_as_diff_op(self) -> LinearPDESystemOperator: @dataclass(frozen=True, repr=False) class HelmholtzKernel(ExpressionKernel): - """ + r"""A kernel for the Helmholtz equation (see e.g. Example 12.14 in [Kress2013]_). + + .. math:: + + \Delta K(\mathbf{x}, \mathbf{y}) + k^2 K(\mathbf{x}, \mathbf{y}) + = \delta(\mathbf{x} - \mathbf{y}). + .. autoattribute:: helmholtz_k_name .. autoattribute:: allow_evanescent """ @@ -679,7 +711,13 @@ def get_pde_as_diff_op(self) -> LinearPDESystemOperator: @dataclass(frozen=True, repr=False) class YukawaKernel(ExpressionKernel): - """ + r"""A kernel for the Yukawa equation. + + .. math:: + + \Delta K(\mathbf{x}, \mathbf{y}) - \lambda^2 K(\mathbf{x}, \mathbf{y}) + = \delta(\mathbf{x} - \mathbf{y}). + .. autoattribute:: yukawa_lambda_name """ @@ -770,12 +808,21 @@ def get_pde_as_diff_op(self) -> LinearPDESystemOperator: @dataclass(frozen=True, repr=False) class ElasticityKernel(ExpressionKernel): - """ + r"""A kernel for the linear elasticity (Navier-Cauchy) equations + (see e.g. Section 2.2 in [Hsiao2008]_). + + .. math:: + + \mu \Delta K_{ij}(\mathbf{x}, \mathbf{y}) + + \frac{\mu}{1 - 2 \nu} \nabla (\nabla \cdot K_{ij}(\mathbf{x}, \mathbf{y})) + = \delta_{ij} \delta(\mathbf{x} - \mathbf{y}). + .. autoattribute:: icomp .. autoattribute:: jcomp - .. autoattribute:: viscosity_mu - .. autoattribute:: poisson_ratio + .. autoattribute:: viscosity_mu_name + .. autoattribute:: poisson_ratio_name """ + mapper_method: ClassVar[str] = "map_elasticity_kernel" icomp: int @@ -783,61 +830,46 @@ class ElasticityKernel(ExpressionKernel): jcomp: int """Component index for the kernel.""" - viscosity_mu: float | SpatialConstant + viscosity_mu_name: str r"""The argument name to use for the dynamic viscosity :math:`\mu` when - generating functions to evaluate this kernel. Can also be a numeric value. + generating functions to evaluate this kernel. """ - poisson_ratio: float | SpatialConstant + poisson_ratio_name: str r"""The argument name to use for Poisson's ratio :math:`\nu` when generating - functions to evaluate this kernel. Can also be a numeric value. + functions to evaluate this kernel. """ - def __new__(cls, - dim: int, icomp: int, jcomp: int, - viscosity_mu: float | str | SpatialConstant = "mu", - poisson_ratio: float | str | SpatialConstant = "nu", - ) -> Self: - if poisson_ratio == 0.5: # noqa: RUF069 - return super().__new__(StokesletKernel) - else: - return super().__new__(cls) - def __init__(self, - dim: int, icomp: int, jcomp: int, - viscosity_mu: float | str | SpatialConstant = "mu", - poisson_ratio: float | str | SpatialConstant = "nu") -> None: - if isinstance(viscosity_mu, str): - mu = SpatialConstant(viscosity_mu) - else: - mu = viscosity_mu + dim: int, + icomp: int, + jcomp: int, + viscosity_mu_name: str = "mu", + poisson_ratio_name: str = "nu") -> None: + if not isinstance(viscosity_mu_name, str): + raise TypeError( + f"'viscosity_mu_name' is not a str: {type(viscosity_mu_name)}" + ) - if isinstance(poisson_ratio, str): - nu = SpatialConstant(poisson_ratio) - else: - nu = poisson_ratio + if not isinstance(poisson_ratio_name, str): + raise TypeError( + f"'poisson_ratio_name' is not a str: {type(poisson_ratio_name)}" + ) + + mu = SpatialConstant(viscosity_mu_name) + nu = SpatialConstant(poisson_ratio_name) + + d = make_sym_vector("d", dim) + r = pymbolic_real_norm_2(d) + delta_ij = 1 if icomp == jcomp else 0 if dim == 2: - d = make_sym_vector("d", dim) - r = pymbolic_real_norm_2(d) # See (Berger and Karageorghis 2001) - expr = ( - -var("log")(r)*((3 - 4 * nu) if icomp == jcomp else 0) - + - d[icomp]*d[jcomp]/r**2 - ) + expr = -var("log")(r)*(3 - 4 * nu)*delta_ij + d[icomp]*d[jcomp]/r**2 scaling = -1/(8*var("pi")*(1 - nu)*mu) - elif dim == 3: - d = make_sym_vector("d", dim) - r = pymbolic_real_norm_2(d) # Kelvin solution - expr = ( - (1/r)*((3 - 4*nu) if icomp == jcomp else 0) - + - d[icomp]*d[jcomp]/r**3 - ) + expr = (1/r)*(3 - 4*nu)*delta_ij + d[icomp]*d[jcomp]/r**3 scaling = -1/(16*var("pi")*(1 - nu)*mu) - else: raise NotImplementedError(f"unsupported dimension: '{dim}'") @@ -845,49 +877,35 @@ def __init__(self, object.__setattr__(self, "icomp", icomp) object.__setattr__(self, "jcomp", jcomp) - object.__setattr__(self, "viscosity_mu", mu) - object.__setattr__(self, "poisson_ratio", nu) + object.__setattr__(self, "viscosity_mu_name", viscosity_mu_name) + object.__setattr__(self, "poisson_ratio_name", poisson_ratio_name) + + @override + def __str__(self) -> str: + return ( + f"ElasticityKnl{self.dim}D_{self.icomp}{self.jcomp}" + f"({self.viscosity_mu_name}, {self.poisson_ratio_name})") @override def __reduce__(self): return ( type(self), - (self.dim, self.icomp, self.jcomp, self.viscosity_mu, self.poisson_ratio)) + (self.dim, self.icomp, self.jcomp, + self.viscosity_mu_name, + self.poisson_ratio_name)) @property @override def is_complex_valued(self) -> bool: return False - @override - def __str__(self) -> str: - return ( - f"ElasticityKnl{self.dim}D_{self.icomp}{self.jcomp}" - f"({self.viscosity_mu}, {self.poisson_ratio})") - @memoize_method @override def get_args(self) -> Sequence[KernelArgument]: - from sumpy.tools import get_all_variables - variables = get_all_variables(self.viscosity_mu) - - args: list[KernelArgument] = [ - KernelArgument(loopy_arg=lp.ValueArg(v.name, np.float64)) - for v in variables] - - return [*args, *self.get_source_args()] - - @memoize_method - @override - def get_source_args(self) -> Sequence[KernelArgument]: - from sumpy.tools import get_all_variables - variables = get_all_variables(self.poisson_ratio) - - args: list[KernelArgument] = [ - KernelArgument(loopy_arg=lp.ValueArg(v.name, np.float64)) - for v in variables] - - return args + return [ + KernelArgument(loopy_arg=lp.ValueArg(self.viscosity_mu_name, np.float64)), + KernelArgument(loopy_arg=lp.ValueArg(self.poisson_ratio_name, np.float64)), + ] @override def get_pde_as_diff_op(self) -> LinearPDESystemOperator: @@ -898,52 +916,119 @@ def get_pde_as_diff_op(self) -> LinearPDESystemOperator: @dataclass(frozen=True, repr=False) -class StokesletKernel(ElasticityKernel): - """ +class StokesletKernel(ExpressionKernel): + r"""A kernel for the Stokes equations (see e.g. Chapter 2 in [Pozrikidis1992]_). + + .. math:: + + \begin{cases} + -\mu \Delta K_{ij}(\mathbf{x}, \mathbf{y}) + + \nabla_i P_j(\mathbf{x}, \mathbf{y}) + = \delta_{ij} \delta(\mathbf{x} - \mathbf{y}), \\ + \nabla_i K_{ij}(\mathbf{x}, \mathbf{y}) = 0, \\ + \end{cases} + + where pressure kernel :math:`P_j = \partial_j K` is the derivative of the + Laplace kernel. This kernel is often called the Stokeslet or the Oseen-Burgers + tensor and it represents the velocity field. + .. autoattribute:: icomp .. autoattribute:: jcomp - .. autoattribute:: viscosity_mu + .. autoattribute:: viscosity_mu_name """ - def __new__(cls, - dim: int, - icomp: int, - jcomp: int, - viscosity_mu: float | str | SpatialConstant = "mu", - poisson_ratio: float | str | SpatialConstant | None = None, - ) -> Self: - return object.__new__(cls) + mapper_method: ClassVar[str] = "map_stokeslet_kernel" + + icomp: int + """Component index for the kernel.""" + jcomp: int + """Component index for the kernel.""" + + viscosity_mu_name: str + r"""The argument name to use for the dynamic viscosity :math:`\mu` when + generating functions to evaluate this kernel. + """ def __init__(self, - dim: int, - icomp: int, - jcomp: int, - viscosity_mu: float | str | SpatialConstant = "mu", - poisson_ratio: float | str | SpatialConstant | None = None) -> None: - if poisson_ratio is None: - poisson_ratio = 0.5 - - if poisson_ratio != 0.5: # noqa: RUF069 - raise ValueError( - "'StokesletKernel' must have a Poisson ratio of 0.5: " - f"got '{poisson_ratio}'") + dim: int, + icomp: int, + jcomp: int, + viscosity_mu_name: str = "mu") -> None: + if not isinstance(viscosity_mu_name, str): + raise TypeError( + f"'viscosity_mu_name' is not a str: {type(viscosity_mu_name)}" + ) + mu = SpatialConstant(viscosity_mu_name) + + d = make_sym_vector("d", dim) + r = pymbolic_real_norm_2(d) + delta_ij = 1 if icomp == jcomp else 0 - super().__init__(dim, icomp, jcomp, viscosity_mu, poisson_ratio) + if dim == 2: + expr = -var("log")(r)*delta_ij + d[icomp]*d[jcomp]/r**2 + scaling = -1/(4*var("pi")*mu) + elif dim == 3: + expr = (1/r)*delta_ij + d[icomp]*d[jcomp]/r**3 + scaling = -1/(8*var("pi")*mu) + else: + raise NotImplementedError(f"unsupported dimension: '{dim}'") + + super().__init__(dim, expression=expr, global_scaling_const=scaling) + object.__setattr__(self, "icomp", icomp) + object.__setattr__(self, "jcomp", jcomp) + object.__setattr__(self, "viscosity_mu_name", viscosity_mu_name) @override def __str__(self) -> str: return ( f"StokesletKnl{self.dim}D_{self.icomp}{self.jcomp}" - f"({self.viscosity_mu}, {self.poisson_ratio})") + f"({self.viscosity_mu_name})") + + @override + def __reduce__(self): + return ( + type(self), + (self.dim, self.icomp, self.jcomp, self.viscosity_mu_name)) + + @property + @override + def is_complex_valued(self) -> bool: + return False + + @memoize_method + @override + def get_args(self) -> Sequence[KernelArgument]: + return [ + KernelArgument( + loopy_arg=lp.ValueArg(self.viscosity_mu_name, np.float64), + ) + ] + + @override + def get_pde_as_diff_op(self) -> LinearPDESystemOperator: + from sumpy.expansion.diff_op import laplacian, make_identity_diff_op + + w = make_identity_diff_op(self.dim) + return laplacian(laplacian(w)) @dataclass(frozen=True, repr=False) class StressletKernel(ExpressionKernel): - """ + r"""A kernel for the Stokes equations (see e.g. Chapter 2 in [Pozrikidis1992]_). + + .. math:: + + K_{ijk}(\mathbf{x}, \mathbf{y}) = + -P_j \delta_{ik} + + \mu (\partial_k K_{ij} + \partial_i K_{kj}) + + where the two-index :math:`K_{ij}` is the :class:`~sumpy.kernel.StokesletKernel`. + This kernel is often called the Stresslet and it represents the stress tensor. + .. autoattribute:: icomp .. autoattribute:: jcomp .. autoattribute:: kcomp - .. autoattribute:: viscosity_mu + .. autoattribute:: viscosity_mu_name """ mapper_method: ClassVar[str] = "map_stresslet_kernel" @@ -953,36 +1038,33 @@ class StressletKernel(ExpressionKernel): """Component index for the kernel.""" kcomp: int """Component index for the kernel.""" - viscosity_mu: float | SpatialConstant + + viscosity_mu_name: str r"""The argument name to use for the dynamic viscosity :math:`\mu` when - generating functions to evaluate this kernel. Can also be a numeric value. + generating functions to evaluate this kernel. """ def __init__(self, - dim: int, icomp: int, jcomp: int, kcomp: int, - viscosity_mu: float | str | SpatialConstant = "mu") -> None: + dim: int, + icomp: int, + jcomp: int, + kcomp: int, + viscosity_mu_name: str = "mu") -> None: # mu is unused but kept for consistency with the Stokeslet. - if isinstance(viscosity_mu, str): - mu = SpatialConstant(viscosity_mu) - else: - mu = viscosity_mu + if not isinstance(viscosity_mu_name, str): + raise TypeError( + f"'viscosity_mu_name' is not a str: {type(viscosity_mu_name)}" + ) + + d = make_sym_vector("d", dim) + r = pymbolic_real_norm_2(d) if dim == 2: - d = make_sym_vector("d", dim) - r = pymbolic_real_norm_2(d) - expr = ( - d[icomp]*d[jcomp]*d[kcomp]/r**4 - ) + expr = d[icomp]*d[jcomp]*d[kcomp]/r**4 scaling = 1/(var("pi")) - elif dim == 3: - d = make_sym_vector("d", dim) - r = pymbolic_real_norm_2(d) - expr = ( - d[icomp]*d[jcomp]*d[kcomp]/r**5 - ) + expr = d[icomp]*d[jcomp]*d[kcomp]/r**5 scaling = 3/(4*var("pi")) - else: raise NotImplementedError(f"unsupported dimension: '{dim}'") @@ -991,38 +1073,38 @@ def __init__(self, object.__setattr__(self, "icomp", icomp) object.__setattr__(self, "jcomp", jcomp) object.__setattr__(self, "kcomp", kcomp) - object.__setattr__(self, "viscosity_mu", mu) + object.__setattr__(self, "viscosity_mu_name", viscosity_mu_name) @override def __reduce__(self) -> tuple[object, ...]: return ( self.__class__, - (self.dim, self.icomp, self.jcomp, self.kcomp, self.viscosity_mu), - ) + (self.dim, self.icomp, self.jcomp, self.kcomp, + self.viscosity_mu_name)) @property @override def is_complex_valued(self) -> bool: return False - @override - def __str__(self) -> str: - return ( - f"StressletKnl{self.dim}D_{self.icomp}{self.jcomp}{self.kcomp}" - f"({self.viscosity_mu})") - @memoize_method @override def get_args(self) -> Sequence[KernelArgument]: - from sumpy.tools import get_all_variables - variables = get_all_variables(self.viscosity_mu) + # NOTE: this is not used, but kept for symmetry with the StokesletKernel return [ - KernelArgument(loopy_arg=lp.ValueArg(v.name, np.float64)) - for v in variables] + KernelArgument(loopy_arg=lp.ValueArg(self.viscosity_mu_name, np.float64)) + ] + + @override + def __str__(self) -> str: + return ( + f"StressletKnl{self.dim}D_{self.icomp}{self.jcomp}{self.kcomp}" + f"({self.viscosity_mu_name})") @override def get_pde_as_diff_op(self) -> LinearPDESystemOperator: from sumpy.expansion.diff_op import laplacian, make_identity_diff_op + w = make_identity_diff_op(self.dim) return laplacian(laplacian(w)) @@ -1030,9 +1112,9 @@ def get_pde_as_diff_op(self) -> LinearPDESystemOperator: @dataclass(frozen=True, repr=False) class LineOfCompressionKernel(ExpressionKernel): """A kernel for the line of compression or dilatation of constant strength - along the axis "axis" from zero to negative infinity. + along an axis from zero to negative infinity. - This is used for the explicit solution to half-space Elasticity problem. + This is used for the explicit solution to half-space linear elasticity problem. See [Mindlin1936]_ for details. .. [Mindlin1936] R. D. Mindlin (1936). @@ -1041,41 +1123,47 @@ class LineOfCompressionKernel(ExpressionKernel): `doi:10.1063/1.1745385 `__. .. autoattribute:: axis - .. autoattribute:: viscosity_mu - .. autoattribute:: poisson_ratio + .. autoattribute:: viscosity_mu_name + .. autoattribute:: poisson_ratio_name """ mapper_method: ClassVar[str] = "map_line_of_compression_kernel" axis: int """Axis number (defaulting to 2 for the z axis).""" - viscosity_mu: float | SpatialConstant + + viscosity_mu_name: str r"""The argument name to use for the dynamic viscosity :math:`\mu` when - generating functions to evaluate this kernel. Can also be a numeric value. + generating functions to evaluate this kernel. """ - poisson_ratio: float | SpatialConstant + poisson_ratio_name: str r"""The argument name to use for Poisson's ratio :math:`\nu` when - generating functions to evaluate this kernel. Can also be a numeric value. + generating functions to evaluate this kernel. """ def __init__(self, dim: int = 3, axis: int = 2, - viscosity_mu: float | str | SpatialConstant = "mu", - poisson_ratio: float | str | SpatialConstant = "nu" + viscosity_mu_name: str = "mu", + poisson_ratio_name: str = "nu" ) -> None: - if isinstance(viscosity_mu, str): - mu = SpatialConstant(viscosity_mu) - else: - mu = viscosity_mu - if isinstance(poisson_ratio, str): - nu = SpatialConstant(poisson_ratio) - else: - nu = poisson_ratio + if not isinstance(viscosity_mu_name, str): + raise TypeError( + f"'viscosity_mu_name' is not a str: {type(viscosity_mu_name)}" + ) + + if not isinstance(poisson_ratio_name, str): + raise TypeError( + f"'poisson_ratio_name' is not a str: {type(poisson_ratio_name)}" + ) + + mu = SpatialConstant(viscosity_mu_name) + nu = SpatialConstant(poisson_ratio_name) if dim == 3: d = make_sym_vector("d", dim) r = pymbolic_real_norm_2(d) + # Kelvin solution expr = d[axis] * var("log")(r + d[axis]) - r scaling = (1 - 2*nu)/(4*var("pi")*mu) @@ -1085,42 +1173,39 @@ def __init__(self, super().__init__(dim, expression=expr, global_scaling_const=scaling) object.__setattr__(self, "axis", axis) - object.__setattr__(self, "viscosity_mu", mu) - object.__setattr__(self, "poisson_ratio", nu) + object.__setattr__(self, "viscosity_mu_name", viscosity_mu_name) + object.__setattr__(self, "poisson_ratio_name", poisson_ratio_name) + + @override + def __str__(self) -> str: + return ( + f"LineOfCompressionKnl{self.dim}D_{self.axis}" + f"({self.viscosity_mu_name}, {self.poisson_ratio_name})") @override def __reduce__(self) -> tuple[object, ...]: return ( self.__class__, - (self.dim, self.axis, self.viscosity_mu, self.poisson_ratio), - ) + (self.dim, self.axis, + self.viscosity_mu_name, self.poisson_ratio_name)) @property @override def is_complex_valued(self) -> bool: return False - @override - def __str__(self) -> str: - return f"LineOfCompressionKnl{self.dim}D_{self.axis}" - @memoize_method @override def get_args(self) -> Sequence[KernelArgument]: - from sumpy.tools import get_all_variables - variables = [ - *get_all_variables(self.viscosity_mu), - *get_all_variables(self.poisson_ratio)] - - args: list[KernelArgument] = [ - KernelArgument(loopy_arg=lp.ValueArg(v.name, np.float64)) - for v in variables] - - return args + return [ + KernelArgument(loopy_arg=lp.ValueArg(self.viscosity_mu_name, np.float64)), + KernelArgument(loopy_arg=lp.ValueArg(self.poisson_ratio_name, np.float64)), + ] @override def get_pde_as_diff_op(self) -> LinearPDESystemOperator: from sumpy.expansion.diff_op import laplacian, make_identity_diff_op + w = make_identity_diff_op(self.dim) return laplacian(w) @@ -1848,15 +1933,26 @@ class KernelIdentityMapper(KernelMapper[Kernel]): def map_expression_kernel(self, kernel: ExpressionKernel) -> Kernel: return kernel - map_laplace_kernel = map_expression_kernel - map_biharmonic_kernel = map_expression_kernel - map_helmholtz_kernel = map_expression_kernel - map_yukawa_kernel = map_expression_kernel - map_elasticity_kernel = map_expression_kernel - map_line_of_compression_kernel = map_expression_kernel - map_stresslet_kernel = map_expression_kernel - map_brinkmanlet_kernel = map_expression_kernel - map_brinkman_stress_kernel = map_expression_kernel + map_laplace_kernel: \ + Callable[[Self, LaplaceKernel], Kernel] = map_expression_kernel + map_biharmonic_kernel: \ + Callable[[Self, BiharmonicKernel], Kernel] = map_expression_kernel + map_helmholtz_kernel: \ + Callable[[Self, HelmholtzKernel], Kernel] = map_expression_kernel + map_yukawa_kernel: \ + Callable[[Self, YukawaKernel], Kernel] = map_expression_kernel + map_elasticity_kernel: \ + Callable[[Self, ElasticityKernel], Kernel] = map_expression_kernel + map_line_of_compression_kernel: \ + Callable[[Self, LineOfCompressionKernel], Kernel] = map_expression_kernel + map_stokeslet_kernel: \ + Callable[[Self, StokesletKernel], Kernel] = map_expression_kernel + map_stresslet_kernel: \ + Callable[[Self, StressletKernel], Kernel] = map_expression_kernel + map_brinkmanlet_kernel: \ + Callable[[Self, BrinkmanletKernel], Kernel] = map_expression_kernel + map_brinkman_stress_kernel: \ + Callable[[Self, BrinkmanStressKernel], Kernel] = map_expression_kernel def map_axis_target_derivative(self, kernel: AxisTargetDerivative) -> Kernel: return type(kernel)(kernel.axis, self.rec(kernel.inner_kernel)) @@ -1923,14 +2019,26 @@ def combine(self, values: Iterable[int]) -> int: def map_expression_kernel(self, kernel: ExpressionKernel) -> int: return 0 - map_laplace_kernel = map_expression_kernel - map_biharmonic_kernel = map_expression_kernel - map_helmholtz_kernel = map_expression_kernel - map_yukawa_kernel = map_expression_kernel - map_line_of_compression_kernel = map_expression_kernel - map_stresslet_kernel = map_expression_kernel - map_brinkmanlet_kernel = map_expression_kernel - map_brinkman_stress_kernel = map_expression_kernel + map_laplace_kernel: \ + Callable[[Self, LaplaceKernel], int] = map_expression_kernel + map_biharmonic_kernel: \ + Callable[[Self, BiharmonicKernel], int] = map_expression_kernel + map_helmholtz_kernel: \ + Callable[[Self, HelmholtzKernel], int] = map_expression_kernel + map_yukawa_kernel: \ + Callable[[Self, YukawaKernel], int] = map_expression_kernel + map_elasticity_kernel: \ + Callable[[Self, ElasticityKernel], int] = map_expression_kernel + map_line_of_compression_kernel: \ + Callable[[Self, LineOfCompressionKernel], int] = map_expression_kernel + map_stokeslet_kernel: \ + Callable[[Self, StokesletKernel], int] = map_expression_kernel + map_stresslet_kernel: \ + Callable[[Self, StressletKernel], int] = map_expression_kernel + map_brinkmanlet_kernel: \ + Callable[[Self, BrinkmanletKernel], int] = map_expression_kernel + map_brinkman_stress_kernel: \ + Callable[[Self, BrinkmanStressKernel], int] = map_expression_kernel @override def map_axis_target_derivative(self, kernel: AxisTargetDerivative) -> int: diff --git a/sumpy/test/test_misc.py b/sumpy/test/test_misc.py index 7affcf89..c6c8245e 100644 --- a/sumpy/test/test_misc.py +++ b/sumpy/test/test_misc.py @@ -545,22 +545,20 @@ def test_as_scalar_pde_brinkman(): # }}} -# {{{ test_elasticity_new +# {{{ test_elasticity_pickle -def test_elasticity_new(): +def test_elasticity_pickle(): from pickle import dumps, loads - stokes_knl = StokesletKernel(3, 0, 1, "mu1", 0.5) - stokes_knl2 = ElasticityKernel(3, 0, 1, "mu1", 0.5) - elasticity_knl = ElasticityKernel(3, 0, 1, "mu1", "nu") - elasticity_helper_knl = LineOfCompressionKernel(3, 0, "mu1", "nu") + stokes_knl = StokesletKernel( + 3, 0, 1, viscosity_mu_name="mu1") + elasticity_knl = ElasticityKernel( + 3, 0, 1, viscosity_mu_name="mu1", poisson_ratio_name="nu1") + elasticity_helper_knl = LineOfCompressionKernel( + 3, 0, viscosity_mu_name="mu1", poisson_ratio_name="nu1") - assert isinstance(stokes_knl2, StokesletKernel) - assert stokes_knl == stokes_knl2 assert loads(dumps(stokes_knl)) == stokes_knl - - for knl in [elasticity_knl, elasticity_helper_knl]: - assert not isinstance(knl, StokesletKernel) - assert loads(dumps(knl)) == knl + assert loads(dumps(elasticity_knl)) == elasticity_knl + assert loads(dumps(elasticity_helper_knl)) == elasticity_helper_knl # }}}