# Library of SPAM functions for dealing with structured meshes
# Copyright (C) 2020 SPAM Contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
"""
This module offers a set of tools in order to manipulate structured meshes.
>>> # import module
>>> import spam.mesh
The strucutred VTK files used to save the data have the form:
.. code-block:: text
# vtk DataFile Version 2.0
VTK file from spam: spam.vtk
ASCII
DATASET STRUCTURED_POINTS
DIMENSIONS nx ny nz
ASPECT_RATIO lx ly lz
ORIGIN ox oy oz
POINT_DATA nx x ny x nz
SCALARS myNodalField1 float
LOOKUP_TABLE default
nodalValue_1
nodalValue_2
nodalValue_3
...
VECTORS myNodalField2 float
LOOKUP_TABLE default
nodalValue_1_X nodalValue_1_Y nodalValue_1_Z
nodalValue_2_X nodalValue_2_Y nodalValue_2_Z
nodalValue_3_X nodalValue_3_Y nodalValue_3_Z
...
CELL_DATA (nx-1) x (ny-1) x (nz-1)
SCALARS myCellField1 float
LOOKUP_TABLE default
cellValue_1
cellValue_2
cellValue_3
...
where nx, ny and nz are the number of nodes in each axis, lx, ly, lz, the mesh length in each axis and ox, oy, oz the spatial postiion of the origin.
"""
[docs]
def createCylindricalMask(shape, radius, voxSize=1.0, centre=None):
"""
Create a image mask of a cylinder in the z direction.
Parameters
----------
shape: array, int
The shape of the array the where the cylinder is saved
radius: float
The radius of the cylinder
voxSize: float (default=1.0)
The physical size of a voxel
centre: array of floats of size 2, (default None)
The center [y,x] of the axis of rotation of the cylinder.
If None it is taken to be the centre of the array.
Returns
-------
cyl: array, bool
The cylinder
"""
import numpy
cyl = numpy.zeros(shape).astype(bool)
if centre is None:
centre = [float(shape[1]) / 2.0, float(shape[2]) / 2.0]
for iy in range(cyl.shape[1]):
y = (float(iy) + 0.5) * float(voxSize)
for ix in range(cyl.shape[2]):
x = (float(ix) + 0.5) * float(voxSize)
dist = numpy.sqrt((x - centre[1]) ** 2 + (y - centre[0]) ** 2)
if dist < radius:
cyl[:, iy, ix] = True
return cyl
[docs]
def structuringElement(radius=1, order=2, margin=0, dim=3):
"""
This function construct a structural element.
Parameters
-----------
radius : int, default=1
The `radius` of the structural element
.. code-block:: text
radius = 1 gives 3x3x3 arrays
radius = 2 gives 5x5x5 arrays
...
radius = n gives (2n+1)x(2n+1)x(2n+1) arrays
order : int, default=2
Defines the shape of the structuring element by setting the order of the norm
used to compute the distance between the centre and the border.
A representation for the slices of a 5x5x5 element (size=2) from the center to on corner (1/8 of the cube)
.. code-block:: text
order=numpy.inf: the cube
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
order=2: the sphere
1 0 0 0 0 0 0 0 0
1 1 0 1 1 0 0 0 0
1 1 1 1 1 0 1 0 0
order=1: the diamond
1 0 0 0 0 0 0 0 0
1 1 0 1 0 0 0 0 0
1 1 1 1 1 0 1 0 0
margin : int, default=0
Gives a 0 valued margin of size margin.
dim : int, default=3
Spatial dimension (2 or 3).
Returns
--------
array
The structural element
"""
import numpy
tb = tuple([2 * radius + 2 * margin + 1 for _ in range(dim)])
ts = tuple([2 * radius + 1 for _ in range(dim)])
c = numpy.abs(numpy.indices(ts) - radius)
d = numpy.zeros(tb)
s = tuple([slice(margin, margin + 2 * radius + 1) for _ in range(dim)])
d[s] = numpy.power(numpy.sum(numpy.power(c, order), axis=0), 1.0 / float(order)) <= radius
return d.astype("<u1")
[docs]
def createLexicoCoordinates(lengths, nNodes, origin=(0, 0, 0)):
"""
Create a list of coordinates following the lexicographical order.
Parameters
----------
lengths : array of floats
The length of the cuboids in every directions.
nNodes : array of int
The number of nodes of the mesh in every directions.
origin : array of floats
The coordinates of the origin of the mesh.
Returns
-------
array
The list of coordinates. ``shape=(nx*ny*nz, 3)``
"""
import numpy
x = numpy.linspace(origin[0], lengths[0] + origin[0], nNodes[0])
y = numpy.linspace(origin[1], lengths[1] + origin[1], nNodes[1])
z = numpy.linspace(origin[2], lengths[2] + origin[2], nNodes[2])
cx = numpy.tile(x, (1, nNodes[1] * nNodes[2]))
cy = numpy.tile(numpy.sort(numpy.tile(y, (1, nNodes[0]))), (1, nNodes[2]))
cz = numpy.sort(numpy.tile(z, (1, nNodes[0] * nNodes[1])))
return numpy.transpose([cx[0], cy[0], cz[0]])