LCOV - code coverage report
Current view: top level - src/meshgenerators - SideSetsFromPointsGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 54 56 96.4 %
Date: 2026-05-29 20:35:17 Functions: 3 3 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 "SideSetsFromPointsGenerator.h"
      11             : #include "Parser.h"
      12             : #include "InputParameters.h"
      13             : #include "MeshTraversingUtils.h"
      14             : #include "MooseMeshUtils.h"
      15             : #include "CastUniquePointer.h"
      16             : 
      17             : #include "libmesh/mesh.h"
      18             : #include "libmesh/mesh_generation.h"
      19             : #include "libmesh/mesh_serializer.h"
      20             : #include "libmesh/string_to_enum.h"
      21             : #include "libmesh/quadrature_gauss.h"
      22             : #include "libmesh/point_locator_base.h"
      23             : #include "libmesh/enum_point_locator_type.h"
      24             : #include "libmesh/distributed_mesh.h"
      25             : #include "libmesh/elem.h"
      26             : #include "libmesh/fe_base.h"
      27             : #include "libmesh/mesh_tools.h"
      28             : 
      29             : #include <typeinfo>
      30             : 
      31             : registerMooseObject("MooseApp", SideSetsFromPointsGenerator);
      32             : 
      33             : InputParameters
      34        3101 : SideSetsFromPointsGenerator::validParams()
      35             : {
      36        3101 :   InputParameters params = SideSetsGeneratorBase::validParams();
      37             : 
      38        6202 :   params.addClassDescription("Adds a new sideset starting at the specified point containing all "
      39             :                              "connected element faces with the same normal.");
      40       12404 :   params.addRequiredParam<std::vector<Point>>(
      41             :       "points", "A list of points from which to start painting sidesets");
      42             : 
      43        6202 :   params.suppressParameter<Point>("normal");
      44        3101 :   params.suppressParameter<Real>("normal_tol");
      45             : 
      46             :   // It doesn't make sense to allow internal sides for this side set generator.
      47        9303 :   params.setParameters("include_only_external_sides", true);
      48        3101 :   params.suppressParameter<bool>("include_only_external_sides");
      49             : 
      50        3101 :   return params;
      51           0 : }
      52             : 
      53          20 : SideSetsFromPointsGenerator::SideSetsFromPointsGenerator(const InputParameters & parameters)
      54          40 :   : SideSetsGeneratorBase(parameters), _points(getParam<std::vector<Point>>("points"))
      55             : {
      56          20 :   if (_points.size() != _boundary_names.size())
      57           0 :     mooseError("point list and boundary list are not the same length");
      58          20 :   _using_normal = true;
      59          20 : }
      60             : 
      61             : std::unique_ptr<MeshBase>
      62          19 : SideSetsFromPointsGenerator::generate()
      63             : {
      64          19 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      65             : 
      66             :   // Our flood fill doesn't do any communication, so it requires a
      67             :   // serialized mesh
      68          19 :   libMesh::MeshSerializer serial(*mesh);
      69             : 
      70             :   // Get the BoundaryIDs from the mesh
      71             :   std::vector<BoundaryID> boundary_ids =
      72          19 :       MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true);
      73             : 
      74          19 :   setup(*mesh);
      75             : 
      76          19 :   _visited.clear();
      77             : 
      78             :   std::unique_ptr<libMesh::PointLocatorBase> pl =
      79          19 :       libMesh::PointLocatorBase::build(libMesh::TREE, *mesh);
      80             : 
      81          75 :   for (const auto i : index_range(boundary_ids))
      82             :   {
      83          59 :     std::set<const Elem *> candidate_elements;
      84          59 :     (*pl)(_points[i], candidate_elements);
      85             : 
      86          59 :     const Elem * elem_to_flood = nullptr;
      87          59 :     Point normal_to_flood;
      88             : 
      89         155 :     for (const Elem * elem : candidate_elements)
      90         550 :       for (const auto side : make_range(elem->n_sides()))
      91             :       {
      92         454 :         if (elem->neighbor_ptr(side))
      93         352 :           continue;
      94             : 
      95             :         // See if this point is on this side
      96         102 :         std::unique_ptr<const Elem> elem_side = elem->side_ptr(side);
      97             : 
      98         102 :         if (elem_side->contains_point(_points[i]))
      99             :         {
     100             :           // This is a good side to paint our sideset with.
     101             :           // Get the normal.
     102         102 :           const std::vector<Point> & normals = _fe_face->get_normals();
     103         102 :           _fe_face->reinit(elem, side);
     104             : 
     105             :           // If we *already* found a good but different side to paint
     106             :           // our sideset with, we've got an ambiguity here.
     107         145 :           if (elem_to_flood &&
     108          43 :               (!MeshTraversingUtils::normalsWithinTol(normal_to_flood, normals[0], _normal_tol) ||
     109          40 :                elem_to_flood->which_neighbor_am_i(elem) == libMesh::invalid_uint))
     110           3 :             mooseError("Two ambiguous potential sideset sources found for boundary `",
     111           3 :                        _boundary_names[i],
     112             :                        "' at ",
     113           3 :                        _points[i],
     114             :                        ":\nElement ",
     115           3 :                        elem_to_flood->id(),
     116             :                        " normal ",
     117             :                        normal_to_flood,
     118             :                        " and\n",
     119             :                        ":\nElement ",
     120           3 :                        elem->id(),
     121             :                        " normal ",
     122           3 :                        normals[0]);
     123             : 
     124          99 :           elem_to_flood = elem;
     125          99 :           normal_to_flood = normals[0];
     126             :           // Don't just flood here; keep looking for possible ambiguity
     127             :         }
     128          99 :       }
     129             : 
     130          56 :     flood(elem_to_flood, normal_to_flood, boundary_ids[i], *mesh);
     131          56 :   }
     132             : 
     133             : #ifdef DEBUG
     134             :   MeshTools::libmesh_assert_valid_boundary_ids(*mesh);
     135             : #endif
     136             : 
     137          16 :   finalize();
     138             : 
     139          72 :   for (const auto i : index_range(boundary_ids))
     140          56 :     mesh->get_boundary_info().sideset_name(boundary_ids[i]) = _boundary_names[i];
     141             : 
     142          16 :   mesh->unset_is_prepared();
     143          32 :   return dynamic_pointer_cast<MeshBase>(mesh);
     144          16 : }

Generated by: LCOV version 1.14