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