LCOV - code coverage report
Current view: top level - src/geomsearch - SecondaryNeighborhoodThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33187 (5aa0b2) with base d7c4bd Lines: 72 72 100.0 %
Date: 2026-06-30 12:18:20 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       20142 : SecondaryNeighborhoodThread::SecondaryNeighborhoodThread(
      20             :     const MooseMesh & mesh,
      21             :     const std::vector<dof_id_type> & trial_primary_nodes,
      22             :     const std::unordered_map<dof_id_type, std::vector<dof_id_type>> & node_to_elem_map,
      23             :     const unsigned int patch_size,
      24       20142 :     KDTree & kd_tree)
      25       20142 :   : _kd_tree(kd_tree),
      26       20142 :     _mesh(mesh),
      27       20142 :     _trial_primary_nodes(trial_primary_nodes),
      28       20142 :     _node_to_elem_map(node_to_elem_map),
      29       20142 :     _patch_size(patch_size)
      30             : {
      31       20142 : }
      32             : 
      33             : // Splitting Constructor
      34        1812 : SecondaryNeighborhoodThread::SecondaryNeighborhoodThread(SecondaryNeighborhoodThread & x,
      35        1812 :                                                          Threads::split /*split*/)
      36        1812 :   : _kd_tree(x._kd_tree),
      37        1812 :     _mesh(x._mesh),
      38        1812 :     _trial_primary_nodes(x._trial_primary_nodes),
      39        1812 :     _node_to_elem_map(x._node_to_elem_map),
      40        1812 :     _patch_size(x._patch_size)
      41             : {
      42        1812 : }
      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       21954 : SecondaryNeighborhoodThread::operator()(const NodeIdRange & range)
      52             : {
      53             :   unsigned int patch_size =
      54       21954 :       std::min(_patch_size, static_cast<unsigned int>(_trial_primary_nodes.size()));
      55             : 
      56       21954 :   std::vector<std::size_t> return_index(patch_size);
      57             : 
      58      113934 :   for (const auto & node_id : range)
      59             :   {
      60       91980 :     const Node & node = _mesh.nodeRef(node_id);
      61       91980 :     Point query_pt;
      62      367920 :     for (const auto i : make_range(Moose::dim))
      63      275940 :       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       91980 :     _kd_tree.neighborSearch(query_pt, patch_size, return_index);
      76             : 
      77       91980 :     std::vector<dof_id_type> neighbor_nodes(return_index.size());
      78     4749785 :     for (unsigned int i = 0; i < return_index.size(); ++i)
      79     4657805 :       neighbor_nodes[i] = _trial_primary_nodes[return_index[i]];
      80             : 
      81       91980 :     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       91980 :     bool need_to_track = false;
      92             : 
      93       91980 :     if (_mesh.nodeRef(node_id).processor_id() == processor_id)
      94       44369 :       need_to_track = true;
      95             :     else
      96             :     {
      97             :       {
      98       47611 :         auto node_to_elem_pair = _node_to_elem_map.find(node_id);
      99       47611 :         if (node_to_elem_pair != _node_to_elem_map.end())
     100             :         {
     101       47611 :           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       83249 :           for (const auto & dof : elems_connected_to_node)
     105       67781 :             if (_mesh.elemPtr(dof)->processor_id() == processor_id)
     106             :             {
     107       32143 :               need_to_track = true;
     108       32143 :               break; // Break out of element loop
     109             :             }
     110             :         }
     111             :       }
     112             : 
     113       47611 :       if (!need_to_track)
     114             :       { // Now check the neighbor nodes to see if we own any of them
     115       55648 :         for (const auto & neighbor_node_id : neighbor_nodes)
     116             :         {
     117       53905 :           if (_mesh.nodeRef(neighbor_node_id).processor_id() == processor_id)
     118       13338 :             need_to_track = true;
     119             :           else // Now see if we own any of the elements connected to the neighbor nodes
     120             :           {
     121       40567 :             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       40567 :             const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     125             : 
     126      164687 :             for (const auto & dof : elems_connected_to_node)
     127      124507 :               if (_mesh.elemPtr(dof)->processor_id() == processor_id)
     128             :               {
     129         387 :                 need_to_track = true;
     130         387 :                 break; // Break out of element loop
     131             :               }
     132             :           }
     133             : 
     134       53905 :           if (need_to_track)
     135       13725 :             break; // Breaking out of neighbor loop
     136             :         }
     137             :       }
     138             :     }
     139             : 
     140       91980 :     if (need_to_track)
     141             :     {
     142             :       // Add this node as a secondary node to search in the future
     143       90237 :       _secondary_nodes.push_back(node_id);
     144             : 
     145             :       // Set it's neighbors
     146       90237 :       _neighbor_nodes[node_id] = neighbor_nodes;
     147             : 
     148             :       { // Add the elements connected to the secondary node to the ghosted list
     149       90237 :         auto node_to_elem_pair = _node_to_elem_map.find(node_id);
     150             : 
     151       90237 :         if (node_to_elem_pair != _node_to_elem_map.end())
     152             :         {
     153       90237 :           const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     154             : 
     155      259909 :           for (const auto & dof : elems_connected_to_node)
     156      169672 :             _ghosted_elems.insert(dof);
     157             :         }
     158             :       }
     159             :       // Now add elements connected to the neighbor nodes to the ghosted list
     160     4711402 :       for (unsigned int neighbor_it = 0; neighbor_it < neighbor_nodes.size(); neighbor_it++)
     161             :       {
     162     4621165 :         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     4621165 :         const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
     166             : 
     167    14928924 :         for (const auto & dof : elems_connected_to_node)
     168    10307759 :           _ghosted_elems.insert(dof);
     169             :       }
     170             :     }
     171       91980 :   }
     172       21954 : }
     173             : 
     174             : void
     175        1812 : SecondaryNeighborhoodThread::join(const SecondaryNeighborhoodThread & other)
     176             : {
     177        3624 :   _secondary_nodes.insert(
     178        1812 :       _secondary_nodes.end(), other._secondary_nodes.begin(), other._secondary_nodes.end());
     179        1812 :   _ghosted_elems.insert(other._ghosted_elems.begin(), other._ghosted_elems.end());
     180        1812 :   _neighbor_nodes.insert(other._neighbor_nodes.begin(), other._neighbor_nodes.end());
     181        1812 : }

Generated by: LCOV version 1.14