https://mooseframework.inl.gov
Classes | Functions
MooseMeshElementConversionUtils Namespace Reference

Classes

struct  BCTupleKeyComp
 

Functions

void hexElemSplitter (ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
 Split a HEX8 element into six TET4 elements. More...
 
void pyramidElemSplitter (ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
 Split a PYRAMID5 element into two TET4 elements. More...
 
void prismElemSplitter (ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
 Split a PRISM6 element into three TET4 elements. More...
 
void nodeRotationHEX8 (const unsigned int min_id_index, const unsigned int sec_min_pos, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
 Rotate a HEX8 element's nodes to ensure that the node with the minimum id is the first node; and the node among its three neighboring nodes with the minimum id is the second node. More...
 
std::vector< unsigned intneighborNodeIndicesHEX8 (unsigned int min_id_index)
 Calculate the indices (within the element nodes) of the three neighboring nodes of a node in a HEX8 element. More...
 
void hexNodesToTetNodesDeterminer (std::vector< const Node *> &hex_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
 For a vector of rotated nodes that can form a HEX8 element, create a vector of four-node sets that can form TET4 elements to replace the original HEX8 element. More...
 
std::vector< bool > quadFaceDiagonalDirectionsHex (const std::vector< const Node *> &hex_nodes)
 For a HEX8 element, determine the direction of the diagonal line of each face that involves the node with the minimum id of that face. More...
 
bool quadFaceDiagonalDirection (const std::vector< const Node *> &quad_nodes)
 For a QUAD4 element, determine the direction of the diagonal line that involves the node with the minimum id of that element. More...
 
std::vector< std::vector< unsigned int > > tetNodesForHex (const std::vector< bool > diagonal_directions, std::vector< std::vector< unsigned int >> &tet_face_indices)
 Creates sets of four nodes indices that can form TET4 elements to replace the original HEX8 element. More...
 
void nodeRotationPRISM6 (unsigned int min_id_index, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
 Rotate a PRISM6 element nodes to ensure that the node with the minimum id is the first node. More...
 
void prismNodesToTetNodesDeterminer (std::vector< const Node *> &prism_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
 For a rotated nodes that can form a PRISM6 element, create a series of four-node set that can form TET4 elements to replace the original PRISM6 element. More...
 
std::vector< std::vector< unsigned int > > tetNodesForPrism (const bool diagonal_direction, std::vector< std::vector< unsigned int >> &tet_face_indices)
 Creates sets of four nodes indices that can form TET4 elements to replace the original PRISM6 element. More...
 
void nodeRotationPYRAMID5 (unsigned int min_id_index, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
 Rotate a PYRAMID5 element nodes to ensure that the node with the minimum id is the first node for the bottom face. More...
 
void pyramidNodesToTetNodesDeterminer (std::vector< const Node *> &pyramid_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
 For a rotated nodes that can form a PYRAMID5 element, create a series of four-node set that can form TET4 elements to replace the original PYRAMID5 element. More...
 
void convert3DMeshToAllTet4 (ReplicatedMesh &mesh, const std::vector< std::pair< dof_id_type, bool >> &elems_to_process, std::vector< dof_id_type > &converted_elems_ids_to_track, const subdomain_id_type block_id_to_remove, const bool delete_block_to_remove)
 Convert all the elements in a 3D mesh, consisting of only linear elements, into TET4 elements. More...
 
void convert3DMeshToAllTet4 (ReplicatedMesh &mesh)
 Convert all the elements in a 3D mesh consisting of only linear elements into TET4 elements. More...
 
void elementBoundaryInfoCollector (const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, const unsigned short n_elem_sides, std::vector< std::vector< boundary_id_type >> &elem_side_list)
 Collect the boundary information of the given element in a mesh. More...
 
void hexElemSplitter (ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
 
void prismElemSplitter (ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
 
void pyramidElemSplitter (ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
 
void hexNodesToTetNodesDeterminer (std::vector< const Node *> &hex_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
 
std::vector< bool > quadFaceDiagonalDirectionsHex (const std::vector< const Node *> &hex_nodes)
 
bool quadFaceDiagonalDirection (const std::vector< const Node *> &quad_nodes)
 
void prismNodesToTetNodesDeterminer (std::vector< const Node *> &prism_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
 
void pyramidNodesToTetNodesDeterminer (std::vector< const Node *> &pyramid_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
 
void convert3DMeshToAllTet4 (ReplicatedMesh &mesh, const std::vector< std::pair< dof_id_type, bool >> &elems_to_process, std::vector< dof_id_type > &converted_elems_ids_to_track, const subdomain_id_type block_id_to_remove, const bool delete_block_to_remove)
 
void convert3DMeshToAllTet4 (ReplicatedMesh &mesh)
 
void elementBoundaryInfoCollector (const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, const unsigned short n_elem_sides, std::vector< std::vector< boundary_id_type >> &elem_side_list)
 Collect the boundary information of the given element in a mesh. More...
 

Function Documentation

◆ convert3DMeshToAllTet4() [1/4]

void MooseMeshElementConversionUtils::convert3DMeshToAllTet4 ( ReplicatedMesh &  mesh,
const std::vector< std::pair< dof_id_type, bool >> &  elems_to_process,
std::vector< dof_id_type > &  converted_elems_ids_to_track,
const subdomain_id_type  block_id_to_remove,
const bool  delete_block_to_remove 
)

Convert all the elements in a 3D mesh, consisting of only linear elements, into TET4 elements.

Parameters
meshThe mesh to be converted
elems_to_processA vector of pairs of element ids and a bool indicating whether the element needs to be fully retained or will be further processed in the following procedures
converted_elems_ids_to_trackA vector of element ids that need to be tracked for beig further processed in the following procedures
block_id_to_removeThe id of a new subdomain in the mesh containing all the elements to be removed
delete_block_to_removeA bool indicating whether the block to be removed will be deleted in this method

Referenced by ElementsToTetrahedronsConverter::generate(), and CutMeshByLevelSetGeneratorBase::generate().

◆ convert3DMeshToAllTet4() [2/4]

void MooseMeshElementConversionUtils::convert3DMeshToAllTet4 ( ReplicatedMesh &  mesh)

Convert all the elements in a 3D mesh consisting of only linear elements into TET4 elements.

Parameters
meshThe mesh to be converted

◆ convert3DMeshToAllTet4() [3/4]

void MooseMeshElementConversionUtils::convert3DMeshToAllTet4 ( ReplicatedMesh mesh,
const std::vector< std::pair< dof_id_type, bool >> &  elems_to_process,
std::vector< dof_id_type > &  converted_elems_ids_to_track,
const subdomain_id_type  block_id_to_remove,
const bool  delete_block_to_remove 
)

Definition at line 582 of file MooseMeshElementConversionUtils.C.

587 {
588  std::vector<dof_id_type> converted_elems_ids_to_retain;
589  // Build boundary information of the mesh
590  BoundaryInfo & boundary_info = mesh.get_boundary_info();
591  const auto bdry_side_list = boundary_info.build_side_list();
592  for (const auto & elem_to_process : elems_to_process)
593  {
594  switch (mesh.elem_ptr(elem_to_process.first)->type())
595  {
596  case ElemType::HEX8:
597  hexElemSplitter(mesh,
598  bdry_side_list,
599  elem_to_process.first,
600  elem_to_process.second ? converted_elems_ids_to_track
601  : converted_elems_ids_to_retain);
602  mesh.elem_ptr(elem_to_process.first)->subdomain_id() = block_id_to_remove;
603  break;
604  case ElemType::PYRAMID5:
605  pyramidElemSplitter(mesh,
606  bdry_side_list,
607  elem_to_process.first,
608  elem_to_process.second ? converted_elems_ids_to_track
609  : converted_elems_ids_to_retain);
610  mesh.elem_ptr(elem_to_process.first)->subdomain_id() = block_id_to_remove;
611  break;
612  case ElemType::PRISM6:
613  prismElemSplitter(mesh,
614  bdry_side_list,
615  elem_to_process.first,
616  elem_to_process.second ? converted_elems_ids_to_track
617  : converted_elems_ids_to_retain);
618  mesh.elem_ptr(elem_to_process.first)->subdomain_id() = block_id_to_remove;
619  break;
620  case ElemType::TET4:
621  if (elem_to_process.second)
622  converted_elems_ids_to_track.push_back(elem_to_process.first);
623  else
624  converted_elems_ids_to_retain.push_back(elem_to_process.first);
625  break;
626  default:
627  mooseError("Unexpected element type.");
628  }
629  }
630 
631  if (delete_block_to_remove)
632  {
633  for (auto elem_it = mesh.active_subdomain_elements_begin(block_id_to_remove);
634  elem_it != mesh.active_subdomain_elements_end(block_id_to_remove);
635  elem_it++)
636  mesh.delete_elem(*elem_it);
637 
638  mesh.contract();
640  }
641 }
void pyramidElemSplitter(ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
virtual void delete_elem(Elem *e)=0
virtual const Elem * elem_ptr(const dof_id_type i) const=0
void prismElemSplitter(ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
virtual bool contract()=0
subdomain_id_type subdomain_id() const
void hexElemSplitter(ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
virtual ElemType type() const=0

◆ convert3DMeshToAllTet4() [4/4]

void MooseMeshElementConversionUtils::convert3DMeshToAllTet4 ( ReplicatedMesh mesh)

Definition at line 644 of file MooseMeshElementConversionUtils.C.

645 {
646  // Subdomain ID for new utility blocks must be new
647  std::set<subdomain_id_type> subdomain_ids_set;
648  mesh.subdomain_ids(subdomain_ids_set);
649  const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
650  const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
651  std::vector<std::pair<dof_id_type, bool>> original_elems;
652 
653  for (auto elem_it = mesh.active_elements_begin(); elem_it != mesh.active_elements_end();
654  elem_it++)
655  {
656  if ((*elem_it)->default_order() != Order::FIRST)
657  mooseError("Only first order elements are supported for cutting.");
658  original_elems.push_back(std::make_pair((*elem_it)->id(), false));
659  }
660 
661  std::vector<dof_id_type> converted_elems_ids_to_track;
662 
664  mesh, original_elems, converted_elems_ids_to_track, block_id_to_remove, true);
665 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
MeshBase & mesh
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const

◆ elementBoundaryInfoCollector() [1/2]

void MooseMeshElementConversionUtils::elementBoundaryInfoCollector ( const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
const unsigned short  n_elem_sides,
std::vector< std::vector< boundary_id_type >> &  elem_side_list 
)

Collect the boundary information of the given element in a mesh.

Parameters
bdry_side_listA list that contains the boundary information of the mesh
elem_idThe id of the element to be processed
n_elem_sidesThe number of sides of the element
elem_side_lista vector of vectors to record the boundary information of the element

Definition at line 668 of file MooseMeshElementConversionUtils.C.

Referenced by hexElemSplitter(), prismElemSplitter(), pyramidElemSplitter(), and CutMeshByLevelSetGeneratorBase::tet4ElemCutter().

672 {
673  elem_side_list.resize(n_elem_sides);
674  const auto selected_bdry_side_list =
675  std::equal_range(bdry_side_list.begin(), bdry_side_list.end(), elem_id, BCTupleKeyComp{});
676  for (auto selected_bdry_side = selected_bdry_side_list.first;
677  selected_bdry_side != selected_bdry_side_list.second;
678  ++selected_bdry_side)
679  {
680  elem_side_list[std::get<1>(*selected_bdry_side)].push_back(std::get<2>(*selected_bdry_side));
681  }
682 }

◆ elementBoundaryInfoCollector() [2/2]

void MooseMeshElementConversionUtils::elementBoundaryInfoCollector ( const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
const unsigned short  n_elem_sides,
std::vector< std::vector< boundary_id_type >> &  elem_side_list 
)

Collect the boundary information of the given element in a mesh.

Parameters
bdry_side_listA list that contains the boundary information of the mesh
elem_idThe id of the element to be processed
n_elem_sidesThe number of sides of the element
elem_side_lista vector of vectors to record the boundary information of the element

Definition at line 668 of file MooseMeshElementConversionUtils.C.

Referenced by hexElemSplitter(), prismElemSplitter(), pyramidElemSplitter(), and CutMeshByLevelSetGeneratorBase::tet4ElemCutter().

672 {
673  elem_side_list.resize(n_elem_sides);
674  const auto selected_bdry_side_list =
675  std::equal_range(bdry_side_list.begin(), bdry_side_list.end(), elem_id, BCTupleKeyComp{});
676  for (auto selected_bdry_side = selected_bdry_side_list.first;
677  selected_bdry_side != selected_bdry_side_list.second;
678  ++selected_bdry_side)
679  {
680  elem_side_list[std::get<1>(*selected_bdry_side)].push_back(std::get<2>(*selected_bdry_side));
681  }
682 }

◆ hexElemSplitter() [1/2]

void MooseMeshElementConversionUtils::hexElemSplitter ( ReplicatedMesh mesh,
const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
std::vector< dof_id_type > &  converted_elems_ids 
)

Definition at line 29 of file MooseMeshElementConversionUtils.C.

Referenced by convert3DMeshToAllTet4().

33 {
34  // Build boundary information of the mesh
35  BoundaryInfo & boundary_info = mesh.get_boundary_info();
36  // Create a list of sidesets involving the element to be split
37  std::vector<std::vector<boundary_id_type>> elem_side_list;
38  elem_side_list.resize(6);
39  elementBoundaryInfoCollector(bdry_side_list, elem_id, 6, elem_side_list);
40 
41  const unsigned int n_elem_extra_ids = mesh.n_elem_integers();
42  std::vector<dof_id_type> exist_extra_ids(n_elem_extra_ids);
43  // Record all the element extra integers of the original quad element
44  for (unsigned int j = 0; j < n_elem_extra_ids; j++)
45  exist_extra_ids[j] = mesh.elem_ptr(elem_id)->get_extra_integer(j);
46 
47  std::vector<std::vector<unsigned int>> opt_option;
48  std::vector<const Node *> elem_node_list = {mesh.elem_ptr(elem_id)->node_ptr(0),
49  mesh.elem_ptr(elem_id)->node_ptr(1),
50  mesh.elem_ptr(elem_id)->node_ptr(2),
51  mesh.elem_ptr(elem_id)->node_ptr(3),
52  mesh.elem_ptr(elem_id)->node_ptr(4),
53  mesh.elem_ptr(elem_id)->node_ptr(5),
54  mesh.elem_ptr(elem_id)->node_ptr(6),
55  mesh.elem_ptr(elem_id)->node_ptr(7)};
56  std::vector<std::vector<unsigned int>> rotated_tet_face_indices;
57 
58  std::vector<std::vector<const Node *>> optimized_node_list;
59  hexNodesToTetNodesDeterminer(elem_node_list, rotated_tet_face_indices, optimized_node_list);
60 
61  std::vector<Elem *> elems_Tet4;
62  for (const auto i : index_range(optimized_node_list))
63  {
64  auto new_elem = std::make_unique<Tet4>();
65  new_elem->set_node(0, const_cast<Node *>(optimized_node_list[i][0]));
66  new_elem->set_node(1, const_cast<Node *>(optimized_node_list[i][1]));
67  new_elem->set_node(2, const_cast<Node *>(optimized_node_list[i][2]));
68  new_elem->set_node(3, const_cast<Node *>(optimized_node_list[i][3]));
69  new_elem->subdomain_id() = mesh.elem_ptr(elem_id)->subdomain_id();
70  elems_Tet4.push_back(mesh.add_elem(std::move(new_elem)));
71  converted_elems_ids.push_back(elems_Tet4.back()->id());
72 
73  for (unsigned int j = 0; j < 4; j++)
74  {
75  // A hex element has 6 faces indexed from 0 to 5
76  // a <6 value indicates that the face of the tet element corresponds to the face of the
77  // original hex; a =6 value means the face of the tet is an interior face of the hex
78  if (rotated_tet_face_indices[i][j] < 6)
79  {
80  for (const auto & side_info : elem_side_list[rotated_tet_face_indices[i][j]])
81  boundary_info.add_side(elems_Tet4.back(), j, side_info);
82  }
83  }
84  }
85 
86  // Retain element extra integers
87  for (unsigned int i = 0; i < 6; i++)
88  for (unsigned int j = 0; j < n_elem_extra_ids; j++)
89  {
90  elems_Tet4[i]->set_extra_integer(j, exist_extra_ids[j]);
91  }
92 }
unsigned int n_elem_integers() const
MeshBase & mesh
void hexNodesToTetNodesDeterminer(std::vector< const Node *> &hex_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
void elementBoundaryInfoCollector(const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, const unsigned short n_elem_sides, std::vector< std::vector< boundary_id_type >> &elem_side_list)
Collect the boundary information of the given element in a mesh.
const BoundaryInfo & get_boundary_info() const
virtual Elem * add_elem(Elem *e)=0
virtual const Elem * elem_ptr(const dof_id_type i) const=0
subdomain_id_type subdomain_id() const
const Node * node_ptr(const unsigned int i) const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
auto index_range(const T &sizable)
dof_id_type get_extra_integer(const unsigned int index) const

◆ hexElemSplitter() [2/2]

void MooseMeshElementConversionUtils::hexElemSplitter ( ReplicatedMesh &  mesh,
const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
std::vector< dof_id_type > &  converted_elems_ids 
)

Split a HEX8 element into six TET4 elements.

Parameters
meshThe mesh to be modified
bdry_side_listA list that contains the boundary information of the original mesh
elem_idThe id of the element to be split
converted_elems_idsa vector to record the ids of the newly created TET4 elements

◆ hexNodesToTetNodesDeterminer() [1/2]

void MooseMeshElementConversionUtils::hexNodesToTetNodesDeterminer ( std::vector< const Node *> &  hex_nodes,
std::vector< std::vector< unsigned int >> &  rotated_tet_face_indices,
std::vector< std::vector< const Node *>> &  tet_nodes_list 
)

For a vector of rotated nodes that can form a HEX8 element, create a vector of four-node sets that can form TET4 elements to replace the original HEX8 element.

All the QUAD4 faces of the HEX8 element will be split by the diagonal line that involves the node with the minimum id of that face.

Parameters
hex_nodesA vector of pointers to the nodes that can form a HEX8 element
rotated_tet_face_indicesA vector of vectors of the original face indices of the HEX8 element corresponding to the faces of the newly created TET4 elements
tet_nodes_lista vector of vectors of pointers to the nodes that can form TET4 elements

◆ hexNodesToTetNodesDeterminer() [2/2]

void MooseMeshElementConversionUtils::hexNodesToTetNodesDeterminer ( std::vector< const Node *> &  hex_nodes,
std::vector< std::vector< unsigned int >> &  rotated_tet_face_indices,
std::vector< std::vector< const Node *>> &  tet_nodes_list 
)

Definition at line 228 of file MooseMeshElementConversionUtils.C.

Referenced by hexElemSplitter().

231 {
232  // Find the node with the minimum id
233  std::vector<dof_id_type> node_ids(8);
234  for (unsigned int i = 0; i < 8; i++)
235  node_ids[i] = hex_nodes[i]->id();
236 
237  const unsigned int min_node_id_index = std::distance(
238  std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
239  // Get the index of the three neighbor nodes of the minimum node
240  // The order is consistent with the description in nodeRotationHEX8()
241  // Then determine the index of the second minimum node
242  const auto neighbor_node_indices = neighborNodeIndicesHEX8(min_node_id_index);
243 
244  const auto neighbor_node_ids = {node_ids[neighbor_node_indices[0]],
245  node_ids[neighbor_node_indices[1]],
246  node_ids[neighbor_node_indices[2]]};
247  const unsigned int sec_min_pos =
248  std::distance(std::begin(neighbor_node_ids),
249  std::min_element(std::begin(neighbor_node_ids), std::end(neighbor_node_ids)));
250 
251  // Rotate the node and face indices based on the identified minimum and second minimum nodes
252  // After the rotation, we guarantee that the minimum node is the first node (Node 0)
253  // And the second node (Node 1) has the minium global id among the three neighbor nodes of Node 0
254  // This makes the splitting process simpler
255  std::vector<unsigned int> face_rotation;
256  std::vector<unsigned int> rotated_indices;
257  nodeRotationHEX8(min_node_id_index, sec_min_pos, face_rotation, rotated_indices);
258  std::vector<const Node *> rotated_hex_nodes;
259  for (unsigned int i = 0; i < 8; i++)
260  rotated_hex_nodes.push_back(hex_nodes[rotated_indices[i]]);
261 
262  // Find the selection of each face's cutting direction
263  const auto diagonal_directions = quadFaceDiagonalDirectionsHex(rotated_hex_nodes);
264 
265  // Based on the determined splitting directions of all the faces, determine the nodes of each
266  // resulting TET4 elements after the splitting.
267  std::vector<std::vector<unsigned int>> tet_face_indices;
268  const auto tet_nodes_set = tetNodesForHex(diagonal_directions, tet_face_indices);
269  for (const auto & tet_face_index : tet_face_indices)
270  {
271  rotated_tet_face_indices.push_back(std::vector<unsigned int>());
272  for (const auto & face_index : tet_face_index)
273  {
274  if (face_index < 6)
275  rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
276  else
277  rotated_tet_face_indices.back().push_back(6);
278  }
279  }
280 
281  for (const auto & tet_nodes : tet_nodes_set)
282  {
283  tet_nodes_list.push_back(std::vector<const Node *>());
284  for (const auto & tet_node : tet_nodes)
285  tet_nodes_list.back().push_back(rotated_hex_nodes[tet_node]);
286  }
287 }
std::vector< bool > quadFaceDiagonalDirectionsHex(const std::vector< const Node *> &hex_nodes)
void nodeRotationHEX8(const unsigned int min_id_index, const unsigned int sec_min_pos, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
Rotate a HEX8 element&#39;s nodes to ensure that the node with the minimum id is the first node; and the ...
std::vector< unsigned int > neighborNodeIndicesHEX8(unsigned int min_id_index)
Calculate the indices (within the element nodes) of the three neighboring nodes of a node in a HEX8 e...
std::vector< std::vector< unsigned int > > tetNodesForHex(const std::vector< bool > diagonal_directions, std::vector< std::vector< unsigned int >> &tet_face_indices)
Creates sets of four nodes indices that can form TET4 elements to replace the original HEX8 element...

◆ neighborNodeIndicesHEX8()

std::vector< unsigned int > MooseMeshElementConversionUtils::neighborNodeIndicesHEX8 ( unsigned int  min_id_index)

Calculate the indices (within the element nodes) of the three neighboring nodes of a node in a HEX8 element.

Parameters
min_id_indexThe index of the node with the minimum id
Returns
a vector of the three neighboring nodes

Definition at line 217 of file MooseMeshElementConversionUtils.C.

Referenced by hexNodesToTetNodesDeterminer().

218 {
219  const std::vector<std::vector<unsigned int>> preset_indices = {
220  {1, 3, 4}, {0, 2, 5}, {3, 1, 6}, {2, 0, 7}, {5, 7, 0}, {4, 6, 1}, {7, 5, 2}, {6, 4, 3}};
221  if (min_id_index > 7)
222  mooseError("The input node index is out of range.");
223  else
224  return preset_indices[min_id_index];
225 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302

◆ nodeRotationHEX8()

void MooseMeshElementConversionUtils::nodeRotationHEX8 ( const unsigned int  min_id_index,
const unsigned int  sec_min_pos,
std::vector< unsigned int > &  face_rotation,
std::vector< unsigned int > &  node_rotation 
)

Rotate a HEX8 element's nodes to ensure that the node with the minimum id is the first node; and the node among its three neighboring nodes with the minimum id is the second node.

Parameters
min_id_indexThe index of the node with the minimum id
sec_min_posThe index of the node among its three neighboring nodes with the minimum id (see comments in the function for more details about how the index is defined)
face_rotationA vector to record the rotation of the faces of the HEX8 element
node_rotationa vector of node indices that can form a HEX8 element

Definition at line 371 of file MooseMeshElementConversionUtils.C.

Referenced by hexNodesToTetNodesDeterminer().

375 {
376  // Assuming the original hex element is a cube, the vectors formed by nodes 0-1, 0-3, and 0-4 are
377  // overlapped with the x, y, and z axes, respectively. sec_min_pos = 0 means the second minimum
378  // node is in the x direction, sec_min_pos = 1 means the second minimum node is in the y
379  // direction, and sec_min_pos = 2 means the second minimum node is in the z direction.
380  const std::vector<std::vector<std::vector<unsigned int>>> preset_indices = {
381  {{0, 1, 2, 3, 4, 5, 6, 7}, {0, 3, 7, 4, 1, 2, 6, 5}, {0, 4, 5, 1, 3, 7, 6, 2}},
382  {{1, 0, 4, 5, 2, 3, 7, 6}, {1, 2, 3, 0, 5, 6, 7, 4}, {1, 5, 6, 2, 0, 4, 7, 3}},
383  {{2, 3, 0, 1, 6, 7, 4, 5}, {2, 1, 5, 6, 3, 0, 4, 7}, {2, 6, 7, 3, 1, 5, 4, 0}},
384  {{3, 2, 6, 7, 0, 1, 5, 4}, {3, 0, 1, 2, 7, 4, 5, 6}, {3, 7, 4, 0, 2, 6, 5, 1}},
385  {{4, 5, 1, 0, 7, 6, 2, 3}, {4, 7, 6, 5, 0, 3, 2, 1}, {4, 0, 3, 7, 5, 1, 2, 6}},
386  {{5, 4, 7, 6, 1, 0, 3, 2}, {5, 6, 2, 1, 4, 7, 3, 0}, {5, 1, 0, 4, 6, 2, 3, 7}},
387  {{6, 7, 3, 2, 5, 4, 0, 1}, {6, 5, 4, 7, 2, 1, 0, 3}, {6, 2, 1, 5, 7, 3, 0, 4}},
388  {{7, 6, 5, 4, 3, 2, 1, 0}, {7, 4, 0, 3, 6, 5, 1, 2}, {7, 3, 2, 6, 4, 0, 1, 5}}};
389 
390  const std::vector<std::vector<std::vector<unsigned int>>> preset_face_indices = {
391  {{0, 1, 2, 3, 4, 5}, {4, 0, 3, 5, 1, 2}, {1, 4, 5, 2, 0, 3}},
392  {{1, 0, 4, 5, 2, 3}, {0, 2, 3, 4, 1, 5}, {2, 1, 5, 3, 0, 4}},
393  {{0, 3, 4, 1, 2, 5}, {2, 0, 1, 5, 3, 4}, {3, 2, 5, 4, 0, 1}},
394  {{3, 0, 2, 5, 4, 1}, {0, 4, 1, 2, 3, 5}, {4, 3, 5, 1, 0, 2}},
395  {{1, 5, 2, 0, 4, 3}, {5, 4, 3, 2, 1, 0}, {4, 1, 0, 3, 5, 2}},
396  {{5, 1, 4, 3, 2, 0}, {2, 5, 3, 0, 1, 4}, {1, 2, 0, 4, 5, 3}},
397  {{3, 5, 4, 0, 2, 1}, {5, 2, 1, 4, 3, 0}, {2, 3, 0, 1, 5, 4}},
398  {{5, 3, 2, 1, 4, 0}, {4, 5, 1, 0, 3, 2}, {3, 4, 0, 2, 5, 1}}};
399 
400  if (min_id_index > 7 || sec_min_pos > 2)
401  mooseError("The input node index is out of range.");
402  else
403  {
404  // index: new face index; value: old face index
405  face_rotation = preset_face_indices[min_id_index][sec_min_pos];
406  node_rotation = preset_indices[min_id_index][sec_min_pos];
407  }
408 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302

◆ nodeRotationPRISM6()

void MooseMeshElementConversionUtils::nodeRotationPRISM6 ( unsigned int  min_id_index,
std::vector< unsigned int > &  face_rotation,
std::vector< unsigned int > &  node_rotation 
)

Rotate a PRISM6 element nodes to ensure that the node with the minimum id is the first node.

Parameters
min_id_indexThe index of the node, within the prism nodes, with the minimum id
face_rotationA vector to record the rotation of the faces of the PRISM6 element
node_rotationa vector of node indices that can form a PRISM6 element

Definition at line 411 of file MooseMeshElementConversionUtils.C.

Referenced by prismNodesToTetNodesDeterminer().

414 {
415  const std::vector<std::vector<unsigned int>> preset_indices = {{0, 1, 2, 3, 4, 5},
416  {1, 2, 0, 4, 5, 3},
417  {2, 0, 1, 5, 3, 4},
418  {3, 5, 4, 0, 2, 1},
419  {4, 3, 5, 1, 0, 2},
420  {5, 4, 3, 2, 1, 0}};
421 
422  const std::vector<std::vector<unsigned int>> preset_face_indices = {{0, 1, 2, 3, 4},
423  {0, 2, 3, 1, 4},
424  {0, 3, 1, 2, 4},
425  {4, 3, 2, 1, 0},
426  {4, 1, 3, 2, 0},
427  {4, 2, 1, 3, 0}};
428 
429  if (min_id_index > 5)
430  mooseError("The input node index is out of range.");
431  else
432  {
433  // index: new face index; value: old face index
434  face_rotation = preset_face_indices[min_id_index];
435  node_rotation = preset_indices[min_id_index];
436  }
437 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302

◆ nodeRotationPYRAMID5()

void MooseMeshElementConversionUtils::nodeRotationPYRAMID5 ( unsigned int  min_id_index,
std::vector< unsigned int > &  face_rotation,
std::vector< unsigned int > &  node_rotation 
)

Rotate a PYRAMID5 element nodes to ensure that the node with the minimum id is the first node for the bottom face.

Parameters
min_id_indexThe index of the node, within the pyramid nodes, with the minimum id for the bottom face
face_rotationA vector to record the rotation of the faces of the PYRAMID5 element
node_rotationa vector of node indices that can form a PYRAMID5 element

Definition at line 512 of file MooseMeshElementConversionUtils.C.

Referenced by pyramidNodesToTetNodesDeterminer().

515 {
516  const std::vector<std::vector<unsigned int>> preset_indices = {
517  {0, 1, 2, 3, 4}, {1, 2, 3, 0, 4}, {2, 3, 0, 1, 4}, {3, 0, 1, 2, 4}};
518 
519  const std::vector<std::vector<unsigned int>> preset_face_indices = {
520  {0, 1, 2, 3, 4}, {1, 2, 3, 0, 4}, {2, 3, 0, 1, 4}, {3, 0, 1, 2, 4}};
521 
522  if (min_id_index > 3)
523  mooseError("The input node index is out of range.");
524  else
525  {
526  // index: new face index; value: old face index
527  face_rotation = preset_face_indices[min_id_index];
528  node_rotation = preset_indices[min_id_index];
529  }
530 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302

◆ prismElemSplitter() [1/2]

void MooseMeshElementConversionUtils::prismElemSplitter ( ReplicatedMesh &  mesh,
const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
std::vector< dof_id_type > &  converted_elems_ids 
)

Split a PRISM6 element into three TET4 elements.

Parameters
meshThe mesh to be modified
bdry_side_listA list that contains the boundary information of the original mesh
elem_idThe id of the element to be split
converted_elems_idsa vector to record the ids of the newly created TET4 elements

◆ prismElemSplitter() [2/2]

void MooseMeshElementConversionUtils::prismElemSplitter ( ReplicatedMesh mesh,
const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
std::vector< dof_id_type > &  converted_elems_ids 
)

Definition at line 95 of file MooseMeshElementConversionUtils.C.

Referenced by convert3DMeshToAllTet4().

99 {
100  // Build boundary information of the mesh
101  BoundaryInfo & boundary_info = mesh.get_boundary_info();
102  // Create a list of sidesets involving the element to be split
103  std::vector<std::vector<boundary_id_type>> elem_side_list;
104  elementBoundaryInfoCollector(bdry_side_list, elem_id, 5, elem_side_list);
105 
106  const unsigned int n_elem_extra_ids = mesh.n_elem_integers();
107  std::vector<dof_id_type> exist_extra_ids(n_elem_extra_ids);
108 
109  // Record all the element extra integers of the original quad element
110  for (unsigned int j = 0; j < n_elem_extra_ids; j++)
111  exist_extra_ids[j] = mesh.elem_ptr(elem_id)->get_extra_integer(j);
112 
113  std::vector<const Node *> elem_node_list = {mesh.elem_ptr(elem_id)->node_ptr(0),
114  mesh.elem_ptr(elem_id)->node_ptr(1),
115  mesh.elem_ptr(elem_id)->node_ptr(2),
116  mesh.elem_ptr(elem_id)->node_ptr(3),
117  mesh.elem_ptr(elem_id)->node_ptr(4),
118  mesh.elem_ptr(elem_id)->node_ptr(5)};
119  std::vector<std::vector<unsigned int>> rotated_tet_face_indices;
120  std::vector<std::vector<const Node *>> optimized_node_list;
121  prismNodesToTetNodesDeterminer(elem_node_list, rotated_tet_face_indices, optimized_node_list);
122 
123  std::vector<Elem *> elems_Tet4;
124  for (const auto i : index_range(optimized_node_list))
125  {
126  auto new_elem = std::make_unique<Tet4>();
127  new_elem->set_node(0, const_cast<Node *>(optimized_node_list[i][0]));
128  new_elem->set_node(1, const_cast<Node *>(optimized_node_list[i][1]));
129  new_elem->set_node(2, const_cast<Node *>(optimized_node_list[i][2]));
130  new_elem->set_node(3, const_cast<Node *>(optimized_node_list[i][3]));
131  new_elem->subdomain_id() = mesh.elem_ptr(elem_id)->subdomain_id();
132  elems_Tet4.push_back(mesh.add_elem(std::move(new_elem)));
133  converted_elems_ids.push_back(elems_Tet4.back()->id());
134 
135  for (unsigned int j = 0; j < 4; j++)
136  {
137  // A prism element has 5 faces indexed from 0 to 4
138  // a <4 value indicates that the face of the tet element corresponds to the face of the
139  // original prism; a =5 value means the face of the tet is an interior face of the prism
140  if (rotated_tet_face_indices[i][j] < 5)
141  {
142  for (const auto & side_info : elem_side_list[rotated_tet_face_indices[i][j]])
143  boundary_info.add_side(elems_Tet4.back(), j, side_info);
144  }
145  }
146  }
147 
148  // Retain element extra integers
149  for (unsigned int i = 0; i < 3; i++)
150  for (unsigned int j = 0; j < n_elem_extra_ids; j++)
151  {
152  elems_Tet4[i]->set_extra_integer(j, exist_extra_ids[j]);
153  }
154 }
unsigned int n_elem_integers() const
MeshBase & mesh
void elementBoundaryInfoCollector(const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, const unsigned short n_elem_sides, std::vector< std::vector< boundary_id_type >> &elem_side_list)
Collect the boundary information of the given element in a mesh.
const BoundaryInfo & get_boundary_info() const
virtual Elem * add_elem(Elem *e)=0
virtual const Elem * elem_ptr(const dof_id_type i) const=0
subdomain_id_type subdomain_id() const
const Node * node_ptr(const unsigned int i) const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
void prismNodesToTetNodesDeterminer(std::vector< const Node *> &prism_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
auto index_range(const T &sizable)
dof_id_type get_extra_integer(const unsigned int index) const

◆ prismNodesToTetNodesDeterminer() [1/2]

void MooseMeshElementConversionUtils::prismNodesToTetNodesDeterminer ( std::vector< const Node *> &  prism_nodes,
std::vector< std::vector< unsigned int >> &  rotated_tet_face_indices,
std::vector< std::vector< const Node *>> &  tet_nodes_list 
)

For a rotated nodes that can form a PRISM6 element, create a series of four-node set that can form TET4 elements to replace the original PRISM6 element.

All the QUAD4 face of the PRISM6 element will be split by the diagonal line that involves the node with the minimum id of that face.

Parameters
prism_nodesA vector of pointers to the nodes that can form a PRISM6 element
rotated_tet_face_indicesA vector of vectors of the original face indices of the PRISM6 element corresponding to the faces of the newly created TET4 elements
tet_nodes_lista vector of vectors of pointers to the nodes that can form TET4 elements

Referenced by CutMeshByLevelSetGeneratorBase::tet4ElemCutter().

◆ prismNodesToTetNodesDeterminer() [2/2]

void MooseMeshElementConversionUtils::prismNodesToTetNodesDeterminer ( std::vector< const Node *> &  prism_nodes,
std::vector< std::vector< unsigned int >> &  rotated_tet_face_indices,
std::vector< std::vector< const Node *>> &  tet_nodes_list 
)

Definition at line 440 of file MooseMeshElementConversionUtils.C.

Referenced by prismElemSplitter().

443 {
444  // Find the node with the minimum id
445  std::vector<dof_id_type> node_ids(6);
446  for (unsigned int i = 0; i < 6; i++)
447  node_ids[i] = prism_nodes[i]->id();
448 
449  const unsigned int min_node_id_index = std::distance(
450  std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
451 
452  // Rotate the node and face indices based on the identified minimum node
453  // After the rotation, we guarantee that the minimum node is the first node (Node 0)
454  // This makes the splitting process simpler
455  std::vector<unsigned int> face_rotation;
456  std::vector<unsigned int> rotated_indices;
457  nodeRotationPRISM6(min_node_id_index, face_rotation, rotated_indices);
458  std::vector<const Node *> rotated_prism_nodes;
459  for (unsigned int i = 0; i < 6; i++)
460  rotated_prism_nodes.push_back(prism_nodes[rotated_indices[i]]);
461 
462  std::vector<const Node *> key_quad_nodes = {rotated_prism_nodes[1],
463  rotated_prism_nodes[2],
464  rotated_prism_nodes[5],
465  rotated_prism_nodes[4]};
466 
467  // Find the selection of each face's cutting direction
468  const bool diagonal_direction = quadFaceDiagonalDirection(key_quad_nodes);
469 
470  // Based on the determined splitting directions of all the faces, determine the nodes of each
471  // resulting TET4 elements after the splitting.
472  std::vector<std::vector<unsigned int>> tet_face_indices;
473  const auto tet_nodes_set = tetNodesForPrism(diagonal_direction, tet_face_indices);
474  for (const auto & tet_face_index : tet_face_indices)
475  {
476  rotated_tet_face_indices.push_back(std::vector<unsigned int>());
477  for (const auto & face_index : tet_face_index)
478  {
479  if (face_index < 5)
480  rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
481  else
482  rotated_tet_face_indices.back().push_back(5);
483  }
484  }
485 
486  for (const auto & tet_nodes : tet_nodes_set)
487  {
488  tet_nodes_list.push_back(std::vector<const Node *>());
489  for (const auto & tet_node : tet_nodes)
490  tet_nodes_list.back().push_back(rotated_prism_nodes[tet_node]);
491  }
492 }
bool quadFaceDiagonalDirection(const std::vector< const Node *> &quad_nodes)
std::vector< std::vector< unsigned int > > tetNodesForPrism(const bool diagonal_direction, std::vector< std::vector< unsigned int >> &tet_face_indices)
Creates sets of four nodes indices that can form TET4 elements to replace the original PRISM6 element...
void nodeRotationPRISM6(unsigned int min_id_index, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
Rotate a PRISM6 element nodes to ensure that the node with the minimum id is the first node...

◆ pyramidElemSplitter() [1/2]

void MooseMeshElementConversionUtils::pyramidElemSplitter ( ReplicatedMesh &  mesh,
const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
std::vector< dof_id_type > &  converted_elems_ids 
)

Split a PYRAMID5 element into two TET4 elements.

Parameters
meshThe mesh to be modified
bdry_side_listA list that contains the boundary information of the original mesh
elem_idThe id of the element to be split
converted_elems_idsa vector to record the ids of the newly created TET4 elements

◆ pyramidElemSplitter() [2/2]

void MooseMeshElementConversionUtils::pyramidElemSplitter ( ReplicatedMesh mesh,
const std::vector< libMesh::BoundaryInfo::BCTuple > &  bdry_side_list,
const dof_id_type  elem_id,
std::vector< dof_id_type > &  converted_elems_ids 
)

Definition at line 157 of file MooseMeshElementConversionUtils.C.

Referenced by convert3DMeshToAllTet4().

161 {
162  // Build boundary information of the mesh
163  BoundaryInfo & boundary_info = mesh.get_boundary_info();
164  // Create a list of sidesets involving the element to be split
165  std::vector<std::vector<boundary_id_type>> elem_side_list;
166  elementBoundaryInfoCollector(bdry_side_list, elem_id, 5, elem_side_list);
167 
168  const unsigned int n_elem_extra_ids = mesh.n_elem_integers();
169  std::vector<dof_id_type> exist_extra_ids(n_elem_extra_ids);
170  // Record all the element extra integers of the original quad element
171  for (unsigned int j = 0; j < n_elem_extra_ids; j++)
172  exist_extra_ids[j] = mesh.elem_ptr(elem_id)->get_extra_integer(j);
173 
174  std::vector<const Node *> elem_node_list = {mesh.elem_ptr(elem_id)->node_ptr(0),
175  mesh.elem_ptr(elem_id)->node_ptr(1),
176  mesh.elem_ptr(elem_id)->node_ptr(2),
177  mesh.elem_ptr(elem_id)->node_ptr(3),
178  mesh.elem_ptr(elem_id)->node_ptr(4)};
179  std::vector<std::vector<unsigned int>> rotated_tet_face_indices;
180  std::vector<std::vector<const Node *>> optimized_node_list;
181  pyramidNodesToTetNodesDeterminer(elem_node_list, rotated_tet_face_indices, optimized_node_list);
182 
183  std::vector<Elem *> elems_Tet4;
184  for (const auto i : index_range(optimized_node_list))
185  {
186  auto new_elem = std::make_unique<Tet4>();
187  new_elem->set_node(0, const_cast<Node *>(optimized_node_list[i][0]));
188  new_elem->set_node(1, const_cast<Node *>(optimized_node_list[i][1]));
189  new_elem->set_node(2, const_cast<Node *>(optimized_node_list[i][2]));
190  new_elem->set_node(3, const_cast<Node *>(optimized_node_list[i][3]));
191  new_elem->subdomain_id() = mesh.elem_ptr(elem_id)->subdomain_id();
192  elems_Tet4.push_back(mesh.add_elem(std::move(new_elem)));
193  converted_elems_ids.push_back(elems_Tet4.back()->id());
194 
195  for (unsigned int j = 0; j < 4; j++)
196  {
197  // A pyramid element has 5 faces indexed from 0 to 4
198  // a <4 value indicates that the face of the tet element corresponds to the face of the
199  // original pyramid; a =5 value means the face of the tet is an interior face of the pyramid
200  if (rotated_tet_face_indices[i][j] < 5)
201  {
202  for (const auto & side_info : elem_side_list[rotated_tet_face_indices[i][j]])
203  boundary_info.add_side(elems_Tet4.back(), j, side_info);
204  }
205  }
206  }
207 
208  // Retain element extra integers
209  for (unsigned int i = 0; i < 2; i++)
210  for (unsigned int j = 0; j < n_elem_extra_ids; j++)
211  {
212  elems_Tet4[i]->set_extra_integer(j, exist_extra_ids[j]);
213  }
214 }
unsigned int n_elem_integers() const
MeshBase & mesh
void elementBoundaryInfoCollector(const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, const unsigned short n_elem_sides, std::vector< std::vector< boundary_id_type >> &elem_side_list)
Collect the boundary information of the given element in a mesh.
const BoundaryInfo & get_boundary_info() const
virtual Elem * add_elem(Elem *e)=0
virtual const Elem * elem_ptr(const dof_id_type i) const=0
subdomain_id_type subdomain_id() const
const Node * node_ptr(const unsigned int i) const
void pyramidNodesToTetNodesDeterminer(std::vector< const Node *> &pyramid_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
auto index_range(const T &sizable)
dof_id_type get_extra_integer(const unsigned int index) const

◆ pyramidNodesToTetNodesDeterminer() [1/2]

void MooseMeshElementConversionUtils::pyramidNodesToTetNodesDeterminer ( std::vector< const Node *> &  pyramid_nodes,
std::vector< std::vector< unsigned int >> &  rotated_tet_face_indices,
std::vector< std::vector< const Node *>> &  tet_nodes_list 
)

For a rotated nodes that can form a PYRAMID5 element, create a series of four-node set that can form TET4 elements to replace the original PYRAMID5 element.

The QUAD4 face of the PYRAMID5 element will be split by the diagonal line that involves the node with the minimum id of that face.

Parameters
pyramid_nodesA vector of pointers to the nodes that can form a PYRAMID5 element
rotated_tet_face_indicesA vector of vectors of the original face indices of the PYRAMID5 element corresponding to the faces of the newly created TET4 elements
tet_nodes_lista vector of vectors of pointers to the nodes that can form TET4 elements

Referenced by CutMeshByLevelSetGeneratorBase::tet4ElemCutter().

◆ pyramidNodesToTetNodesDeterminer() [2/2]

void MooseMeshElementConversionUtils::pyramidNodesToTetNodesDeterminer ( std::vector< const Node *> &  pyramid_nodes,
std::vector< std::vector< unsigned int >> &  rotated_tet_face_indices,
std::vector< std::vector< const Node *>> &  tet_nodes_list 
)

Definition at line 533 of file MooseMeshElementConversionUtils.C.

Referenced by pyramidElemSplitter().

536 {
537  // Find the node with the minimum id, ignoring the top node
538  std::vector<dof_id_type> node_ids(4);
539  for (unsigned int i = 0; i < 4; i++)
540  node_ids[i] = pyramid_nodes[i]->id();
541 
542  const unsigned int min_node_id_index = std::distance(
543  std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
544 
545  // Rotate the node and face indices based on the identified minimum nodes
546  // After the rotation, we guarantee that the minimum node is the first node (Node 0)
547  // This makes the splitting process simpler
548  std::vector<unsigned int> face_rotation;
549  std::vector<unsigned int> rotated_indices;
550  nodeRotationPYRAMID5(min_node_id_index, face_rotation, rotated_indices);
551  std::vector<const Node *> rotated_pyramid_nodes;
552  for (unsigned int i = 0; i < 5; i++)
553  rotated_pyramid_nodes.push_back(pyramid_nodes[rotated_indices[i]]);
554 
555  // There is only one quad face in a pyramid element, so the splitting selection is binary
556  const std::vector<std::vector<unsigned int>> tet_nodes_set = {{0, 1, 2, 4}, {0, 2, 3, 4}};
557  const std::vector<std::vector<unsigned int>> tet_face_indices = {{4, 0, 1, 5}, {4, 5, 2, 3}};
558 
559  // Based on the determined splitting direction, determine the nodes of each resulting TET4
560  // elements after the splitting.
561  for (const auto & tet_face_index : tet_face_indices)
562  {
563  rotated_tet_face_indices.push_back(std::vector<unsigned int>());
564  for (const auto & face_index : tet_face_index)
565  {
566  if (face_index < 5)
567  rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
568  else
569  rotated_tet_face_indices.back().push_back(5);
570  }
571  }
572 
573  for (const auto & tet_nodes : tet_nodes_set)
574  {
575  tet_nodes_list.push_back(std::vector<const Node *>());
576  for (const auto & tet_node : tet_nodes)
577  tet_nodes_list.back().push_back(rotated_pyramid_nodes[tet_node]);
578  }
579 }
void nodeRotationPYRAMID5(unsigned int min_id_index, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
Rotate a PYRAMID5 element nodes to ensure that the node with the minimum id is the first node for the...

◆ quadFaceDiagonalDirection() [1/2]

bool MooseMeshElementConversionUtils::quadFaceDiagonalDirection ( const std::vector< const Node *> &  quad_nodes)

For a QUAD4 element, determine the direction of the diagonal line that involves the node with the minimum id of that element.

Parameters
quad_nodesA vector of pointers to the nodes that can form a QUAD4 element
Returns
a boolean value indicating the direction of the diagonal line

◆ quadFaceDiagonalDirection() [2/2]

bool MooseMeshElementConversionUtils::quadFaceDiagonalDirection ( const std::vector< const Node *> &  quad_nodes)

Definition at line 308 of file MooseMeshElementConversionUtils.C.

Referenced by prismNodesToTetNodesDeterminer(), and quadFaceDiagonalDirectionsHex().

309 {
310  const std::vector<dof_id_type> node_ids = {
311  quad_nodes[0]->id(), quad_nodes[1]->id(), quad_nodes[2]->id(), quad_nodes[3]->id()};
312  const unsigned int min_id_index = std::distance(
313  std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
314  if (min_id_index == 0 || min_id_index == 2)
315  return true;
316  else
317  return false;
318 }

◆ quadFaceDiagonalDirectionsHex() [1/2]

std::vector<bool> MooseMeshElementConversionUtils::quadFaceDiagonalDirectionsHex ( const std::vector< const Node *> &  hex_nodes)

For a HEX8 element, determine the direction of the diagonal line of each face that involves the node with the minimum id of that face.

Parameters
hex_nodesA vector of pointers to the nodes that can form a HEX8 element
Returns
a vector of boolean values indicating the direction of the diagonal line of each face

◆ quadFaceDiagonalDirectionsHex() [2/2]

std::vector<bool> MooseMeshElementConversionUtils::quadFaceDiagonalDirectionsHex ( const std::vector< const Node *> &  hex_nodes)

Definition at line 290 of file MooseMeshElementConversionUtils.C.

Referenced by hexNodesToTetNodesDeterminer().

291 {
292  // Bottom/Top; Front/Back; Right/Left
293  const std::vector<std::vector<unsigned int>> face_indices = {
294  {0, 1, 2, 3}, {4, 5, 6, 7}, {0, 1, 5, 4}, {2, 3, 7, 6}, {1, 2, 6, 5}, {3, 0, 4, 7}};
295  std::vector<bool> diagonal_directions;
296  for (const auto & face_index : face_indices)
297  {
298  std::vector<const Node *> quad_nodes = {hex_nodes[face_index[0]],
299  hex_nodes[face_index[1]],
300  hex_nodes[face_index[2]],
301  hex_nodes[face_index[3]]};
302  diagonal_directions.push_back(quadFaceDiagonalDirection(quad_nodes));
303  }
304  return diagonal_directions;
305 }
bool quadFaceDiagonalDirection(const std::vector< const Node *> &quad_nodes)

◆ tetNodesForHex()

std::vector< std::vector< unsigned int > > MooseMeshElementConversionUtils::tetNodesForHex ( const std::vector< bool >  diagonal_directions,
std::vector< std::vector< unsigned int >> &  tet_face_indices 
)

Creates sets of four nodes indices that can form TET4 elements to replace the original HEX8 element.

Parameters
diagonal_directionsA vector of boolean values indicating the direction of the diagonal line of each face; true means the diagonal line is connecting node 0 and node 2, false means the diagonal line is connecting node 1 and node 3 of that quad face
tet_face_indicesA vector of vectors of the original face indices of the HEX8 element corresponding to the faces of the newly created TET4 elements
Returns
a vector of vectors of node indices that can form TET4 elements

Definition at line 321 of file MooseMeshElementConversionUtils.C.

Referenced by hexNodesToTetNodesDeterminer().

323 {
324  const std::vector<std::vector<bool>> possible_inputs = {{true, true, true, true, true, false},
325  {true, true, true, true, false, false},
326  {true, true, true, false, true, false},
327  {true, false, true, true, true, false},
328  {true, false, true, true, false, false},
329  {true, false, true, false, true, false},
330  {true, false, true, false, false, false}};
331 
332  const unsigned int input_index = std::distance(
333  std::begin(possible_inputs),
334  std::find(std::begin(possible_inputs), std::end(possible_inputs), diagonal_directions));
335 
336  switch (input_index)
337  {
338  case 0:
339  tet_face_indices = {
340  {0, 6, 2, 6}, {1, 6, 2, 6}, {1, 6, 5, 6}, {0, 6, 3, 4}, {6, 6, 3, 6}, {6, 4, 5, 6}};
341  return {{0, 1, 2, 6}, {0, 5, 1, 6}, {0, 4, 5, 6}, {0, 2, 3, 7}, {0, 6, 2, 7}, {0, 4, 6, 7}};
342  case 1:
343  tet_face_indices = {
344  {0, 1, 2, 6}, {6, 6, 2, 6}, {6, 6, 5, 1}, {0, 6, 3, 4}, {6, 6, 3, 6}, {6, 4, 5, 6}};
345  return {{0, 1, 2, 5}, {0, 2, 6, 5}, {0, 6, 4, 5}, {0, 2, 3, 7}, {0, 6, 2, 7}, {0, 4, 6, 7}};
346  case 2:
347  tet_face_indices = {
348  {0, 6, 2, 6}, {1, 6, 2, 6}, {1, 6, 5, 6}, {4, 6, 5, 6}, {4, 6, 3, 6}, {0, 6, 3, 6}};
349  return {{0, 1, 2, 6}, {0, 5, 1, 6}, {0, 4, 5, 6}, {0, 7, 4, 6}, {0, 3, 7, 6}, {0, 2, 3, 6}};
350  case 3:
351  tet_face_indices = {
352  {4, 6, 5, 1}, {6, 6, 5, 6}, {6, 1, 2, 6}, {4, 0, 3, 6}, {6, 6, 3, 6}, {6, 6, 2, 0}};
353  return {{0, 7, 4, 5}, {0, 6, 7, 5}, {0, 1, 6, 5}, {0, 3, 7, 2}, {0, 7, 6, 2}, {0, 6, 1, 2}};
354  case 4:
355  tet_face_indices = {{0, 1, 2, 6}, {0, 6, 3, 4}, {5, 4, 6, 1}, {5, 6, 3, 2}, {6, 6, 6, 6}};
356  return {{0, 1, 2, 5}, {0, 2, 3, 7}, {4, 7, 5, 0}, {5, 7, 6, 2}, {0, 2, 7, 5}};
357  case 5:
358  tet_face_indices = {
359  {4, 6, 5, 1}, {6, 6, 5, 6}, {6, 1, 2, 6}, {2, 6, 6, 0}, {3, 6, 6, 0}, {3, 6, 6, 4}};
360  return {{0, 7, 4, 5}, {0, 6, 7, 5}, {0, 1, 6, 5}, {1, 6, 2, 0}, {2, 6, 3, 0}, {3, 6, 7, 0}};
361  case 6:
362  tet_face_indices = {
363  {1, 4, 5, 6}, {6, 6, 5, 6}, {6, 6, 3, 4}, {1, 6, 2, 0}, {6, 6, 2, 6}, {6, 0, 3, 6}};
364  return {{0, 4, 5, 7}, {0, 5, 6, 7}, {0, 6, 3, 7}, {0, 5, 1, 2}, {0, 6, 5, 2}, {0, 3, 6, 2}};
365  default:
366  mooseError("Unexpected input.");
367  }
368 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302

◆ tetNodesForPrism()

std::vector< std::vector< unsigned int > > MooseMeshElementConversionUtils::tetNodesForPrism ( const bool  diagonal_direction,
std::vector< std::vector< unsigned int >> &  tet_face_indices 
)

Creates sets of four nodes indices that can form TET4 elements to replace the original PRISM6 element.

Parameters
diagonal_directionA boolean value indicating the direction of the diagonal line of Face 2
tet_face_indicesA vector of vectors of the original face indices of the PRISM6 element corresponding to the faces of the newly created TET4 elements
Returns
a vector of vectors of node indices that can form TET4 elements

Definition at line 495 of file MooseMeshElementConversionUtils.C.

Referenced by prismNodesToTetNodesDeterminer().

497 {
498 
499  if (diagonal_direction)
500  {
501  tet_face_indices = {{4, 3, 5, 1}, {2, 1, 5, 5}, {2, 5, 3, 0}};
502  return {{3, 5, 4, 0}, {1, 4, 5, 0}, {1, 5, 2, 0}};
503  }
504  else
505  {
506  tet_face_indices = {{4, 3, 5, 1}, {2, 1, 5, 0}, {2, 5, 5, 3}};
507  return {{3, 5, 4, 0}, {1, 4, 2, 0}, {2, 4, 5, 0}};
508  }
509 }