v0.13.1
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
21namespace MoFEM {
22template <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 */
36template <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 */
50template <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 if (cnt > 1) {
57 ierr = PetscObjectDereference(MoFEM::getPetscObject(obj));
58 } else {
59 ierr = PetscObjectDestroy(reinterpret_cast<PetscObject *>(&obj));
60 }
61 }
62 auto comm = PetscObjectComm(MoFEM::getPetscObject(obj));
63 CHKERRABORT(comm, ierr);
64 }
65}
66
67template <> void intrusive_ptr_release<Vec>(Vec obj);
68template <> void intrusive_ptr_release<Mat>(Mat obj);
69template <> void intrusive_ptr_release<DM>(DM obj);
70template <> void intrusive_ptr_release<IS>(IS obj);
71template <> void intrusive_ptr_release<AO>(AO obj);
72template <> void intrusive_ptr_release<KSP>(KSP obj);
73template <> void intrusive_ptr_release<SNES>(SNES obj);
74template <> void intrusive_ptr_release<TS>(TS obj);
75
76namespace MoFEM {
77/**
78 * @brief intrusive_ptr for managing petsc objects
79 *
80 * It manages destruction, referencing and dereferencing petsc objects. It is
81 * similar how smart_ptr pointers works, but applied for petsc objects like Vec,
82 * DM, Mat, etc.
83 *
84 * \code
85 * SmartPetscObj<Vec> smart_vec = createSmartGhostVector(...);
86 * \endcode
87 *
88 * @tparam OBJ
89 */
90template <typename OBJ>
92 : public boost::intrusive_ptr<typename std::remove_pointer<OBJ>::type> {
93
95
96 using Derived::Derived;
97
98 SmartPetscObj(std::nullptr_t ptr) : SmartPetscObj() {}
99
100 /**
101 * @brief Construct a new Smart Petsc Obj object
102 *
103 * \note If add_red is set to true, you have to destroy OBJ.
104 *
105 * @param o
106 * @param add_ref // if false ownership of OBJ is taken by SmartPetscObj
107 */
108 explicit SmartPetscObj(OBJ o, bool add_ref = false)
109 : boost::intrusive_ptr<typename std::remove_pointer<OBJ>::type>(o,
110 add_ref) {
111 }
112
113 operator OBJ() { return this->get(); }
114 explicit operator PetscObject() {
115 return reinterpret_cast<PetscObject>(this->get());
116 }
117
118 int use_count() const {
119 if (this->get()) {
120 int cnt;
121 ierr = PetscObjectGetReference(getPetscObject(this->get()), &cnt);
122 CHKERRABORT(PetscObjectComm(getPetscObject(this->get())), ierr);
123 return cnt;
124 } else
125 return 0;
126 }
127};
128
129/**
130 * @brief Creates smart DM object
131 *
132 * DM object can be used as any other object, but is destroyed as smart pointer
133 * when no loneger used.
134 *
135 * \code
136 * CHKERR DMRegister_MoFEM("MOFEM")
137 * {
138 * auto dm = createSmartDM(PETSC_COMM_WORLD, "MOFEM");
139 *
140 * // ...
141 *
142 * // dm is autmatically destroyed when program goes out of the scope
143 * }
144 *
145 *
146 *
147 * \endcode
148 *
149 */
150inline auto createSmartDM(MPI_Comm comm, const std::string dm_type_name) {
151 DM dm;
152 CHK_THROW_MESSAGE(DMCreate(comm, &dm), "Failed to create DM");
153 CHK_THROW_MESSAGE(DMSetType(dm, dm_type_name.c_str()), "Failed set DM type");
154 return SmartPetscObj<DM>(dm);
155};
156
157/**
158 * @brief Get the Comm From Petsc Object object
159 *
160 * @param obj
161 * @return MPI_Comm
162 */
163inline MPI_Comm getCommFromPetscObject(PetscObject obj) {
164 MPI_Comm comm;
165 CHK_THROW_MESSAGE(PetscObjectGetComm(obj, &comm),
166 "Failed to get comm from PETSc object");
167 return comm;
168};
169
170/**
171 * @brief Create smart ghost vector
172 *
173 * For details abut arguments see here:
174 * <a
175 * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecCreateGhost.html>VecCreateGhost</a>.
176 *
177 * \code
178 * auto vec = createSmartGhostVector(...);
179 * \endcode
180 *
181 */
182inline auto createSmartGhostVector(MPI_Comm comm, PetscInt n, PetscInt N,
183 PetscInt nghost, const PetscInt ghosts[]) {
184 Vec vv;
185 CHK_THROW_MESSAGE(VecCreateGhost(comm, n, N, nghost, ghosts, &vv),
186 "Failed to create ghosted Vec");
187 return SmartPetscObj<Vec>(vv);
188};
189
190/**
191 * @brief Create MPI Vector
192 *
193 * For details abut arguments see here:
194 * <a
195 * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecCreateMPI.html>VecCreateMPI</a>.
196 *
197 */
198inline auto createSmartVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N) {
199 Vec vv;
200 CHK_THROW_MESSAGE(VecCreateMPI(comm, n, N, &vv), "Failed to create Vec");
201 return SmartPetscObj<Vec>(vv);
202};
203
204/**
205 * @brief Create duplicate vector of smart vector
206 *
207 * For details abut arguments see here:
208 * <a
209 * href=https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecDuplicate.html>VecDuplicate</a>.
210 */
212 if (vec.use_count()) {
213 Vec duplicate;
214 CHK_THROW_MESSAGE(VecDuplicate(vec, &duplicate), "Failed to duplicate Vec");
215 return SmartPetscObj<Vec>(duplicate);
216 } else {
217 return SmartPetscObj<Vec>();
218 }
219};
220
222 Vec duplicate;
223 CHK_THROW_MESSAGE(VecDuplicate(vec, &duplicate), "Failed to duplicate Vec");
224 return SmartPetscObj<Vec>(duplicate);
225};
226
227inline SmartPetscObj<Mat> smartMatDuplicate(Mat &mat, MatDuplicateOption op) {
228 Mat duplicate;
229 CHK_THROW_MESSAGE(MatDuplicate(mat, op, &duplicate),
230 "Failed to duplicate Mat");
231 return SmartPetscObj<Mat>(duplicate);
232};
233
235 MatDuplicateOption op) {
236 if (mat.use_count()) {
237 Mat duplicate;
238 CHK_THROW_MESSAGE(MatDuplicate(mat, op, &duplicate),
239 "Failed to duplicate Mat");
240 return SmartPetscObj<Mat>(duplicate);
241 } else {
242 return SmartPetscObj<Mat>();
243 }
244};
245
246inline auto createTS(MPI_Comm comm) {
247 TS ts;
248 CHK_THROW_MESSAGE(TSCreate(comm, &ts), "Failed to create TS");
249 return SmartPetscObj<TS>(ts);
250};
251
252inline auto createSNES(MPI_Comm comm) {
253 SNES snes;
254 CHK_THROW_MESSAGE(SNESCreate(comm, &snes), "Failed to create SNES");
255 return SmartPetscObj<SNES>(snes);
256};
257
258inline auto createKSP(MPI_Comm comm) {
259 KSP ksp;
260 CHK_THROW_MESSAGE(KSPCreate(comm, &ksp), "Failed to create KSP");
261 return SmartPetscObj<KSP>(ksp);
262};
263
264inline auto createPC(MPI_Comm comm) {
265 PC pc;
266 CHK_THROW_MESSAGE(PCCreate(comm, &pc), "Failed to create PC");
267 return SmartPetscObj<PC>(pc);
268};
269
270} // namespace MoFEM
271
272#endif
static Index< 'n', 3 > n
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.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
Definition: definitions.h:608
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
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)
STL namespace.
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