libMesh
distributed_vector.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 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 #include "libmesh/libmesh_common.h"
21 
22 
23 
24 #ifndef LIBMESH_DISTRIBUTED_VECTOR_H
25 #define LIBMESH_DISTRIBUTED_VECTOR_H
26 
27 // Local includes
28 #include "libmesh/int_range.h"
29 #include "libmesh/numeric_vector.h"
30 #include "libmesh/parallel.h"
31 
32 // C++ includes
33 #include <vector>
34 #include <algorithm>
35 #include <limits>
36 #include <mutex>
37 
38 namespace libMesh
39 {
40 
53 template <typename T>
54 class DistributedVector final : public NumericVector<T>
55 {
56 public:
57 
61  explicit
63  const ParallelType = AUTOMATIC);
64 
68  explicit
70  const numeric_index_type n,
71  const ParallelType ptype = AUTOMATIC);
72 
78  const numeric_index_type n,
79  const numeric_index_type n_local,
80  const ParallelType ptype = AUTOMATIC);
81 
88  const numeric_index_type N,
89  const numeric_index_type n_local,
90  const std::vector<numeric_index_type> & ghost,
91  const ParallelType ptype = AUTOMATIC);
92 
101 
106  DistributedVector (DistributedVector &&) = default;
107  DistributedVector (const DistributedVector &) = default;
109  virtual ~DistributedVector () = default;
110 
111  virtual void close () override;
112 
113  virtual void clear () override;
114 
115  virtual void zero () override;
116 
117  virtual std::unique_ptr<NumericVector<T>> zero_clone () const override;
118 
119  virtual std::unique_ptr<NumericVector<T>> clone () const override;
120 
121  virtual void init (const numeric_index_type N,
122  const numeric_index_type n_local,
123  const bool fast=false,
124  const ParallelType ptype=AUTOMATIC) override;
125 
126  virtual void init (const numeric_index_type N,
127  const bool fast=false,
128  const ParallelType ptype=AUTOMATIC) override;
129 
130  virtual void init (const numeric_index_type N,
131  const numeric_index_type n_local,
132  const std::vector<numeric_index_type> & ghost,
133  const bool fast = false,
134  const ParallelType = AUTOMATIC) override;
135 
136  virtual void init (const NumericVector<T> & other,
137  const bool fast = false) override;
138 
139  virtual NumericVector<T> & operator= (const T s) override;
140 
141  virtual NumericVector<T> & operator= (const NumericVector<T> & v) override;
142 
143  virtual NumericVector<T> & operator= (const std::vector<T> & v) override;
144 
145  virtual Real min () const override;
146 
147  virtual Real max () const override;
148 
149  virtual T sum() const override;
150 
151  virtual Real l1_norm () const override;
152 
153  virtual Real l2_norm () const override;
154 
155  virtual Real linfty_norm () const override;
156 
157  virtual numeric_index_type size () const override;
158 
159  virtual numeric_index_type local_size() const override;
160 
161  virtual numeric_index_type first_local_index() const override;
162 
163  virtual numeric_index_type last_local_index() const override;
164 
165  virtual T operator() (const numeric_index_type i) const override;
166 
167  virtual NumericVector<T> & operator += (const NumericVector<T> & v) override;
168 
169  virtual NumericVector<T> & operator -= (const NumericVector<T> & v) override;
170 
171  virtual NumericVector<T> & operator *= (const NumericVector<T> & v) override;
172 
173  virtual NumericVector<T> & operator /= (const NumericVector<T> & v) override;
174 
175  virtual void reciprocal() override;
176 
177  virtual void conjugate() override;
178 
179  virtual void set (const numeric_index_type i, const T value) override;
180 
181  virtual void add (const numeric_index_type i, const T value) override;
182 
183  virtual void add (const T s) override;
184 
185  virtual void add (const NumericVector<T> & V) override;
186 
187  virtual void add (const T a, const NumericVector<T> & v) override;
188 
194 
195  virtual void add_vector (const NumericVector<T> &,
196  const SparseMatrix<T> &) override
197  { libmesh_not_implemented(); }
198 
199  virtual void add_vector_transpose (const NumericVector<T> &,
200  const SparseMatrix<T> &) override
201  { libmesh_not_implemented(); }
202 
203  virtual void scale (const T factor) override;
204 
205  virtual void abs() override;
206 
207  virtual T dot(const NumericVector<T> & V) const override;
208 
209  virtual void localize (std::vector<T> & v_local) const override;
210 
211  virtual void localize (NumericVector<T> & v_local) const override;
212 
213  virtual void localize (NumericVector<T> & v_local,
214  const std::vector<numeric_index_type> & send_list) const override;
215 
216  virtual void localize (std::vector<T> & v_local,
217  const std::vector<numeric_index_type> & indices) const override;
218 
219  virtual void localize (const numeric_index_type first_local_idx,
220  const numeric_index_type last_local_idx,
221  const std::vector<numeric_index_type> & send_list) override;
222 
223  virtual void localize_to_one (std::vector<T> & v_local,
224  const processor_id_type proc_id=0) const override;
225 
226  virtual void pointwise_mult (const NumericVector<T> & vec1,
227  const NumericVector<T> & vec2) override;
228 
229  virtual void pointwise_divide (const NumericVector<T> & vec1,
230  const NumericVector<T> & vec2) override;
231 
232  virtual void swap (NumericVector<T> & v) override;
233 
234  virtual std::size_t max_allowed_id() const override;
235 
236 private:
237 
241  std::vector<T> _values;
242 
247 
252 
257 
262 };
263 
264 
265 //--------------------------------------------------------------------------
266 // DistributedVector inline methods
267 template <typename T>
268 inline
270  const ParallelType ptype) :
271  NumericVector<T>(comm_in, ptype),
272  _global_size (0),
273  _local_size (0),
274  _first_local_index(0),
275  _last_local_index (0)
276 {
277  this->_type = ptype;
278 }
279 
280 
281 
282 template <typename T>
283 inline
285  const numeric_index_type n,
286  const ParallelType ptype)
287  : NumericVector<T>(comm_in, ptype)
288 {
289  this->init(n, n, false, ptype);
290 }
291 
292 
293 
294 template <typename T>
295 inline
297  const numeric_index_type n,
298  const numeric_index_type n_local,
299  const ParallelType ptype)
300  : NumericVector<T>(comm_in, ptype)
301 {
302  this->init(n, n_local, false, ptype);
303 }
304 
305 
306 
307 template <typename T>
308 inline
310  const numeric_index_type n,
311  const numeric_index_type n_local,
312  const std::vector<numeric_index_type> & ghost,
313  const ParallelType ptype)
314  : NumericVector<T>(comm_in, ptype)
315 {
316  this->init(n, n_local, ghost, false, ptype);
317 }
318 
319 
320 
321 template <typename T>
322 inline
324  const numeric_index_type n_local,
325  const bool fast,
326  const ParallelType ptype)
327 {
328  // This function must be run on all processors at once
329  parallel_object_only();
330 
331  libmesh_assert_less_equal (n_local, n);
332 
333  if (ptype == AUTOMATIC)
334  {
335  if (n == n_local)
336  this->_type = SERIAL;
337  else
338  this->_type = PARALLEL;
339  }
340  else if (ptype == GHOSTED &&
341  n == n_local) // We can support GHOSTED with no ghosts...
342  this->_type = SERIAL;
343  else
344  this->_type = ptype;
345 
346  libmesh_assert ((this->_type==SERIAL && n==n_local) ||
347  this->_type==PARALLEL);
348 
349  // Clear the data structures if already initialized
350  if (this->initialized())
351  this->clear();
352 
353  // Initialize data structures
354  _values.resize(n_local);
355  _local_size = n_local;
356  _global_size = n;
357 
358  _first_local_index = 0;
359 
360 #ifdef LIBMESH_HAVE_MPI
361 
362  std::vector<numeric_index_type> local_sizes (this->n_processors(), 0);
363 
364  local_sizes[this->processor_id()] = n_local;
365 
366  this->comm().sum(local_sizes);
367 
368  // _first_local_index is the sum of _local_size
369  // for all processor ids less than ours
370  for (auto p : make_range(this->processor_id()))
371  _first_local_index += local_sizes[p];
372 
373 
374 # ifdef DEBUG
375  // Make sure all the local sizes sum up to the global
376  // size, otherwise there is big trouble!
377  numeric_index_type dbg_sum=0;
378 
379  for (auto p : make_range(this->n_processors()))
380  dbg_sum += local_sizes[p];
381 
382  libmesh_assert_equal_to (dbg_sum, n);
383 
384 # endif
385 
386 #else
387 
388  // No other options without MPI!
389  libmesh_error_msg_if(n != n_local, "ERROR: MPI is required for n != n_local!");
390 
391 #endif
392 
393  _last_local_index = _first_local_index + n_local;
394 
395  // Set the initialized flag
396  this->_is_initialized = true;
397 
398  // Zero the components unless directed otherwise
399  if (!fast)
400  this->zero();
401 }
402 
403 
404 template <typename T>
405 inline
407  const numeric_index_type n_local,
408  const std::vector<numeric_index_type> & /*ghost*/,
409  const bool fast,
410  const ParallelType ptype)
411 {
412  // TODO: we shouldn't ignore the ghost sparsity pattern
413  this->init(n, n_local, fast, ptype);
414 }
415 
416 
417 
418 /* Default implementation for solver packages for which ghosted
419  vectors are not yet implemented. */
420 template <class T>
422  const bool fast)
423 {
424  this->init(other.size(),other.local_size(),fast,other.type());
425 }
426 
427 
428 
429 template <typename T>
430 inline
432  const bool fast,
433  const ParallelType ptype)
434 {
435  this->init(n,n,fast,ptype);
436 }
437 
438 
439 
440 template <typename T>
441 inline
443 {
444  libmesh_assert (this->initialized());
445 
446  this->_is_closed = true;
447 }
448 
449 
450 
451 template <typename T>
452 inline
454 {
455  _values.clear();
456 
457  _global_size =
458  _local_size =
459  _first_local_index =
460  _last_local_index = 0;
461 
462 
463  this->_is_closed = this->_is_initialized = false;
464 }
465 
466 
467 
468 template <typename T>
469 inline
471 {
472  libmesh_assert (this->initialized());
473  libmesh_assert_equal_to (_values.size(), _local_size);
474  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
475 
476  std::fill (_values.begin(),
477  _values.end(),
478  0.);
479 }
480 
481 
482 
483 template <typename T>
484 inline
485 std::unique_ptr<NumericVector<T>> DistributedVector<T>::zero_clone () const
486 {
487  NumericVector<T> * cloned_vector = new DistributedVector<T>(this->comm());
488  cloned_vector->init(*this);
489  return std::unique_ptr<NumericVector<T>>(cloned_vector);
490 }
491 
492 
493 
494 template <typename T>
495 inline
496 std::unique_ptr<NumericVector<T>> DistributedVector<T>::clone () const
497 {
498  NumericVector<T> * cloned_vector = new DistributedVector<T>(this->comm());
499  cloned_vector->init(*this, true);
500  *cloned_vector = *this;
501  return std::unique_ptr<NumericVector<T>>(cloned_vector);
502 }
503 
504 
505 
506 template <typename T>
507 inline
509 {
510  libmesh_assert (this->initialized());
511  libmesh_assert_equal_to (_values.size(), _local_size);
512  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
513 
514  return _global_size;
515 }
516 
517 
518 
519 template <typename T>
520 inline
522 {
523  libmesh_assert (this->initialized());
524  libmesh_assert_equal_to (_values.size(), _local_size);
525  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
526 
527  return _local_size;
528 }
529 
530 
531 
532 template <typename T>
533 inline
535 {
536  libmesh_assert (this->initialized());
537  libmesh_assert_equal_to (_values.size(), _local_size);
538  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
539 
540  return _first_local_index;
541 }
542 
543 
544 
545 template <typename T>
546 inline
548 {
549  libmesh_assert (this->initialized());
550  libmesh_assert_equal_to (_values.size(), _local_size);
551  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
552 
553  return _last_local_index;
554 }
555 
556 
557 
558 template <typename T>
559 inline
561 {
562  libmesh_assert (this->initialized());
563  libmesh_assert_equal_to (_values.size(), _local_size);
564  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
565  libmesh_assert ( ((i >= first_local_index()) &&
566  (i < last_local_index())) );
567 
568  return _values[i - _first_local_index];
569 }
570 
571 
572 
573 template <typename T>
574 inline
576 {
577  libmesh_assert (this->initialized());
578  libmesh_assert_equal_to (_values.size(), _local_size);
579  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
580  libmesh_assert_less (i, size());
581  libmesh_assert_less (i-first_local_index(), local_size());
582 
583  std::scoped_lock lock(this->_numeric_vector_mutex);
584  _values[i - _first_local_index] = value;
585 
586 
587  this->_is_closed = false;
588 }
589 
590 
591 
592 
593 template <typename T>
594 inline
596 {
597  libmesh_assert (this->initialized());
598  libmesh_assert_equal_to (_values.size(), _local_size);
599  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
600  libmesh_assert_less (i, size());
601  libmesh_assert_less (i-first_local_index(), local_size());
602 
603  std::scoped_lock lock(this->_numeric_vector_mutex);
604  _values[i - _first_local_index] += value;
605 
606 
607  this->_is_closed = false;
608 }
609 
610 
611 
612 template <typename T>
613 inline
615 {
616  // This function must be run on all processors at once
617  parallel_object_only();
618 
619  libmesh_assert (this->initialized());
620  libmesh_assert_equal_to (_values.size(), _local_size);
621  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
622 
623  Real local_min = std::numeric_limits<Real>::max();
624  for (auto v : _values)
625  local_min = std::min(libmesh_real(v), local_min);
626 
627  this->comm().min(local_min);
628 
629  return local_min;
630 }
631 
632 
633 
634 template <typename T>
635 inline
637 {
638  // This function must be run on all processors at once
639  parallel_object_only();
640 
641  libmesh_assert (this->initialized());
642  libmesh_assert_equal_to (_values.size(), _local_size);
643  libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size);
644 
645  Real local_max = -std::numeric_limits<Real>::max();
646  for (auto v : _values)
647  local_max = std::max(libmesh_real(v), local_max);
648 
649  this->comm().max(local_max);
650 
651  return local_max;
652 }
653 
654 
655 template <typename T>
656 inline
658 {
659  DistributedVector<T> & v = cast_ref<DistributedVector<T> &>(other);
660 
661  std::swap(_global_size, v._global_size);
662  std::swap(_local_size, v._local_size);
663  std::swap(_first_local_index, v._first_local_index);
664  std::swap(_last_local_index, v._last_local_index);
665 
666  std::swap(this->_is_initialized, v._is_initialized);
667 
668  // This should be O(1) with any reasonable STL implementation
669  std::swap(_values, v._values);
670 }
671 
672 template <typename T>
673 inline
675 {
676  // Uses a std:vector<T>, so our indexing matches that
677  return std::numeric_limits<typename std::vector<T>::size_type>::max();
678 }
679 
680 } // namespace libMesh
681 
682 
683 #endif // LIBMESH_DISTRIBUTED_VECTOR_H
T libmesh_real(T a)
virtual Real max() const override
virtual T dot(const NumericVector< T > &V) const override
numeric_index_type _last_local_index
The last component (+1) stored locally.
virtual void scale(const T factor) override
Scale each element of the vector by the given factor.
virtual void add_vector(const NumericVector< T > &, const SparseMatrix< T > &) override
Computes , i.e.
virtual numeric_index_type last_local_index() const override
virtual void close() override
Calls the NumericVector&#39;s internal assembly routines, ensuring that the values are consistent across ...
virtual numeric_index_type size() const =0
virtual void set(const numeric_index_type i, const T value) override
Sets v(i) = value.
virtual NumericVector< T > & operator-=(const NumericVector< T > &v) override
Subtracts v from *this, .
DistributedVector & operator=(const DistributedVector &)
Copy assignment operator.
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
Definition: vector_fe_ex5.C:43
const Parallel::Communicator & comm() const
virtual NumericVector< T > & operator/=(const NumericVector< T > &v) override
Computes the component-wise division of this vector&#39;s entries by another&#39;s, .
virtual void add(const numeric_index_type i, const T value) override
Adds value to the vector entry specified by i.
bool _is_initialized
true once init() has been called.
virtual Real linfty_norm() const override
The libMesh namespace provides an interface to certain functionality in the library.
numeric_index_type _global_size
The global vector size.
virtual std::unique_ptr< NumericVector< T > > zero_clone() const override
const Number zero
.
Definition: libmesh.h:280
virtual numeric_index_type local_size() const override
virtual void init(const numeric_index_type n, const numeric_index_type n_local, const bool fast=false, const ParallelType ptype=AUTOMATIC)=0
Change the dimension of the vector to n.
virtual NumericVector< T > & operator+=(const NumericVector< T > &v) override
Adds v to *this, .
uint8_t processor_id_type
Definition: id_types.h:104
Generic sparse matrix.
Definition: vector_fe_ex5.C:45
virtual void reciprocal() override
Computes the component-wise reciprocal, .
virtual void zero() override
Set all entries to zero.
virtual Real l1_norm() const override
This class provides a simple parallel, distributed vector datatype which is specific to libmesh...
dof_id_type numeric_index_type
Definition: id_types.h:99
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:247
virtual ~DistributedVector()=default
virtual numeric_index_type size() const override
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libmesh_assert(ctx)
virtual std::size_t max_allowed_id() const override
virtual void pointwise_divide(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
ParallelType _type
Type of vector.
virtual std::unique_ptr< NumericVector< T > > clone() const override
virtual void pointwise_mult(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
virtual void conjugate() override
Negates the imaginary component of each entry in the vector.
ParallelType type() const
virtual void localize_to_one(std::vector< T > &v_local, const processor_id_type proc_id=0) const override
Creates a local copy of the global vector in v_local only on processor proc_id.
numeric_index_type _local_size
The local vector size.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual numeric_index_type first_local_index() const override
virtual NumericVector< T > & operator*=(const NumericVector< T > &v) override
Computes the component-wise multiplication of this vector&#39;s entries by another&#39;s, ...
virtual void localize(std::vector< T > &v_local) const override
Creates a copy of the global vector in the local vector v_local.
virtual Real l2_norm() const override
virtual numeric_index_type local_size() const =0
virtual void abs() override
Sets for each entry in the vector.
static const bool value
Definition: xdr_io.C:54
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:134
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:266
virtual void init(const numeric_index_type N, const numeric_index_type n_local, const bool fast=false, const ParallelType ptype=AUTOMATIC) override
Change the dimension of the vector to n.
virtual void clear() override
Restores the NumericVector<T> to a pristine state.
std::vector< T > _values
Actual vector datatype to hold vector entries.
virtual Real min() const override
virtual T sum() const override
virtual void swap(NumericVector< T > &v) override
Swaps the contents of this with v.
virtual void add_vector_transpose(const NumericVector< T > &, const SparseMatrix< T > &) override
Computes , i.e.
DistributedVector(const Parallel::Communicator &comm, const ParallelType=AUTOMATIC)
Dummy-Constructor.
numeric_index_type _first_local_index
The first component stored locally.
ParallelType
Defines an enum for parallel data structure types.
virtual T operator()(const numeric_index_type i) const override