Skip to content

curvature

Kg(manifold)

An alias for the gaussian_curvature() operator.

See also

gaussian_curvature : Computes the Gaussian curvature.

Source code in src/dxtr/operators/curvature.py
301
302
303
304
305
306
307
308
def Kg(manifold: SimplicialManifold) -> Optional[Cochain]:
    """An alias for the `gaussian_curvature()` operator.

    See also
    --------
    gaussian_curvature : Computes the Gaussian curvature.
    """
    return gaussian_curvature(manifold)

Km(manifold, dual=False, return_vector=False)

An alias for the mean_curvature() operator.

See also

mean_curvature : Computes the mean curvature.

Source code in src/dxtr/operators/curvature.py
310
311
312
313
314
315
316
317
318
319
def Km(manifold: SimplicialManifold, 
       dual: bool=False, 
       return_vector: bool=False) -> Optional[Cochain]:
    """An alias for the `mean_curvature()` operator.

    See also
    --------
    mean_curvature : Computes the mean curvature.
    """
    return mean_curvature(manifold, dual, return_vector)

extrinsic_curvature(manifold, dual=False)

Computes the extrinsic curvature of a 2-D SimplicialManifold.

Parameters
manifold : SimplicialManifold
    The `SimplicialManifold` to work on.
dual : bool, optional
    If True the extrinsic curvature is computed from the normals to the top simplices. 
    Else, it is computed from the normals at the 0-simplices. Default is False.
Returns
Cochain
    A vector-valued 1-`Cochain` containing the seeked values.
Notes
* This implementation is based on the Weingarten formula, relating the extrinsic curvature to the spatial derivative of the normal vector field: 
  $$\kappa_{ij} =   au_i\cdot

abla_j(n).$$ * The idea is to describe a symmetric 2nd-order tensor field as a vector-valued 1-form.

Source code in src/dxtr/operators/curvature.py
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
@typecheck(SimplicialManifold)
def extrinsic_curvature(manifold: SimplicialManifold, 
                        dual: bool=False) -> Cochain:
    """Computes the extrinsic curvature of a 2-D `SimplicialManifold`.

    Parameters
    ----------
    manifold : SimplicialManifold
        The `SimplicialManifold` to work on.
    dual : bool, optional
        If True the extrinsic curvature is computed from the normals to the top simplices. 
        Else, it is computed from the normals at the 0-simplices. Default is False.

    Returns
    -------
    Cochain
        A vector-valued 1-`Cochain` containing the seeked values. 

    Notes
    -----
    * This implementation is based on the Weingarten formula, relating the extrinsic curvature to the spatial derivative of the normal vector field: 
      $$\kappa_{ij} = \tau_i\cdot\nabla_j(n).$$
    * The idea is to describe a symmetric 2nd-order tensor field as a vector-valued 1-form.
    """

    n = manifold.dim

    try:
        assert n == 2, 'The provided manifold should be 2D.'
    except AssertionError as msg:
        logger.warning(msg)
        return None

    nrls = normals(manifold, dual=dual)
    edge_lengths = manifold[n-1].covolumes if dual else manifold[1].volumes
    weights = (1 / edge_lengths).reshape(*edge_lengths.shape, 1)

    return  exterior_derivative(nrls) * weights

gaussian_curvature(manifold)

Computes a discrete version of the Gaussian curvature.

Parameters:

Name Type Description Default
manifold SimplicialManifold

The n-simplicial manifold to compute the curvature on.

required

Returns:

Type Description
Optional[Cochain]

A Cochain containing the values of the estimated curvature for each (n-2)-simplices.

Notes
  • We define the Gaussian curvature as the deficit angle around hinges of topological dimension n-2, n being the top-simplex dimension.
  • The deficit angle is then divided by the hinge covolume (i.e. surface of the dual 2-cell) to get a value that is indeed the inverse of a surface.
  • The sum(curvature * covolume)/2pi must equal the Euler characteristics.
Source code in src/dxtr/operators/curvature.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
@typecheck(SimplicialManifold)
def gaussian_curvature(manifold: SimplicialManifold) -> Optional[Cochain]:
    """Computes a discrete version of the Gaussian curvature.

    Parameters
    ----------
    manifold : SimplicialManifold
        The n-simplicial manifold to compute the curvature on.

    Returns
    -------
    Optional[Cochain]
        A `Cochain` containing the values of the estimated curvature for each (n-2)-simplices.

    Notes
    -----
    * We define the Gaussian curvature as the deficit angle around hinges of topological dimension n-2, n being the top-simplex dimension.
    * The deficit angle is then divided by the hinge covolume (i.e. surface of the dual 2-cell) to get a value that is indeed the inverse of a surface.
    * The sum(curvature * covolume)/2pi must equal the Euler characteristics.
    """

    n = manifold.dim

    gauss = deepcopy(manifold.deficit_angles)
    gauss /= manifold[n-2].covolumes

    return Cochain(manifold, n-2, values=gauss, name='Gaussian curvature')

