Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : 19 : #ifndef LIBMESH_PARALLEL_HILBERT_H 20 : #define LIBMESH_PARALLEL_HILBERT_H 21 : 22 : // This class contains all the functionality for bin sorting 23 : // Templated on the type of keys you will be sorting and the 24 : // type of iterator you will be using. 25 : 26 : #include "libmesh/libmesh_config.h" 27 : #include "libmesh/id_types.h" 28 : 29 : #if defined(LIBMESH_HAVE_LIBHILBERT) 30 : 31 : // TIMPI includes 32 : #include "timpi/standard_type.h" 33 : 34 : // C/C++ includes 35 : 36 : // So many implicit-fallthrough warnings in crazy libHilbert macros... 37 : #include "libmesh/ignore_warnings.h" 38 : #include "hilbert.h" 39 : #include "libmesh/restore_warnings.h" 40 : 41 : #include <cstddef> 42 : #include <utility> 43 : 44 : namespace TIMPI { 45 : 46 : #ifdef LIBMESH_HAVE_MPI 47 : // A StandardType<> specialization to return a derived MPI datatype 48 : // to handle communication of HilbertIndices. We use a singleton 49 : // pattern here because a global variable would have tried to call 50 : // MPI functions before MPI got initialized. 51 : template <> 52 : class StandardType<Hilbert::HilbertIndices> : public DataType 53 : { 54 : public: 55 : explicit 56 1190 : StandardType(const Hilbert::HilbertIndices * =nullptr) 57 1190 : { 58 1190 : _datatype = DataType(StandardType<Hilbert::inttype>(), 3); 59 1190 : } 60 : 61 : StandardType(const StandardType<Hilbert::HilbertIndices> & t) 62 : : DataType() 63 : { 64 : timpi_call_mpi (MPI_Type_dup (t._datatype, &_datatype)); 65 : } 66 : 67 1190 : ~StandardType() { this->free(); } 68 : 69 : static const bool is_fixed_type = true; 70 : }; 71 : 72 : #endif // LIBMESH_HAVE_MPI 73 : 74 : } // namespace TIMPI 75 : 76 : 77 : namespace libMesh { 78 : 79 : namespace Parallel { 80 : 81 : /** 82 : * The key by which DofObjects are sorted for partition-agnostic numbering: the Hilbert index of 83 : * the object's location and a tiebreaker for objects that share a location, such as a parent 84 : * element and a child with the same vertex average. The tiebreaker is the object's unique id when 85 : * unique ids are enabled; otherwise it is the element level, and zero for nodes. 86 : */ 87 : typedef std::pair<Hilbert::HilbertIndices, unique_id_type> DofObjectKey; 88 : 89 : } // namespace Parallel 90 : 91 : } // namespace libMesh 92 : 93 : 94 : namespace Hilbert { 95 : 96 : // This has to be in the Hilbert namespace for Koenig lookup to work? 97 : // g++ doesn't find it if it's in the global namespace. 98 : // XCode didn't find it in the libMesh namespace. 99 : inline 100 0 : std::ostream & operator << (std::ostream & os, 101 : const libMesh::Parallel::DofObjectKey & hilbert_pair) 102 : { 103 0 : os << '(' << hilbert_pair.first << ',' << hilbert_pair.second << ')' << std::endl; 104 0 : return os; 105 : } 106 : 107 : } 108 : 109 : 110 : // Appropriate operator< definitions for std::pair let the same code handle 111 : // both DofObjectKey types 112 : 113 : inline 114 25648 : void dofobjectkey_max_op (libMesh::Parallel::DofObjectKey * in, 115 : libMesh::Parallel::DofObjectKey * inout, 116 : int * len, void *) 117 : { 118 : // When (*in <= *inout), then inout already contains max(*in,*inout) 119 : // Otherwise we need to copy from in. 120 51296 : for (int i=0; i<*len; i++, in++, inout++) 121 25648 : if (*inout < *in) 122 1899 : *inout = *in; 123 25648 : } 124 : 125 : inline 126 25648 : void dofobjectkey_min_op (libMesh::Parallel::DofObjectKey * in, 127 : libMesh::Parallel::DofObjectKey * inout, 128 : int * len, void *) 129 : { 130 : // When (*in >= *inout), then inout already contains min(*in,*inout) 131 : // Otherwise we need to copy from in. 132 51296 : for (int i=0; i<*len; i++, in++, inout++) 133 25648 : if (*in < *inout) 134 1953 : *inout = *in; 135 25648 : } 136 : 137 : #endif // LIBMESH_HAVE_LIBHILBERT 138 : 139 : #endif // LIBMESH_PARALLEL_HILBERT_H