https://mooseframework.inl.gov
Loading...
Searching...
No Matches
StochasticToolsUtils.h
Go to the documentation of this file.
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#pragma once
11
12#include "MooseUtils.h"
13#include "libmesh/communicator.h"
14
15namespace StochasticTools
16{
17
21template <typename T>
23{
24 static constexpr bool value = false;
25};
26template <typename T>
27struct canDefaultGather<std::vector<T>>
28{
29 static constexpr bool value = std::is_base_of<TIMPI::DataType, TIMPI::StandardType<T>>::value;
30};
31template <typename T>
33{
34 static constexpr bool value = false;
35};
36template <typename T>
37struct canStochasticGather<std::vector<T>>
38{
39 static constexpr bool value = canStochasticGather<T>::value ||
40 std::is_base_of<TIMPI::DataType, TIMPI::StandardType<T>>::value ||
41 std::is_same<T, std::string>::value || std::is_same<T, bool>::value;
42};
43
44/*
45 * Methods for gathering nested vectors
46 */
47template <typename T>
48void
50{
51 ::mooseError("Cannot gather values of type ", MooseUtils::prettyCppType<T>());
52}
53template <typename T,
54 typename std::enable_if<canDefaultGather<std::vector<T>>::value, int>::type = 0>
55void
57 processor_id_type root_id,
58 std::vector<T> & val)
59{
60 comm.gather(root_id, val);
61}
62template <
63 typename T,
64 typename std::enable_if<canStochasticGather<std::vector<std::vector<T>>>::value, int>::type = 0>
65void
67 processor_id_type root_id,
68 std::vector<std::vector<T>> & val)
69{
70 // Get local vector sizes
71 std::size_t num_local_vecs = val.size();
72 std::vector<std::size_t> val_sizes;
73 val_sizes.reserve(num_local_vecs);
74 std::size_t num_local_vals = 0;
75 for (const auto & v : val)
76 {
77 val_sizes.push_back(v.size());
78 num_local_vals += v.size();
79 }
80
81 // Flatten the local vector of vectors
82 std::vector<T> val_exp;
83 val_exp.reserve(num_local_vals);
84 for (auto & v : val)
85 std::copy(v.begin(), v.end(), std::back_inserter(val_exp));
86
87 // Gather the vector sizes and the flattened vector
88 comm.gather(root_id, val_sizes);
89 stochasticGather(comm, root_id, val_exp);
90
91 // Build the vector of vectors from the gathered flatten vector
92 if (comm.rank() == root_id)
93 {
94 val.resize(val_sizes.size());
95 std::size_t ind = num_local_vals;
96 for (std::size_t i = num_local_vecs; i < val_sizes.size(); ++i)
97 {
98 val[i].resize(val_sizes[i]);
99 std::move(val_exp.begin() + ind, val_exp.begin() + ind + val_sizes[i], val[i].begin());
100 ind += val_sizes[i];
101 }
102 }
103}
104// Gathering a vector of strings hasn't been implemented in libMesh, so just gonna do it the hard
105// way
106template <typename T>
107void
109 processor_id_type root_id,
110 std::vector<std::basic_string<T>> & val)
111{
112 std::vector<std::basic_string<T>> val_gath = val;
113 comm.allgather(val_gath);
114 if (comm.rank() == root_id)
115 val = std::move(val_gath);
116}
117// Gathering bool is weird
118template <typename A>
119void
121 processor_id_type root_id,
122 std::vector<bool, A> & val)
123{
124 std::vector<unsigned short int> temp(val.size());
125 for (std::size_t i = 0; i < val.size(); ++i)
126 temp[i] = val[i] ? 1 : 0;
127 comm.gather(root_id, temp);
128 if (comm.rank() == root_id)
129 {
130 val.resize(temp.size());
131 for (std::size_t i = 0; i < temp.size(); ++i)
132 val[i] = temp[i] == 1;
133 }
134}
135
136/*
137 * Methods for gathering nested vectors on all processors
138 */
139template <typename T>
140void
142{
143 ::mooseError("Cannot gather values of type ", MooseUtils::prettyCppType<T>());
144}
145template <typename T,
146 typename std::enable_if<canDefaultGather<std::vector<T>>::value, int>::type = 0>
147void
148stochasticAllGather(const libMesh::Parallel::Communicator & comm, std::vector<T> & val)
149{
150 comm.allgather(val);
151}
152template <
153 typename T,
154 typename std::enable_if<canStochasticGather<std::vector<std::vector<T>>>::value, int>::type = 0>
155void
156stochasticAllGather(const libMesh::Parallel::Communicator & comm, std::vector<std::vector<T>> & val)
157{
158 // Get local vector sizes
159 std::size_t num_local_vecs = val.size();
160 std::vector<std::size_t> val_sizes;
161 val_sizes.reserve(num_local_vecs);
162 std::size_t num_local_vals = 0;
163 for (const auto & v : val)
164 {
165 val_sizes.push_back(v.size());
166 num_local_vals += v.size();
167 }
168
169 // Flatten the local vector of vectors
170 std::vector<T> val_exp;
171 val_exp.reserve(num_local_vals);
172 for (auto & v : val)
173 std::copy(v.begin(), v.end(), std::back_inserter(val_exp));
174
175 // Gather the vector sizes and the flattened vector
176 comm.allgather(val_sizes);
177 stochasticAllGather(comm, val_exp);
178
179 // Build the vector of vectors from the gathered flatten vector
180 val.resize(val_sizes.size());
181 std::size_t ind = 0;
182 for (std::size_t i = 0; i < val_sizes.size(); ++i)
183 {
184 val[i].resize(val_sizes[i]);
185 std::move(val_exp.begin() + ind, val_exp.begin() + ind + val_sizes[i], val[i].begin());
186 ind += val_sizes[i];
187 }
188}
189// Gathering a vector of strings hasn't been implemented in libMesh, so just gonna do it the hard
190// way
191template <typename T>
192void
194 std::vector<std::basic_string<T>> & val)
195{
196 comm.allgather(val);
197}
198// Gathering bool is weird
199template <typename A>
200void
201stochasticAllGather(const libMesh::Parallel::Communicator & comm, std::vector<bool, A> & val)
202{
203 std::vector<unsigned short int> temp(val.size());
204 for (std::size_t i = 0; i < val.size(); ++i)
205 temp[i] = val[i] ? 1 : 0;
206 comm.allgather(temp);
207 val.resize(temp.size());
208 for (std::size_t i = 0; i < temp.size(); ++i)
209 val[i] = temp[i] == 1;
210}
211
212/*
213 * Methods for sorting vectors of vectors with elements inplace. For example:
214 * {{7, 5, 2}, {3, 8, 6}, {9, 9, 1}} -> {{3, 5, 1}, {7, 8, 2}, {9, 9, 6}}
215 */
216template <typename T>
217void
218inplaceSort(std::vector<T> & values)
219{
220 std::sort(values.begin(), values.end());
221}
222template <typename T>
223void
224inplaceSort(std::vector<std::vector<T>> & values)
225{
226 if (values.empty())
227 return;
228
229 const std::size_t sz = values[0].size();
230 mooseAssert(std::find_if(values.begin(),
231 values.end(),
232 [&sz](const std::vector<T> & val)
233 { return val.size() != sz; }) == values.end(),
234 "All vectors must be same size to sort.");
235
236 std::vector<T> vals(values.size());
237 for (const auto & i : make_range(sz))
238 {
239 for (const auto & k : index_range(values))
240 vals[k] = values[k][i];
241 inplaceSort(vals);
242 for (const auto & k : index_range(values))
243 values[k][i] = std::move(vals[k]);
244 }
245}
246
257template <typename T>
258std::vector<std::vector<T>>
259reshapeVector(const std::vector<T> & vec, std::size_t n, bool row_major)
260{
261 const auto nelem = vec.size();
262 const auto nrow = row_major ? nelem / n : n;
263 const auto ncol = row_major ? n : nelem / n;
264 if (nelem % n != 0)
265 ::mooseError(
266 "Reshaping dimensions (", nrow, ", ", ncol, ") does not match vector size (", nelem, ").");
267
268 std::vector<std::vector<T>> mat(nrow, std::vector<T>(ncol));
269 for (const auto & i : make_range(nrow))
270 for (const auto & j : make_range(ncol))
271 {
272 const auto k = row_major ? (i * ncol + j) : (j * nrow + i);
273 mat[i][j] = vec[k];
274 }
275 return mat;
276}
277
278} // StochasticTools namespace
const double T
const double v
std::array< Real, 2 > values
processor_id_type rank() const
void gather(const unsigned int root_id, const T &send_data, std::vector< T, A > &recv) const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
Enum for batch type in stochastic tools MultiApp.
void stochasticGather(const libMesh::Parallel::Communicator &, processor_id_type, T &)
void stochasticAllGather(const libMesh::Parallel::Communicator &, T &)
std::vector< std::vector< T > > reshapeVector(const std::vector< T > &vec, std::size_t n, bool row_major)
Reshape a vector into matrix-like vector of vectors.
void inplaceSort(std::vector< T > &values)
Custom type trait that has a value of true for types that can be gathered.