mean_curvature(manifold, dual=False, return_vector=False)

Computes a discrete version of the Mean curvature.

Parameters:

Name Type Description Default
manifold SimplicialManifold

The simplicial manifold to compute the mean curvature of.

required
dual bool

If True, compute the mean curvature on the dual complex. Default is False.

False
return_vector bool

If True, return the mean curvature as a vector. Default is False.

False

Returns:

Type Description
Optional[Cochain]

A Cochain containing the values of the estimated curvature for each 0-simplex.

Notes
  • We define the Mean curvature as the norm of the Laplacian operator applied to position vectors.
  • In the primal case, the position vectors correspond to the positions of the 0-simplices.
  • In the dual case, the position vectors correspond to the circumcenters of the n-simplices.
See also

K. Crane course, section 5.2.1, p.88.

Source code in src/dxtr/operators/curvature.py
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
@typecheck(SimplicialManifold)
def mean_curvature(manifold: SimplicialManifold, 
                   dual: bool=False, 
                   return_vector: bool=False) -> Optional[Cochain]:
    """Computes a discrete version of the Mean curvature.

    Parameters
    ----------
    manifold : SimplicialManifold
        The simplicial manifold to compute the mean curvature of.
    dual : bool, optional
        If True, compute the mean curvature on the dual complex. Default is False.
    return_vector : bool, optional
        If True, return the mean curvature as a vector. Default is False.

    Returns
    -------
    Optional[Cochain]
        A `Cochain` containing the values of the estimated curvature for each 0-simplex.

    Notes
    -----
    * We define the Mean curvature as the norm of the Laplacian operator applied to position vectors.
    * In the primal case, the position vectors correspond to the positions of the 0-simplices. 
    * In the dual case, the position vectors correspond to the circumcenters of the n-simplices.

    See also
    --------
    K. Crane course, section 5.2.1, p.88.
    """

    x = positions(manifold, dual=dual)
    mn_curv_nrl = -.5 * laplacian(x)
    mn_curv_nrl._name = 'Mean Curvature Normal Vector Field'

    if not return_vector:
        mn_curv_nrl._values = lng.norm(mn_curv_nrl._values, axis=-1)
        mn_curv_nrl._name = 'Mean Curvature'

    return mn_curv_nrl

normal_curvature(direction)

Computes the normal curvature along a vector field.

Parameters:

Name Type Description Default
direction Cochain

The vector field along which we want to compute the normal curvature.

required

Returns:

Type Description
Optional[Cochain]

A dual 0-Cochain containing the seeked values.

Notes
  • The normal curvature along a vector field $oldsymbol{v}$ is defined as the projection of the extrinsic curvature along this vector field:
  • The vector field must be normalized prior to the projection.
  • This definition is valid for a manifold embedded within a higher-dimensional space.
  • For now it should be limited to the case of 2D surfaces.
Source code in src/dxtr/operators/curvature.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
@typecheck(Cochain)
def normal_curvature(direction: Cochain) -> Optional[Cochain]:
    """Computes the normal curvature along a vector field.

    Parameters
    ----------
    direction : Cochain
        The vector field along which we want to compute the normal curvature.

    Returns
    -------
    Optional[Cochain]
        A dual 0-`Cochain` containing the seeked values. 

    Notes
    -----
    * The normal curvature along a vector field $\boldsymbol{v}$ is defined as the projection of the extrinsic curvature along this vector field:
      $$\kappa_n = \boldsymbol{\kappa} \colon \hat{\boldsymbol{v}}\otimes\hat{\boldsymbol{v}}$$
    * The vector field must be normalized prior to the projection.
    * This definition is valid for a manifold embedded within a higher-dimensional space.
    * For now it should be limited to the case of 2D surfaces.
    """

    if not _isvalid(direction): return None

    mfld = direction.complex
    proj = projector(direction, normalized=True).values
    xcurv = sharp(extrinsic_curvature(mfld)).values
    ncurv = np.einsum('ijk, ijk -> i', xcurv, proj)

    return Cochain(mfld, dim=0, dual=True, values=ncurv)

normals(manifold, dual=False)

Computes the unit normal vector field on a simplicial manifold.

Parameters:

Name Type Description Default
manifold SimplicialManifold

The SimplicialManifold to work on.

required
dual bool

If False, the normal vectors are computed on the vertices of the primal complex. Else, the normal vectors are computed on the circumcenters of the top simplices. Default is False.

False

Returns:

Type Description
Optional[Cochain]

A Cochain with a (N0, D)-shaped array as value, with N0 = number of 0-simplices or n-simplices (if dual == True) within the considered SimplicialManifold and D = the dimension of the embedding space.

