LCOV - code coverage report
Current view: top level - src/geomsearch - SecondaryNeighborhoodThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 72 72 100.0 %
Date: 2025-07-17 01:28:37 Functions: 4 4 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 "SecondaryNeighborhoodThread.h"
      11             : 
      12             : #include "AuxiliarySystem.h"
      13             : #include "Problem.h"
      14             : #include "FEProblem.h"
      15             : #include "MooseMesh.h"
      16             : 
      17             : #include "libmesh/threads.h"
      18             : 
      19       19994 : SecondaryNeighborhoodThread::SecondaryNeighborhoodThread(
      20             :     const MooseMesh & mesh,
      21             :     const std::vector<dof_id_type> & trial_primary_nodes,
      22             :     const std::map<dof_id_type, std::vector<dof_id_type>> & node_to_elem_map,
      23             :     const unsigned int patch_size,
      24       19994 :     KDTree & kd_tree)
      25       19994 :   : _kd_tree(kd_tree),
      26       19994 :     _mesh(mesh),
      27       19994 :     _trial_primary_nodes(trial_primary_nodes),
      28       19994 :     _node_to_elem_map(node_to_elem_map),
      29       19994 :     _patch_size(patch_size)
      30             : {
      31       19994 : }
      32             : 
      33             : // Splitting Constructor
      34        1805 : SecondaryNeighborhoodThread::SecondaryNeighborhoodThread(SecondaryNeighborhoodThread & x,
      35        1805 :                                                          Threads::split /*split*/)
      36        1805 :   : _kd_tree(x._kd_tree),
      37        1805 :     _mesh(x._mesh),
      38        1805 :     _trial_primary_nodes(x._trial_primary_nodes),
      39        1805 :     _node_to_elem_map(x._node_to_elem_map),
      40        1805 :     _patch_size(x._patch_size)
      41             : {
      42        1805 : }
      43             : 
      44             : /**
      45             :  * Save a patch of nodes that are close to each of the secondary nodes to speed the search algorithm
      46             :  * TODO: This needs to be updated at some point in time.  If the hits into this data structure
      47             :  * approach "the end"
      48             :  * then it may be time to update
      49             :  */
      50             : void
      51       21799 : SecondaryNeighborhoodThread::operator()(const NodeIdRange & range)
      52             : {
      53             :   unsigned int patch_size =
      54       21799 :       std::min(_patch_size, static_cast<unsigned int>(_trial_primary_nodes.size()));
      55             : 
      56       21799 :   std::vector<std::size_t> return_index(patch_size);
      57             : 
      58      109195 :   for (const auto & node_id : range)
      59             :   {
      60       87396 :     const Node & node = _mesh.nodeRef(node_id);
      61       87396 :     Point query_pt;
      62      349584 :     for (const auto i : make_range(Moose::dim))
      63      262188 :       query_pt(i) = node(i);
      64             : 
      65             :     /**
      66             :      * neighborSearch function takes the secondary coordinates and patch_size as
      67             :      * input and
      68             :      * finds the k (=patch_size) nearest neighbors to the secondary node from the
      69             :      * trial
      70             :      *  primary node set. The indices of the nearest neighbors are stored in the
      71             :      * array
      72             :      * return_index.
      73             :      */
      74             : 
      75       87396 :     _kd_tree.neighborSearch(query_pt, patch_size, return_index);
      76             : 
      77       87396 :     std::vector<dof_id_type> neighbor_nodes(return_index.size());
      78     4582753 :     for (unsigned int i = 0; i < return_index.size(); ++i)
      79     4495357 :       neighbor_nodes[i] = _trial_primary_nodes[return_index[i]];
      80             : 
      81       87396 :     processor_id_type processor_id = _mesh.processor_id();
      82             : 
      83             :     /**
      84             :      * Now see if _this_ processor needs to keep track of this secondary and it's neighbors
      85             :      * We're going to see if this processor owns the secondary, any of the neighborhood nodes
      86             :      * or any of the elements connected to either set.  If it does then we're going to ghost
      87             :      * all of the elements connected to the secondary node and the neighborhood nodes to this
      88             :      * processor. This is a very conservative approach that we might revisit later.
      89             :      */
      90             : 
      91       87396 :     bool need_to_track = false;
      92             : 
      93       87396 :     if (_mesh.nodeRef(node_id).processor_id() == processor_id)
      94       41001 :       need_to_track = true;
      95             :     else
      96             :     {
      97             :       {
      98       46395 :         auto node_to_elem_pair = _node_to_elem_map.find(node_id);
      99       46395 :         if (node_to_elem_pair != _node_to_elem_map.end())
     100             :         {
     101       46395 :           const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     102             : 
     103             :           // See if we own any of the elements connected to the secondary node
     104       79976 :           for (const auto & dof : elems_connected_to_node)
     105       65576 :             if (_mesh.elemPtr(dof)->processor_id() == processor_id)
     106             :             {
     107       31995 :               need_to_track = true;
     108       31995 :               break; // Break out of element loop
     109             :             }
     110             :         }
     111             :       }
     112             : 
     113       46395 :       if (!need_to_track)
     114             :       { // Now check the neighbor nodes to see if we own any of them
     115       42622 :         for (const auto & neighbor_node_id : neighbor_nodes)
     116             :         {
     117       41191 :           if (_mesh.nodeRef(neighbor_node_id).processor_id() == processor_id)
     118       12586 :             need_to_track = true;
     119             :           else // Now see if we own any of the elements connected to the neighbor nodes
     120             :           {
     121       28605 :             auto node_to_elem_pair = _node_to_elem_map.find(neighbor_node_id);
     122             :             mooseAssert(node_to_elem_pair != _node_to_elem_map.end(),
     123             :                         "Missing entry in node to elem map");
     124       28605 :             const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     125             : 
     126      136199 :             for (const auto & dof : elems_connected_to_node)
     127      107977 :               if (_mesh.elemPtr(dof)->processor_id() == processor_id)
     128             :               {
     129         383 :                 need_to_track = true;
     130         383 :                 break; // Break out of element loop
     131             :               }
     132             :           }
     133             : 
     134       41191 :           if (need_to_track)
     135       12969 :             break; // Breaking out of neighbor loop
     136             :         }
     137             :       }
     138             :     }
     139             : 
     140       87396 :     if (need_to_track)
     141             :     {
     142             :       // Add this node as a secondary node to search in the future
     143       85965 :       _secondary_nodes.push_back(node_id);
     144             : 
     145             :       // Set it's neighbors
     146       85965 :       _neighbor_nodes[node_id] = neighbor_nodes;
     147             : 
     148             :       { // Add the elements connected to the secondary node to the ghosted list
     149       85965 :         auto node_to_elem_pair = _node_to_elem_map.find(node_id);
     150             : 
     151       85965 :         if (node_to_elem_pair != _node_to_elem_map.end())
     152             :         {
     153       85965 :           const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     154             : 
     155      246546 :           for (const auto & dof : elems_connected_to_node)
     156      160581 :             _ghosted_elems.insert(dof);
     157             :         }
     158             :       }
     159             :       // Now add elements connected to the neighbor nodes to the ghosted list
     160     4555794 :       for (unsigned int neighbor_it = 0; neighbor_it < neighbor_nodes.size(); neighbor_it++)
     161             :       {
     162     4469829 :         auto node_to_elem_pair = _node_to_elem_map.find(neighbor_nodes[neighbor_it]);
     163             :         mooseAssert(node_to_elem_pair != _node_to_elem_map.end(),
     164             :                     "Missing entry in node to elem map");
     165     4469829 :         const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     166             : 
     167    14549899 :         for (const auto & dof : elems_connected_to_node)
     168    10080070 :           _ghosted_elems.insert(dof);
     169             :       }
     170             :     }
     171       87396 :   }
     172       21799 : }
     173             : 
     174             : void
     175        1805 : SecondaryNeighborhoodThread::join(const SecondaryNeighborhoodThread & other)
     176             : {
     177        3610 :   _secondary_nodes.insert(
     178        1805 :       _secondary_nodes.end(), other._secondary_nodes.begin(), other._secondary_nodes.end());
     179        1805 :   _ghosted_elems.insert(other._ghosted_elems.begin(), other._ghosted_elems.end());
     180        1805 :   _neighbor_nodes.insert(other._neighbor_nodes.begin(), other._neighbor_nodes.end());
     181        1805 : }

Generated by: LCOV version 1.14