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 "NodePositions.h" 11 : 12 : #include "libmesh/parallel_algebra.h" 13 : 14 : registerMooseObject("MooseApp", NodePositions); 15 : 16 : InputParameters 17 14313 : NodePositions::validParams() 18 : { 19 14313 : InputParameters params = Positions::validParams(); 20 14313 : params.addClassDescription("Positions of element nodes."); 21 14313 : params += BlockRestrictable::validParams(); 22 : 23 : // Element nodes must be sorted to remove duplicates. 24 14313 : params.suppressParameter<bool>("auto_sort"); 25 14313 : params.set<bool>("auto_sort") = true; 26 : // Gathered locally, should be broadcast on every process 27 14313 : params.set<bool>("auto_broadcast") = true; 28 : 29 14313 : return params; 30 0 : } 31 : 32 24 : NodePositions::NodePositions(const InputParameters & parameters) 33 24 : : Positions(parameters), BlockRestrictable(this), _mesh(_fe_problem.mesh()) 34 : { 35 : // Mesh is ready at construction 36 24 : initialize(); 37 : // Trigger synchronization as the initialization is distributed 38 24 : finalize(); 39 24 : } 40 : 41 : void 42 24 : NodePositions::initialize() 43 : { 44 24 : clearPositions(); 45 : 46 1140 : for (const auto & [node_id, elems_ids] : _fe_problem.mesh().nodeToElemMap()) 47 : { 48 1116 : if (!_mesh.queryNodePtr(node_id)) 49 0 : continue; 50 : 51 : // Check the elements associated with the node to see if they're in the block 52 : // we're block-restricting. If so, add the node to the positions vector and move 53 : // on to the next node (to minimize duplicates). 54 1984 : for (const auto elem_id : elems_ids) 55 : { 56 1662 : const auto e = _mesh.queryElemPtr(elem_id); 57 1662 : if (e && hasBlocks(e->subdomain_id())) 58 : { 59 794 : _positions.emplace_back(_mesh.nodeRef(node_id)); 60 794 : break; 61 : } 62 : } 63 : } 64 : 65 24 : _initialized = true; 66 24 : } 67 : 68 : void 69 24 : NodePositions::finalize() 70 : { 71 : // Gather up the positions vector on all ranks 72 : mooseAssert(initialized(false), "Positions vector has not been initialized."); 73 24 : if (_need_broadcast) 74 : // The consumer/producer reporter interface can keep track of whether a reduction is needed 75 : // (for example if a consumer needs replicated data, but the producer is distributed) however, 76 : // we have currently made the decision that positions should ALWAYS be replicated 77 24 : _communicator.allgather(_positions, /* identical buffer lengths = */ false); 78 : 79 : // We always need to sort the positions as nodes on the boundary between different mesh partitions 80 : // are duplicated. We sort by X, then Y, then Z, and prune the positions list. 81 24 : std::sort(_positions.begin(), _positions.end()); 82 24 : _positions.erase(std::unique(_positions.begin(), _positions.end()), _positions.end()); 83 : 84 : // Make a KDTree with the positions 85 24 : _positions_kd_tree = std::make_unique<KDTree>(_positions, 1); 86 : 87 : // For now at least, we expect positions to be the same on all ranks 88 : mooseAssert(comm().verify(_positions), "Positions should be the same across all MPI processes."); 89 24 : }