LCOV - code coverage report
Current view: top level - src/meshgenerators - OrientSurfaceMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 43 46 93.5 %
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 "OrientSurfaceMeshGenerator.h"
      11             : #include "Parser.h"
      12             : #include "InputParameters.h"
      13             : #include "CastUniquePointer.h"
      14             : 
      15             : #include "libmesh/fe_base.h"
      16             : #include "libmesh/mesh_generation.h"
      17             : #include "libmesh/mesh.h"
      18             : #include "libmesh/string_to_enum.h"
      19             : #include "libmesh/quadrature_gauss.h"
      20             : #include "libmesh/point_locator_base.h"
      21             : #include "libmesh/distributed_mesh.h"
      22             : #include "libmesh/elem.h"
      23             : 
      24             : #include <typeinfo>
      25             : 
      26             : registerMooseObject("MooseApp", OrientSurfaceMeshGenerator);
      27             : 
      28             : InputParameters
      29        3117 : OrientSurfaceMeshGenerator::validParams()
      30             : {
      31        3117 :   InputParameters params = SurfaceMeshGeneratorBase::validParams();
      32             : 
      33             :   // NOTE: libmesh tetrahedralization code actually has a clever heuristic
      34             :   // to re-orient elements starting from the known orientation of the "bottom-most"
      35             :   // surface element. We could import that logic here, once we identify and separate connected
      36             :   // (contiguous) components of the mesh.
      37             : 
      38             :   // Which elements to apply the change on
      39       12468 :   params.setDocString(
      40             :       "included_subdomains",
      41             :       "Subdomain names or ids for the elements that may have their normal modified.");
      42             : 
      43             :   // How to set the normal
      44       18702 :   params.renameParam("normal",
      45             :                      "normal_to_align_with",
      46             :                      "Direction vector that element normals should be pointing in the same "
      47             :                      "direction as (dot product > 0)");
      48       12468 :   params.addParam<std::vector<dof_id_type>>(
      49             :       "element_ids_to_flood_from",
      50             :       "IDs of elements to start flooding and changing the subdomains from");
      51             : 
      52             :   // This mesh generator does not modify the subdomains
      53        6234 :   params.suppressParameter<std::vector<SubdomainName>>("new_subdomain");
      54             :   // This mesh generator is specifically intended to flip normals
      55        6234 :   params.set<bool>("flip_inverted_normals") = true;
      56        6234 :   params.suppressParameter<bool>("flip_inverted_normals");
      57        6234 :   params.set<bool>("consider_flipped_normals") = true;
      58        6234 :   params.set<bool>("_using_normal") = true;
      59             : 
      60        3117 :   params.addClassDescription("Change the orientation of (part of) the surface mesh.");
      61        3117 :   return params;
      62           0 : }
      63             : 
      64          28 : OrientSurfaceMeshGenerator::OrientSurfaceMeshGenerator(const InputParameters & parameters)
      65          28 :   : SurfaceMeshGeneratorBase(parameters), _num_flipped(0)
      66             : {
      67         120 :   if (!isParamValid("element_ids_to_flood_from") && !isParamSetByUser("normal_to_align_with"))
      68           0 :     paramError("normal_to_align_with",
      69             :                "Either a 'normal_to_align_with' or 'element_ids_to_flood_from' must be specified "
      70             :                "to select the behavior of this mesh generator.");
      71          28 : }
      72             : 
      73             : std::unique_ptr<MeshBase>
      74          28 : OrientSurfaceMeshGenerator::generate()
      75             : {
      76          28 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      77          28 :   setup(*mesh);
      78             : 
      79          28 :   auto & binfo = mesh->get_boundary_info();
      80          56 :   bool normal_is_input = isParamSetByUser("normal_to_align_with");
      81             : 
      82          84 :   if (!isParamValid("element_ids_to_flood_from"))
      83             :     // We'll need to loop over all of the elements to adjust normals with the fixed normal option
      84         250 :     for (auto & elem : mesh->element_ptr_range())
      85             :     {
      86             :       // Nothing to do with edges or 3D elements
      87         232 :       if (elem->dim() != 2)
      88         160 :         continue;
      89             : 
      90             :       // Check if element should be used to paint from
      91         424 :       if (_included_subdomain_ids.size() &&
      92         192 :           std::find(_included_subdomain_ids.begin(),
      93             :                     _included_subdomain_ids.end(),
      94         616 :                     elem->subdomain_id()) == _included_subdomain_ids.end())
      95         160 :         continue;
      96             : 
      97             :       // Compute the normal
      98          72 :       const auto normal = get2DElemNormal(elem);
      99             : 
     100          72 :       if (normal * _normal < 0)
     101             :       {
     102          72 :         elem->flip(&binfo);
     103          72 :         _num_flipped++;
     104             :       }
     105          18 :     }
     106             :   else
     107             :     // We'll flood and re-adjust orientations starting from a few given elements
     108             :     // NOTE: user's responsibility to make sure these surface elements' orientations are consistent
     109          40 :     for (const auto eid : getParam<std::vector<dof_id_type>>("element_ids_to_flood_from"))
     110             :     {
     111          10 :       auto elem = mesh->elem_ptr(eid);
     112             : 
     113             :       // Nothing to do with edges or 3D elements
     114          10 :       if (elem->dim() != 2)
     115           0 :         continue;
     116             : 
     117             :       // Compute the normal
     118          10 :       const auto normal = normal_is_input ? _normal : get2DElemNormal(elem);
     119             : 
     120          10 :       flood(elem, normal, *elem, elem->subdomain_id(), *mesh);
     121             :     }
     122             : 
     123          28 :   if (_num_flipped)
     124          28 :     _console << "Flipped the orientation of " << _num_flipped << " surface elements." << std::endl;
     125             : 
     126          56 :   return dynamic_pointer_cast<MeshBase>(mesh);
     127          28 : }

Generated by: LCOV version 1.14