pymoto.VoxelDomain

class pymoto.VoxelDomain(nelx: int, nely: int, nelz: int = 0, unitx: float = 1.0, unity: float = 1.0, unitz: float = 1.0)

Definition for a structured voxel domain Nodal numbering used in the domain is given below.

Quadrangle in 2D

      ^
      | y
3 -------- 4
|     |    |   x
|      --- | ---->
|          |
1 -------- 2

Hexahedron in 3D

       y
2----------3
|\     ^   |\
| \    |   | \
|  \   |   |  \
|   6------+---7
|   |  +-- |-- | -> x
0---+---\--1   |
 \  |    \  \  |
  \ |     \  \ |
   \|      z  \|
    4----------5
dim

Dimensionality of the object

nel

Total number of elements

nnodes

Total number of nodes

elemnodes

Number of nodes per element

node_numbering

The numbering scheme used to number the nodes in each element

conn

Connectivity matrix of size (# elements, # nodes per element)

elements

Helper array for element slicing of size (nelx, nely, nelz)

nodes

Helper array for node slicing of size (nelx+1, nely+1, nelz+1)

__init__(nelx: int, nely: int, nelz: int = 0, unitx: float = 1.0, unity: float = 1.0, unitz: float = 1.0)

Create a 2D or 3D voxel domain

Parameters:
  • nelx (int) – Number of elements in x-direction

  • nely (int) – Number of elements in y-direction

  • nelz (int, optional) – Number of elements in z-direction; if zero it is a 2D domain. Defaults to 0.

  • unitx (float, optional) – Element size in x-direction. Defaults to 1.0.

  • unity (float, optional) – Element size in y-direction. Defaults to 1.0.

  • unitz (float, optional) – Element size in z-direction. Defaults to 1.0.

Methods

__init__(nelx, nely[, nelz, unitx, unity, unitz])

Create a 2D or 3D voxel domain

create_for_mesh(mesh, h[, Nmin, Npadding])

Make a suitable domain for given (triangle) meshes (see :py:module:`numpy-stl`)

eval_shape_fun(pos)

Evaluate the linear shape functions of the finite element

eval_shape_fun_der(pos)

Evaluates the shape function derivatives in x, y, and optionally z-direction.

get_dofconnectivity(ndof)

Get the connectivity in terms of degrees of freedom

get_dofnumber(nod_idx[, dof_idx, ndof])

Gets the degree of freedom number(s) for node(s) with given node number(s)

get_elemconnectivity(i, j[, k])

Get the connectivity for element identified with Cartesian indices (i, j, k) This is where the nodal numbers are defined

get_element_indices([el_idx])

Gets the Cartesian index (i, j, k) for given element number(s)

get_element_position([el_idx])

get_elemnumber(eli, elj[, elk])

Gets the element number(s) for element(s) with given Cartesian indices (i, j, k)

get_node_indices([nod_idx])

Gets the Cartesian index (i, j, k) for given node number(s)

get_node_position([nod_idx])

Calculate the nodal coordinates of given node number(s)

get_nodenumber(nodi, nodj[, nodk])

Gets the node number(s) for nodes with given Cartesian indices (i, j, k)

get_rigid_body_modes()

Construct rigid body modes for given spatial domain

plot(ax[, deformation, scaling])

update_plot(patches[, deformation, scaling])

voxelize(mesh[, surface])

Convert a mesh body or surface to a voxel grid

write_to_vti(vectors[, filename, scale])

Write all given vectors to a Paraview (VTI) file

Attributes

domain_size

Domain size in each direction

element_size

Element size in each direction

size

Number of elements in each direction

property element_size

Element size in each direction

property domain_size

Domain size in each direction

property size

Number of elements in each direction

get_elemnumber(eli: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], elj: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], elk: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = 0)

Gets the element number(s) for element(s) with given Cartesian indices (i, j, k)

Parameters:
  • eli – Ith element in the x-direction; can be integer or array

  • elj – Jth element in the y-direction; can be integer or array

  • elk – Kth element in the z-direction; can be integer or array

Returns:

The element number(s) corresponding to selected indices

get_nodenumber(nodi: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], nodj: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], nodk: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = 0)

Gets the node number(s) for nodes with given Cartesian indices (i, j, k)

Parameters:
  • nodi – Ith node in the x-direction; can be integer or array

  • nodj – Jth node in the y-direction; can be integer or array

  • nodk – Kth node in the z-direction; can be integer or array

Returns:

The node number(s) corresponding to selected indices

get_dofnumber(nod_idx: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], dof_idx: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = None, ndof: int = None)

Gets the degree of freedom number(s) for node(s) with given node number(s)

Parameters:
  • nod_idx – Node number; can be integer or array

  • dof_idx (optional) – Dof index to request (e.g. 0 for x, [0, 1] for x and y) (default is all dofs)

  • ndof (optional) – Number of degrees of freedom per node (default is domain.dim)

Returns:

The dof number(s) corresponding to selected node index(es)

get_node_indices(nod_idx: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = None)

Gets the Cartesian index (i, j, k) for given node number(s)

Parameters:

nod_idx (optional) – Node index; can be integer or array. Defaults to None, which returns all nodes.

Returns:

