Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 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 : 20 : // Local Includes 21 : #include "libmesh/linear_partitioner.h" 22 : #include "libmesh/libmesh_logging.h" 23 : #include "libmesh/elem.h" 24 : #include "libmesh/enum_partitioner_type.h" 25 : #include "libmesh/parallel.h" 26 : 27 : namespace libMesh 28 : { 29 : 30 142 : PartitionerType LinearPartitioner::type() const 31 : { 32 142 : return LINEAR_PARTITIONER; 33 : } 34 : 35 : 36 2194 : void LinearPartitioner::partition_range(MeshBase & mesh, 37 : MeshBase::element_iterator it, 38 : MeshBase::element_iterator end, 39 : const unsigned int n) 40 : { 41 2194 : const bool mesh_is_serial = mesh.is_serial(); 42 : 43 : // Check for easy returns 44 2194 : if (it == end && mesh_is_serial) 45 71 : return; 46 : 47 2123 : if (n == 1) 48 : { 49 0 : this->single_partition_range (it, end); 50 0 : return; 51 : } 52 : 53 50 : libmesh_assert_greater (n, 0); 54 : 55 : // Create a simple linear partitioning 56 100 : LOG_SCOPE ("partition_range()", "LinearPartitioner"); 57 : 58 : // This has to be an ordered set 59 100 : std::set<dof_id_type> element_ids; 60 : 61 : // If we're on a serialized mesh, we know our range is the same on 62 : // every processor. 63 2123 : if (mesh_is_serial) 64 : { 65 : const dof_id_type blksize = cast_int<dof_id_type> 66 1034 : (std::distance(it, end) / n); 67 : 68 44 : dof_id_type e = 0; 69 23813 : for (auto & elem : as_range(it, end)) 70 : { 71 21789 : if ((e/blksize) < n) 72 20187 : elem->processor_id() = cast_int<processor_id_type>(e/blksize); 73 : else 74 1602 : elem->processor_id() = 0; 75 : 76 21789 : e++; 77 946 : } 78 : } 79 : // If we're on a replicated mesh, we might have different ranges on 80 : // different processors, and we'll need to gather the full range. 81 : // 82 : // This is not an efficient way to do this, but if you want to be 83 : // efficient then you want to be using a different partitioner to 84 : // begin with; LinearPartitioner is more for debugging than 85 : // performance. 86 : else 87 : { 88 19447 : for (const auto & elem : as_range(it, end)) 89 18352 : element_ids.insert(elem->id()); 90 : 91 1089 : mesh.comm().set_union(element_ids); 92 : 93 : const dof_id_type blksize = cast_int<dof_id_type> 94 1089 : (element_ids.size() / n); 95 : 96 6 : dof_id_type e = 0; 97 56193 : for (auto eid : element_ids) 98 : { 99 55104 : Elem * elem = mesh.query_elem_ptr(eid); 100 55104 : if (elem) 101 : { 102 17275 : if ((e/blksize) < n) 103 16432 : elem->processor_id() = cast_int<processor_id_type>(e/blksize); 104 : else 105 843 : elem->processor_id() = 0; 106 : } 107 : 108 55104 : e++; 109 : } 110 : } 111 : } 112 : 113 : 114 : 115 1798 : void LinearPartitioner::_do_partition (MeshBase & mesh, 116 : const unsigned int n) 117 : { 118 1798 : this->partition_range(mesh, 119 3596 : mesh.active_elements_begin(), 120 1850 : mesh.active_elements_end(), 121 104 : n); 122 1798 : } 123 : 124 : } // namespace libMesh