A grid is composed of containers. The container (aka "bin") is uniquely identified by its "left-most" corner (aka key). Any coordinate in 2D or 3D can be quickly compared with the "left-most" corner; therefore, we can find coordinates efficiently.
The main idea revolves around the following expression that calculates the index of a container where the coordinates x
fall in (Eq. 8 of the Reference):
ratio[i] = truncate((x[i] - xmin[i]) / Δx[i])
key = ratio[0] + ratio[1] * ndiv[0]
Below is an illustration of a grid with two triangles:
Only the containers touched by the bounding box of the triangle are saved. Thus, we use a map
from container key to a "set" of triangles belonging to this container. Therefore, all data is stored in the following data structure;
typedef std::set<size_t> Container_t;
typedef std::map<size_t, Container_t> Containers_t;
This data structure avoids repetition, saves space, and is somewhat efficient.
The GridSearch
only works if the minimum container size (edge/side length) is greater than the maximum dimension of the largest triangle. Therefore, if one triangle is much larger that the other ones, the algorithm won't perform as well as it could. On the other hand, if the triangles have similar "sizes," then the search should be fast.
In summary, we need to make sure that:
- The container's
side_length
must be greater than the maximum dimension of the largest triangle
Update. Nonetheless, a performance improvement is available now where the large triangles are stored in a separate list. If 20% or fewer triangles are "too large," these large triangles are held in a separate list which will not affect the grid sizing. Otherwise, if more than 20% (GS_LARGE_CELLS_MAX_COUNT_PCT) triangles are "large," the "standard" algorithm takes place, i.e., no separate list is used, and all triangles affect the grid sizing. The definition of a "large" triangle is as follows: A large triangle has the largest dimension of its bounding box greater than or equal to 0.75 (GS_LARGE_CELLS_CUTOFF) times the size of the largest dimension of the largest triangle among all triangles.
The figures below show before and after the update. The darker yellow triangles are the "large" triangles in the mesh.
Before
After
- Find cells in 2D: example_grid_search_2d.cpp
- Find cells in 3D: example_grid_search_3d.cpp
In 2D, Delaunay triangulation is performed using the fantastic Triangle. In 3D, the Delaunay tetrahedralization is performed with an old version of Tetgen: Tetgen (1.4).
Given a "cloud" of points:
// generate Delaunay triangulation/tetrahedralization
auto triangles = delaunay_2d(cloud_2d, false);
auto tetrahedra = delaunay_3d(cloud_3d, false);
Full example example_delaunay_2d.cpp
Full example example_delaunay_3d.cpp
The code should generate a mesh like the one below:
- Durand, Farias, and Pedroso (2015) Computing intersections between non-compatible curves and finite elements, Computational Mechanics; DOI=10.1007/s00466-015-1181-y
Using the fixed code from Kratos
https://github.com/KratosMultiphysics/Kratos/tree/master/external_libraries