Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "ElementGenerator.h" 11 : #include "CastUniquePointer.h" 12 : 13 : #include "libmesh/replicated_mesh.h" 14 : #include "libmesh/string_to_enum.h" 15 : #include "libmesh/face_c0polygon.h" 16 : #include "libmesh/cell_c0polyhedron.h" 17 : 18 : #include "MooseEnum.h" 19 : 20 : registerMooseObject("MooseApp", ElementGenerator); 21 : 22 : InputParameters 23 4591 : ElementGenerator::validParams() 24 : { 25 4591 : InputParameters params = MeshGenerator::validParams(); 26 : 27 9182 : MooseEnum elem_types(LIST_GEOM_ELEM); // no default 28 : 29 18364 : params.addParam<MeshGeneratorName>("input", "Optional input mesh to add the elements to"); 30 : 31 : // Element shape and location 32 18364 : params.addRequiredParam<std::vector<Point>>("nodal_positions", 33 : "The x,y,z positions of the nodes"); 34 18364 : params.addParam<std::vector<dof_id_type>>("element_connectivity", 35 : "List of nodes to use for each element."); 36 18364 : params.addParam<std::vector<std::vector<dof_id_type>>>( 37 : "polygon_faces_connectivity", 38 : "List of nodes to use for each face of the polygon faces of the polyhedron. Only use this " 39 : "parameter for a polyhedron 'elem_type'"); 40 18364 : params.addRequiredParam<MooseEnum>( 41 : "elem_type", elem_types, "The type of element from libMesh to generate"); 42 : 43 : // Subdomain 44 18364 : params.addParam<SubdomainName>("subdomain_name", "Subdomain name"); 45 18364 : params.addParam<SubdomainID>("subdomain_id", 0, "Subdomain id"); 46 : // Sidesets 47 13773 : params.addParam<bool>("create_sidesets", 48 9182 : false, 49 : "Create separate sidesets for each side. " 50 : "The side index is used as the boundary ID for each sideset."); 51 : 52 4591 : params.addClassDescription("Generates individual elements given a list of nodal positions."); 53 : 54 9182 : return params; 55 4591 : } 56 : 57 760 : ElementGenerator::ElementGenerator(const InputParameters & parameters) 58 : : MeshGenerator(parameters), 59 760 : _input(getMesh("input", /* allow_invalid = */ true)), 60 1520 : _nodal_positions(getParam<std::vector<Point>>("nodal_positions")), 61 1670 : _element_connectivity( 62 2280 : isParamValid("polygon_faces_connectivity") 63 760 : ? getParam<std::vector<std::vector<dof_id_type>>>("polygon_faces_connectivity") 64 : : std::vector<std::vector<dof_id_type>>( 65 1980 : 1, getParam<std::vector<dof_id_type>>("element_connectivity"))), 66 2280 : _elem_type(getParam<MooseEnum>("elem_type")) 67 : { 68 760 : if (_elem_type != "C0POLYHEDRON" && _element_connectivity.size() != 1) 69 0 : paramError("element_connectivity", "Must be of size 1 for all element types but polyhedra"); 70 2580 : if (isParamValid("polygon_faces_connectivity") && isParamValid("element_connectivity")) 71 0 : paramError("element_connectivity", 72 : "Either 'element_connectivity' or 'polygon_faces_connectivity' must be specified"); 73 760 : } 74 : 75 : std::unique_ptr<Elem> 76 513 : ElementGenerator::getElemType(const std::string & type) 77 : { 78 513 : return Elem::build(Utility::string_to_enum<ElemType>(type)); 79 : } 80 : 81 : std::unique_ptr<MeshBase> 82 673 : ElementGenerator::generate() 83 : { 84 673 : std::unique_ptr<MeshBase> mesh = std::move(_input); 85 : 86 : // If there was no input mesh then let's just make a new one 87 673 : if (!mesh) 88 540 : mesh = buildMeshBaseObject(); 89 : 90 : // For polyhedra we need to know the side elements first 91 : // For polygons we need to specify the number of sides/nodes 92 673 : std::unique_ptr<Elem> elem; 93 673 : if (_elem_type != "C0POLYGON" && _elem_type != "C0POLYHEDRON") 94 513 : elem = getElemType(_elem_type); 95 160 : else if (_elem_type == "C0POLYGON") 96 10 : elem = std::make_unique<libMesh::C0Polygon>(_nodal_positions.size()); 97 : 98 673 : std::vector<Node *> nodes; 99 673 : nodes.reserve(_nodal_positions.size()); 100 : 101 : // Add all the nodes to the mesh, keep pointers to them 102 5651 : for (const auto & point : _nodal_positions) 103 4978 : nodes.push_back(mesh->add_point(point)); 104 : 105 : // Set the nodes in the element 106 673 : if (_elem_type != "C0POLYHEDRON") 107 : { 108 523 : auto n = elem->n_nodes(); 109 3461 : for (const auto j : make_range(n)) 110 2938 : elem->set_node(j, nodes[_element_connectivity[0][j]]); 111 : } 112 : else 113 : { 114 150 : const auto n_sides = _element_connectivity.size(); 115 : // Create all the polygon sides 116 150 : std::vector<std::shared_ptr<libMesh::Polygon>> sides; 117 150 : sides.reserve(n_sides); 118 1800 : for (const auto i : make_range(n_sides)) 119 : { 120 1650 : auto side = std::make_shared<libMesh::C0Polygon>(_element_connectivity[i].size()); 121 8430 : for (const auto i_node : index_range(_element_connectivity[i])) 122 6780 : side->set_node(i_node, nodes[_element_connectivity[i][i_node]]); 123 1650 : sides.push_back(side); 124 1650 : } 125 : 126 : // With the polygons we can create the polyhedron 127 150 : std::unique_ptr<libMesh::Node> mid_elem_node; 128 150 : elem = std::make_unique<libMesh::C0Polyhedron>(sides, mid_elem_node); 129 150 : if (mid_elem_node) 130 130 : mesh->add_node(std::move(mid_elem_node)); 131 150 : } 132 : 133 : // Subdomain information 134 1346 : elem->subdomain_id() = getParam<SubdomainID>("subdomain_id"); 135 2019 : if (isParamValid("subdomain_name")) 136 510 : mesh->subdomain_name(getParam<SubdomainID>("subdomain_id")) = 137 850 : getParam<SubdomainName>("subdomain_name"); 138 : 139 673 : mesh->set_mesh_dimension(std::max((unsigned int)elem->dim(), mesh->mesh_dimension())); 140 : 141 2019 : if (getParam<bool>("create_sidesets")) 142 1864 : for (const auto i_side : make_range(elem->n_sides())) 143 1582 : mesh->get_boundary_info().add_side(elem.get(), i_side, i_side); 144 : 145 673 : mesh->add_elem(std::move(elem)); 146 : // We just added an element 147 673 : mesh->unset_is_prepared(); 148 : 149 1346 : return dynamic_pointer_cast<MeshBase>(mesh); 150 673 : }