Skip to content

whitneymap

WhitneyMap dataclass

A minimalist container for the Whitney k-map on a simplicial complex.

Attributes:

Name Type Description
base np.ndarray of float

(NfkNn, (D,)k)-array containing the Whitney forms for each couple (n-simplex, k-face), see Notes.

positions np.ndarray of float

(Nn, D)-array containing the position vectors of the circumcenters of all the Nn top simplices of the considered n-complex.

Notes
  • A Whitney k-map, as we envision it here, is the collection of all base k-forms interpolated at the circumcenter of each n-simplex of a simplicial complex/manifold.
  • Each base k-form is the interpolation of the base function associated to a k-simplex. Since a k-simplex (k<n) is shared by several n-simplices, we have one interpolation of each base k-form on each of those.
  • About the shape of the attribute base:
  • Each top simplex is surrounded by Nfk k-faces. We compute a Whitney k-form for each of these k faces, specific to each top simplex. Therefore we compute Nfk*Nn Whitney k-forms in total (Nn being the number of n-simplices).
  • We depict a k-form as a k-degree anti-symmetric tensor in a space of dimension D. 1-forms are encoded as Dd vectors, i.e. (D,)-arrays; 2-forms as DD matrices, i.e. (D,D)-arrays -> generalization: k-forms are encoded as (D,..D)-arrays, D being repeated k times. We noted this (D,)k in the attribute description.
Source code in src/dxtr/cochains/whitneymap.py
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
@dataclass
class WhitneyMap():
    """A minimalist container for the Whitney k-map on a simplicial complex.

    Attributes
    ----------
    base : np.ndarray of float
        (Nfk*Nn, (D,)*k)-array containing the Whitney forms 
        for each couple (n-simplex, k-face), see Notes.
    positions : np.ndarray of float
        (Nn, D)-array containing the position vectors of the circumcenters
        of all the Nn top simplices of the considered n-complex.

    Notes
    -----
    * A Whitney k-map, as we envision it here, is the collection of all base 
      k-forms interpolated at the circumcenter of each n-simplex of 
      a simplicial complex/manifold.
    * Each base k-form is the interpolation of the base function associated 
      to a k-simplex. Since a k-simplex (k<n) is shared by several 
      n-simplices, we have one interpolation of each base k-form on each 
      of those.
    * About the shape of the attribute *base*: 
      * Each top simplex is surrounded by Nfk k-faces. We compute 
        a Whitney k-form for each of these k faces, specific to each top 
        simplex. Therefore we compute Nfk*Nn Whitney k-forms in total 
        (Nn being the number of n-simplices).
      * We depict a k-form as a k-degree anti-symmetric tensor in a space 
        of dimension D. 1-forms are encoded as Dd vectors, i.e. (D,)-arrays;
        2-forms as D*D matrices, i.e. (D,D)-arrays -> generalization: 
        k-forms are encoded as (D,..D)-arrays, D being repeated k times. 
        We noted this (D,)*k in the attribute description.
    """

    base: np.ndarray[float] = field(repr=False)
    positions: np.ndarray[float] = field(repr=False)
    _rows: np.ndarray[int] = field(repr=False)
    _cols: np.ndarray[int] = field(repr=False)

    def __post_init__(self):
        self.base = np.asarray(self.base)
        self.positions = np.asarray(self.positions)

    @property
    def indices(self) -> Optional[list[tuple[int]]]:
        """Returns a (sid, fid) tuple for each value.

        Returns
        -------
        list of tuple of int, optional
            A list of (sid, fid) tuples.
        """
        return [(i,j) for i, j in zip(self._rows, self._cols)]

    @property
    def degree(self) -> int:
        """Gets the degree (k) of the base k-forms.

        Returns
        -------
        int
            The degree of the base k-forms.
        """
        return self.base.ndim - 1

    @classmethod
    def of(cls, manifold: SimplicialManifold, degree: int, 
           normalized: bool = False) -> Optional[WhitneyMap]:
        """Computes all the Whitney k-forms at the barycenter of top simplices.

        Parameters
        ----------
        manifold : SimplicialManifold
            The n-simplicial manifold to work on.
        degree : int
            The topological degree (k) of the form to compute.
            Should verify 0 <= degree < manifold.dim.
        normalized : bool, optional
            If True the computed Whitney forms are normalized. Default is False.

        Returns
        -------
        WhitneyMap or None
            The base of all Whitney k-forms on the provided n-simplicial 
            manifold, expressed at the circumcenters of all the top simplices.

        Notes
        -----
        * We are constructing a matrix where each row corresponds 
          to a top simplex and each column to a small degree-simplex.
        """

        k = degree
        n = manifold.dim

        try:
            assert 0<= k < n, (
                'Condition 0 <= degree < manifold.dim not verified.')
        except AssertionError as msg:
            logger.warning(msg)
            return None

        top_simplices = manifold[-1]
        face_indices = manifold.faces(n, k)

        rows, cols, values = [], [], []
        for sid, vtcs in enumerate(top_simplices.vertices):
            rows += [sid]*(n+1)
            cols += face_indices[sid]

            phi = circumcenter_barycentric_coordinates(vtcs)
            dphi = gradient_barycentric_coordinates(vtcs) 

            values += [whitney_form(phi, dphi, indices, normalized=normalized) 
                       for indices in it.combinations(range(n+1), (k+1))]

        return cls(values, top_simplices.circumcenters, rows, cols)

