Flow123d  release_3.0.0-973-g92f55e826
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 #include "mesh/long_idx.hh"
26 
27 #include <petscvec.h>
28 
29 /**
30  * Auxiliary class for output elementwise concentration vectors
31  * in convection transport, sorptions, dual porosity etc.
32  *
33  * Stores data in two formats:
34  * - shared pointer to std::vector of double
35  * - pointer to PETSC vector that use same data
36  *
37  * Allows the following functionalities:
38  * - access to local part
39  * - return shared pointer to std::vector of double
40  * - return pointer to PETSC vector
41  */
42 class VectorMPI {
43 public:
44  typedef typename std::vector<double> VectorData;
45  typedef typename std::shared_ptr< VectorData > VectorDataPtr;
46 
47  VectorMPI(MPI_Comm comm = PETSC_COMM_SELF)
48  : communicator_(comm) {}
49 
50  /// Create shared pointer and PETSC vector with given size. COLLECTIVE.
51  VectorMPI(unsigned int local_size, MPI_Comm comm = PETSC_COMM_WORLD)
52  : communicator_(comm) {
53  resize(local_size);
54  }
55 
56  /// Create PETSc vector with ghost values whose indices are specified in @p ghost_idx.
57  VectorMPI(unsigned int local_size, std::vector<LongIdx> &ghost_idx)
58  : communicator_(PETSC_COMM_WORLD) {
59  resize(local_size, ghost_idx);
60  }
61 
62  /**
63  * Helper method creating VectorMPI of given size with serial Petsc communicator.
64  *
65  * Method is used for better readability of code.
66  */
67  static VectorMPI sequential(unsigned int size)
68  {
69  return VectorMPI(size, PETSC_COMM_SELF);
70  }
71 
72  /**
73  * Resize the vector to given local size. Operation is allowed only if this object is
74  * a unique vector object pointing to the actual data.
75  */
76  void resize(unsigned int local_size) {
77  if (data_ptr_.use_count() ==0) {
78  data_ptr_ = std::make_shared< std::vector<double> >(local_size);
79  } else {
80  ASSERT_DBG( data_ptr_.use_count() == 1 ) ( data_ptr_.use_count() ).error("Object referenced by other pointer. Can not resize.");
81  chkerr(VecDestroy(&data_petsc_));
82  data_ptr_->resize(local_size);
83  }
84  if (communicator_ == PETSC_COMM_SELF)
85  chkerr(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, local_size, &((*data_ptr_)[0]), &data_petsc_));
86  else
87  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, local_size, PETSC_DECIDE, &((*data_ptr_)[0]), &data_petsc_));
88  chkerr(VecZeroEntries( data_petsc_ ));
89  }
90 
91  /**
92  * Resize the vector to given local size with ghost values. Indices of ghost values are in ghost_idx.
93  */
94  void resize(unsigned int local_size, std::vector<LongIdx> &ghost_idx) {
95  ASSERT_DBG(communicator_ == PETSC_COMM_WORLD).error("Cannot allocate ghost values in sequential vector.");
96  if (data_ptr_.use_count() ==0) {
97  data_ptr_ = std::make_shared< std::vector<double> >(local_size + ghost_idx.size());
98  } else {
99  ASSERT_DBG( data_ptr_.use_count() == 1 ) ( data_ptr_.use_count() ).error("Object referenced by other pointer. Can not resize.");
100  chkerr(VecDestroy(&data_petsc_));
101  data_ptr_->resize(local_size + ghost_idx.size());
102  }
103  chkerr(VecCreateGhostWithArray(PETSC_COMM_WORLD, local_size, PETSC_DECIDE, ghost_idx.size(), ghost_idx.data(), data_ptr_->data(), &data_petsc_));
104  chkerr(VecZeroEntries( data_petsc_ ));
105  }
106 
107  /// Return new vector with same parallel structure.
108  void duplicate(VectorMPI other) {
109  ASSERT_EQ(this->communicator_, other.communicator_);
110  this->resize(other.data().size());
111  }
112 
113  /// Getter for shared pointer of output data.
115  {
116  return data_ptr_;
117  }
118 
119  /// Getter for PETSC vector of output data (e.g. can be used by scatters).
120  Vec &petsc_vec()
121  {
122  return data_petsc_;
123  }
124 
125  void zero_entries() {
126  chkerr(VecZeroEntries( data_petsc_ ));
127  }
128 
130  {
132  return *data_ptr_;
133  }
134 
135  void swap(VectorMPI &other) {
136  ASSERT_EQ(this->communicator_, other.communicator_);
137  ASSERT_EQ(this->data_ptr_->size(), other.data_ptr_->size());
138  uint size = this->data_ptr_->size();
139  std::swap(this->data_ptr_, other.data_ptr_);
140  chkerr(VecDestroy(&data_petsc_));
141  chkerr(VecDestroy(&other.data_petsc_));
142  if (communicator_ == PETSC_COMM_SELF) {
143  chkerr(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, size, &((*data_ptr_)[0]), &data_petsc_));
144  chkerr(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, size, &((*other.data_ptr_)[0]), &other.data_petsc_));
145  } else {
146  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, size, PETSC_DECIDE, &((*data_ptr_)[0]), &data_petsc_));
147  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, size, PETSC_DECIDE, &((*other.data_ptr_)[0]), &other.data_petsc_));
148  }
149  }
150 
151 
152  void copy(VectorMPI &other) {
153  ASSERT_EQ(this->communicator_, other.communicator_);
154  ASSERT_EQ(this->data_ptr_->size(), other.data_ptr_->size());
155  chkerr(VecCopy(other.data_petsc_, data_petsc_));
156  }
157 
158  /// local_to_ghost_{begin,end} updates the ghost values on neighbouring processors from local values
160  VecGhostUpdateBegin(data_petsc_, INSERT_VALUES, SCATTER_FORWARD);
161  }
162 
163  /// local_to_ghost_{begin,end} updates the ghost values on neighbouring processors from local values
165  VecGhostUpdateEnd(data_petsc_, INSERT_VALUES, SCATTER_FORWARD);
166  }
167 
168  /// ghost_to_local_{begin,end} updates the local values by adding ghost values from neighbouring processors
170  VecGhostUpdateBegin(data_petsc_, ADD_VALUES, SCATTER_REVERSE);
171  }
172 
173  /// ghost_to_local_{begin,end} updates the local values by adding ghost values from neighbouring processors
175  VecGhostUpdateEnd(data_petsc_, ADD_VALUES, SCATTER_REVERSE);
176  }
177 
178  /// Return size of output data.
179  unsigned int size() const
180  {
181  ASSERT_PTR(data_ptr_).error("Uninitialized data vector.\n");
182  return data_ptr_->size();
183  }
184 
185 
186  /// Destructor.
188  {
189  if (data_ptr_.use_count() == 1)
190  if (data_petsc_) chkerr(VecDestroy(&data_petsc_));
191  }
192 
193  /**
194  * Access to the vector element on index @p idx.
195  */
196  inline double &operator[](unsigned int idx)
197  {
199  ASSERT_DBG(idx < data_ptr_->size()) (idx) (data_ptr_->size());
200  return (*data_ptr_)[idx];
201  }
202 
203 private:
204 
205  /// shared pointer to vector of data
207  /// stored vector of data in PETSC format
209  /// communicator
211 };
212 
213 
214 #endif /* VECTOR_MPI_HH_ */
VectorMPI::operator[]
double & operator[](unsigned int idx)
Definition: vector_mpi.hh:196
VectorMPI::copy
void copy(VectorMPI &other)
Definition: vector_mpi.hh:152
VectorMPI::data_ptr_
VectorDataPtr data_ptr_
shared pointer to vector of data
Definition: vector_mpi.hh:206
std::swap
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value and is_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:8688
VectorMPI::VectorMPI
VectorMPI(MPI_Comm comm=PETSC_COMM_SELF)
Definition: vector_mpi.hh:47
VectorMPI::sequential
static VectorMPI sequential(unsigned int size)
Definition: vector_mpi.hh:67
VectorMPI::ghost_to_local_begin
void ghost_to_local_begin()
ghost_to_local_{begin,end} updates the local values by adding ghost values from neighbouring processo...
Definition: vector_mpi.hh:169
VectorMPI::zero_entries
void zero_entries()
Definition: vector_mpi.hh:125
VectorMPI::resize
void resize(unsigned int local_size)
Definition: vector_mpi.hh:76
ASSERT_DBG
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
chkerr
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Definition: system.hh:147
std::vector< double >
system.hh
uint
unsigned int uint
Definition: mh_dofhandler.hh:108
VectorMPI::VectorMPI
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:51
VectorMPI::resize
void resize(unsigned int local_size, std::vector< LongIdx > &ghost_idx)
Definition: vector_mpi.hh:94
VectorMPI::swap
void swap(VectorMPI &other)
Definition: vector_mpi.hh:135
VectorMPI::VectorDataPtr
std::shared_ptr< VectorData > VectorDataPtr
Definition: vector_mpi.hh:45
VectorMPI::data_petsc_
Vec data_petsc_
stored vector of data in PETSC format
Definition: vector_mpi.hh:208
ASSERT_EQ
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:327
VectorMPI::ghost_to_local_end
void ghost_to_local_end()
ghost_to_local_{begin,end} updates the local values by adding ghost values from neighbouring processo...
Definition: vector_mpi.hh:174
VectorMPI::local_to_ghost_begin
void local_to_ghost_begin()
local_to_ghost_{begin,end} updates the ghost values on neighbouring processors from local values
Definition: vector_mpi.hh:159
VectorMPI::~VectorMPI
~VectorMPI()
Destructor.
Definition: vector_mpi.hh:187
MPI_Comm
int MPI_Comm
Definition: mpi.h:141
VectorMPI::communicator_
MPI_Comm communicator_
communicator
Definition: vector_mpi.hh:210
global_defs.h
Global macros to enhance readability and debugging, general constants.
VectorMPI::local_to_ghost_end
void local_to_ghost_end()
local_to_ghost_{begin,end} updates the ghost values on neighbouring processors from local values
Definition: vector_mpi.hh:164
VectorMPI::VectorMPI
VectorMPI(unsigned int local_size, std::vector< LongIdx > &ghost_idx)
Create PETSc vector with ghost values whose indices are specified in ghost_idx.
Definition: vector_mpi.hh:57
std::vector::data
T data
Definition: doxy_dummy_defs.hh:7
long_idx.hh
VectorMPI::data_ptr
VectorDataPtr data_ptr()
Getter for shared pointer of output data.
Definition: vector_mpi.hh:114
VectorMPI
Definition: vector_mpi.hh:42
VectorMPI::petsc_vec
Vec & petsc_vec()
Getter for PETSC vector of output data (e.g. can be used by scatters).
Definition: vector_mpi.hh:120
ASSERT_PTR
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
VectorMPI::data
VectorData & data()
Definition: vector_mpi.hh:129
VectorMPI::size
unsigned int size() const
Return size of output data.
Definition: vector_mpi.hh:179
VectorMPI::VectorData
std::vector< double > VectorData
Definition: vector_mpi.hh:44
VectorMPI::duplicate
void duplicate(VectorMPI other)
Return new vector with same parallel structure.
Definition: vector_mpi.hh:108