LCOV - code coverage report
Current view: top level - src/meshgenerators - SideSetsFromBoundingBoxGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31706 (f8ed4a) with base bb0a08 Lines: 82 86 95.3 %
Date: 2025-11-03 17:23:24 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 "SideSetsFromBoundingBoxGenerator.h"
      11             : #include "Conversion.h"
      12             : #include "MooseTypes.h"
      13             : #include "MooseMeshUtils.h"
      14             : #include "CastUniquePointer.h"
      15             : #include "MooseUtils.h"
      16             : 
      17             : #include "libmesh/distributed_mesh.h"
      18             : #include "libmesh/elem.h"
      19             : 
      20             : #include <typeinfo>
      21             : 
      22             : registerMooseObject("MooseApp", SideSetsFromBoundingBoxGenerator);
      23             : 
      24             : InputParameters
      25       15357 : SideSetsFromBoundingBoxGenerator::validParams()
      26             : {
      27       15357 :   InputParameters params = SideSetsGeneratorBase::validParams();
      28             : 
      29       30714 :   params.addClassDescription("Defines new sidesets using currently-defined sideset IDs inside or "
      30             :                              "outside of a bounding box.");
      31             : 
      32       61428 :   MooseEnum location("INSIDE OUTSIDE", "INSIDE");
      33             : 
      34       61428 :   params.addRequiredParam<RealVectorValue>(
      35             :       "bottom_left", "The bottom left point (in x,y,z with spaces in-between).");
      36       61428 :   params.addRequiredParam<RealVectorValue>(
      37             :       "top_right", "The bottom left point (in x,y,z with spaces in-between).");
      38       92142 :   params.addDeprecatedParam<subdomain_id_type>(
      39             :       "block_id",
      40             :       "Subdomain id to set for inside/outside the bounding box",
      41             :       "The parameter 'block_id' is not used.");
      42       61428 :   params.addRequiredParam<BoundaryName>(
      43             :       "boundary_new", "Boundary on specified block within the bounding box to assign");
      44       46071 :   params.addParam<bool>("boundary_id_overlap",
      45       30714 :                         false,
      46             :                         "Set to true if boundaries need to overlap on sideset to be detected.");
      47       61428 :   params.addParam<MooseEnum>(
      48             :       "location", location, "Control of where the subdomain id is to be set");
      49             : 
      50             :   // TODO: Implement each of these in the generate() routine using utilities in SidesetGeneratorBase
      51       30714 :   params.suppressParameter<bool>("fixed_normal");
      52       15357 :   params.suppressParameter<std::vector<BoundaryName>>("new_boundary");
      53             : 
      54       30714 :   return params;
      55       15357 : }
      56             : 
      57         245 : SideSetsFromBoundingBoxGenerator::SideSetsFromBoundingBoxGenerator(
      58         245 :     const InputParameters & parameters)
      59             :   : SideSetsGeneratorBase(parameters),
      60         245 :     _location(parameters.get<MooseEnum>("location")),
      61         245 :     _bounding_box(MooseUtils::buildBoundingBox(parameters.get<RealVectorValue>("bottom_left"),
      62         245 :                                                parameters.get<RealVectorValue>("top_right"))),
      63         735 :     _boundary_id_overlap(parameters.get<bool>("boundary_id_overlap"))
      64             : {
      65         245 :   if (_boundary_id_overlap)
      66             :   {
      67             :     const std::vector<std::string> incompatible_params = {"normal",
      68             :                                                           "replace",
      69             :                                                           "include_only_external_sides",
      70             :                                                           "included_subdomains",
      71         144 :                                                           "included_neighbors"};
      72         432 :     for (const auto & param_name : incompatible_params)
      73         360 :       if (isParamSetByUser(param_name))
      74           0 :         paramError(param_name, "Parameter should not be used with boundary_id_overlap = true.");
      75          72 :   }
      76             : 
      77         245 :   _boundary_names.push_back(parameters.get<BoundaryName>("boundary_new"));
      78         245 : }
      79             : 
      80             : std::unique_ptr<MeshBase>
      81         242 : SideSetsFromBoundingBoxGenerator::generate()
      82             : {
      83         242 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      84         242 :   if (!mesh->is_replicated())
      85           0 :     mooseError("SideSetsFromBoundingBoxGenerator is not implemented for distributed meshes");
      86             : 
      87             :   // construct the FE object so we can compute normals of faces
      88         242 :   setup(*mesh);
      89             : 
      90             :   // Get a reference to our BoundaryInfo object for later use
      91         242 :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
      92         242 :   boundary_info.build_node_list_from_side_list();
      93             : 
      94         242 :   bool found_element = false;
      95         242 :   bool found_side_sets = false;
      96         242 :   const bool inside = (_location == "INSIDE");
      97             : 
      98             :   // Attempt to get the new boundary id from the name
      99         242 :   auto boundary_id_new = MooseMeshUtils::getBoundaryID(_boundary_names[0], *mesh);
     100             : 
     101             :   // If the new boundary id is not valid, make it instead
     102         242 :   if (boundary_id_new == Moose::INVALID_BOUNDARY_ID)
     103             :   {
     104           9 :     boundary_id_new = MooseMeshUtils::getNextFreeBoundaryID(*mesh);
     105             : 
     106             :     // Write the name alias of the boundary id to the mesh boundary info
     107           9 :     boundary_info.sideset_name(boundary_id_new) = _boundary_names[0];
     108           9 :     boundary_info.nodeset_name(boundary_id_new) = _boundary_names[0];
     109             :   }
     110             : 
     111         242 :   if (!_boundary_id_overlap)
     112             :   {
     113             :     // Request to compute normal vectors
     114         173 :     const std::vector<Point> & face_normals = _fe_face->get_normals();
     115             : 
     116             :     // Loop over the elements
     117       89295 :     for (const auto & elem : mesh->active_element_ptr_range())
     118             :     {
     119             :       // boolean if element centroid is in bounding box
     120       44561 :       bool contains = _bounding_box.contains_point(elem->vertex_average());
     121             : 
     122             :       // check if active elements are found either in or out of the bounding box, apropos "inside"
     123       44561 :       if (contains == inside)
     124             :       {
     125        3711 :         found_element = true;
     126             :         // loop over sides of elements within bounding box
     127       21489 :         for (const auto & side : make_range(elem->n_sides()))
     128             :         {
     129       17778 :           _fe_face->reinit(elem, side);
     130             :           // We'll just use the normal of the first qp
     131       17778 :           const Point face_normal = face_normals[0];
     132             : 
     133       17778 :           if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
     134             :           {
     135             :             // assign new boundary value to boundary which meets meshmodifier criteria
     136         971 :             if (_replace)
     137           0 :               boundary_info.remove_side(elem, side);
     138         971 :             boundary_info.add_side(elem, side, boundary_id_new);
     139         971 :             found_side_sets = true;
     140             :           }
     141             :         }
     142             :       }
     143         173 :     }
     144         173 :     if (!found_element && inside)
     145           4 :       mooseError("No elements found within the bounding box");
     146             : 
     147         169 :     if (!found_element && !inside)
     148           0 :       mooseError("No elements found outside the bounding box");
     149             : 
     150         169 :     if (!found_side_sets)
     151           4 :       mooseError("No side sets found on active elements within the bounding box");
     152             :   }
     153             : 
     154          69 :   else if (_boundary_id_overlap)
     155             :   {
     156          69 :     if (_included_boundary_ids.size() < 2)
     157           8 :       mooseError("boundary_id_old out of bounds: ",
     158           4 :                  _included_boundary_ids.size(),
     159             :                  " Must be 2 boundary inputs or more.");
     160             : 
     161          65 :     bool found_node = false;
     162             : 
     163             :     // Loop over the elements and assign node set id to nodes within the bounding box
     164      163415 :     for (auto node = mesh->active_nodes_begin(); node != mesh->active_nodes_end(); ++node)
     165             :     {
     166             :       // check if nodes are inside of bounding box
     167       81675 :       if (_bounding_box.contains_point(**node) == inside)
     168             :       {
     169             :         // read out boundary ids for nodes
     170       81319 :         std::vector<boundary_id_type> node_boundary_ids;
     171       81319 :         boundary_info.boundary_ids(*node, node_boundary_ids);
     172             : 
     173             :         // sort boundary ids on node and sort boundary ids provided in input file
     174       81319 :         std::sort(node_boundary_ids.begin(), node_boundary_ids.end());
     175       81319 :         std::sort(_included_boundary_ids.begin(), _included_boundary_ids.end());
     176             : 
     177             :         // check if input boundary ids are all contained in the node
     178             :         // if true, write new boundary id on respective node
     179       81319 :         if (std::includes(node_boundary_ids.begin(),
     180             :                           node_boundary_ids.end(),
     181             :                           _included_boundary_ids.begin(),
     182             :                           _included_boundary_ids.end()))
     183             :         {
     184         437 :           boundary_info.add_node(*node, boundary_id_new);
     185         437 :           found_node = true;
     186             :         }
     187       81319 :       }
     188          65 :     }
     189             : 
     190          65 :     if (!found_node)
     191           8 :       mooseError("No nodes found within the bounding box");
     192             :   }
     193             : 
     194         222 :   mesh->set_isnt_prepared();
     195         444 :   return dynamic_pointer_cast<MeshBase>(mesh);
     196         222 : }

Generated by: LCOV version 1.14