v0.10.0
AuxPETSc.hpp
Go to the documentation of this file.
1 /** \file AuxPETSc.hpp
2  * \brief Auxiliary MoFEM-PETSc structures
3  */
4 
5 /* This file is part of MoFEM.
6  * MoFEM is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * MoFEM is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14  * License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with MoFEM. If not, see <http://www.gnu.org/licenses/>. */
18 
19 #ifndef __AUXPETSC_HPP__
20 #define __AUXPETSC_HPP__
21 
22 namespace MoFEM {
23 template <typename T> inline PetscObject getPetscObject(T obj) {
24  return reinterpret_cast<PetscObject>(obj);
25 }
26 } // namespace MoFEM
27 
28 /**
29  * @brief It is used by intrusive_ptr to bump reference
30  *
31  * \note It should not be used directly, it is internally called by
32  * intrusive_ptr
33  *
34  * @tparam OBJ
35  * @param obj
36  */
37 template <typename OBJ> void intrusive_ptr_add_ref(OBJ obj) {
38  PetscErrorCode ierr = PetscObjectReference(MoFEM::getPetscObject(obj));
39  CHKERRABORT(PetscObjectComm(MoFEM::getPetscObject(obj)), ierr);
40 }
41 
42 /**
43  * @brief It is used by intrusive_ptr to dereference and destroy petsc object
44  *
45  * \note It should not be used directly, it is internally called by
46  * intrusive_ptr
47  *
48  * @tparam OBJ
49  * @param obj
50  */
51 template <typename OBJ> void intrusive_ptr_release(OBJ obj) {
52  int cnt = 0;
53  PetscErrorCode ierr =
54  PetscObjectGetReference(MoFEM::getPetscObject(obj), &cnt);
55  if (!ierr) {
56  if (cnt) {
57  auto comm = PetscObjectComm(MoFEM::getPetscObject(obj));
58  if (cnt > 1) {
59  ierr = PetscObjectDereference(MoFEM::getPetscObject(obj));
60  CHKERRABORT(comm, ierr);
61  } else {
62  ierr = PetscObjectDestroy(reinterpret_cast<PetscObject *>(&obj));
63  CHKERRABORT(comm, ierr);
64  }
65  }
66  }
67 }
68 
69 namespace MoFEM {
70 
71 struct PairNameFEMethodPtr : public std::pair<std::string, FEMethod *> {
72 
73  PairNameFEMethodPtr(std::string name, FEMethod *ptr)
74  : std::pair<std::string, FEMethod *>(name, ptr) {}
75  template <typename FEMETHOD>
76  PairNameFEMethodPtr(std::string name, boost::shared_ptr<FEMETHOD> ptr)
77  : std::pair<std::string, FEMethod *>(name, ptr.get()), fePtr(ptr) {}
78  virtual ~PairNameFEMethodPtr() {}
79 
80  inline boost::shared_ptr<BasicMethod> getSharedPtr() const {
81  if (!fePtr)
82  THROW_MESSAGE("Shared pointer not set. You have to be using raw "
83  "pointer, that is unsafe.");
84  return fePtr;
85  }
86 
87 private:
88  boost::shared_ptr<FEMethod> fePtr;
89 };
90 
93  template <typename BASICMETHOD>
94  BasicMethodPtr(boost::shared_ptr<BASICMETHOD> ptr)
95  : rawPtr(ptr.get()), bmPtr(ptr) {}
96  inline BasicMethod &operator*() const { return *rawPtr; };
97  inline BasicMethod *operator->() const { return rawPtr; }
98 
99  inline boost::shared_ptr<BasicMethod> getSharedPtr() const {
100  if (!bmPtr)
101  THROW_MESSAGE("Shared pointer not set. You have to be using raw "
102  "pointer, that is unsafe.");
103  return bmPtr;
104  }
105 
106 private:
108  boost::shared_ptr<BasicMethod> bmPtr;
109 };
110 
111 typedef std::vector<PairNameFEMethodPtr> FEMethodsSequence;
112 typedef std::vector<BasicMethodPtr> BasicMethodsSequence;
113 
114 /**
115  * @brief intrusive_ptr for managing petsc objects
116  *
117  * It manages destruction, referencing and dereferencing petsc objects. It is
118  * similar how smart_ptr pointers works, but applied for petsc objects like Vec,
119  * DM, Mat, etc.
120  *
121  * \code
122  * SmartPetscObj<Vec> smart_vec = createSmartGhostVector(...);
123  * \endcode
124  *
125  * @tparam OBJ
126  */
127 template <typename OBJ>
129  : public boost::intrusive_ptr<typename std::remove_pointer<OBJ>::type> {
130 
132  : boost::intrusive_ptr<typename std::remove_pointer<OBJ>::type>() {}
133  SmartPetscObj(OBJ o, bool add_ref = false)
134  : boost::intrusive_ptr<typename std::remove_pointer<OBJ>::type>(o,
135  add_ref) {
136  }
137  operator OBJ() { return this->get(); }
138  explicit operator PetscObject() {
139  return reinterpret_cast<PetscObject>(this->get());
140  }
141 
142  int use_count() const {
143  if (this->get()) {
144  int cnt;
145  ierr = PetscObjectGetReference(getPetscObject(this->get()), &cnt);
146  CHKERRABORT(PetscObjectComm(getPetscObject(this->get())), ierr);
147  return cnt;
148  } else
149  return 0;
150  }
151 };
152 
153 /**
154  * @brief Creates smart DM object
155  *
156  * DM object can be used as any other object, but is destroyed as smart pointer
157  * when no loneger used.
158  *
159  * \code
160  * CHKERR DMRegister_MoFEM("MOFEM")
161  * {
162  * auto dm = createSmartDM(PETSC_COMM_WORLD, "MOFEM");
163  *
164  * // ...
165  *
166  * // dm is autmatically destroyed when program goes out of the scope
167  * }
168  *
169  *
170  *
171  * \endcode
172  *
173  */
174 auto createSmartDM = [](MPI_Comm comm, const std::string dm_type_name) {
175  DM dm;
176  ierr = DMCreate(comm, &dm);
177  CHKERRABORT(comm, ierr);
178  ierr = DMSetType(dm, dm_type_name.c_str());
179  CHKERRABORT(comm, ierr);
180  return SmartPetscObj<DM>(dm);
181 };
182 
183 /**
184  * @brief Get the Comm From Petsc Object object
185  *
186  * @param obj
187  * @return MPI_Comm
188  */
189 inline MPI_Comm getCommFromPetscObject(PetscObject obj) {
190  MPI_Comm comm;
191  ierr = PetscObjectGetComm(obj, &comm);
192  CHKERRABORT(PETSC_COMM_SELF, ierr);
193  return comm;
194 };
195 
196 /**
197  * @brief Create smart ghost vector
198  *
199  * For details abut arguments see here:
200  * <a
201  * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecCreateGhost.html>VecCreateGhost</a>.
202  *
203  * \code
204  * auto vec = createSmartGhostVector(...);
205  * \endcode
206  *
207  */
208 auto createSmartGhostVector = [](MPI_Comm comm, PetscInt n, PetscInt N,
209  PetscInt nghost, const PetscInt ghosts[]) {
210  Vec vv;
211  ierr = VecCreateGhost(comm, n, N, nghost, ghosts, &vv);
212  CHKERRABORT(comm, ierr);
213  return SmartPetscObj<Vec>(vv);
214 };
215 
216 /**
217  * @brief Create MPI Vector
218  *
219  * For details abut arguments see here:
220  * <a
221  * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecCreateMPI.html>VecCreateMPI</a>.
222  *
223  */
224 auto createSmartVectorMPI = [](MPI_Comm comm, PetscInt n, PetscInt N) {
225  Vec vv;
226  ierr = VecCreateMPI(comm, n, N, &vv);
227  CHKERRABORT(comm, ierr);
228  return SmartPetscObj<Vec>(vv);
229 };
230 
231 /**
232  * @brief Create duplicate vector of smart vector
233  *
234  * For details abut arguments see here:
235  * <a
236  * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecDuplicate.html>VecDuplicate</a>.
237  */
239  if (vec.use_count()) {
240  Vec duplicate;
241  ierr = VecDuplicate(vec, &duplicate);
242  CHKERRABORT(PETSC_COMM_SELF, ierr);
243  return SmartPetscObj<Vec>(duplicate);
244  } else {
245  return SmartPetscObj<Vec>();
246  }
247 };
248 
250  Vec duplicate;
251  ierr = VecDuplicate(vec, &duplicate);
252  CHKERRABORT(PETSC_COMM_SELF, ierr);
253  return SmartPetscObj<Vec>(duplicate);
254 };
255 
256 inline SmartPetscObj<Mat> smartMatDuplicate(Mat &mat, MatDuplicateOption op) {
257  Mat duplicate;
258  ierr = MatDuplicate(mat, op, &duplicate);
259  CHKERRABORT(PETSC_COMM_SELF, ierr);
260  return SmartPetscObj<Mat>(duplicate);
261 };
262 
264  MatDuplicateOption op) {
265  if (mat.use_count()) {
266  Mat duplicate;
267  ierr = MatDuplicate(mat, op, &duplicate);
268  CHKERRABORT(PETSC_COMM_SELF, ierr);
269  return SmartPetscObj<Mat>(duplicate);
270  } else {
271  return SmartPetscObj<Mat>();
272  }
273 };
274 
275 auto createTS = [](MPI_Comm comm) {
276  TS ts;
277  ierr = TSCreate(comm, &ts);
278  CHKERRABORT(comm, ierr);
279  return SmartPetscObj<TS>(ts);
280 };
281 
282 auto createSNES = [](MPI_Comm comm) {
283  SNES snes;
284  ierr = SNESCreate(comm, &snes);
285  CHKERRABORT(comm, ierr);
286  return SmartPetscObj<SNES>(snes);
287 };
288 
289 auto createKSP = [](MPI_Comm comm) {
290  KSP ksp;
291  ierr = KSPCreate(comm, &ksp);
292  CHKERRABORT(comm, ierr);
293  return SmartPetscObj<KSP>(ksp);
294 };
295 
296 auto createPC = [](MPI_Comm comm) {
297  PC pc;
298  ierr = PCCreate(comm, &pc);
299  CHKERRABORT(comm, ierr);
300  return SmartPetscObj<PC>(pc);
301 };
302 
303 } // namespace MoFEM
304 
305 #endif // __AUXPETSC_HPP__
306 
307 /**
308  * \defgroup mofem_petsc_solvers PETSc solvers
309  * \brief PETSc solvers
310  *
311  * \ingroup mofem
312  */
BasicMethodPtr(BasicMethod *ptr)
Definition: AuxPETSc.hpp:92
structure for User Loop Methods on finite elementsIt can be used to calculate stiffness matrices,...
MPI_Comm getCommFromPetscObject(PetscObject obj)
Get the Comm From Petsc Object object.
Definition: AuxPETSc.hpp:189
virtual ~PairNameFEMethodPtr()
Definition: AuxPETSc.hpp:78
SmartPetscObj< Mat > smartMatDuplicate(Mat &mat, MatDuplicateOption op)
Definition: AuxPETSc.hpp:256
auto createTS
Definition: AuxPETSc.hpp:275
const FTensor::Tensor2< T, Dim, Dim > Vec
int use_count() const
Definition: AuxPETSc.hpp:142
auto createSNES
Definition: AuxPETSc.hpp:282
PetscObject getPetscObject(T obj)
Definition: AuxPETSc.hpp:23
#define THROW_MESSAGE(a)
Throw MoFEM exception.
Definition: definitions.h:628
SmartPetscObj< Vec > smartVectorDuplicate(SmartPetscObj< Vec > &vec)
Create duplicate vector of smart vector.
Definition: AuxPETSc.hpp:238
boost::shared_ptr< BasicMethod > getSharedPtr() const
Definition: AuxPETSc.hpp:80
BasicMethodPtr(boost::shared_ptr< BASICMETHOD > ptr)
Definition: AuxPETSc.hpp:94
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:21
BasicMethod * rawPtr
Definition: AuxPETSc.hpp:107
static Index< 'n', 3 > n
auto createPC
Definition: AuxPETSc.hpp:296
auto createSmartVectorMPI
Create MPI Vector.
Definition: AuxPETSc.hpp:224
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Exceptions.hpp:87
std::vector< BasicMethodPtr > BasicMethodsSequence
Definition: AuxPETSc.hpp:112
static Index< 'o', 3 > o
SmartPetscObj(OBJ o, bool add_ref=false)
Definition: AuxPETSc.hpp:133
std::vector< PairNameFEMethodPtr > FEMethodsSequence
Definition: AuxPETSc.hpp:111
BasicMethod & operator *() const
Definition: AuxPETSc.hpp:96
boost::shared_ptr< BasicMethod > getSharedPtr() const
Definition: AuxPETSc.hpp:99
BasicMethod * operator->() const
Definition: AuxPETSc.hpp:97
void intrusive_ptr_release(OBJ obj)
It is used by intrusive_ptr to dereference and destroy petsc object.
Definition: AuxPETSc.hpp:51
auto createKSP
Definition: AuxPETSc.hpp:289
auto createSmartGhostVector
Create smart ghost vector.
Definition: AuxPETSc.hpp:208
void intrusive_ptr_add_ref(OBJ obj)
It is used by intrusive_ptr to bump reference.
Definition: AuxPETSc.hpp:37
boost::shared_ptr< BasicMethod > bmPtr
Definition: AuxPETSc.hpp:108
PairNameFEMethodPtr(std::string name, boost::shared_ptr< FEMETHOD > ptr)
Definition: AuxPETSc.hpp:76
intrusive_ptr for managing petsc objects
Definition: AuxPETSc.hpp:128
const int N
Definition: speed_test.cpp:3
auto createSmartDM
Creates smart DM object.
Definition: AuxPETSc.hpp:174
boost::shared_ptr< FEMethod > fePtr
Definition: AuxPETSc.hpp:88
Data structure to exchange data between mofem and User Loop Methods.It allows to exchange data betwee...
PairNameFEMethodPtr(std::string name, FEMethod *ptr)
Definition: AuxPETSc.hpp:73