0

Problem summary

I have a rectangular prism like in the image below where I know the coordinates of the vertices.

enter image description here

I want to discretize the lateral faces of the prism into an unstructured surface mesh using quadrilateral elements with a certain objective side length. More precisely, I am not interested in saving the mesh to a file, but I want a list representing the elements of the mesh and including a reference to the nodes composing each element (both in terms of id and coordinates). Is there a python library that can do this?

Why an unstructured mesh?

For a perfect rectangular prism like the one in the image above, it is fairly simple to obtain a structured surface mesh just by playing with the coordinates and numpy.linspace. However, I want to be able to mesh a prism with some taper or with different bases. In those cases, a structured mesh might lead to very skewed elements, while I would like the elements to be as close as possible to a square with side equal to the objective length.

Starting point

Ideally, the python script would start with the definition of the coordinates of the vertices and of the faces that have to be meshed:

import numpy as np
# Geometric properties
aspect_ratio = 9.
c = 1e3 # [mm]
b = aspect_ratio*c
non_dimensional_height = 0.1
h = c*non_dimensional_height # [mm]
non_dimensional_thickness = 0.001
t = c*non_dimensional_thickness # [mm]
# Objective length of the side of the quadrilateral elements
side_length = 10 # [mm]
# Define points coordinates
points_xyz = np.array([(0., 0., h/2),   # 0 -> A
                       (c, 0., h/2),    # 1 -> B
                       (0., 0., -h/2),  # 2 -> C
                       (c, 0., -h/2),   # 3 -> D
                       (0., b, h/2),    # 4 -> A'
                       (c, b, h/2),     # 5 -> B'
                       (0., b, -h/2),   # 6 -> C'
                       (c, b, -h/2)])   # 7 -> D'
# Define faces by sequence of points
faces = np.array([(0,1,5,4), (1,2,6,5), (2,3,7,6), (3,0,4,7)])

and then it would continue with the discretization of the faces and returning a list with all the elements of the unstructured mesh, where each element has a reference to its nodes (both in terms of ids and coordinates).

I have seen that there are libraries like pyvista and gmsh, but I got the impression that they are more oriented towards working with meshes imported from files rather than actually produce a mesh and the mesh connectivity information from some coordinates like I want to do.

martineau
  • 119,623
  • 25
  • 170
  • 301
fma
  • 219
  • 2
  • 14

1 Answers1

1

pyvista can also be used to generate meshes using Polydata():

Dataset consisting of surface geometry (e.g. vertices, lines, and polygons).

Can be initialized in several ways:

  • Create an empty mesh
  • Initialize from a vtk.vtkPolyData
  • Using vertices
  • Using vertices and faces
  • From a file

There are also some helper functions for simple geometric objects, e.g. Box (it uses quadrilateral elements by default):

import pyvista
mesh = pyvista.Box((0, c, 0, b, -h/2, h/2), level=10, quads=True)

print(mesh)
#PolyData (0x197125e5f40)
#  N Cells: 726
#  N Points:    728
#  X Bounds:    0.000e+00, 1.000e+03
#  Y Bounds:    0.000e+00, 9.000e+03
#  Z Bounds:    -5.000e+01, 5.000e+01
#  N Arrays:    0

for i in range(mesh.number_of_cells):
    print(mesh.cell_points(i))
#[[  0.           0.         -50.        ]
# [  0.           0.         -40.90909195]
# [  0.         818.18182373 -40.90909195]
# [  0.         818.18182373 -50.        ]]
# ...

You can cast PolyData to UnstructuredGrid using cast_to_unstructured_grid.

For more information see the Data Model section of the user guide.

Stef
  • 28,728
  • 2
  • 24
  • 52
  • Thanks, looks like a great functionality! Just one question: as far as I can see in the documentation, `Box` creates a solid mesh rather than a surface mesh, am I correct? Is there a corresponding method to create a surface mesh? Furthermore, how does `level` control the discretization of the mesh? It's not crystal clear from the docs – fma Jun 10 '22 at 16:14
  • Yes, `Box` creates a solid mesh, you can extract its surface using [`extract_surface`](https://docs.pyvista.org/examples/01-filter/extract-surface.html). `level` subdivides each dimension of the box (width, length, height) into `level + 1` cells. You can visualize the effect by `mesh.plot(show_edges=True)`. Unfortunately, you can't specify different levels for the individual dimensions. – Stef Jun 10 '22 at 20:20
  • What do you mean by solid mesh? `PolyData` meshes only define polygonal type cells, which fill areas in 2D. A closed surface may define a volume that it encloses. `UnstructuredGrid` meshes can fill areas in 3D with the cells themselves. Note that using `extract_surface` returns another `PolyData` mesh. – Matthew Flamm Jun 11 '22 at 00:52
  • @MatthewFlamm: thanks for the clarification. Solid was just the term used in fma's comment. – Stef Jun 11 '22 at 06:11
  • Sorry for the confusion. I meant to point this question to @fma. Maybe they meant having solid faces, or solid volume. – Matthew Flamm Jun 11 '22 at 14:15