LCOV - code coverage report
Current view: top level - src/meshgenerators - SubdomainPerElementGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 56 63 88.9 %
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 "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       28790 : SubdomainPerElementGenerator::validParams()
      23             : {
      24       28790 :   InputParameters params = MeshGenerator::validParams();
      25             : 
      26       28790 :   params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
      27       28790 :   params.addRequiredParam<std::vector<SubdomainID>>("subdomain_ids",
      28             :                                                     "New subdomain IDs of all elements");
      29       28790 :   params.addParam<std::vector<dof_id_type>>("element_ids", "New element IDs of all elements");
      30       28790 :   params.addClassDescription(
      31             :       "Allows the user to assign each element the subdomain ID of their choice");
      32       28790 :   return params;
      33           0 : }
      34             : 
      35         130 : SubdomainPerElementGenerator::SubdomainPerElementGenerator(const InputParameters & parameters)
      36         130 :   : MeshGenerator(parameters), _input(getMesh("input"))
      37             : {
      38         130 : }
      39             : 
      40             : std::unique_ptr<MeshBase>
      41         124 : SubdomainPerElementGenerator::generate()
      42             : {
      43         124 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      44             : 
      45         124 :   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         124 :   std::vector<Elem *> elements;
      49         124 :   if (isParamValid("element_ids"))
      50             :   {
      51          22 :     std::vector<dof_id_type> elemids = getParam<std::vector<dof_id_type>>("element_ids");
      52          99 :     for (const auto & dof : elemids)
      53             :     {
      54          77 :       Elem * elem = mesh->query_elem_ptr(dof);
      55          77 :       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          77 :       this->comm().max(has_elem);
      63          77 :       if (!has_elem)
      64           0 :         mooseError("invalid element ID is in element_ids");
      65             :       else
      66          77 :         elements.push_back(elem);
      67             :     }
      68          22 :   }
      69             : 
      70             :   else
      71             :   {
      72         102 :     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         102 :     dof_id_type end_id = mesh->max_elem_id();
      91         102 :     this->comm().max(end_id);
      92             : 
      93        2743 :     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        2641 :       Elem * elem = mesh->query_elem_ptr(e);
     100        2641 :       bool someone_has_elem = elem;
     101        2641 :       if (!mesh->is_replicated())
     102         448 :         this->comm().max(someone_has_elem);
     103             : 
     104        2641 :       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        2641 :       if (someone_has_elem)
     111        2641 :         elements.push_back(elem);
     112             :     }
     113             :   }
     114             : 
     115         124 :   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         124 :   std::map<ElemType, std::set<SubdomainID>> type2blocks;
     121        2842 :   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        2718 :     Elem * elem = elements[e];
     126        2718 :     if (!elem)
     127          42 :       continue;
     128             : 
     129        2676 :     ElemType type = elem->type();
     130        2676 :     SubdomainID newid = bids[e];
     131             : 
     132        2676 :     bool has_type = false;
     133        5228 :     for (auto & it : type2blocks)
     134             :     {
     135        2552 :       if (it.first == type)
     136             :       {
     137        2552 :         has_type = true;
     138        2552 :         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        2676 :     if (!has_type)
     145             :     {
     146         124 :       std::set<SubdomainID> blocks;
     147         124 :       blocks.insert(newid);
     148         124 :       type2blocks.insert(std::make_pair(type, blocks));
     149         124 :     }
     150             : 
     151        2676 :     elem->subdomain_id() = newid;
     152             :   }
     153             : 
     154         124 :   mesh->set_isnt_prepared();
     155         248 :   return dynamic_pointer_cast<MeshBase>(mesh);
     156         124 : }

Generated by: LCOV version 1.14