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 : }