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 14369 : NodePositions::validParams() 18 : { 19 14369 : InputParameters params = Positions::validParams(); 20 14369 : params.addClassDescription("Positions of element nodes."); 21 14369 : params += BlockRestrictable::validParams(); 22 14369 : params += BoundaryRestrictable::validParams(); 23 : 24 : // Element nodes must be sorted to remove duplicates. 25 28738 : params.suppressParameter<bool>("auto_sort"); 26 28738 : params.set<bool>("auto_sort") = true; 27 : // Gathered locally, should be broadcast on every process 28 14369 : params.set<bool>("auto_broadcast") = true; 29 : 30 14369 : return params; 31 0 : } 32 : 33 52 : NodePositions::NodePositions(const InputParameters & parameters) 34 : : Positions(parameters), 35 : BlockRestrictable(this), 36 : BoundaryRestrictable(this, true), 37 52 : _mesh(_subproblem.mesh()) 38 : { 39 : // Mesh is ready at construction 40 52 : initialize(); 41 : // Trigger synchronization as the initialization is distributed 42 52 : finalize(); 43 52 : } 44 : 45 : void 46 52 : NodePositions::initialize() 47 : { 48 52 : clearPositions(); 49 : 50 : // Only needed for boundary restriction 51 52 : const BoundaryInfo * binfo = nullptr; 52 52 : if (boundaryRestricted()) 53 26 : binfo = &_mesh.getMesh().get_boundary_info(); 54 : 55 2476 : for (const auto & [node_id, elems_ids] : _mesh.nodeToElemMap()) 56 : { 57 2424 : const auto * const node = _mesh.queryNodePtr(node_id); 58 2424 : if (!node) 59 757 : continue; 60 : 61 : // Check that node is part of boundary restriction 62 2424 : if (binfo) 63 : { 64 1212 : if (!binfo->get_nodeset_map().count(node)) 65 0 : continue; 66 : else 67 : { 68 2794 : for (const auto [_, nodeset_id] : as_range(binfo->get_nodeset_map().equal_range(node))) 69 2037 : if (hasBoundary(nodeset_id)) 70 455 : goto inRestriction; 71 : } 72 757 : continue; 73 757 : } 74 1212 : inRestriction: 75 : // Check the elements associated with the node to see if they're in the block 76 : // we're block-restricting. If so, add the node to the positions vector and move 77 : // on to the next node (to minimize duplicates). 78 3083 : for (const auto elem_id : elems_ids) 79 : { 80 2558 : const auto e = _mesh.queryElemPtr(elem_id); 81 2558 : if (e && hasBlocks(e->subdomain_id())) 82 : { 83 1142 : _positions.emplace_back(_mesh.nodeRef(node_id)); 84 1142 : break; 85 : } 86 : } 87 : } 88 : 89 52 : _initialized = true; 90 52 : } 91 : 92 : void 93 52 : NodePositions::finalize() 94 : { 95 : // Gather up the positions vector on all ranks 96 : mooseAssert(initialized(false), "Positions vector has not been initialized."); 97 52 : if (_need_broadcast) 98 : // The consumer/producer reporter interface can keep track of whether a reduction is needed 99 : // (for example if a consumer needs replicated data, but the producer is distributed) however, 100 : // we have currently made the decision that positions should ALWAYS be replicated 101 52 : _communicator.allgather(_positions, /* identical buffer lengths = */ false); 102 : 103 : // We always need to sort the positions as nodes on the boundary between different mesh partitions 104 : // are duplicated. We sort by X, then Y, then Z, and prune the positions list. 105 52 : std::sort(_positions.begin(), _positions.end()); 106 52 : _positions.erase(std::unique(_positions.begin(), _positions.end()), _positions.end()); 107 : 108 : // Make a KDTree with the positions 109 52 : _positions_kd_tree = std::make_unique<KDTree>(_positions, 1); 110 : 111 : // For now at least, we expect positions to be the same on all ranks 112 : mooseAssert(comm().verify(_positions), "Positions should be the same across all MPI processes."); 113 52 : }