From e399a7207def827dae28bf7f624e39c052b8fad7 Mon Sep 17 00:00:00 2001 From: Max Kruse Date: Sun, 2 Feb 2025 20:26:36 +0100 Subject: [PATCH 1/3] fix: fix new stric equinox abstract-or-final pattern --- examples/parametric_derivatives.ipynb | 14 +++++- src/eikonax/derivator.py | 2 +- src/eikonax/solver.py | 5 ++- src/eikonax/tensorfield.py | 61 ++++++++++++++++++++------- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/examples/parametric_derivatives.ipynb b/examples/parametric_derivatives.ipynb index 4f2c7fe..5e81067 100644 --- a/examples/parametric_derivatives.ipynb +++ b/examples/parametric_derivatives.ipynb @@ -117,9 +117,19 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": {}, "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, { "data": { "image/png": "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", @@ -170,7 +180,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.1" + "version": "3.12.8" } }, "nbformat": 4, diff --git a/src/eikonax/derivator.py b/src/eikonax/derivator.py index a6924ea..8133110 100644 --- a/src/eikonax/derivator.py +++ b/src/eikonax/derivator.py @@ -49,7 +49,7 @@ class PartialDerivatorData: # ================================================================================================== -class PartialDerivator(eqx.Module): +class PartialDerivator(eqx.Module, strict=True): r"""Component for computing partial derivatives of the Godunov Update operator. Given a tensor field $M$ and a solution vector $u$, the partial derivator computes the partial diff --git a/src/eikonax/solver.py b/src/eikonax/solver.py index ecf98b4..b69e211 100644 --- a/src/eikonax/solver.py +++ b/src/eikonax/solver.py @@ -77,11 +77,12 @@ class Solution: # ================================================================================================== -class Solver(eqx.Module): +class Solver(eqx.Module, strict=True): r"""Eikonax solver class. The solver class is the main component for computing the solution $u$ of the Eikonal equation - for given geometry $\Omega$ of dimension $d$, tensor field $\mathbf{M}$, and initial sites $\Gamma$, + for given geometry $\Omega$ of dimension $d$, tensor field $\mathbf{M}$, and initial sites + $\Gamma$, $$ \begin{gather*} diff --git a/src/eikonax/tensorfield.py b/src/eikonax/tensorfield.py index 21b8bff..89ae94a 100644 --- a/src/eikonax/tensorfield.py +++ b/src/eikonax/tensorfield.py @@ -29,7 +29,7 @@ TensorField: Tensor field component """ -from abc import ABC, abstractmethod +from abc import abstractmethod import equinox as eqx import jax @@ -42,7 +42,7 @@ # ================================================================================================== -class BaseVectorToSimplicesMap(ABC, eqx.Module): +class AbstractVectorToSimplicesMap(eqx.Module, strict=True): """ABC interface contract for vector-to-simplices maps. Every component derived from this class needs to implement the `map` method, which maps returns @@ -82,7 +82,7 @@ def map( # -------------------------------------------------------------------------------------------------- -class LinearScalarMap(BaseVectorToSimplicesMap): +class LinearScalarMap(AbstractVectorToSimplicesMap): r"""Simple one-to-one map from global to simplex parameters. Every simplex takes exactly one parameter $m_s$, which is sorted in the global parameter @@ -109,7 +109,7 @@ def map( # ================================================================================================== -class BaseSimplexTensor(ABC, eqx.Module): +class AbstractSimplexTensor(eqx.Module, strict=True): """ABC interface contract for assembly of the tensor field. `SimplexTensor` components assemble the tensor field for a given simplex and a set of parameters @@ -127,13 +127,15 @@ class BaseSimplexTensor(ABC, eqx.Module): """ # Equinox modules are data classes, so we have to define attributes at the class level - _dimension: int + _dimension: eqx.AbstractVar[int] # ---------------------------------------------------------------------------------------------- - def __init__(self, dimension: int) -> None: - """Constructor, simply fixes the dimension of the tensor field.""" - self._dimension = dimension + def __check_init__(self) -> None: + """Check that dimension is initialized correctly in subclasses.""" + if not isinstance(self._dimension, int): + raise TypeError("Dimension must be an integer") + # ---------------------------------------------------------------------------------------------- @abstractmethod def assemble( self, @@ -158,6 +160,7 @@ def assemble( """ raise NotImplementedError + # ---------------------------------------------------------------------------------------------- @abstractmethod def derivative( self, @@ -184,8 +187,8 @@ def derivative( raise NotImplementedError -# -------------------------------------------------------------------------------------------------- -class LinearScalarSimplexTensor(BaseSimplexTensor): +# ================================================================================================== +class LinearScalarSimplexTensor(AbstractSimplexTensor): r"""SimplexTensor implementation relying on one parameter per simplex. Given a scalar parameter $m_s$, the tensor field is assembled as $m_s \cdot \mathbf{I}$, where @@ -196,6 +199,18 @@ class LinearScalarSimplexTensor(BaseSimplexTensor): derivative: Parametric derivative of the `assemble` method """ + _dimension: int + + # ---------------------------------------------------------------------------------------------- + def __init__(self, dimension: int) -> None: + """Constructor. + + Args: + dimension (int): Dimension of the tensor field + """ + self._dimension = dimension + + # ---------------------------------------------------------------------------------------------- def assemble( self, _simplex_ind: jtInt[jax.Array, ""], parameters: jtFloat[jax.Array, ""] ) -> jtFloat[jax.Array, "dim dim"]: @@ -213,6 +228,7 @@ def assemble( tensor = parameters * jnp.identity(self._dimension, dtype=jnp.float32) return tensor + # ---------------------------------------------------------------------------------------------- def derivative( self, _simplex_ind: jtInt[jax.Array, ""], _parameters: jtFloat[jax.Array, ""] ) -> jtFloat[jax.Array, "dim dim num_parameters_local"]: @@ -229,8 +245,8 @@ def derivative( return derivative -# -------------------------------------------------------------------------------------------------- -class InvLinearScalarSimplexTensor(BaseSimplexTensor): +# ================================================================================================== +class InvLinearScalarSimplexTensor(AbstractSimplexTensor): r"""SimplexTensor implementation relying on one parameter per simplex. Given a scalar parameter $m_s$, the tensor field is assembled as @@ -241,6 +257,18 @@ class InvLinearScalarSimplexTensor(BaseSimplexTensor): derivative: Parametric derivative of the `assemble` method """ + _dimension: int + + # ---------------------------------------------------------------------------------------------- + def __init__(self, dimension: int) -> None: + """Constructor. + + Args: + dimension (int): Dimension of the tensor field + """ + self._dimension = dimension + + # ---------------------------------------------------------------------------------------------- def assemble( self, _simplex_ind: jtInt[jax.Array, ""], parameters: jtFloat[jax.Array, ""] ) -> jtFloat[jax.Array, "dim dim"]: @@ -258,6 +286,7 @@ def assemble( tensor = 1 / parameters * jnp.identity(self._dimension, dtype=jnp.float32) return tensor + # ---------------------------------------------------------------------------------------------- def derivative( self, _simplex_ind: jtInt[jax.Array, ""], parameters: jtFloat[jax.Array, ""] ) -> jtFloat[jax.Array, "dim dim num_parameters_local"]: @@ -302,15 +331,15 @@ class TensorField(eqx.Module): # Equinox modules are data classes, so we have to define attributes at the class level _num_simplices: int _simplex_inds: jtFloat[jax.Array, "num_simplices"] - _vector_to_simplices_map: BaseVectorToSimplicesMap - _simplex_tensor: BaseSimplexTensor + _vector_to_simplices_map: AbstractVectorToSimplicesMap + _simplex_tensor: AbstractSimplexTensor # ---------------------------------------------------------------------------------------------- def __init__( self, num_simplices: int, - vector_to_simplices_map: BaseVectorToSimplicesMap, - simplex_tensor: BaseSimplexTensor, + vector_to_simplices_map: AbstractVectorToSimplicesMap, + simplex_tensor: AbstractSimplexTensor, ) -> None: """Constructor. From 3696cad02e764c4804cc8d58a7df317a89590504 Mon Sep 17 00:00:00 2001 From: Max Kruse Date: Sun, 2 Feb 2025 20:45:55 +0100 Subject: [PATCH 2/3] feat: mark classes as final to prevent subclassing --- src/eikonax/tensorfield.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/eikonax/tensorfield.py b/src/eikonax/tensorfield.py index 89ae94a..4a8a0b1 100644 --- a/src/eikonax/tensorfield.py +++ b/src/eikonax/tensorfield.py @@ -30,6 +30,7 @@ """ from abc import abstractmethod +from typing import final import equinox as eqx import jax @@ -82,6 +83,7 @@ def map( # -------------------------------------------------------------------------------------------------- +@final class LinearScalarMap(AbstractVectorToSimplicesMap): r"""Simple one-to-one map from global to simplex parameters. @@ -188,6 +190,7 @@ def derivative( # ================================================================================================== +@final class LinearScalarSimplexTensor(AbstractSimplexTensor): r"""SimplexTensor implementation relying on one parameter per simplex. @@ -246,6 +249,7 @@ def derivative( # ================================================================================================== +@final class InvLinearScalarSimplexTensor(AbstractSimplexTensor): r"""SimplexTensor implementation relying on one parameter per simplex. From d7292f3c52f59cbd3f65cf50ca778d97443ae6ae Mon Sep 17 00:00:00 2001 From: Max Kruse Date: Sun, 2 Feb 2025 20:48:38 +0100 Subject: [PATCH 3/3] docs: improve formatting of Jacobian description in DerivativeSolver --- src/eikonax/derivator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/eikonax/derivator.py b/src/eikonax/derivator.py index 8133110..9e48935 100644 --- a/src/eikonax/derivator.py +++ b/src/eikonax/derivator.py @@ -586,7 +586,8 @@ class DerivativeSolver: \mathbf{u}(\mathbf{m}) = \mathbf{G}(\mathbf{u}(\mathbf{m}), \mathbf{M}(\mathbf{m})) $$ - To obtain the Jacobian $\mathbf{J} = \frac{d\mathbf{u}}{d\mathbf{m}}\in\mathbb{R}^{N_V\times M}$, + To obtain the Jacobian + $\mathbf{J} = \frac{d\mathbf{u}}{d\mathbf{m}}\in\mathbb{R}^{N_V\times M}$, we simply differentiate the fixed point relation, $$