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