degree property

Gets the degree (k) of the base k-forms.

Returns:

Type Description
int

The degree of the base k-forms.

indices property

Returns a (sid, fid) tuple for each value.

Returns:

Type Description
list of tuple of int, optional

A list of (sid, fid) tuples.

of(manifold, degree, normalized=False) classmethod

Computes all the Whitney k-forms at the barycenter of top simplices.

Parameters:

Name Type Description Default
manifold SimplicialManifold

The n-simplicial manifold to work on.

required
degree int

The topological degree (k) of the form to compute. Should verify 0 <= degree < manifold.dim.

required
normalized bool

If True the computed Whitney forms are normalized. Default is False.

False

Returns:

Type Description
WhitneyMap or None

The base of all Whitney k-forms on the provided n-simplicial manifold, expressed at the circumcenters of all the top simplices.

Notes
  • We are constructing a matrix where each row corresponds to a top simplex and each column to a small degree-simplex.
Source code in src/dxtr/cochains/whitneymap.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
@classmethod
def of(cls, manifold: SimplicialManifold, degree: int, 
       normalized: bool = False) -> Optional[WhitneyMap]:
    """Computes all the Whitney k-forms at the barycenter of top simplices.

    Parameters
    ----------
    manifold : SimplicialManifold
        The n-simplicial manifold to work on.
    degree : int
        The topological degree (k) of the form to compute.
        Should verify 0 <= degree < manifold.dim.
    normalized : bool, optional
        If True the computed Whitney forms are normalized. Default is False.

    Returns
    -------
    WhitneyMap or None
        The base of all Whitney k-forms on the provided n-simplicial 
        manifold, expressed at the circumcenters of all the top simplices.

    Notes
    -----
    * We are constructing a matrix where each row corresponds 
      to a top simplex and each column to a small degree-simplex.
    """

    k = degree
    n = manifold.dim

    try:
        assert 0<= k < n, (
            'Condition 0 <= degree < manifold.dim not verified.')
    except AssertionError as msg:
        logger.warning(msg)
        return None

    top_simplices = manifold[-1]
    face_indices = manifold.faces(n, k)

    rows, cols, values = [], [], []
    for sid, vtcs in enumerate(top_simplices.vertices):
        rows += [sid]*(n+1)
        cols += face_indices[sid]

        phi = circumcenter_barycentric_coordinates(vtcs)
        dphi = gradient_barycentric_coordinates(vtcs) 

        values += [whitney_form(phi, dphi, indices, normalized=normalized) 
                   for indices in it.combinations(range(n+1), (k+1))]

    return cls(values, top_simplices.circumcenters, rows, cols)