LCOV - code coverage report
Current view: top level - src/meshgenerators - SubdomainPerElementGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 56 63 88.9 %
Date: 2025-08-08 20:01:16 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 "SubdomainPerElementGenerator.h"
      11             : #include "CastUniquePointer.h"
      12             : 
      13             : #include "libmesh/elem.h"
      14             : 
      15             : registerMooseObject("MooseApp", SubdomainPerElementGenerator);
      16             : registerMooseObjectRenamed("MooseApp",
      17             :                            ElementSubdomainIDGenerator,
      18             :                            "05/18/2024 24:00",
      19             :                            SubdomainPerElementGenerator);
      20             : 
      21             : InputParameters
      22       28814 : SubdomainPerElementGenerator::validParams()
      23             : {
      24       28814 :   InputParameters params = MeshGenerator::validParams();
      25             : 
      26       28814 :   params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
      27       28814 :   params.addRequiredParam<std::vector<SubdomainID>>("subdomain_ids",
      28             :                                                     "New subdomain IDs of all elements");
      29       28814 :   params.addParam<std::vector<dof_id_type>>("element_ids", "New element IDs of all elements");
      30       28814 :   params.addClassDescription(
      31             :       "Allows the user to assign each element the subdomain ID of their choice");
      32       28814 :   return params;
      33           0 : }
      34             : 
      35         142 : SubdomainPerElementGenerator::SubdomainPerElementGenerator(const InputParameters & parameters)
      36         142 :   : MeshGenerator(parameters), _input(getMesh("input"))
      37             : {
      38         142 : }
      39             : 
      40             : std::unique_ptr<MeshBase>
      41         136 : SubdomainPerElementGenerator::generate()
      42             : {
      43         136 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      44             : 
      45         136 :   std::vector<SubdomainID> bids = getParam<std::vector<SubdomainID>>("subdomain_ids");
      46             : 
      47             :   // Generate a list of elements to which new subdomain IDs are to be assigned
      48         136 :   std::vector<Elem *> elements;
      49         136 :   if (isParamValid("element_ids"))
      50             :   {
      51          24 :     std::vector<dof_id_type> elemids = getParam<std::vector<dof_id_type>>("element_ids");
      52         108 :     for (const auto & dof : elemids)
      53             :     {
      54          84 :       Elem * elem = mesh->query_elem_ptr(dof);
      55          84 :       bool has_elem = elem;
      56             : 
      57             :       // If no processor sees this element, something must be wrong
      58             :       // with the specified ID.  If another processor sees this
      59             :       // element but we don't, we'll insert NULL into our elements
      60             :       // vector anyway so as to keep the indexing matching our bids
      61             :       // vector.
      62          84 :       this->comm().max(has_elem);
      63          84 :       if (!has_elem)
      64           0 :         mooseError("invalid element ID is in element_ids");
      65             :       else
      66          84 :         elements.push_back(elem);
      67             :     }
      68          24 :   }
      69             : 
      70             :   else
      71             :   {
      72         112 :     bool has_warned_remapping = false;
      73             : 
      74             :     // On a distributed mesh, iterating over all elements in
      75             :     // increasing order is tricky.  We have to consider element ids
      76             :     // which aren't on a particular processor because they're remote,
      77             :     // *and* elements which aren't on a particular processor because
      78             :     // there's a hole in the current numbering.
      79             :     //
      80             :     // I don't see how to do this without a ton of communication,
      81             :     // which is hopefully okay because it only happens at mesh setup,
      82             :     // and because nobody who is here trying to use
      83             :     // AssignElementSubdomainID to hand write every single element's
      84             :     // subdomain ID will have a huge number of elements on their
      85             :     // initial mesh.
      86             : 
      87             :     // Using plain max_elem_id() currently gives the same result on
      88             :     // every processor, but that isn't guaranteed by the libMesh
      89             :     // documentation, so let's be paranoid.
      90         112 :     dof_id_type end_id = mesh->max_elem_id();
      91         112 :     this->comm().max(end_id);
      92             : 
      93        3017 :     for (dof_id_type e = 0; e != end_id; ++e)
      94             :     {
      95             :       // This is O(1) on ReplicatedMesh but O(log(N_elem)) on
      96             :       // DistributedMesh.  We can switch to more complicated but
      97             :       // asymptotically faster code if my "nobody who is here ... will
      98             :       // have a huge number of elements" claim turns out to be false.
      99        2905 :       Elem * elem = mesh->query_elem_ptr(e);
     100        2905 :       bool someone_has_elem = elem;
     101        2905 :       if (!mesh->is_replicated())
     102         448 :         this->comm().max(someone_has_elem);
     103             : 
     104        2905 :       if (elem && elem->id() != e && (!has_warned_remapping))
     105             :       {
     106           0 :         mooseWarning("AssignElementSubdomainID will ignore the element remapping");
     107           0 :         has_warned_remapping = true;
     108             :       }
     109             : 
     110        2905 :       if (someone_has_elem)
     111        2905 :         elements.push_back(elem);
     112             :     }
     113             :   }
     114             : 
     115         136 :   if (bids.size() != elements.size())
     116           0 :     mooseError(" Size of subdomain_ids is not consistent with the number of elements");
     117             : 
     118             :   // Assign new subdomain IDs and make sure elements in different types are not assigned with the
     119             :   // same subdomain ID
     120         136 :   std::map<ElemType, std::set<SubdomainID>> type2blocks;
     121        3125 :   for (dof_id_type e = 0; e < elements.size(); ++e)
     122             :   {
     123             :     // Get the element we need to assign, or skip it if we just have a
     124             :     // nullptr placeholder indicating a remote element.
     125        2989 :     Elem * elem = elements[e];
     126        2989 :     if (!elem)
     127          42 :       continue;
     128             : 
     129        2947 :     ElemType type = elem->type();
     130        2947 :     SubdomainID newid = bids[e];
     131             : 
     132        2947 :     bool has_type = false;
     133        5758 :     for (auto & it : type2blocks)
     134             :     {
     135        2811 :       if (it.first == type)
     136             :       {
     137        2811 :         has_type = true;
     138        2811 :         it.second.insert(newid);
     139             :       }
     140           0 :       else if (it.second.count(newid) > 0)
     141           0 :         mooseError("trying to assign elements with different types with the same subdomain ID");
     142             :     }
     143             : 
     144        2947 :     if (!has_type)
     145             :     {
     146         136 :       std::set<SubdomainID> blocks;
     147         136 :       blocks.insert(newid);
     148         136 :       type2blocks.insert(std::make_pair(type, blocks));
     149         136 :     }
     150             : 
     151        2947 :     elem->subdomain_id() = newid;
     152             :   }
     153             : 
     154         136 :   mesh->set_isnt_prepared();
     155         272 :   return dynamic_pointer_cast<MeshBase>(mesh);
     156         136 : }

Generated by: LCOV version 1.14