i, j, k for requested node(s); k is only returned in 3D

get_node_position(nod_idx: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = None)

Calculate the nodal coordinates of given node number(s)

Parameters:

nod_idx (optional) – Selected node indices. Defaults to None, which returns all nodes.

Returns:

Coordinates numpy array of size (dim, #nodes)

get_rigid_body_modes()

Construct rigid body modes for given spatial domain

  • For dim==2, there are 3 rigid body modes: x-translation, y-translation, and z-rotation.

  • For dim==3, there are 6: x-, y-, z-translations, and x-, y-, z-rotations.

The translations are in the same units as the coordinates (e.g. in [m]), and the rotations are around the origin (e.g. in [rad]).

Returns:

Numpy array with rigid body modes of size (#dim * #nodes, #rbm)

get_element_indices(el_idx: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = None)

Gets the Cartesian index (i, j, k) for given element number(s)

Parameters:

el_idx – element index; can be integer or array

Returns:

i, j, k for requested element(s); k is only returned in 3D

get_element_position(el_idx: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = None)
get_elemconnectivity(i: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], j: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]], k: int | Iterable[int] | ndarray[tuple[Any, ...], dtype[integer]] = 0)

Get the connectivity for element identified with Cartesian indices (i, j, k) This is where the nodal numbers are defined

Parameters:
  • i – Ith element in the x-direction; can be integer or array

  • j – Jth element in the y-direction; can be integer or array

  • k – Kth element in the z-direction; can be integer or array

Returns:

The node numbers corresponding to selected elements of size (# selected elements, # nodes per element)

get_dofconnectivity(ndof: int)

Get the connectivity in terms of degrees of freedom

Parameters:

ndof – The number of degrees of freedom per node

Returns:

The dof numbers corresponding to each element of size (# total elements, # dofs per element)

eval_shape_fun(pos: ndarray)

Evaluate the linear shape functions of the finite element

In 1D .. math:

N_1(x) = \frac{1}{w} \left(\frac{w}{2} - x\right)

N_2(x) = \frac{1}{w} \left(\frac{w}{2} + x\right)

In 2D [1] .. math:

N_1(x,y) = \frac{1}{A} \left(\frac{w}{2} - x\right) \left(\frac{h}{2} - y\right)

N_2(x,y) = \frac{1}{A} \left(\frac{w}{2} + x\right) \left(\frac{h}{2} - y\right)

N_3(x,y) = \frac{1}{A} \left(\frac{w}{2} - x\right) \left(\frac{h}{2} + y\right)

N_4(x,y) = \frac{1}{A} \left(\frac{w}{2} + x\right) \left(\frac{h}{2} + y\right)

with \(A = wh\)

In 3D .. math:

N_1(x,y,z) = \frac{1}{V} \left(\frac{w}{2}-x\right) \left(\frac{h}{2}-y\right) \left(\frac{d}{2}-z\right)

\dotsc

with \(V = whd\)

Parameters:

pos – Evaluation coordinates [x, y, z (optional)] within bounds of [-element_size/2, element_size/2]

Returns:

Array of evaluated shape functions [N1(x), N2(x), …]

References

[1] Cook, et al. (2002). Concepts and applications of finite element analysis (4th ed.), eq. (6.2-3)

eval_shape_fun_der(pos: ndarray)

Evaluates the shape function derivatives in x, y, and optionally z-direction. For 1D domains, the y and z directions are optional. For 2D domains, the z direction is optional.

Parameters:

pos – Evaluation coordinates [x, y, z(optional)] within bounds of [-element_size/2, element_size/2]

Returns:

Shape function derivatives of size (#dimensions, #shape functions)

plot(ax, deformation=None, scaling=None)
update_plot(patches, deformation=None, scaling=None)
write_to_vti(vectors: dict, filename='out.vti', scale=1.0)

Write all given vectors to a Paraview (VTI) file

The size of the vectors should be a multiple of nel or nnodes. Based on their size they are marked as cell-data or point-data in the VTI file. For 2D data (size is equal to 2*nnodes), the z-dimension is padded with zeros to have 3-dimensional data. Also block-vectors of multiple dimensions (e.g. (2, 3*nnodes)) are accepted, which get the suffixed as _00.

Parameters:
  • vectors – A dictionary of vectors to write. Keys are used as vector names.

  • filename (str) – The file loction

  • scale – Uniform scaling of the gridpoints

static create_for_mesh(mesh: MeshT | list[MeshT], h: float, Nmin: int = 1, Npadding: int = 0)

Make a suitable domain for given (triangle) meshes (see :py:module:`numpy-stl`)

Parameters:
  • meshes – List of mesh objects that should fit inside the domain

  • h – The element size

  • Nmin (optional) – Minimum common divisor in the shape (#elements) of the domain

  • Npadding (optional) – Minimum number of elements to add as padding on all sides

Returns:

The created voxel domain

Return type:

VoxelDomain

voxelize(mesh: MeshT, surface: bool = False) ndarray

Convert a mesh body or surface to a voxel grid

Parameters:
  • mesh (MeshT) – The input mesh

  • surface (bool, optional) – Treat as a surface mesh (only voxels intersected by the surface are marked)

Returns:

Indices of selected voxels

Return type:

np.ndarray