/opt/conda/envs/dxtr/lib/python3.12/site-packages/pyvista/plotting/utilities/xvfb.py:48: PyVistaDeprecationWarning: This function is deprecated and will be removed in future version of PyVista. Use vtk-osmesa instead. warnings.warn(
Cochains¶
As mentioned in the DEC introduction, Cochains represent the discrete version of differencial forms. Given a nD simplicial complex, a k-cochain (0≤k≤n) can be depicted as a series of values corresponding to its evaluation over all the k-simplices of the complex, see formula.
Within the Dxtr library, k-cochains are implemented through the Cochain
class, stored within the Cochains module. As it is a fundemental object for
the library, it can directly be imported from its root.
In order to instanciate a Cochain one needs to provide three mandatory
arguments:
complex: TheSimplicialComplexinstance upon which the cochain will be defined.dim: The topological dimension of the desired cochain.values: The values of the cochain on each (dim)-simplex of thecomplex.
from dxtr import Cochain
from dxtr.complexes import disk
cplx = disk() # The complex on which the cochain will be defined.
k = 2 # The chosen topological dimension.
Nk = cplx[k].size # The number of (k)-simplices in the chosen complex.
values = [v for v in range(Nk)] # A series of values, one for each (k)-simplex.
cchn = Cochain(cplx, k, values, name='my first cochain')
/builds/j2uR5rszh/0/oali/dxtr/src/dxtr/math/geometry.py:58: SyntaxWarning: invalid escape sequence '\{'
the frame $\{e_1,...,e_n\}$ verify: $v = \sum_i x_i e_i$.
/builds/j2uR5rszh/0/oali/dxtr/src/dxtr/math/geometry.py:146: SyntaxWarning: invalid escape sequence '\l'
$N \leq D$.
/builds/j2uR5rszh/0/oali/dxtr/src/dxtr/math/geometry.py:231: SyntaxWarning: invalid escape sequence '\l'
dimension. N.B.: these should verify: $k \leq D$.
/builds/j2uR5rszh/0/oali/dxtr/src/dxtr/math/geometry.py:278: SyntaxWarning: invalid escape sequence '\ '
* /!\ This is not a DEC implementation of the wedge_between product in any case.
The three arguments used to instanciate the cochain becomes properties that can be retrieved as properties a posteriori:
print(f'The values of {cchn.name}, a ({cchn.dim})-cochain defined on \n{cchn.complex}, are: \n {cchn.values}')
The values of my first cochain, a (2)-cochain defined on 2D Simplicial Complex of shape (1743, 5092, 3350), embedded in R^3., are: [ 0 1 2 ... 3347 3348 3349]
Like, simplicial complexes, cochains can be visualized in Dxtr. However,
when provided with a Cochain instance, the visualize() function is using
calling the pyvista library, not the plotly one as it is the case by default
for SimplicialComplex instances.
from dxtr.visu import visualize
visualize(cchn)
<pyvista.plotting.plotter.Plotter at 0x7f4f98a15bb0>
Note: Why using two different libraries for visualization?
Well, because both libraries have specific features that can be of interest to study simplicial complexes and cochain: As you can see on figures in the complexes section, the plotly library enables information display when overing the various elements of the displayed complex. This can be very useful for careful analysis of the complexes and their structures. Such a feature is not directly available out-of-the-box in the pyvista library (at least to our knowledge). However, the pyvista library excels at handleling large meshes and displaying properties computed on them. This makes it ideal for visualizing cochains and their dynamics.
Cochain algebraic manipulations¶
As the ultimate goal of the Dxtr library is to perform calculus on cochains,
we implemented basic algebraic operators directly within the Cochain class by
supercharging classic dunder methods:
__add__()and__sub__()enable respectively the addition and substractions of twoCochaininstances by simply supercharging the usual+-operators[^1].__mul__()and__rmul__()supercharge the*operator[^1] and enable to multiplyCochaininstances by scalar values, arrays or even by anotherCochaininstance.- Finally,
__truediv__()supercharges the/operator[^1] and enables the division on the right by scalar or array.
k = 2
Nk = cplx[k].size
v1, v2, v3 = 5, 2, 28
vals_1 = [v1 for _ in range(Nk)]
vals_2 = [v2 for _ in range(Nk)]
vals_3 = [v3 for _ in range(Nk)]
c1 = Cochain(cplx, k, vals_1)
c2 = Cochain(cplx, k, vals_2)
c3 = Cochain(cplx, k, vals_3)
c4 = 2*c1 + c2*c2 - c3/2.
if (c4.values == 0).all: print('One can do arithmetics with cochains !')
One can do arithmetics with cochains !
Thanks to the pyvista library, custom visualization can easily be generated to investigate cochain behaviors:
import pyvista as pv
fig = pv.Plotter(shape=(2,2), border=False)
for i, c in enumerate([c1, c2, c3, c4]):
fig.subplot(i//2, i%2)
params = {'title': f'2-cochain of val={c.values[0]}',
'show_colorbar': True,
'color_range': (0, 20)}
visualize(c, fig=fig, display=False, layout_parameters=params)
fig.link_views()
fig.show()
Dual cochains¶
Cochains can either be associated with simplices of (primal) simplicial complex or with the cells of the corresponding dual cellular complex.
TODO: Finish this section on duality...
Vector-valued cochains & vector fields¶
The values of cochain are not necessary scalars, they can also be defined as
vectors[^2].
In this case, the corresponding cochain is said to be vector-valued. Such cochains
can be implemented in Dxtr, by provinding for instance an array of ndim > 1.
In this case, the properties isvectorvalued and shape will return respectively
True and the shape of the array numpy.asarray(Cochain.values).
Vector fields¶
Discrete vector fields can be handled in Dxtr. As such vector fields are definde as a series of vectors defined on a series of positions, it is natural to implement them as vector-valued 0-cochains, defined on vertices. In most cases, we consider dual vector-valued 0-cochains for such cochains are defined at the circumcenters of the highest-degree simplices.
[^1]: It also works for the addition and substraction assignment operators +=,
-=, *= & /=.
[^2]: Even higher order tensors, but so that this working case has not been explored.
Now that the Cochain data structure has been introduce, we can look at the various
operators working on it.
indices =[[1,3,4], [3,4,5]]
from dxtr import SimplicialComplex
sc = SimplicialComplex(indices)
dxtr.abstractsimplicialcomplex | INFO: Building a 2-Abstract Simplicial Complex with 2 2-simplices
dxtr.simplicialcomplex | WARNING: No vertices are defined.