-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26581 from miaoyinb/3dcut
3D Cutting Capability Implementation
- Loading branch information
Showing
28 changed files
with
1,998 additions
and
2 deletions.
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
framework/doc/content/source/meshgenerators/CutMeshByPlaneGenerator.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# CutMeshByPlaneGenerator | ||
|
||
!syntax description /Mesh/CutMeshByPlaneGenerator | ||
|
||
## Overview | ||
|
||
The `CutMeshByPlaneGenerator` is basically the 3D version of [`XYMeshLineCutter`](/XYMeshLineCutter.md). It is used to slice a 3D input mesh along a given plane, and discard the portion of the mesh on one side of the plane. The input mesh, given by [!param](/Mesh/CutMeshByPlaneGenerator/input), must be 3D and contain only first-order elements. The cutting plane is specified by [!param](/Mesh/CutMeshByPlaneGenerator/plane_normal) and [!param](/Mesh/CutMeshByPlaneGenerator/plane_point), which are two `libMesh::Point` type data that represent the normal vector of the cutting plane and a point on the cutting plane, respectively. This mesh generator removes the part of the mesh located on the side of the plane in the direction of the normal vector. The mesh is then smoothed to ensure a straight cut instead of a "zigzag" cut along element boundaries as generated by [`PlaneDeletionGenerator`](/PlaneDeletionGenerator.md). | ||
|
||
## Methods | ||
|
||
`CutMeshByPlaneGenerator` first converts all elements of the input mesh into `TET4` elements. Next, the `TET4` elements sliced by the cutting plane are further split into `TET4` elements. | ||
|
||
### Splitting of Non-TET4 Elements | ||
|
||
The splitting of non-TET4 elements was performed using the same algorithm as described in [`ElementsToTetrahedronsConverter`](/ElementsToTetrahedronsConverter.md). Note that only those elements that will be fully or partially retained after the cutting are split. | ||
|
||
### Cutting of TET4 Elements along Plane | ||
|
||
Once all the elements of the input mesh have been converted into TET elements, the cutting method only needs to be applied to TET elements. First, all the elements that are cut by the given cutting plane are identified. For the TET elements involved, their relationship with the cutting plane can be categorized into one of the six cases shown in [tet_cut]. For each of these six cases, new nodes are created at the intersection points between the cutting plane and the edges of the TET element. Then the red part of the original TET element is removed and new TET element(s) are created as shown in [tet_cut]. The cross-sections created by this cutting procedure are assigned a new boundary ID as defined by [!param](/Mesh/CutMeshByPlaneGenerator/cut_face_id) | ||
|
||
!media framework/meshgenerators/tet_cut.png | ||
style=display: block;margin-left:auto;margin-right:auto;width:75%; | ||
id=tet_cut | ||
caption=The six possible cases when slicing a TET element. The cutting plane intersection with the element is shown as blue faces. The red part of the original TET element is removed after cutting, while the blue part of the original TET element is kept and split into multiple TET elements if necessary. | ||
|
||
## Example Syntax | ||
|
||
!listing test/tests/meshgenerators/cut_mesh_by_plane_generator/simple_cut.i block=Mesh/cut | ||
|
||
!syntax parameters /Mesh/CutMeshByPlaneGenerator | ||
|
||
!syntax inputs /Mesh/CutMeshByPlaneGenerator | ||
|
||
!syntax children /Mesh/CutMeshByPlaneGenerator | ||
|
55 changes: 55 additions & 0 deletions
55
framework/doc/content/source/meshgenerators/ElementsToTetrahedronsConverter.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# ElementsToTetrahedronsConverter | ||
|
||
!syntax description /Mesh/ElementsToTetrahedronsConverter | ||
|
||
## Overview | ||
|
||
The `ElementsToTetrahedronsConverter` converts a 3D mesh that consists of first-order elements (e.g., TET4, PYRAMID5, PRISM6, and HEX8) into a mesh that only contains TET4 elements. | ||
|
||
## Methods | ||
|
||
All original mesh elements which are not TET4 type are converted into TET4 elements through splitting by this mesh generator. To be specific, each HEX8 element is split into six TET4 elements; each PRISM6 element is split into three TET4 elements; and each PYRAMID5 element is split into two TET4 elements. Details on the splitting approach follow. | ||
|
||
!media framework/meshgenerators/hex_split.png | ||
style=display: block;margin-left:auto;margin-right:auto;width:32%;float:left; | ||
id=hex_split | ||
caption=An example of splitting of a HEX8 element into six TET4 elements. | ||
|
||
!media framework/meshgenerators/prism_split.png | ||
style=display: block;margin-left:auto;margin-right:auto;width:32%;float:left; | ||
id=prism_split | ||
caption=An example of splitting of a PRISM6 element into three TET4 elements. | ||
|
||
!media framework/meshgenerators/pyramid_split.png | ||
style=display: block;margin-left:auto;margin-right:auto;width:36%;float:left; | ||
id=pyramid_split | ||
caption=An example of splitting of a PYRAMID5 element into two TET4 elements. | ||
|
||
After this conversion, all the elements become TET4 elements. In that case, all the subdomain IDs and names can be preserved. | ||
|
||
### Splitting of HEX8 Elements | ||
|
||
There are multiple ways to split one HEX8 element into multiple TET4 elements, resulting in either five or six TET4 elements (or even more if additional nodes can be added). A splitting method that does not require adding nodes needs to split each of the six quadrilateral faces of a HEX8 element into two triangles, which can be done in two different ways for each face. As these quadrilateral faces could be shared with neighboring HEX8 or other types of elements, the splitting of the quadrilateral faces on neighboring elements must be performed consistently. To achieve a consistent splitting approach, which will be discussed later in this documentation page, a HEX8 element needs to be split into six TET4 elements. An example of this splitting is illustrated in [hex_split]. Note that the splitting approach shown in [hex_split] is not unique and will be discussed later. | ||
|
||
### Splitting of PRISM6 Elements | ||
|
||
A PRISM6 element can be split into three TET4 elements. An example of this splitting is illustrated in [prism_split]. Note that the splitting approach shown in [prism_split] is not unique and will be discussed later. Namely, the three quadrilateral faces of a PRISM6 element need to be split consistently with the neighboring elements. | ||
|
||
### Splitting of PYRAMID5 Elements | ||
|
||
A PYRAMID5 element can be split into two TET4 elements. An example of this splitting is illustrated in [pyramid_split]. Note that the splitting approach shown in [pyramid_split] is not unique and will be discussed later. Namely, the one quadrilateral face of a PYRAMID5 element needs to be split consistently with the neighboring elements. | ||
|
||
### Consistent Splitting for Neighboring Elements | ||
|
||
As discussed above, although splitting of non-TET elements into TET4 elements is not unique, it is crucial to ensure that the splitting of the neighboring elements involves consistent splitting of the quadrilateral faces. To achieve this, the following approach is used. For each quadrilateral face, there are two ways to split it into two triangles, which correspond to the two diagonal lines of the quadrilateral face. Therefore, in order to ensure that one of the two diagonal lines is selected consistently for all the elements, the diagonal line that involves the node with the lowest global node ID among the four nodes of the quadrilateral face is selected. | ||
|
||
## Example Syntax | ||
|
||
!listing test/tests/meshgenerators/elements_to_tetrahedrons_convertor/simple_convert.i block=Mesh/convert | ||
|
||
!syntax parameters /Mesh/ElementsToTetrahedronsConverter | ||
|
||
!syntax inputs /Mesh/ElementsToTetrahedronsConverter | ||
|
||
!syntax children /Mesh/ElementsToTetrahedronsConverter | ||
|
106 changes: 106 additions & 0 deletions
106
framework/include/meshgenerators/CutMeshByPlaneGenerator.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
//* This file is part of the MOOSE framework | ||
//* https://www.mooseframework.org | ||
//* | ||
//* All rights reserved, see COPYRIGHT for full restrictions | ||
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT | ||
//* | ||
//* Licensed under LGPL 2.1, please see LICENSE for details | ||
//* https://www.gnu.org/licenses/lgpl-2.1.html | ||
|
||
#pragma once | ||
#include "MeshGenerator.h" | ||
|
||
/** | ||
* This CutMeshByPlaneGenerator object is designed to trim the input mesh by removing all the | ||
* elements on one side of a given plane with special processing on the elements crossed by the | ||
* cutting line to ensure a smooth cross-section. The output mesh only consists of TET4 elements. | ||
*/ | ||
class CutMeshByPlaneGenerator : public MeshGenerator | ||
{ | ||
public: | ||
static InputParameters validParams(); | ||
|
||
CutMeshByPlaneGenerator(const InputParameters & parameters); | ||
|
||
std::unique_ptr<MeshBase> generate() override; | ||
|
||
/// An enum class for style of input polygon size | ||
enum class PointPlaneRelationIndex : short int | ||
{ | ||
plane_normal_side = 1, | ||
opposite_plane_normal_side = -1, | ||
on_plane = 0 | ||
}; | ||
|
||
protected: | ||
/// Name of the input mesh | ||
const MeshGeneratorName _input_name; | ||
/// A point on the cutting plane | ||
const Point _plane_point; | ||
/// A normal vector of the cutting plane | ||
const Point _plane_normal; | ||
/// The boundary id of the face generated by the cut. | ||
boundary_id_type _cut_face_id; | ||
/// The boundary name of the face generated by the cut. | ||
const BoundaryName _cut_face_name; | ||
/// Reference to input mesh pointer | ||
std::unique_ptr<MeshBase> & _input; | ||
|
||
/** | ||
* Determine the relation between a point and a plane. | ||
* @param point The point of interest to be determined | ||
* @param plane_point A point on the plane of interest | ||
* @param plane_normal The normal vector of the plane of interest | ||
* @return an enum indicating the relation between the point and the plane | ||
*/ | ||
PointPlaneRelationIndex pointPlaneRelation(const Point & point, | ||
const Point & plane_point, | ||
const Point & plane_normal) const; | ||
|
||
/** | ||
* Calculate the intersection point of a plane and a line segment defined by two points separated | ||
* by the plane. | ||
* @param point1 The first point of the line segment | ||
* @param point2 The second point of the line segment | ||
* @param plane_point A point on the plane of interest | ||
* @param plane_normal The normal vector of the plane of interest | ||
* @return the intersection point of the plane and the line segment | ||
*/ | ||
Point pointPairPlaneInterception(const Point & point1, | ||
const Point & point2, | ||
const Point & plane_point, | ||
const Point & plane_normal) const; | ||
|
||
/** | ||
* For a TET4 elements crossed by the cutting plane, keep the part of the element on the retaining | ||
* side of the plane using a number of TET4 elements. | ||
* @param mesh The mesh to be modified | ||
* @param bdry_side_list A list that contains the boundary information of the original mesh | ||
* @param elem_id The id of the element to be cut | ||
* @param plane_point A point on the cutting plane | ||
* @param plane_normal The normal vector of the cutting plane | ||
* @param block_id_to_remove The subdomain id of the part of the element to be removed | ||
* @param new_on_plane_nodes A vector to record the pointers to the newly created nodes on the | ||
* cutting plane | ||
*/ | ||
void tet4ElemCutter(ReplicatedMesh & mesh, | ||
const std::vector<libMesh::BoundaryInfo::BCTuple> & bdry_side_list, | ||
const dof_id_type elem_id, | ||
const Point & plane_point, | ||
const Point & plane_normal, | ||
const subdomain_id_type & block_id_to_remove, | ||
std::vector<const Node *> & new_on_plane_nodes); | ||
|
||
/** | ||
* Check if a position on a plane has already been used as a node in the mesh. If so, return the | ||
* pointer to the existing node. If not, create a new node and return the pointer to the new node. | ||
* @param mesh The mesh to be modified | ||
* @param new_on_plane_nodes A vector to record the pointers to the newly created nodes on the | ||
* cutting plane | ||
* @param new_point The position of the potential new node | ||
* @return a pointer to the existing node or the newly created node | ||
*/ | ||
const Node * nonDuplicateNodeCreator(ReplicatedMesh & mesh, | ||
std::vector<const Node *> & new_on_plane_nodes, | ||
const Point & new_point); | ||
}; |
39 changes: 39 additions & 0 deletions
39
framework/include/meshgenerators/ElementsToTetrahedronsConverter.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
//* This file is part of the MOOSE framework | ||
//* https://www.mooseframework.org | ||
//* | ||
//* All rights reserved, see COPYRIGHT for full restrictions | ||
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT | ||
//* | ||
//* Licensed under LGPL 2.1, please see LICENSE for details | ||
//* https://www.gnu.org/licenses/lgpl-2.1.html | ||
|
||
#pragma once | ||
#include "MeshGenerator.h" | ||
|
||
/** | ||
* This ElementsToTetrahedronsConverter object is designed to convert all the elements in a 3D mesh | ||
* consisting of only linear elements into TET4 elements. | ||
*/ | ||
class ElementsToTetrahedronsConverter : public MeshGenerator | ||
{ | ||
public: | ||
static InputParameters validParams(); | ||
|
||
ElementsToTetrahedronsConverter(const InputParameters & parameters); | ||
|
||
std::unique_ptr<MeshBase> generate() override; | ||
|
||
/// An enum class for style of input polygon size | ||
enum class PointPlaneRelationIndex : short int | ||
{ | ||
plane_normal_side = 1, | ||
opposite_plane_normal_side = -1, | ||
on_plane = 0 | ||
}; | ||
|
||
protected: | ||
/// Name of the input mesh | ||
const MeshGeneratorName _input_name; | ||
/// Reference to input mesh pointer | ||
std::unique_ptr<MeshBase> & _input; | ||
}; |
Oops, something went wrong.