Coverage for /usr/local/lib/python3.10/site-packages/spam/mesh/structured.py: 100%
29 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-24 17:26 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-24 17:26 +0000
1# Library of SPAM functions for dealing with structured meshes
2# Copyright (C) 2020 SPAM Contributors
3#
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License as published by the Free
6# Software Foundation, either version 3 of the License, or (at your option)
7# any later version.
8#
9# This program is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# this program. If not, see <http://www.gnu.org/licenses/>.
17"""
18This module offers a set of tools in order to manipulate structured meshes.
20>>> # import module
21>>> import spam.mesh
24The strucutred VTK files used to save the data have the form:
26.. code-block:: text
28 # vtk DataFile Version 2.0
29 VTK file from spam: spam.vtk
30 ASCII
32 DATASET STRUCTURED_POINTS
33 DIMENSIONS nx ny nz
34 ASPECT_RATIO lx ly lz
35 ORIGIN ox oy oz
37 POINT_DATA nx x ny x nz
39 SCALARS myNodalField1 float
40 LOOKUP_TABLE default
41 nodalValue_1
42 nodalValue_2
43 nodalValue_3
44 ...
46 VECTORS myNodalField2 float
47 LOOKUP_TABLE default
48 nodalValue_1_X nodalValue_1_Y nodalValue_1_Z
49 nodalValue_2_X nodalValue_2_Y nodalValue_2_Z
50 nodalValue_3_X nodalValue_3_Y nodalValue_3_Z
51 ...
53 CELL_DATA (nx-1) x (ny-1) x (nz-1)
55 SCALARS myCellField1 float
56 LOOKUP_TABLE default
57 cellValue_1
58 cellValue_2
59 cellValue_3
60 ...
62where 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.
63"""
64import numpy
67def createCylindricalMask(shape, radius, voxSize=1.0, centre=None):
68 """
69 Create a image mask of a cylinder in the z direction.
71 Parameters
72 ----------
73 shape: array, int
74 The shape of the array the where the cylinder is saved
76 radius: float
77 The radius of the cylinder
79 voxSize: float (default=1.0)
80 The physical size of a voxel
82 centre: array of floats of size 2, (default None)
83 The center [y,x] of the axis of rotation of the cylinder.
84 If None it is taken to be the centre of the array.
86 Returns
87 -------
88 cyl: array, bool
89 The cylinder
91 """
92 cyl = numpy.zeros(shape).astype(bool)
94 if centre is None:
95 centre = [float(shape[1]) / 2.0, float(shape[2]) / 2.0]
97 for iy in range(cyl.shape[1]):
98 y = (float(iy) + 0.5) * float(voxSize)
99 for ix in range(cyl.shape[2]):
100 x = (float(ix) + 0.5) * float(voxSize)
101 dist = numpy.sqrt((x - centre[1]) ** 2 + (y - centre[0]) ** 2)
102 if dist < radius:
103 cyl[:, iy, ix] = True
105 return cyl
108def structuringElement(radius=1, order=2, margin=0, dim=3):
109 """
110 This function construct a structural element.
112 Parameters
113 -----------
114 radius : int, default=1
115 The `radius` of the structural element
117 .. code-block:: text
119 radius = 1 gives 3x3x3 arrays
120 radius = 2 gives 5x5x5 arrays
121 ...
122 radius = n gives (2n+1)x(2n+1)x(2n+1) arrays
124 order : int, default=2
125 Defines the shape of the structuring element by setting the order of the norm
126 used to compute the distance between the centre and the border.
128 A representation for the slices of a 5x5x5 element (size=2) from the center to on corner (1/8 of the cube)
130 .. code-block:: text
132 order=numpy.inf: the cube
133 1 1 1 1 1 1 1 1 1
134 1 1 1 1 1 1 1 1 1
135 1 1 1 1 1 1 1 1 1
137 order=2: the sphere
138 1 0 0 0 0 0 0 0 0
139 1 1 0 1 1 0 0 0 0
140 1 1 1 1 1 0 1 0 0
142 order=1: the diamond
143 1 0 0 0 0 0 0 0 0
144 1 1 0 1 0 0 0 0 0
145 1 1 1 1 1 0 1 0 0
147 margin : int, default=0
148 Gives a 0 valued margin of size margin.
150 dim : int, default=3
151 Spatial dimension (2 or 3).
153 Returns
154 --------
155 array
156 The structural element
157 """
158 tb = tuple([2 * radius + 2 * margin + 1 for _ in range(dim)])
159 ts = tuple([2 * radius + 1 for _ in range(dim)])
160 c = numpy.abs(numpy.indices(ts) - radius)
161 d = numpy.zeros(tb)
162 s = tuple([slice(margin, margin + 2 * radius + 1) for _ in range(dim)])
163 d[s] = numpy.power(numpy.sum(numpy.power(c, order), axis=0), 1.0 / float(order)) <= radius
164 return d.astype("<u1")
167def createLexicoCoordinates(lengths, nNodes, origin=(0, 0, 0)):
168 """
169 Create a list of coordinates following the lexicographical order.
171 Parameters
172 ----------
173 lengths : array of floats
174 The length of the cuboids in every directions.
175 nNodes : array of int
176 The number of nodes of the mesh in every directions.
177 origin : array of floats
178 The coordinates of the origin of the mesh.
180 Returns
181 -------
182 array
183 The list of coordinates. ``shape=(nx*ny*nz, 3)``
185 """
186 x = numpy.linspace(origin[0], lengths[0] + origin[0], nNodes[0])
187 y = numpy.linspace(origin[1], lengths[1] + origin[1], nNodes[1])
188 z = numpy.linspace(origin[2], lengths[2] + origin[2], nNodes[2])
189 cx = numpy.tile(x, (1, nNodes[1] * nNodes[2]))
190 cy = numpy.tile(numpy.sort(numpy.tile(y, (1, nNodes[0]))), (1, nNodes[2]))
191 cz = numpy.sort(numpy.tile(z, (1, nNodes[0] * nNodes[1])))
192 return numpy.transpose([cx[0], cy[0], cz[0]])