LCOV - code coverage report
Current view: top level - src/meshgenerators - SideSetsFromNormalsGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 44 48 91.7 %
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 "SideSetsFromNormalsGenerator.h"
      11             : #include "Parser.h"
      12             : #include "InputParameters.h"
      13             : #include "MeshTraversingUtils.h"
      14             : #include "MooseMeshUtils.h"
      15             : #include "CastUniquePointer.h"
      16             : #include "MooseApp.h"
      17             : #include "MeshGeneratorSystem.h"
      18             : 
      19             : #include "libmesh/mesh_generation.h"
      20             : #include "libmesh/mesh.h"
      21             : #include "libmesh/string_to_enum.h"
      22             : #include "libmesh/quadrature_gauss.h"
      23             : #include "libmesh/point_locator_base.h"
      24             : #include "libmesh/distributed_mesh.h"
      25             : #include "libmesh/elem.h"
      26             : #include "libmesh/fe_base.h"
      27             : 
      28             : #include <typeinfo>
      29             : 
      30             : registerMooseObject("MooseApp", SideSetsFromNormalsGenerator);
      31             : 
      32             : InputParameters
      33        3155 : SideSetsFromNormalsGenerator::validParams()
      34             : {
      35        3155 :   InputParameters params = SideSetsGeneratorBase::validParams();
      36             : 
      37        6310 :   params.addClassDescription(
      38             :       "Adds a new named sideset to the mesh for all faces matching the specified normal.");
      39        9465 :   params.addRequiredParam<std::vector<Point>>(
      40             :       "normals", "A list of normals for which to start painting sidesets");
      41             : 
      42             :   // We want to use a different normal_tol for this generator than from the base class to preserve
      43             :   // old behavior.
      44        9465 :   params.setParameters("normal_tol", 1e-5);
      45             : 
      46             :   // We are using 'normals' instead
      47        3155 :   params.suppressParameter<Point>("normal");
      48             : 
      49             :   // It doesn't make sense to allow internal sides for this side set generator.
      50        9465 :   params.setParameters("include_only_external_sides", true);
      51        3155 :   params.suppressParameter<bool>("include_only_external_sides");
      52             : 
      53        3155 :   return params;
      54           0 : }
      55             : 
      56          47 : SideSetsFromNormalsGenerator::SideSetsFromNormalsGenerator(const InputParameters & parameters)
      57             :   : SideSetsGeneratorBase(parameters),
      58          47 :     _normals(getParam<std::vector<Point>>("normals")),
      59          47 :     _boundary_to_normal_map(
      60         141 :         declareMeshProperty<std::map<BoundaryID, RealVectorValue>>("boundary_normals"))
      61             : {
      62             :   // Get the BoundaryIDs from the mesh
      63          47 :   if (_normals.size() != _boundary_names.size())
      64           0 :     mooseError("normal list and boundary list are not the same length");
      65             : 
      66             :   // Make sure that the normals are normalized
      67         155 :   for (auto & normal : _normals)
      68             :   {
      69         108 :     if (normal.norm() < 1e-5)
      70           0 :       mooseError("Normal is zero");
      71         108 :     normal /= normal.norm();
      72             :   }
      73             : 
      74          47 :   _using_normal = true;
      75          47 : }
      76             : 
      77             : std::unique_ptr<MeshBase>
      78          46 : SideSetsFromNormalsGenerator::generate()
      79             : {
      80          46 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      81          46 :   if (!_fixed_normal && !mesh->is_replicated())
      82           0 :     mooseError("SideSetsFromNormalsGenerator is not implemented for distributed meshes when "
      83             :                "fixed_normal = false");
      84             : 
      85             :   std::vector<BoundaryID> boundary_ids =
      86          46 :       MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true);
      87             : 
      88          46 :   setup(*mesh);
      89             : 
      90          46 :   _visited.clear();
      91             : 
      92             :   // Request to compute normal vectors
      93          46 :   const std::vector<Point> & face_normals = _fe_face->get_normals();
      94             : 
      95             :   // We'll need to loop over all of the elements to find ones that match this normal.
      96             :   // We can't rely on flood catching them all here...
      97       70222 :   for (const auto & elem : mesh->element_ptr_range())
      98      226164 :     for (const auto side : make_range(elem->n_sides()))
      99             :     {
     100      191076 :       if (elem->neighbor_ptr(side))
     101      174500 :         continue;
     102             : 
     103       16576 :       _fe_face->reinit(elem, side);
     104             : 
     105             :       // We'll just use the normal of the first qp
     106       16576 :       const Point & face_normal = face_normals[0];
     107             : 
     108       56392 :       for (const auto i : make_range(boundary_ids.size()))
     109             :       {
     110       39816 :         if (MeshTraversingUtils::normalsWithinTol(_normals[i], face_normal, _normal_tol))
     111        5886 :           flood(elem, _normals[i], boundary_ids[i], *mesh);
     112             :       }
     113          46 :     }
     114             : 
     115          46 :   finalize();
     116             : 
     117          46 :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
     118         152 :   for (const auto i : make_range(boundary_ids.size()))
     119             :   {
     120         106 :     boundary_info.sideset_name(boundary_ids[i]) = _boundary_names[i];
     121         106 :     _boundary_to_normal_map[boundary_ids[i]] = _normals[i];
     122             :   }
     123             : 
     124          46 :   mesh->unset_is_prepared();
     125          92 :   return dynamic_pointer_cast<MeshBase>(mesh);
     126          46 : }

Generated by: LCOV version 1.14