iterative-solver 0.0
 
Loading...
Searching...
No Matches
DistrArray.h
1#ifndef LINEARALGEBRA_SRC_MOLPRO_LINALG_ARRAY_DISTRARRAY_H
2#define LINEARALGEBRA_SRC_MOLPRO_LINALG_ARRAY_DISTRARRAY_H
3#include <cmath>
4#include <cstdlib>
5#include <list>
6#include <map>
7#include <memory>
8#include <string>
9#include <molpro/mpi.h>
10#include <vector>
11#include <type_traits>
12#include <compare>
13#include <iterator>
14#include <ranges>
15
16#include <molpro/linalg/array/Span.h>
17#include <molpro/linalg/array/util/Distribution.h>
18
19namespace molpro::linalg::array {
20namespace util {
31 template<typename Array>
32 class ValueProxy {
33 public:
34 ValueProxy(const ValueProxy &) = delete;
35 ValueProxy(ValueProxy &&) = delete;
36
37 // Assigning a proxy writes the *value* it refers to into this proxy's cell,
38 // rather than rebinding this proxy to a different array/index -- that keeps
39 // *it1 = *it2 (as used by std::copy et al.) working between two DistrArrays.
40 ValueProxy &operator=(const ValueProxy &other) { return *this = static_cast<typename Array::value_type>(other); }
41 ValueProxy &operator=(ValueProxy &&other) { return *this = static_cast<typename Array::value_type>(other); }
42 template <typename OtherArray>
44 return *this = static_cast<typename OtherArray::value_type>(other);
45 }
46
47 ValueProxy &operator=(Array::value_type val) {
48 m_arr.set(m_idx, std::move(val));
49
50 return *this;
51 }
52
53 operator typename Array::value_type() const {
54 return m_arr.at(m_idx);
55 }
56
57 private:
58 std::add_lvalue_reference_t<Array> m_arr;
59 Array::index_type m_idx;
60
61 friend std::remove_const_t<Array>;
62
63 ValueProxy(std::add_lvalue_reference_t<Array> arr, Array::index_type idx) : m_arr(arr), m_idx(idx) {}
64 };
65}
139public:
140 using distributed_array = void;
141 using value_type = double;
142 using index_type = size_t;
143 using SparseArray = std::map<index_type, double>;
145
146protected:
148 MPI_Comm m_communicator;
150 DistrArray(size_t dimension, MPI_Comm commun);
151 DistrArray() = default;
152
153public:
154 virtual ~DistrArray() = default;
155 // Declared explicitly because the user-declared destructor suppresses the implicit move operations
156 DistrArray(const DistrArray&) = default;
157 DistrArray(DistrArray&&) noexcept = default;
158 DistrArray& operator=(const DistrArray&) = default;
159 DistrArray& operator=(DistrArray&&) noexcept = default;
160
162 MPI_Comm communicator() const { return m_communicator; }
164 virtual void sync() const;
166 size_t size() const { return m_dimension; };
168 bool compatible(const DistrArray &other) const;
169
174protected:
176 class LocalBuffer : public span::Span<value_type> {
177 public:
178 virtual ~LocalBuffer() = default;
180 friend void swap(LocalBuffer &, LocalBuffer &) = delete;
182 bool compatible(const LocalBuffer &other) const { return start() == other.start() && size() == other.size(); };
184 size_type start() const { return m_start; }
185
186 protected:
188 };
189
190public:
192 [[nodiscard]] virtual std::unique_ptr<LocalBuffer> local_buffer() = 0;
193 [[nodiscard]] virtual std::unique_ptr<const LocalBuffer> local_buffer() const = 0;
195 [[nodiscard]] virtual const Distribution &distribution() const = 0;
198 [[nodiscard]] virtual size_t disk_page_size() const { return 0; }
200
206 [[nodiscard]] virtual value_type at(index_type ind) const = 0;
207 [[nodiscard]] value_type operator[](index_type ind) const;
210 virtual void set(index_type ind, value_type val) = 0;
212 virtual void get(index_type lo, index_type hi, value_type *buf) const = 0;
213 [[nodiscard]] virtual std::vector<value_type> get(index_type lo, index_type hi) const = 0;
215 virtual void put(index_type lo, index_type hi, const value_type *data) = 0;
217 virtual void acc(index_type lo, index_type hi, const value_type *data) = 0;
222 [[nodiscard]] virtual std::vector<value_type> gather(const std::vector<index_type> &indices) const = 0;
227 virtual void scatter(const std::vector<index_type> &indices, const std::vector<value_type> &data) = 0;
233 virtual void scatter_acc(std::vector<index_type> &indices, const std::vector<value_type> &data) = 0;
238 [[nodiscard]] virtual std::vector<value_type> vec() const = 0;
240
245 virtual void fill(value_type val);
248 virtual void copy(const DistrArray &y);
256 virtual void copy_patch(const DistrArray &y, index_type start, index_type end);
261 virtual void axpy(value_type a, const DistrArray &y);
262 virtual void axpy(value_type a, const SparseArray &y);
264 void copy(const SparseArray &y);
266
278 void copy_to(Span<value_type> y) const;
281 void axpy_to(value_type a, Span<value_type> y) const;
283 [[nodiscard]] value_type dot(Span<const value_type> y) const;
285 [[nodiscard]] std::map<size_t, value_type> select_max_dot(size_t n, Span<const value_type> y) const;
287
292 virtual void scal(value_type a);
294 virtual void add(const DistrArray &y);
296 virtual void add(value_type a);
298 virtual void sub(const DistrArray &y);
300 virtual void sub(value_type a);
302 virtual void recip();
304 virtual void times(const DistrArray &y);
306 virtual void times(const DistrArray &y, const DistrArray &z);
308
312
317 [[nodiscard]] virtual value_type dot(const DistrArray &y) const;
318 [[nodiscard]] virtual value_type dot(const SparseArray &y) const;
319
331 void divide(const DistrArray &y, const DistrArray &z, value_type shift = 0, bool append = false,
332 bool negative = false) {
333 _divide(y, z, shift, append, negative);
334 }
335
341 [[nodiscard]] std::list<std::pair<index_type, value_type>> min_n(int n) const;
342
348 [[nodiscard]] std::list<std::pair<index_type, value_type>> max_n(int n) const;
349
355 [[nodiscard]] std::list<std::pair<index_type, value_type>> min_abs_n(int n) const;
356
362 [[nodiscard]] std::list<std::pair<index_type, value_type>> max_abs_n(int n) const;
363
369 [[nodiscard]] std::vector<index_type> min_loc_n(int n) const;
370
371 [[nodiscard]] std::map<size_t, value_type> select_max_dot(size_t n, const DistrArray &y) const;
372 [[nodiscard]] std::map<size_t, value_type> select_max_dot(size_t n, const SparseArray &y) const;
373 [[nodiscard]] std::map<size_t, value_type> select(size_t n, bool max = false, bool ignore_sign = false) const;
375
377 virtual void zero();
378
380 virtual void error(const std::string &message) const;
381
382protected:
384 void check_compatible(Span<const value_type> y, const std::string &name) const;
385 virtual void _divide(const DistrArray &y, const DistrArray &z, value_type shift, bool append, bool negative);
386};
387
388namespace util {
389template <typename T, class Compare>
391 constexpr bool operator()(const T &lhs, const T &rhs) const { return Compare()(std::abs(lhs), std::abs(rhs)); }
392};
393template <class Compare>
394[[nodiscard]] std::list<std::pair<DistrArray::index_type, DistrArray::value_type>> extrema(const DistrArray &x, int n);
395std::map<size_t, double> select_max_dot_broadcast(size_t n, std::map<size_t, double> &local_selection,
396 MPI_Comm communicator);
397#ifdef HAVE_MPI_H
399inline MPI_Datatype mpi_index_type() {
400 static_assert(sizeof(DistrArray::index_type) == sizeof(unsigned long) ||
401 sizeof(DistrArray::index_type) == sizeof(unsigned long long));
402 return sizeof(DistrArray::index_type) == sizeof(unsigned long) ? MPI_UNSIGNED_LONG : MPI_UNSIGNED_LONG_LONG;
403}
404#endif
405
406template<bool is_const>
408 public:
409 using value_type = std::conditional_t<
413 using difference_type = std::ptrdiff_t;
414 // *this dereferences to a proxy, not an lvalue reference, so there is no meaningful
415 // pointer type. iterator_category is spelled out explicitly because std::iterator_traits'
416 // legacy (pre-C++20) fallback cannot deduce past input_iterator_tag for a proxy iterator,
417 // which would make std::fill/std::copy etc. reject the single-pass-only overloads even
418 // though this iterator satisfies std::random_access_iterator (see the static_assert below).
419 using pointer = void;
420 using iterator_category = std::random_access_iterator_tag;
421
423 DistrArrayIteratorImpl(std::conditional_t<is_const, const DistrArray, DistrArray> &array,
424 DistrArray::index_type pos) : m_arr(&array), m_pos(pos) {}
425
427 m_pos += val;
428 return *this;
429 }
431 return DistrArrayIteratorImpl(*it.m_arr, it.m_pos + val);
432 }
434 return it + val;
435 }
437 ++m_pos;
438 return *this;
439 }
441 DistrArrayIteratorImpl copy(*this);
442 ++m_pos;
443 return copy;
444 }
445
447 m_pos -= val;
448 return *this;
449 }
451 return DistrArrayIteratorImpl(*it.m_arr, it.m_pos - val);
452 }
454 --m_pos;
455 return *this;
456 }
458 DistrArrayIteratorImpl copy(*this);
459 --m_pos;
460 return copy;
461 }
462
463 reference operator*() const { return (*m_arr)[m_pos]; }
464
465 reference operator[](difference_type offset) const { return (*m_arr)[m_pos + offset]; }
466
467 difference_type operator-(const DistrArrayIteratorImpl &other) const { return m_pos - other.m_pos; }
468
469 bool operator==(const DistrArrayIteratorImpl &) const = default;
470 std::strong_ordering operator<=>(const DistrArrayIteratorImpl &) const = default;
471
472 private:
473 std::conditional_t<is_const, const DistrArray, DistrArray> *m_arr = nullptr;
474 DistrArray::index_type m_pos = 0;
475};
476
477static_assert(std::random_access_iterator<DistrArrayIteratorImpl<true>>);
478static_assert(std::random_access_iterator<DistrArrayIteratorImpl<false>>);
479
480} // namespace util
481
484
485inline DistrArrayIterator begin(DistrArray &array) { return DistrArrayIterator(array, 0); }
486inline DistrArrayIterator end(DistrArray &array) { return DistrArrayIterator(array, array.size()); }
487inline DistrArrayConstIterator begin(const DistrArray &array) { return DistrArrayConstIterator(array, 0); }
488inline DistrArrayConstIterator end(const DistrArray &array) { return DistrArrayConstIterator(array, array.size()); }
489inline DistrArrayConstIterator cbegin(const DistrArray &array) { return begin(array); }
490inline DistrArrayConstIterator cend(const DistrArray &array) { return end(array); }
491
492} // namespace molpro::linalg::array
493
494#endif // LINEARALGEBRA_SRC_MOLPRO_LINALG_ARRAY_DISTRARRAY_H
Provides access to the local portion of the array.
Definition DistrArray.h:176
bool compatible(const LocalBuffer &other) const
Checks that the current and the other buffers correspond to the same section of their respective arra...
Definition DistrArray.h:182
size_type m_start
index of first element of local buffer in the array
Definition DistrArray.h:187
friend void swap(LocalBuffer &, LocalBuffer &)=delete
size_type start() const
Return index to the start of the local buffer section in the distributed array.
Definition DistrArray.h:184
Array distributed across many processes supporting remote-memory-access, access to process local buff...
Definition DistrArray.h:138
double value_type
Definition DistrArray.h:141
virtual void _divide(const DistrArray &y, const DistrArray &z, value_type shift, bool append, bool negative)
Definition DistrArray.cpp:283
virtual void zero()
Set all local elements to zero.
Definition DistrArray.cpp:207
virtual void fill(value_type val)
Definition DistrArray.cpp:209
virtual void recip()
Take element-wise reciprocal of this. Local. No checks are made for zero values.
Definition DistrArray.cpp:245
void distributed_array
a compile time tag that this is a distributed array
Definition DistrArray.h:140
virtual void copy(const DistrArray &y)
Definition DistrArray.cpp:539
bool compatible(const DistrArray &other) const
Checks that arrays are of the same dimensionality.
Definition DistrArray.cpp:183
std::list< std::pair< index_type, value_type > > min_n(int n) const
returns n smallest elements in array x Collective operation, must be called by all processes in the g...
Definition DistrArray.cpp:516
virtual void axpy(value_type a, const DistrArray &y)
this[:] += a * y[:]. Throws an error if any array is empty. Add a multiple of another array to this o...
Definition DistrArray.cpp:215
MPI_Comm m_communicator
Definition DistrArray.h:148
virtual std::vector< value_type > vec() const =0
Copies the whole buffer into a vector. Blocking.
virtual void get(index_type lo, index_type hi, value_type *buf) const =0
Gets buffer[lo:hi) from global array (hi is past-the-end). Blocking.
virtual void put(index_type lo, index_type hi, const value_type *data)=0
array[lo:hi) = data[:] (hi is past-the-end). Blocking
std::list< std::pair< index_type, value_type > > max_n(int n) const
returns n largest elements in array x Collective operation, must be called by all processes in the gr...
Definition DistrArray.cpp:520
virtual std::vector< value_type > get(index_type lo, index_type hi) const =0
std::map< index_type, double > SparseArray
Definition DistrArray.h:143
virtual size_t disk_page_size() const
Definition DistrArray.h:198
virtual void set(index_type ind, value_type val)=0
Set one element to a scalar. Global operation.
std::map< size_t, value_type > select_max_dot(size_t n, Span< const value_type > y) const
The n indices with the largest |this[i]*y[i]|. Collective.
Definition DistrArray.cpp:642
std::list< std::pair< index_type, value_type > > min_abs_n(int n) const
returns n elements that are largest by absolute value in array x Collective operation,...
Definition DistrArray.cpp:524
std::map< size_t, value_type > select(size_t n, bool max=false, bool ignore_sign=false) const
Definition DistrArray.cpp:403
virtual const Distribution & distribution() const =0
Access distribution of the array among processes.
virtual std::unique_ptr< LocalBuffer > local_buffer()=0
Access the buffer local to this process.
virtual void times(const DistrArray &y)
this[i] *= y[i]. Throws error if any array is empty.
Definition DistrArray.cpp:252
index_type m_dimension
number of elements in the array
Definition DistrArray.h:147
virtual void scatter_acc(std::vector< index_type > &indices, const std::vector< value_type > &data)=0
array[indices[i]] += vals[i] Accumulates vals of elements into discontinuous indices of array....
DistrArray(const DistrArray &)=default
virtual std::vector< value_type > gather(const std::vector< index_type > &indices) const =0
gets elements with discontinuous indices from array. Blocking
virtual void sync() const
Synchronizes all process in this group and ensures any outstanding operations on the array have compl...
Definition DistrArray.cpp:172
virtual void scal(value_type a)
Definition DistrArray.cpp:225
void copy_to(Span< value_type > y) const
y[:] = this[:]. Collective: each process copies its local section, and then y is replicated over all ...
Definition DistrArray.cpp:617
size_t size() const
total number of elements, same as overall dimension of array
Definition DistrArray.h:166
MPI_Comm communicator() const
return a copy of the communicator
Definition DistrArray.h:162
DistrArray(DistrArray &&) noexcept=default
void divide(const DistrArray &y, const DistrArray &z, value_type shift=0, bool append=false, bool negative=false)
this[i] = y[i]/(z[i]+shift). Collective. Throws error if any array is empty.
Definition DistrArray.h:331
virtual void error(const std::string &message) const
stops application with an error
Definition DistrArray.cpp:174
value_type operator[](index_type ind) const
Definition DistrArray.cpp:199
virtual void add(const DistrArray &y)
Add another array to this. Local. Throws error if any array is empty.
Definition DistrArray.cpp:232
std::vector< index_type > min_loc_n(int n) const
find the index of n smallest components in array x Collective operation, must be called by all proces...
Definition DistrArray.cpp:532
void check_compatible(Span< const value_type > y, const std::string &name) const
Stops with an error unless the contiguous array y has as many elements as this.
Definition DistrArray.cpp:606
virtual std::unique_ptr< const LocalBuffer > local_buffer() const =0
virtual value_type at(index_type ind) const =0
virtual void copy_patch(const DistrArray &y, index_type start, index_type end)
Copies elements in a patch of y. If both arrays are empty than does nothing. If only one is empty,...
Definition DistrArray.cpp:546
virtual void acc(index_type lo, index_type hi, const value_type *data)=0
array[lo:hi) += scaling_constant * data[:] (hi is past-the-end). Blocking
size_t index_type
Definition DistrArray.h:142
virtual void scatter(const std::vector< index_type > &indices, const std::vector< value_type > &data)=0
array[indices[i]] = data[i] Puts vals of elements with discontinuous indices of array....
virtual void sub(const DistrArray &y)
Subtract another array from this. Local. Throws error if any array is empty.
Definition DistrArray.cpp:241
value_type dot(Span< const value_type > y) const
Scalar product <this|y>. Collective, the result is available to each process.
Definition DistrArray.cpp:636
void axpy_to(value_type a, Span< value_type > y) const
Definition DistrArray.cpp:628
std::list< std::pair< index_type, value_type > > max_abs_n(int n) const
returns n elements that are largest by absolute value in array x Collective operation,...
Definition DistrArray.cpp:528
Non-owning container taking a pointer to the data buffer and its size and exposing routines for itera...
Definition Span.h:31
size_type size() const
Definition Span.h:80
DistrArrayIteratorImpl & operator++()
Definition DistrArray.h:436
DistrArrayIteratorImpl & operator+=(difference_type val)
Definition DistrArray.h:426
reference operator*() const
Definition DistrArray.h:463
DistrArrayIteratorImpl & operator-=(difference_type val)
Definition DistrArray.h:446
std::strong_ordering operator<=>(const DistrArrayIteratorImpl &) const =default
std::random_access_iterator_tag iterator_category
Definition DistrArray.h:420
friend DistrArrayIteratorImpl operator+(const DistrArrayIteratorImpl &it, difference_type val)
Definition DistrArray.h:430
difference_type operator-(const DistrArrayIteratorImpl &other) const
Definition DistrArray.h:467
friend DistrArrayIteratorImpl operator-(const DistrArrayIteratorImpl &it, difference_type val)
Definition DistrArray.h:450
value_type reference
Definition DistrArray.h:411
DistrArrayIteratorImpl(std::conditional_t< is_const, const DistrArray, DistrArray > &array, DistrArray::index_type pos)
Definition DistrArray.h:423
bool operator==(const DistrArrayIteratorImpl &) const =default
DistrArrayIteratorImpl operator++(int)
Definition DistrArray.h:440
std::conditional_t< is_const, DistrArray::value_type, ValueProxy< DistrArray > > value_type
Definition DistrArray.h:410
reference const_reference
Definition DistrArray.h:412
friend DistrArrayIteratorImpl operator+(difference_type val, const DistrArrayIteratorImpl &it)
Definition DistrArray.h:433
DistrArrayIteratorImpl operator--(int)
Definition DistrArray.h:457
reference operator[](difference_type offset) const
Definition DistrArray.h:465
std::ptrdiff_t difference_type
Definition DistrArray.h:413
DistrArrayIteratorImpl & operator--()
Definition DistrArray.h:453
Specifies distribution of a contiguous array into non-overlapping chunks.
Definition Distribution.h:16
Definition DistrArray.h:32
ValueProxy(const ValueProxy &)=delete
ValueProxy & operator=(const ValueProxy &other)
Definition DistrArray.h:40
ValueProxy & operator=(ValueProxy &&other)
Definition DistrArray.h:41
ValueProxy & operator=(const ValueProxy< OtherArray > &other)
Definition DistrArray.h:43
ValueProxy & operator=(Array::value_type val)
Definition DistrArray.h:47
auto begin(Span< T > &x)
Definition Span.h:90
auto end(Span< T > &x)
Definition Span.h:100
std::map< size_t, double > select_max_dot_broadcast(size_t n, std::map< size_t, double > &local_selection, MPI_Comm communicator)
Definition DistrArray.cpp:314
std::list< std::pair< DistrArray::index_type, DistrArray::value_type > > extrema(const DistrArray &x, int n)
Definition DistrArray.cpp:426
Definition ArrayHandler.h:19
DistrArrayConstIterator cbegin(const DistrArray &array)
Definition DistrArray.h:489
util::DistrArrayIteratorImpl< true > DistrArrayConstIterator
Definition DistrArray.h:483
DistrArrayConstIterator cend(const DistrArray &array)
Definition DistrArray.h:490
util::DistrArrayIteratorImpl< false > DistrArrayIterator
Definition DistrArray.h:482
Definition DistrArray.h:390
constexpr bool operator()(const T &lhs, const T &rhs) const
Definition DistrArray.h:391