LCOV - code coverage report
Current view: top level - src/meshgenerators - ElementGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 71 73 97.3 %
Date: 2026-05-29 20:35:17 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14