LCOV - code coverage report
Current view: top level - src/meshgenerators - SideSetsBetweenSubdomainsGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33390 (250e9c) with base 846a5c Lines: 86 89 96.6 %
Date: 2026-07-31 18:15:22 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 "SideSetsBetweenSubdomainsGenerator.h"
      11             : #include "InputParameters.h"
      12             : #include "MooseTypes.h"
      13             : #include "MeshTraversingUtils.h"
      14             : #include "MooseMeshUtils.h"
      15             : #include "CastUniquePointer.h"
      16             : 
      17             : #include "libmesh/remote_elem.h"
      18             : 
      19             : registerMooseObject("MooseApp", SideSetsBetweenSubdomainsGenerator);
      20             : 
      21             : InputParameters
      22        9787 : SideSetsBetweenSubdomainsGenerator::validParams()
      23             : {
      24        9787 :   InputParameters params = SideSetsGeneratorBase::validParams();
      25             : 
      26       58722 :   params.renameParam("included_subdomains",
      27             :                      "primary_block",
      28             :                      "The primary set of blocks for which to draw a sideset between");
      29       19574 :   params.makeParamRequired<std::vector<SubdomainName>>("primary_block");
      30       58722 :   params.renameParam("included_neighbors",
      31             :                      "paired_block",
      32             :                      "The paired set of blocks for which to draw a sideset between");
      33       19574 :   params.makeParamRequired<std::vector<SubdomainName>>("paired_block");
      34       19574 :   params.addClassDescription("MeshGenerator that creates a sideset composed of the nodes located "
      35             :                              "between two or more subdomains.");
      36             : 
      37             :   // TODO: Implement each of these in the generate() routine using utilities in SidesetGeneratorBase
      38       19574 :   params.suppressParameter<bool>("fixed_normal");
      39        9787 :   params.suppressParameter<bool>("include_only_external_sides");
      40             : 
      41        9787 :   return params;
      42           0 : }
      43             : 
      44        3346 : SideSetsBetweenSubdomainsGenerator::SideSetsBetweenSubdomainsGenerator(
      45        3346 :     const InputParameters & parameters)
      46        3346 :   : SideSetsGeneratorBase(parameters)
      47             : {
      48        3346 : }
      49             : 
      50             : std::unique_ptr<MeshBase>
      51        3198 : SideSetsBetweenSubdomainsGenerator::generate()
      52             : {
      53        3198 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      54             : 
      55             :   // construct the FE object so we can compute normals of faces
      56        3198 :   setup(*mesh);
      57             : 
      58             :   std::vector<boundary_id_type> boundary_ids =
      59        3192 :       MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true);
      60             : 
      61             :   // Get a reference to our BoundaryInfo object for later use
      62        3192 :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
      63             : 
      64             :   // Prepare to query about sides adjacent to remote elements if we're
      65             :   // on a distributed mesh
      66        3192 :   const processor_id_type my_n_proc = mesh->n_processors();
      67        3192 :   const processor_id_type my_proc_id = mesh->processor_id();
      68             :   typedef std::vector<std::pair<dof_id_type, unsigned int>> vec_type;
      69        3192 :   std::vector<vec_type> queries(my_n_proc);
      70             : 
      71             :   // Request to compute normal vectors
      72        3192 :   const std::vector<Point> & face_normals = _fe_face->get_normals();
      73             : 
      74      309745 :   for (const auto & elem : mesh->active_element_ptr_range())
      75             :   {
      76             :     // We only need to loop over elements in the primary subdomain
      77      613106 :     if (_check_subdomains &&
      78      306553 :         !MeshTraversingUtils::elementSubdomainIdInList(elem, _included_subdomain_ids))
      79      155662 :       continue;
      80             : 
      81      924375 :     for (const auto & side : make_range(elem->n_sides()))
      82             :     {
      83      773484 :       const Elem * neighbor = elem->neighbor_ptr(side);
      84             : 
      85             :       // On a replicated mesh, we add all subdomain sides ourselves.
      86             :       // On a distributed mesh, we may have missed sides which
      87             :       // neighbor remote elements.  We should query any such cases.
      88      773484 :       if (neighbor == remote_elem)
      89             :       {
      90        1471 :         queries[elem->processor_id()].push_back(std::make_pair(elem->id(), side));
      91             :       }
      92      772013 :       else if (neighbor != NULL)
      93             :       {
      94      655403 :         _fe_face->reinit(elem, side);
      95             :         // We'll just use the normal of the first qp
      96      655403 :         const Point & face_normal = face_normals[0];
      97             :         // Add the boundaries, if appropriate
      98      655403 :         if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
      99             :         {
     100             :           // Add the boundaries
     101       38988 :           if (_replace)
     102           0 :             boundary_info.remove_side(elem, side);
     103       77976 :           for (const auto & boundary_id : boundary_ids)
     104       38988 :             boundary_info.add_side(elem, side, boundary_id);
     105             :         }
     106             :       }
     107             :     }
     108        3192 :   }
     109             : 
     110        3192 :   if (!mesh->is_serial())
     111             :   {
     112         328 :     const auto queries_tag = mesh->comm().get_unique_tag(),
     113         328 :                replies_tag = mesh->comm().get_unique_tag();
     114             : 
     115         984 :     std::vector<Parallel::Request> side_requests(my_n_proc - 1), reply_requests(my_n_proc - 1);
     116             : 
     117             :     // Make all requests
     118         912 :     for (const auto & p : make_range(my_n_proc))
     119             :     {
     120         584 :       if (p == my_proc_id)
     121         328 :         continue;
     122             : 
     123         256 :       Parallel::Request & request = side_requests[p - (p > my_proc_id)];
     124             : 
     125         256 :       mesh->comm().send(p, queries[p], request, queries_tag);
     126             :     }
     127             : 
     128             :     // Reply to all requests
     129         328 :     std::vector<vec_type> responses(my_n_proc - 1);
     130             : 
     131         584 :     for (const auto & p : make_range(uint(1), my_n_proc))
     132             :     {
     133         256 :       vec_type query;
     134             : 
     135         256 :       Parallel::Status status(mesh->comm().probe(Parallel::any_source, queries_tag));
     136         256 :       const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
     137             : 
     138         256 :       mesh->comm().receive(source_pid, query, queries_tag);
     139             : 
     140         256 :       Parallel::Request & request = reply_requests[p - 1];
     141             : 
     142        1727 :       for (const auto & q : query)
     143             :       {
     144        1471 :         const Elem * elem = mesh->elem_ptr(q.first);
     145        1471 :         const unsigned int side = q.second;
     146        1471 :         const Elem * neighbor = elem->neighbor_ptr(side);
     147             : 
     148        1471 :         if (neighbor != NULL)
     149             :         {
     150        1471 :           _fe_face->reinit(elem, side);
     151             :           // We'll just use the normal of the first qp
     152        1471 :           const Point & face_normal = _fe_face->get_normals()[0];
     153             :           // Add the boundaries, if appropriate
     154        1471 :           if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
     155         114 :             responses[p - 1].push_back(std::make_pair(elem->id(), side));
     156             :         }
     157             :       }
     158             : 
     159         256 :       mesh->comm().send(source_pid, responses[p - 1], request, replies_tag);
     160         256 :     }
     161             : 
     162             :     // Process all incoming replies
     163         584 :     for (processor_id_type p = 1; p != my_n_proc; ++p)
     164             :     {
     165         256 :       Parallel::Status status(this->comm().probe(Parallel::any_source, replies_tag));
     166         256 :       const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
     167             : 
     168         256 :       vec_type response;
     169             : 
     170         256 :       this->comm().receive(source_pid, response, replies_tag);
     171             : 
     172         370 :       for (const auto & r : response)
     173             :       {
     174         114 :         const Elem * elem = mesh->elem_ptr(r.first);
     175         114 :         const unsigned int side = r.second;
     176             : 
     177         114 :         if (_replace)
     178           0 :           boundary_info.remove_side(elem, side);
     179         228 :         for (const auto & boundary_id : boundary_ids)
     180         114 :           boundary_info.add_side(elem, side, boundary_id);
     181             :       }
     182         256 :     }
     183             : 
     184         328 :     Parallel::wait(side_requests);
     185         328 :     Parallel::wait(reply_requests);
     186         328 :   }
     187             : 
     188        6384 :   for (const auto & i : make_range(boundary_ids.size()))
     189        3192 :     boundary_info.sideset_name(boundary_ids[i]) = _boundary_names[i];
     190             : 
     191        3192 :   mesh->unset_is_prepared();
     192        6384 :   return dynamic_pointer_cast<MeshBase>(mesh);
     193        3192 : }

Generated by: LCOV version 1.14