Flow123d  release_3.0.0-688-g6b683cf
vector_mpi.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file vector_mpi.hh
15  * @brief
16  */
17 
18 #ifndef VECTOR_MPI_HH_
19 #define VECTOR_MPI_HH_
20 
21 #include <vector>
22 #include <memory>
23 #include "system/system.hh"
24 #include "system/global_defs.h"
25 
26 #include <petscvec.h>
27 
28 /**
29  * Auxiliary class for output elementwise concentration vectors
30  * in convection transport, sorptions, dual porosity etc.
31  *
32  * Stores data in two formats:
33  * - shared pointer to std::vector of double
34  * - pointer to PETSC vector that use same data
35  *
36  * Allows the following functionalities:
37  * - access to local part
38  * - return shared pointer to std::vector of double
39  * - return pointer to PETSC vector
40  */
41 class VectorMPI {
42 public:
43  typedef typename std::vector<double> VectorData;
44  typedef typename std::shared_ptr< VectorData > VectorDataPtr;
45 
46  VectorMPI(MPI_Comm comm = PETSC_COMM_SELF)
47  : communicator_(comm) {}
48 
49  /// Create shared pointer and PETSC vector with given size. COLLECTIVE.
50  VectorMPI(unsigned int local_size, MPI_Comm comm = PETSC_COMM_WORLD)
51  : communicator_(comm) {
52  resize(local_size);
53  }
54 
55  /**
56  * Helper method creating VectorMPI of given size with serial Petsc communicator.
57  *
58  * Method is used for better readability of code.
59  */
60  static VectorMPI * sequential(unsigned int size)
61  {
62  return new VectorMPI(size, PETSC_COMM_SELF);
63  }
64 
65  /**
66  * Resize the vector to given local size. Operation is allowed only if this object is
67  * a unique vector object pointing to the actual data.
68  */
69  void resize(unsigned int local_size) {
70  if (data_ptr_.use_count() ==0) {
71  data_ptr_ = std::make_shared< std::vector<double> >(local_size);
72  } else {
73  ASSERT_DBG( data_ptr_.use_count() == 1 ) ( data_ptr_.use_count() ).error("Object referenced by other pointer. Can not resize.");
74  chkerr(VecDestroy(&data_petsc_));
75  data_ptr_->resize(local_size);
76  }
77  if (communicator_ == PETSC_COMM_SELF)
78  chkerr(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, local_size, &((*data_ptr_)[0]), &data_petsc_));
79  else
80  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, local_size, PETSC_DECIDE, &((*data_ptr_)[0]), &data_petsc_));
81  chkerr(VecZeroEntries( data_petsc_ ));
82  }
83 
84  /// Return new vector with same parallel structure.
85  void duplicate(VectorMPI other) {
87  this->resize(other.data().size());
88  }
89 
90  /// Getter for shared pointer of output data.
91  VectorDataPtr data_ptr()
92  {
93  return data_ptr_;
94  }
95 
96  /// Getter for PETSC vector of output data (e.g. can be used by scatters).
97  Vec &petsc_vec()
98  {
99  return data_petsc_;
100  }
101 
102  void zero_entries() {
103  chkerr(VecZeroEntries( data_petsc_ ));
104  }
105 
106  VectorData &data()
107  {
109  return *data_ptr_;
110  }
111 
112  void swap(VectorMPI &other) {
113  ASSERT_EQ(this->communicator_, other.communicator_);
114  ASSERT_EQ(this->data_ptr_->size(), other.data_ptr_->size());
115  uint size = this->data_ptr_->size();
116  std::swap(this->data_ptr_, other.data_ptr_);
117  chkerr(VecDestroy(&data_petsc_));
118  chkerr(VecDestroy(&other.data_petsc_));
119  if (communicator_ == PETSC_COMM_SELF) {
120  chkerr(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, size, &((*data_ptr_)[0]), &data_petsc_));
121  chkerr(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, size, &((*other.data_ptr_)[0]), &other.data_petsc_));
122  } else {
123  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, size, PETSC_DECIDE, &((*data_ptr_)[0]), &data_petsc_));
124  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, size, PETSC_DECIDE, &((*other.data_ptr_)[0]), &other.data_petsc_));
125  }
126  }
127 
128 
129  void copy(VectorMPI &other) {
130  ASSERT_EQ(this->communicator_, other.communicator_);
131  ASSERT_EQ(this->data_ptr_->size(), other.data_ptr_->size());
132  chkerr(VecCopy(other.data_petsc_, data_petsc_));
133  }
134 
135  /// Return size of output data.
136  unsigned int size()
137  {
138  ASSERT_PTR(data_ptr_).error("Uninitialized data vector.\n");
139  return data_ptr_->size();
140  }
141 
142 
143  /// Destructor.
145  {
146  if (data_ptr_.use_count() == 1) chkerr(VecDestroy(&data_petsc_));
147  }
148 
149  /**
150  * Access to the vector element on index @p idx.
151  */
152  inline double &operator[](unsigned int idx)
153  {
155  ASSERT_DBG(idx < data_ptr_->size()) (idx) (data_ptr_->size());
156  return (*data_ptr_)[idx];
157  }
158 
159 private:
160 
161  /// shared pointer to vector of data
162  VectorDataPtr data_ptr_;
163  /// stored vector of data in PETSC format
165  /// communicator
167 };
168 
169 
170 #endif /* VECTOR_MPI_HH_ */
MPI_Comm communicator_
communicator
Definition: vector_mpi.hh:166
void copy(VectorMPI &other)
Definition: vector_mpi.hh:129
unsigned int uint
int MPI_Comm
Definition: mpi.h:141
VectorMPI(unsigned int local_size, MPI_Comm comm=PETSC_COMM_WORLD)
Create shared pointer and PETSC vector with given size. COLLECTIVE.
Definition: vector_mpi.hh:50
void zero_entries()
Definition: vector_mpi.hh:102
static VectorMPI * sequential(unsigned int size)
Definition: vector_mpi.hh:60
void duplicate(VectorMPI other)
Return new vector with same parallel structure.
Definition: vector_mpi.hh:85
std::vector< double > VectorData
Definition: vector_mpi.hh:43
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Definition: system.hh:147
VectorDataPtr data_ptr()
Getter for shared pointer of output data.
Definition: vector_mpi.hh:91
double & operator[](unsigned int idx)
Definition: vector_mpi.hh:152
~VectorMPI()
Destructor.
Definition: vector_mpi.hh:144
VectorMPI(MPI_Comm comm=PETSC_COMM_SELF)
Definition: vector_mpi.hh:46
Global macros to enhance readability and debugging, general constants.
VectorDataPtr data_ptr_
shared pointer to vector of data
Definition: vector_mpi.hh:162
Vec data_petsc_
stored vector of data in PETSC format
Definition: vector_mpi.hh:164
void resize(unsigned int local_size)
Definition: vector_mpi.hh:69
Vec & petsc_vec()
Getter for PETSC vector of output data (e.g. can be used by scatters).
Definition: vector_mpi.hh:97
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value andis_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:8688
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
void swap(VectorMPI &other)
Definition: vector_mpi.hh:112
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
std::shared_ptr< VectorData > VectorDataPtr
Definition: vector_mpi.hh:44
VectorData & data()
Definition: vector_mpi.hh:106
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:327
unsigned int size()
Return size of output data.
Definition: vector_mpi.hh:136