libMesh
Loading...
Searching...
No Matches
parallel_bin_sorter.C
Go to the documentation of this file.
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// C++ includes
20#include <algorithm> // is_sorted, lower_bound
21
22// Local includes
23#include "libmesh/libmesh_common.h"
24#include "libmesh/parallel.h"
25#include "libmesh/parallel_bin_sorter.h"
26#include "libmesh/parallel_hilbert.h"
27#include "libmesh/parallel_histogram.h"
28#include "libmesh/parallel_conversion_utils.h"
29
30namespace libMesh
31{
32
33
34
35namespace Parallel {
36
37template <typename KeyType, typename IdxType>
39 const std::vector<KeyType> & d) :
40 ParallelObject(comm_in),
41 data(d)
42{
43 libmesh_assert (std::is_sorted (data.begin(), data.end()));
44}
45
46
47
48template <typename KeyType, typename IdxType>
49void BinSorter<KeyType,IdxType>::binsort (const IdxType nbins,
50 KeyType max,
51 KeyType min)
52{
53 libmesh_assert_less (min, max);
54
55 // Build a histogram in parallel from our data.
56 // Use this to create quasi-uniform bins.
57 Parallel::Histogram<KeyType,IdxType> phist (this->comm(), data);
58 phist.make_histogram (nbins*50, max, min);
59 phist.build_histogram ();
60
61 const std::vector<IdxType> & histogram =
62 phist.get_histogram();
63
64
65 // Now we will locate the bin boundaries so
66 // that each bin is roughly equal size
67 {
68 // Find the total size of the data set
69 IdxType local_data_size = cast_int<IdxType>(data.size());
70 IdxType global_data_size = cast_int<IdxType>(local_data_size);
71
72 this->comm().sum(global_data_size);
73
74 std::vector<IdxType> target_bin_size (nbins, global_data_size / nbins);
75
76 // Equally distribute the remainder
77 for (IdxType i=0; i<(global_data_size % nbins); i++)
78 ++target_bin_size[i];
79
80 // Set the iterators corresponding to the bin boundaries
81 {
82 std::vector<double> bin_bounds (nbins+1);
83 bin_iters.resize (nbins+1, data.begin());
84
85 // Set the minimum bin boundary iterator
86 bin_iters[0] = data.begin();
87 bin_bounds[0] = Parallel::Utils::to_double(min);
88
89 // The current location in the histogram
90 IdxType current_histogram_bin = 0;
91
92 // How much above (+) or below (-) we are from the
93 // target size for the last bin.
94 // Note that when delta is (-) we will
95 // accept a slightly larger size for the next bin,
96 // the goal being to keep the whole mess average
97 int delta = 0;
98
99 // Set the internal bin boundary iterators
100 for (IdxType b=0; b<nbins; ++b)
101 {
102 // The size of bin b. We want this to
103 // be ~= target_bin_size[b]
104 int current_bin_size = 0;
105
106 // Step through the histogram until we have the
107 // desired bin size
108 while ((current_bin_size +
109 cast_int<int>(histogram[current_histogram_bin]) +
110 delta) <= cast_int<int>(target_bin_size[b]))
111 {
112 // Don't index out of the histogram!
113 if ((current_histogram_bin+1) == phist.n_bins())
114 break;
115
116 current_bin_size += histogram[current_histogram_bin++];
117 }
118
119 delta += current_bin_size - static_cast<int>(target_bin_size[b]);
120
121 // Set the upper bound of the bin
122 bin_bounds[b+1] = phist.upper_bound (current_histogram_bin);
123 bin_iters[b+1] =
124 std::lower_bound(bin_iters[b], data.end(),
126 }
127
128 // Just be sure the last boundary points to the right place
129 bin_iters[nbins] = data.end();
130 // This gets destructed here anyway
131 // bin_bounds[nbins] = Parallel::Utils::to_double(max);
132 }
133 }
134}
135
136}
137
138
139// Explicitly instantiate for int, double
140template class LIBMESH_EXPORT Parallel::BinSorter<int, unsigned int>;
141template class LIBMESH_EXPORT Parallel::BinSorter<double, unsigned int>;
142#ifdef LIBMESH_HAVE_LIBHILBERT
144#endif
145
146} // namespace libMesh
An object whose state is distributed along a set of processors.
Perform a parallel sort using a bin-sort method.
void binsort(const IdxType nbins, KeyType max, KeyType min)
The actual function which sorts the data into nbins.
const std::vector< KeyType > & data
BinSorter(const Parallel::Communicator &comm, const std::vector< KeyType > &d)
Defines a histogram to be used in parallel in conjunction with a BinSorter.
const std::vector< IdxType > & get_histogram() const
void make_histogram(const IdxType nbins, KeyType max, KeyType min)
The actual function which sorts the data into nbins.
double upper_bound(const IdxType bin) const
IdxType n_bins() const
The number of bins in the histogram.
void build_histogram()
Build the histogram across all processors and store the result in the input vector hist.
static const Real b
double to_double(const KeyType &k)
A utility function which converts whatever KeyType is to a double for the histogram bounds.
The libMesh namespace provides an interface to certain functionality in the library.
libmesh_assert(ctx)
A utility to convert a double to some sort of KeyType, for interpreting how histogram bounds relate t...