v0.8.23
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  operator OBJ() { return this->get(); }
137  explicit operator PetscObject() {
138  return reinterpret_cast<PetscObject>(this->get());
139  }
140 
141  int use_count() const {
142  if (this->get()) {
143  int cnt;
144  ierr = PetscObjectGetReference(getPetscObject(this->get()), &cnt);
145  CHKERRABORT(PetscObjectComm(getPetscObject(this->get())), ierr);
146  return cnt;
147  } else
148  return 0;
149  }
150 };
151 
152 /**
153  * @brief Creates smart DM object
154  *
155  * DM object can be used as any other object, but is destroyed as smart pointer
156  * when no loneger used.
157  *
158  * \code
159  * CHKERR DMRegister_MoFEM("MOFEM")
160  * {
161  * auto dm = createSmartDM(PETSC_COMM_WORLD, "MOFEM");
162  *
163  * // ...
164  *
165  * // dm is autmatically destroyed when program goes out of the scope
166  * }
167  *
168  *
169  *
170  * \endcode
171  *
172  */
173 auto createSmartDM = [](MPI_Comm comm, const std::string dm_type_name) {
174  DM dm;
175  ierr = DMCreate(comm, &dm);
176  CHKERRABORT(comm, ierr);
177  ierr = DMSetType(dm, dm_type_name.c_str());
178  CHKERRABORT(comm, ierr);
179  return SmartPetscObj<DM>(dm);
180 };
181 
182 /**
183  * @brief Create smart ghost vector
184  *
185  * For details abut arguments see here:
186  * <a
187  * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecCreateGhost.html>VecCreateGhost</a>.
188  *
189  * \code
190  * auto vec = createSmartGhostVector(...);
191  * \endcode
192  *
193  */
194 auto createSmartGhostVector = [](MPI_Comm comm, PetscInt n, PetscInt N,
195  PetscInt nghost, const PetscInt ghosts[]) {
196  Vec vv;
197  ierr = VecCreateGhost(comm, n, N, nghost, ghosts, &vv);
198  CHKERRABORT(comm, ierr);
199  return SmartPetscObj<Vec>(vv);
200 };
201 
202 /**
203  * @brief Create duplicate vector of smart vector
204  *
205  * For details abut arguments see here:
206  * <a
207  * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecDuplicate.html>VecDuplicate</a>.
208  */
210  if (vec.use_count()) {
211  Vec duplicate;
212  ierr = VecDuplicate(vec, &duplicate);
213  CHKERRABORT(PETSC_COMM_SELF, ierr);
214  return SmartPetscObj<Vec>(duplicate);
215  } else {
216  return SmartPetscObj<Vec>();
217  }
218 };
219 
221  Vec duplicate;
222  ierr = VecDuplicate(vec, &duplicate);
223  CHKERRABORT(PETSC_COMM_SELF, ierr);
224  return SmartPetscObj<Vec>(duplicate);
225 };
226 
227 auto createTS = [](MPI_Comm comm) {
228  TS ts;
229  ierr = TSCreate(comm, &ts);
230  CHKERRABORT(comm, ierr);
231  return SmartPetscObj<TS>(ts);
232 };
233 
234 auto createSNES = [](MPI_Comm comm) {
235  SNES snes;
236  ierr = SNESCreate(comm, &snes);
237  CHKERRABORT(comm, ierr);
238  return SmartPetscObj<SNES>(snes);
239 };
240 
241 auto createKSP = [](MPI_Comm comm) {
242  KSP ksp;
243  ierr = KSPCreate(comm, &ksp);
244  CHKERRABORT(comm, ierr);
245  return SmartPetscObj<KSP>(ksp);
246 };
247 
248 auto createPC = [](MPI_Comm comm) {
249  PC pc;
250  ierr = PCCreate(comm, &pc);
251  CHKERRABORT(comm, ierr);
252  return SmartPetscObj<PC>(pc);
253 };
254 
255 } // namespace MoFEM
256 
257 #endif // __AUXPETSC_HPP__
BasicMethodPtr(BasicMethod *ptr)
Definition: AuxPETSc.hpp:92
structure for User Loop Methods on finite elementsIt can be used to calculate stiffness matrices,...
virtual ~PairNameFEMethodPtr()
Definition: AuxPETSc.hpp:78
auto createTS
Definition: AuxPETSc.hpp:227
int use_count() const
Definition: AuxPETSc.hpp:141
auto createSNES
Definition: AuxPETSc.hpp:234
PetscObject getPetscObject(T obj)
Definition: AuxPETSc.hpp:23
#define THROW_MESSAGE(a)
Throw MoFEM exception.
Definition: definitions.h:620
SmartPetscObj< Vec > smartVectorDuplicate(SmartPetscObj< Vec > &vec)
Create duplicate vector of smart vector.
Definition: AuxPETSc.hpp:209
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
auto createPC
Definition: AuxPETSc.hpp:248
std::vector< BasicMethodPtr > BasicMethodsSequence
Definition: AuxPETSc.hpp:112
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:241
auto createSmartGhostVector
Create smart ghost vector.
Definition: AuxPETSc.hpp:194
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:173
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