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

Generated by: LCOV version 1.14