tfields

Tensors, Tensor Fields, Mesh Manipulation and More

A Library by Daniel Böckenhoff

Overview

Installation

Pypi:

pip install tfields

Git:

git clone https://gitlab.mpcdf.mpg.de/dboe/tfields.git

Standards

python > 2.7

Tested on Linux / Windows / Mac

Unit tested with ~ 80 % coverage

Introduction

Base Objects: Tensors of any dimension

In [1]:
import tfields
In [2]:
scalars = tfields.Tensors([0, 1, 2.])
scalars.rank, scalars.dim
Out[2]:
(0, 1)
In [3]:
vectors = tfields.Tensors([[0, 0, 0],
                           [0, 0, 1],
                           [0, -1, 0.]])
vectors.rank, vectors.dim
Out[3]:
(1, 3)
In [4]:
# Levi-Zivita Tensor
matrices = tfields.Tensors([[[0, 0, 0], [0, 0, 1], [0, -1, 0]],
                            [[0, 0, -1], [0, 0, 0], [1, 0, 0]],
                            [[0, 1, 0], [-1, 0, 0], [0, 0, 0]]])
matrices.rank, matrices.dim
Out[4]:
(2, 3)

Symbolic Coordinate System and Transformation

Coordinate System as attribute

In [5]:
vectors.coord_sys  # Default
Out[5]:
'cartesian'
In [6]:
vectors_cylinder = tfields.Tensors([[1, 1, 1]], coord_sys='cylinder')  # Initialization with different base
vectors_cylinder.coord_sys
Out[6]:
'cylinder'

Transformations

Bijective Transformations @ Singularities

In [7]:
orig = vectors.copy()
vectors.transform('spherical')
vectors.transform('cylinder')
vectors.transform('cartesian')
vectors.equal(orig, atol=1e-15)
Out[7]:
True

Tensor Fields

In [9]:
scalar_field = tfields.TensorFields(vectors, scalars)

Slicing, Indexing and Comparison e.g.

In [11]:
vectors.equal(scalar_field)
Out[11]:
True
In [12]:
scalar_field[:2].fields[0]
Out[12]:
Tensors([ 0.,  1.])

Tensor Maps (Graph Theory)

Tensors considered as Nodes → Maps define Connections

In [29]:
maps = [tfields.TensorFields([[0, 1, 2]], fields=[[42]])]  # very simple map that connects the first three nodes
graph = tfields.TensorMaps(scalar_field, maps=maps)

This is the special case of a 3D CAD mesh

In [32]:
mesh = tfields.Mesh3D(scalar_field, maps=maps)

%matplotlib notebook
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
mesh.plot(axis=ax, color='b', edgecolor='k')
[(0.0, 0.0, 1.0, 1)]
Out[32]:
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7ff9a44a8518>

Glimpses

Curl Vector Field

In [31]:
import tfields
basis_vectors = tfields.Tensors.grid((0.5, 1, 3),  # R linspace
                                     (-np.pi, np.pi, 11),  # Phi linspace
                                     (-1, 1, 1),  # Z linspace
                                     coord_sys='cylinder')
field_vectors = basis_vectors.copy(); field_vectors[:, 1] += np.pi / 2
whirl = tfields.TensorFields(basis_vectors, field_vectors, coord_sys='cartesian')  # TODO

%matplotlib notebook
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
artist = whirl.plot(axis=ax, field_index=0)

Approximated sphere translated in y

In [17]:
%matplotlib notebook
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')

sphere = tfields.Mesh3D.grid((1, 1, 1),
                             (-np.pi, np.pi, 12),
                             (-np.pi / 2, np.pi / 2, 12),
                             coord_sys='spherical')
sphere.transform('cartesian')
sphere[:, 1] += 3
artist = sphere.plot(axis=ax,
                     color='b',
                     edgecolor='k')
[(0.0, 0.0, 1.0, 1)]

Oktaeder

In [18]:
%matplotlib notebook
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')

oktaeder = tfields.Mesh3D.grid((1, 1, 1),
                               (-np.pi, np.pi, 5),
                               (-np.pi / 2, np.pi / 2, 3),
                               coord_sys='spherical')
oktaeder.transform('cartesian')
artist = oktaeder.plot(axis=ax,
                       color='r',
                       edgecolor='k')
[(1.0, 0.0, 0.0, 1)]

Merging

In [24]:
%matplotlib notebook
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')

complex = tfields.Mesh3D.merged(sphere, oktaeder)
artist = complex.plot(axis=ax, edgecolor='k')
[(0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0)]

Splitting using fast algorithms from Graph Theory (Disjoint Nodes)

In [20]:
map_description = complex.disjoint_map(0)
parts = complex.parts(map_description)
parts[0].equal(sphere), parts[1].equal(oktaeder)
Out[20]:
(True, True)

Cutting using Symbolic Maths

In [34]:
%matplotlib notebook
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
tfields.plotting.set_aspect_equal(ax)

import sympy
import tfields
x, y, z = sympy.symbols('x y z')
halfed = sphere.cut(x > 0, at_intersection='keep')
artist = halfed.plot(axis=ax, edgecolor='k')
[(0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0)]

Templates

Such cuts or disjonts can be used as templates with decision trees -> Huge speedup