Notes
  • The returned vectors must be of unit norms.
  • This algo relies on the computation of a discrete version of the normal curvature vector field.
  • In the case of a flat SimplicialManifold it will return None.
  • This function will be useful to compute the normal curvature.
See Also

mean_curvature : Computes the mean curvature.

Source code in src/dxtr/operators/curvature.py
 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
@typecheck(SimplicialManifold)
def normals(manifold: SimplicialManifold, 
            dual: bool=False) -> Optional[Cochain]:
    """Computes the unit normal vector field on a simplicial manifold.

    Parameters
    ----------
    manifold : SimplicialManifold
        The `SimplicialManifold` to work on.
    dual : bool, optional
        If False, the normal vectors are computed on the vertices of the primal complex. 
        Else, the normal vectors are computed on the circumcenters of the top simplices. Default is False.

    Returns
    -------
    Optional[Cochain]
        A `Cochain` with a (N0, D)-shaped array as value, with N0 = number of 0-simplices or n-simplices 
        (if dual == True) within the considered `SimplicialManifold` and D = the dimension of the embedding space.

    Notes
    -----
    * The returned vectors must be of unit norms.
    * This algo relies on the computation of a discrete version of the normal curvature vector field.
    * In the case of a flat `SimplicialManifold` it will return None.
    * This function will be useful to compute the normal curvature.

    See Also
    --------
    mean_curvature : Computes the mean curvature.
    """

    nrl_vct = mean_curvature(manifold, return_vector=True, dual=dual)
    mn_curv = lng.norm(nrl_vct.values, axis=-1)[..., None]

    nrl_vct *= 1/mn_curv

    nrl_vct._name = 'Unit Normal'

    return nrl_vct

positions(complex, dual=False)

Generates a vector-valued 0-Cochain of the position vectors.

Parameters:

Name Type Description Default
complex SimplicialComplex

The SimplicialComplex we want the position vectors of.

required
dual bool

If True, return a dual 0-Cochain containing the top-simplex circumcenters. Else, returns a primal 0-Cochain containing the 0-simplex vertices. Default is False.

False

Returns:

Type Description
Optional[Cochain]

The seeked Cochain.

Notes
  • If dual==True, the complex argument must be a SimplicialManifold instance.
Source code in src/dxtr/operators/curvature.py
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
@typecheck(SimplicialComplex)
def positions(complex: SimplicialComplex, 
              dual: bool=False) -> Optional[Cochain]:
    """Generates a vector-valued 0-`Cochain` of the position vectors.

    Parameters
    ----------
    complex : SimplicialComplex
        The `SimplicialComplex` we want the position vectors of.
    dual : bool, optional
        If True, return a dual 0-`Cochain` containing the top-simplex circumcenters. 
        Else, returns a primal 0-`Cochain` containing the 0-simplex vertices. Default is False.

    Returns
    -------
    Optional[Cochain]
        The seeked `Cochain`.

    Notes
    -----
    * If dual==True, the `complex` argument must be a `SimplicialManifold` instance.
    """
    try:
        if dual: 
            assert isinstance(complex, SimplicialManifold), (
                'dual positions can only be computed on `SimplicialManifold`')

        pos = complex[-1].circumcenters if dual else complex[0].vertices
        return Cochain(complex, dim=0, dual=dual, values=pos)

    except AssertionError as msg:
        logger.warning(msg)
        return None

projector(vector_field, normalized=False)

Computes the projector along a vector field.

Parameters:

Name Type Description Default
vector_field Cochain

The vector field we want the projector of.

required
normalized bool

If True, the vector field is normalized prior to the computation of its projector. Default is False.

False

Returns:

Type Description
Cochain

A dual tensor-valued 0-Cochain.

Notes
  • The projector along a vector field is defined as the following symmetric second order tensor:
Source code in src/dxtr/operators/curvature.py
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
@typecheck(Cochain)
def projector(vector_field: Cochain, 
              normalized: bool=False) -> Cochain:
    """Computes the projector along a vector field.

    Parameters
    ----------
    vector_field : Cochain
        The vector field we want the projector of.
    normalized : bool, optional
        If True, the vector field is normalized prior to the computation of its projector. Default is False.

    Returns
    -------
    Cochain
        A dual tensor-valued 0-`Cochain`.

    Notes
    -----
    * The projector along a vector field is defined as the following symmetric second order tensor:
      $$\boldsymbol{P}(\boldsymbol{v}) = \boldsymbol{v}\otimes\boldsymbol{v}$$
    """

    if normalized:
        Nn = vector_field.shape[0]
        vectors = vector_field.values
        vector_field /= lng.norm(vectors, axis=-1).reshape((Nn, 1))

    proj_field = np.array([np.outer(vct, vct) for vct in vector_field.values])

    return Cochain(vector_field.complex, dim=0, dual=True, values=proj_field)