16#define scint64_t static_cast<int64_t>
17#define scint static_cast<int>
18#define scshort static_cast<short>
24 const uint64_t global_size,
25 const MPI_Comm communicator)
27 extents_(DefineExtents(local_size, process_count_, communicator)),
28 values_(local_size_, 0.0)
33 :
ParallelVector(other), extents_(other.extents_), values_(other.values_)
39 extents_(other.extents_),
40 values_(std::move(other.values_))
46 return std::make_unique<ParallelSTLVector>(*
this);
51 auto new_vec = std::make_unique<ParallelSTLVector>(*
this);
70 return std::vector<double>(
values_.begin(),
77 "Invalid local index provided. " +
78 std::to_string(local_id) +
" vs [0," +
79 std::to_string(
values_.size()) +
")");
87 "Invalid local index provided. " +
88 std::to_string(local_id) +
" vs [0," +
89 std::to_string(
values_.size()) +
")");
102 "Incompatible local vector size.");
106 std::copy(local_vector.begin(),
112 int64_t local_offset,
116 "y.size() < num_values " + std::to_string(y.size()) +
117 " < " + std::to_string(num_values));
119 const int64_t local_end = local_offset + num_values;
122 "local_offset + num_values=" + std::to_string(local_end) +
123 ", is out of range for destination vector with local size " +
126 std::copy(y.begin(), y.begin() + num_values,
values_.begin() + local_offset);
132 "y.LocalSize() != local_size_");
134 "y.GlobalSize() != global_size_");
138 const double* y_data = y.
Data();
146 VecGetLocalSize(y, &n);
149 "Attempted update with a vector of insufficient size.");
152 VecGetArrayRead(y, &x);
153 std::copy(x, x + n,
values_.begin());
154 VecRestoreArrayRead(y, &x);
159 int64_t local_offset,
165 const int64_t y_end = y_offset + num_values;
166 const int64_t local_end = local_offset + num_values;
169 "y_offset + num_values=" + std::to_string(y_end) +
170 ", is out of range for vector y with local size " +
175 "local_offset + num_values=" + std::to_string(local_end) +
176 ", is out of range for destination vector with local size " +
181 const double* y_data = y.
Data();
183 std::copy(y_data + y_offset,
184 y_data + y_offset + num_values,
185 values_.begin() + local_offset);
190 int64_t local_offset,
196 const int64_t y_end = y_offset + num_values;
197 const int64_t local_end = local_offset + num_values;
199 int64_t y_local_size;
200 VecGetLocalSize(y, &y_local_size);
203 "y_offset + num_values=" + std::to_string(y_end) +
204 ", is out of range for vector y with local size " +
205 std::to_string(y_local_size));
209 "local_offset + num_values=" + std::to_string(local_end) +
210 ", is out of range for destination vector with local size " +
213 const double* y_data;
214 VecGetArrayRead(y, &y_data);
216 std::copy(y_data + y_offset,
217 y_data + y_offset + num_values,
218 values_.begin() + local_offset);
220 VecRestoreArrayRead(y, &y_data);
228 "Invalid global index encountered. Global indices "
229 "must be in the range [0, this->GlobalSize()].");
232 op_cache.emplace_back(global_id, value);
236 const std::vector<double>& values,
240 "Size mismatch between indices and values.");
243 for (
size_t i = 0; i < global_ids.size(); ++i)
245 const auto& global_id = global_ids[i];
247 "Invalid global index encountered. Global indices "
248 "must be in the range [0, this->GlobalSize()].");
249 op_cache.emplace_back(global_id, values[i]);
256 "y.LocalSize() != local_size_");
258 "y.GlobalSize() != global_size_");
262 const double* y_data = y.
Data();
271 "y.LocalSize() != local_size_");
273 "y.GlobalSize() != global_size_");
277 const double* y_data = y.
Data();
293 "y.LocalSize() != local_size_");
295 "y.GlobalSize() != global_size_");
299 const double* y_data = y.
Data();
324 const double local_norm_val = std::accumulate(
327 double global_norm_val;
328 MPI_Allreduce(&local_norm_val,
335 return global_norm_val;
339 double local_norm_val = 0.0;
342 const double value =
values_[i];
343 local_norm_val += value * value;
345 double global_norm_val;
346 MPI_Allreduce(&local_norm_val,
353 return std::sqrt(global_norm_val);
357 const double local_norm_val = *std::max_element(
360 double global_norm_val;
361 MPI_Allreduce(&local_norm_val,
368 return global_norm_val;
385 MPI_Allreduce(&local_mode, &global_mode, 1, MPI_SHORT, MPI_MAX,
comm_);
388 if (global_mode == 0)
return;
392 local_mode != 0 and local_mode != global_mode,
393 "The operation on each process must be either 0 (do nothing),"
394 "or the same across all processes.");
398 const auto global_op_type =
static_cast<OpType
>(global_mode);
403 std::vector<std::pair<int64_t, double>> local_cache;
404 std::vector<std::pair<int64_t, double>> nonlocal_cache;
405 for (
const auto& op : op_cache)
408 if (op_pid ==
location_id_) local_cache.emplace_back(op);
410 nonlocal_cache.emplace_back(op);
414 for (
const auto& [global_id, value] : local_cache)
418 "Invalid mapping from global to local.");
420 if (global_op_type == OpType::SET_VALUE)
values_[local_id] = value;
430 std::map<int, chi_data_types::ByteArray> pid_send_map;
431 for (
const auto& [global_id, value] : nonlocal_cache)
434 auto& byte_array = pid_send_map[pid];
435 byte_array.Write(global_id);
436 byte_array.Write(value);
441 std::map<int, std::vector<std::byte>> pid_send_map_bytes;
442 for (
const auto& [pid, byte_array] : pid_send_map)
443 pid_send_map_bytes[pid] = byte_array.Data();
450 std::map<int, std::vector<std::byte>> pid_recv_map_bytes =
455 for (
const auto& [pid, byte_vector] : pid_recv_map_bytes)
457 const auto packet_size =
sizeof(std::pair<int64_t, double>);
460 byte_vector.size() % packet_size != 0,
461 "Unrecognized received operations. Operations are serialized with "
462 "an int64_t and double, but the received packet from process " +
463 std::to_string(pid) +
" on process " + std::to_string(
location_id_) +
464 " is not an integer multiple of the size of an int64_t and double.");
466 const size_t num_ops = byte_vector.size() / packet_size;
468 for (
size_t k = 0; k < num_ops; ++k)
470 const int64_t global_id = byte_array.
Read<int64_t>();
471 const double value = byte_array.
Read<
double>();
477 "A non-local global ID was received by process " +
479 std::to_string(pid) +
" during vector assembly.");
482 if (global_op_type == OpType ::SET_VALUE)
values_[local_id] = value;
494 MPI_Comm communicator)
497 std::vector<uint64_t> local_sizes(comm_size, 0);
498 MPI_Allgather(&local_size,
510 std::vector<uint64_t> extents(comm_size + 1, 0);
511 for (
size_t p = 1; p < comm_size; ++p)
512 extents[p] = extents[p - 1] + local_sizes[p - 1];
513 extents[comm_size] = extents[comm_size - 1] + local_sizes.back();
521 "Invalid global id specified.");
530 std::stringstream ss;
531 for (
size_t i = 0; i <
values_.size(); ++i)
532 ss << (i == 0 ?
"[" :
"") <<
values_[i]
533 << (i <
values_.size() - 1 ?
" " :
"]");
#define ChiLogicalErrorIf(condition, message)
#define ChiInvalidArgumentIf(condition, message)
const std::vector< uint64_t > extents_
const std::vector< double > & LocalSTLData() const
void SetValue(int64_t global_id, double value, VecOpType op_type) override
ParallelSTLVector(uint64_t local_size, uint64_t global_size, MPI_Comm communicator)
double ComputeNorm(chi_math::NormType norm_type) const override
std::unique_ptr< ParallelVector > MakeClone() const override
void BlockSet(const std::vector< double > &y, int64_t local_offset, int64_t num_values) override
void SetValues(const std::vector< int64_t > &global_ids, const std::vector< double > &values, VecOpType op_type) override
void PlusAY(const ParallelVector &y, double a) override
void AXPlusY(double a, const ParallelVector &y) override
int FindOwnerPID(uint64_t global_id) const
void operator+=(const ParallelVector &y) override
void Shift(double a) override
std::vector< double > values_
void Scale(double a) override
void BlockCopyLocalValues(const ParallelVector &y, int64_t y_offset, int64_t local_offset, int64_t num_values) override
static std::vector< uint64_t > DefineExtents(uint64_t local_size, int comm_size, MPI_Comm communicator)
void Set(double value) override
double operator[](int64_t local_id) const override
std::vector< Operation > add_cache_
std::string PrintStr() const override
Print the local vectors to stings.
std::vector< double > MakeLocalVector() override
Return a vector containing the locally owned data.
std::vector< Operation > set_cache_
void CopyLocalValues(const ParallelVector &y) override
std::unique_ptr< ParallelVector > MakeCopy() const override
const uint64_t global_size_
virtual double * Data()=0
const uint64_t local_size_
uint64_t GlobalSize() const
Return the global size of the parallel vector.
uint64_t LocalSize() const
Return the size of the locally owned portion of the parallel vector.
std::map< K, std::vector< T > > MapAllToAll(const std::map< K, std::vector< T > > &pid_data_pairs, const MPI_Datatype data_mpi_type, const MPI_Comm communicator=Chi::mpi.comm)