LCOV - code coverage report
Current view: top level - src/relationshipmanagers - RedistributeProperties.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 67 75 89.3 %
Date: 2025-07-17 01:28:37 Functions: 6 9 66.7 %
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 "RedistributeProperties.h"
      11             : 
      12             : #include "MaterialProperty.h"
      13             : #include "MaterialPropertyStorage.h"
      14             : 
      15             : #include <timpi/parallel_sync.h>
      16             : 
      17             : registerMooseObject("MooseApp", RedistributeProperties);
      18             : 
      19             : InputParameters
      20       14397 : RedistributeProperties::validParams()
      21             : {
      22       14397 :   InputParameters params = RelationshipManager::validParams();
      23       14397 :   return params;
      24             : }
      25             : 
      26          66 : RedistributeProperties::RedistributeProperties(const InputParameters & parameters)
      27          66 :   : RelationshipManager(parameters)
      28             : {
      29          66 : }
      30             : 
      31             : void
      32          72 : RedistributeProperties::operator()(const MeshBase::const_element_iterator &,
      33             :                                    const MeshBase::const_element_iterator &,
      34             :                                    processor_id_type,
      35             :                                    map_type &)
      36             : {
      37          72 : }
      38             : 
      39             : std::unique_ptr<libMesh::GhostingFunctor>
      40           0 : RedistributeProperties::clone() const
      41             : {
      42           0 :   return _app.getFactory().copyConstruct(*this);
      43             : }
      44             : 
      45             : std::string
      46           0 : RedistributeProperties::getInfo() const
      47             : {
      48           0 :   return "RedistributeProperties";
      49             : }
      50             : 
      51             : // the LHS ("this" object) in MooseApp::addRelationshipManager is the existing RelationshipManager
      52             : // object to which we are comparing the rhs to determine whether it should get added
      53             : bool
      54           0 : RedistributeProperties::operator>=(const RelationshipManager & rhs) const
      55             : {
      56           0 :   const auto * rm = dynamic_cast<const RedistributeProperties *>(&rhs);
      57             : 
      58             :   // All RedistributeProperties objects are effectively equivalent
      59           0 :   return rm;
      60             : }
      61             : 
      62             : void
      63         198 : RedistributeProperties::addMaterialPropertyStorage(MaterialPropertyStorage & mat_props)
      64             : {
      65         198 :   _materials.emplace_back(&mat_props);
      66         198 : }
      67             : 
      68             : void
      69          88 : RedistributeProperties::redistribute()
      70             : {
      71          88 :   const MeshBase & mesh = _moose_mesh->getMesh();
      72          88 :   const processor_id_type pid = mesh.processor_id();
      73             : 
      74         352 :   for (auto & mat_prop_store : _materials)
      75             :   {
      76             :     // Once we've redistributed data elsewhere we'll delete it here.
      77             :     //
      78             :     // We don't need stored properties on non-local elements, and so
      79             :     // we don't compute them and we don't *bother deleting them when
      80             :     // non-local elements are coarsened away*, so this may be our last
      81             :     // chance to avoid dangling pointers in future redistribute()
      82             :     // calls.
      83         264 :     std::set<const Elem *> elems_being_migrated;
      84             : 
      85         264 :     if (mat_prop_store->hasStatefulProperties())
      86             :     {
      87             :       mooseAssert(
      88             :           !Threads::in_threads,
      89             :           "This routine has not been implemented for threads. Please query this routine before "
      90             :           "a threaded region or contact a MOOSE developer to discuss.");
      91             : 
      92         900 :       for (const auto state : mat_prop_store->stateIndexRange())
      93             :       {
      94         636 :         MaterialPropertyStorage::PropsType & props_map = mat_prop_store->setProps(state);
      95             :         typedef std::unordered_map<unsigned int, std::string> stored_props_type;
      96             :         typedef std::tuple<stored_props_type, dof_id_type, int> stored_elem_type;
      97         636 :         std::map<processor_id_type, std::vector<stored_elem_type>> props_to_push;
      98             : 
      99             :         // Take non-const references here for compatibility with dataStore(T&)
     100       31141 :         for (auto & [elem, elem_props_map] : props_map)
     101             :         {
     102             :           // There better be an element here
     103             :           mooseAssert(elem, "Null element found in material property map?");
     104             : 
     105             :           // It had better be a *real* element here, not a dangling
     106             :           // pointer
     107             :           mooseAssert(elem->id() < mesh.max_elem_id(),
     108             :                       "Invalid (dangling? corrupted?) element in material property map?");
     109             :           mooseAssert(elem->processor_id() < mesh.n_processors(),
     110             :                       "Invalid (corrupted?) element in material property map?");
     111             : 
     112             :           // If it's not in the particular mesh we're responsible for,
     113             :           // we can skip it.  MOOSE mixes non-displaced with displaced
     114             :           // mesh properties in their storages.
     115       30505 :           if (elem != mesh.query_elem_ptr(elem->id()))
     116           0 :             continue;
     117             : 
     118       30505 :           std::set<processor_id_type> target_pids;
     119             : 
     120       30505 :           if (elem->active())
     121       21465 :             target_pids.insert(elem->processor_id());
     122        9040 :           else if (elem->subactive())
     123             :           {
     124             :             mooseAssert(elem->parent(),
     125             :                         "Invalid (corrupted?) subactive element in material property map");
     126             :             mooseAssert(elem->parent()->refinement_flag() == Elem::JUST_COARSENED,
     127             :                         "Invalid (subactive child of not-just-coarsened) element in material "
     128             :                         "property map");
     129        6376 :             target_pids.insert(elem->parent()->processor_id());
     130             :           }
     131             :           else
     132             :           {
     133             :             mooseAssert(elem->ancestor(),
     134             :                         "Unexpected relationship for element in material property map?");
     135             :             mooseAssert(elem->has_children(),
     136             :                         "Ancestor element with no children in material property map?");
     137       17928 :             for (const Elem & child : elem->child_ref_range())
     138       15264 :               target_pids.insert(child.processor_id());
     139             :           }
     140             : 
     141             :           // If we're being migrated elsewhere and we're not needed
     142             :           // for AMR/C locally then we should erase the local entry
     143       30505 :           bool remote_pid = false, local_pid = false;
     144       61246 :           for (processor_id_type target_pid : target_pids)
     145       30741 :             if (target_pid == pid)
     146       24222 :               local_pid = true;
     147             :             else
     148             :             {
     149        6519 :               remote_pid = true;
     150             : 
     151        6519 :               stored_props_type stored_props;
     152        6519 :               unsigned int n_q_points = 0;
     153       13090 :               for (auto & [prop_id, prop_vals] : elem_props_map)
     154             :               {
     155             :                 mooseAssert(!prop_vals.empty(),
     156             :                             "Empty MaterialProperties in stateful properties map?");
     157             : 
     158       13142 :                 for (const auto & prop : prop_vals)
     159        6571 :                   n_q_points = std::max(n_q_points, prop.size());
     160             : 
     161        6571 :                 std::ostringstream oss;
     162        6571 :                 dataStore(oss, prop_vals, nullptr);
     163        6571 :                 stored_props[prop_id] = oss.str();
     164        6571 :               }
     165             : 
     166             :               // Get the stored data ready to push to the element's new
     167             :               // processor
     168       13038 :               props_to_push[target_pid].emplace_back(
     169        6519 :                   std::move(stored_props), elem->id(), n_q_points);
     170        6519 :             }
     171             : 
     172       30505 :           if (remote_pid && !local_pid)
     173        6283 :             elems_being_migrated.insert(elem);
     174       30505 :         }
     175             : 
     176         773 :         auto recv_functor = [&, mat_prop_store_ptr = mat_prop_store](
     177        6571 :                                 processor_id_type, const std::vector<stored_elem_type> & data)
     178             :         {
     179        6656 :           for (const auto & [elem_hash, elem_id, n_q_points] : data)
     180             :           {
     181        6519 :             const Elem * elem = mesh.elem_ptr(elem_id);
     182        6519 :             auto & elem_props = props_map[elem];
     183             : 
     184       13090 :             for (const auto & [prop_id, prop_str] : elem_hash)
     185             :             {
     186             :               // This should be called "initPropsIfNecessary"... which
     187             :               // is confusing but convenient.
     188             :               //
     189             :               // We need to *only* initProps for the map we're working
     190             :               // on, otherwise we might see an
     191             :               // initialized-but-not-filled entry in the next map and
     192             :               // foolishly try to send it places.
     193        6571 :               mat_prop_store_ptr->initProps(0, state, elem, prop_id, n_q_points);
     194             : 
     195             :               mooseAssert(elem_props.contains(prop_id),
     196             :                           "Trying to load into a nonexistant property id?");
     197        6571 :               MaterialProperties & mat_props = elem_props[prop_id];
     198        6571 :               std::istringstream iss(prop_str);
     199        6571 :               dataLoad(iss, mat_props, nullptr);
     200        6571 :             }
     201             :           }
     202         137 :         };
     203             : 
     204         636 :         Parallel::push_parallel_vector_data(mesh.comm(), props_to_push, recv_functor);
     205         636 :       }
     206             :     }
     207             : 
     208        2786 :     for (const Elem * elem : elems_being_migrated)
     209        2522 :       mat_prop_store->eraseProperty(elem);
     210         264 :   }
     211          88 : }

Generated by: LCOV version 1.14