1 /*
2 Defines the basic header of all PETSc objects.
3 */
4 #pragma once
5 #include <petscsys.h>
6
7 /* SUBMANSEC = Sys */
8
9 #if defined(PETSC_CLANG_STATIC_ANALYZER)
10 #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
11 #else
12 #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
13 #endif
14
15 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
16 PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
17 PETSC_INTERN PetscErrorCode PetscStackReset(void);
18 PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
19 PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
20 #else
21 #define PetscStackSetCheck(check) PETSC_SUCCESS
22 #define PetscStackReset() PETSC_SUCCESS
23 #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
24 #define PetscStackPrint(stack, file) PETSC_SUCCESS
25 #endif
26
27 /* These are used internally by PETSc ASCII IO routines*/
28 #include <stdarg.h>
29 PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);
30
31 /*
32 All major PETSc data structures have a common core; this is defined
33 below by PETSCHEADER.
34
35 PetscHeaderCreate() should be used whenever creating a PETSc structure.
36 */
37
38 /*
39 PetscOps: structure of core operations that all PETSc objects support.
40
41 view() - Is the routine for viewing the entire PETSc object; for
42 example, MatView() is the general matrix viewing routine.
43 This is used by PetscObjectView((PetscObject)obj) to allow
44 viewing any PETSc object.
45 destroy() - Is the routine for destroying the entire PETSc object;
46 for example,MatDestroy() is the general matrix
47 destruction routine.
48 This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
49 destroying any PETSc object.
50 */
51
52 typedef struct {
53 PetscErrorCode (*view)(PetscObject, PetscViewer);
54 PetscErrorCode (*destroy)(PetscObject *);
55 } PetscOps;
56
57 /*E
58 PetscFortranCallbackType - Indicates if a Fortran callback stored in a `PetscObject` is associated with the class or the current particular type of the object
59
60 Values:
61 + `PETSC_FORTRAN_CALLBACK_CLASS` - the callback is associated with the class
62 - `PETSC_FORTRAN_CALLBACK_SUBTYPE` - the callback is associated with the current particular subtype
63
64 Level: developer
65
66 Developer Note:
67 The two sets of callbacks are stored in different arrays in the `PetscObject` because the `PETSC_FORTRAN_CALLBACK_SUBTYPE` callbacks must
68 be removed whenever the type of the object is changed (because they are not appropriate for other types). The removal is done in
69 `PetscObjectChangeTypeName()`.
70
71 .seealso: `PetscFortranCallbackFn`, `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`, `PetscObjectChangeTypeName()`
72 E*/
73 typedef enum {
74 PETSC_FORTRAN_CALLBACK_CLASS,
75 PETSC_FORTRAN_CALLBACK_SUBTYPE,
76 PETSC_FORTRAN_CALLBACK_MAXTYPE
77 } PetscFortranCallbackType;
78
79 typedef size_t PetscFortranCallbackId;
80 #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
81 PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
82 PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);
83
84 /*S
85 PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback
86
87 Level: advanced
88
89 Notes:
90 `PetscFortranCallbackFn *` plays the role of `void *` for function pointers in the PETSc Fortran API.
91
92 .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
93 S*/
94 PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);
95
96 typedef struct {
97 PetscFortranCallbackFn *func;
98 void *ctx;
99 } PetscFortranCallback;
100
101 /*
102 All PETSc objects begin with the fields defined in PETSCHEADER.
103 The PetscObject is a way of examining these fields regardless of
104 the specific object. In C++ this could be a base abstract class
105 from which all objects are derived.
106 */
107 #define PETSC_MAX_OPTIONS_HANDLER 5
108 typedef struct _p_PetscObject {
109 PetscOps bops[1];
110 PetscClassId classid;
111 MPI_Comm comm;
112 PetscObjectId id; /* this is used to compare object for identity that may no longer exist since memory addresses get recycled for new objects */
113 PetscInt refct;
114 PetscErrorCode (*non_cyclic_references)(PetscObject, PetscInt *);
115 PetscInt64 cidx;
116 PetscMPIInt tag;
117 PetscFunctionList qlist;
118 PetscObjectList olist;
119 char *class_name; /* for example, "Vec" */
120 char *description;
121 char *mansec;
122 char *type_name; /* this is the subclass, for example VECSEQ which equals "seq" */
123 char *name;
124 char *prefix;
125 PetscInt tablevel;
126 void *cpp;
127 PetscObjectState state;
128 PetscInt int_idmax, intstar_idmax;
129 PetscObjectState *intcomposedstate, *intstarcomposedstate;
130 PetscInt *intcomposeddata, **intstarcomposeddata;
131 PetscInt real_idmax, realstar_idmax;
132 PetscObjectState *realcomposedstate, *realstarcomposedstate;
133 PetscReal *realcomposeddata, **realstarcomposeddata;
134 #if PetscDefined(USE_COMPLEX)
135 PetscInt scalar_idmax, scalarstar_idmax;
136 PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
137 PetscScalar *scalarcomposeddata, **scalarstarcomposeddata;
138 #endif
139 PetscFortranCallbackFn **fortran_func_pointers; /* used by Fortran interface functions to stash user provided Fortran functions */
140 PetscFortranCallbackId num_fortran_func_pointers; /* number of Fortran function pointers allocated */
141 PetscFortranCallback *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
142 PetscFortranCallbackId num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
143 void *python_context;
144 PetscErrorCode (*python_destroy)(void *);
145
146 PetscInt noptionhandler;
147 PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems, PetscCtx);
148 PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscCtxRt);
149 void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
150 #if defined(PETSC_HAVE_SAWS)
151 PetscBool amsmem; /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
152 PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
153 #endif
154 PetscOptions options; /* options database used, NULL means default */
155 PetscBool optionsprinted;
156 PetscBool donotPetscObjectPrintClassNamePrefixType;
157 } _p_PetscObject;
158
159 #define PETSCHEADER(ObjectOps) \
160 _p_PetscObject hdr; \
161 ObjectOps ops[1]
162
163 #define PETSCFREEDHEADER -1
164
165 /*S
166 PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`
167
168 Calling Sequence:
169 . obj - the `PetscObject` to destroy
170
171 Level: beginner
172
173 Note:
174 The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.
175
176 .seealso: `PetscObject`, `PetscObjectDestroy()`
177 S*/
178 PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);
179
180 PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;
181
182 /*S
183 PetscObjectViewFn - A prototype of a function that can view a `PetscObject`
184
185 Calling Sequence:
186 + obj - the `PetscObject` to view
187 - v - the viewer
188
189 Level: beginner
190
191 Note:
192 The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.
193
194 .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
195 S*/
196 PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);
197
198 PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;
199
200 /*MC
201 PetscHeaderCreate - Creates a raw PETSc object of a particular class
202
203 Synopsis:
204 #include <petsc/private/petscimpl.h>
205 PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn * destroy, PetscObjectViewFn * view)
206
207 Collective
208
209 Input Parameters:
210 + classid - The classid associated with this object (for example `VEC_CLASSID`)
211 . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
212 . descr - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
213 . mansec - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`
214 . comm - The MPI Communicator
215 . destroy - The destroy routine for this object (for example `VecDestroy()`)
216 - view - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`
217
218 Output Parameter:
219 . h - The newly created `PetscObject`
220
221 Level: developer
222
223 Notes:
224 Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
225 C/C++ structure which satisfies all of the following\:
226
227 1. The first member of the structure must be a `_p_PetscObject`.
228 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
229 - Has no virtual functions or base classes.
230 - Has only standard layout non-static members (if any).
231 - Has only standard layout base classes (if any).
232
233 See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
234 information.
235
236 Example Usage:
237 Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
238 objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
239 `<OBJECT_TYPE>View()`.
240 .vb
241 Vec v;
242
243 PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
244 .ve
245
246 It is possible to create custom `PetscObject`s, note however that they must abide by the
247 restrictions set forth above.
248 .vb
249 // OK, first member of C structure is _p_PetscObject
250 struct MyCPetscObject_s
251 {
252 _p_PetscObject header;
253 int some_data;
254 };
255 typedef struct *MyCPetscObject_s MyCPetscObject;
256
257 PetscErrorCode MyObjectDestroy(MyObject *);
258 PetscErrorCode MyObjectView(MyObject);
259
260 MyCPetscObject obj;
261
262 // assume MY_PETSC_CLASSID is already registered
263 PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
264
265 // OK, only destroy function must be given, all others may be NULL
266 PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
267
268 // ERROR must be a single-level pointer
269 PetscHeaderCreate(&obj, ...);
270 .ve
271
272 Illustrating proper construction from C++\:
273 .vb
274 // ERROR, class is not standard layout, first member must be publicly accessible
275 class BadCppPetscObject
276 {
277 _p_PetscObject header;
278 };
279
280 // ERROR, class is not standard layout, has a virtual function and virtual inheritance
281 class BadCppPetscObject2 : virtual BaseClass
282 {
283 public:
284 _p_PetscObject header;
285
286 virtual void foo();
287 };
288
289 // ERROR, class is not standard layout! Has non-standard layout member
290 class BadCppPetscObject2
291 {
292 public:
293 _p_PetscObject header;
294 BadCppPetscObject non_standard_layout;
295 };
296
297 // OK, class is standard layout!
298 class GoodCppPetscObject;
299 using MyCppObject = GoodCppPetscObject *;
300
301 // OK, non-virtual inheritance of other standard layout class does not affect layout
302 class GoodCppPetscObject : StandardLayoutClass
303 {
304 public:
305 // OK, non standard layout member is static, does not affect layout
306 static BadCppPetscObject non_standard_layout;
307
308 // OK, first non-static member is _p_PetscObject
309 _p_PetscObject header;
310
311 // OK, non-virtual member functions do not affect class layout
312 void foo();
313
314 // OK, may use "member" functions for destroy and view so long as they are static
315 static PetscErrorCode destroy(MyCppObject *);
316 static PetscErrorCode view(MyCppObject);
317 };
318
319 // OK, usage via pointer
320 MyObject obj;
321
322 PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
323 .ve
324
325 .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
326 M*/
327 #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
328 PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))
329
330 PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
331 PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
332 PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
333 PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
334 PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
335
336 /*MC
337 PetscHeaderDestroy - Final step in destroying a `PetscObject`
338
339 Synopsis:
340 #include <petsc/private/petscimpl.h>
341 PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
342
343 Collective
344
345 Input Parameter:
346 . h - A pointer to the header created with `PetscHeaderCreate()`
347
348 Level: developer
349
350 Notes:
351 `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
352
353 Example Usage:
354 .vb
355 PetscObject obj;
356
357 PetscHeaderCreate(obj, ...);
358 // use obj...
359
360 // note pointer to obj is used
361 PetscHeaderDestroy(&obj);
362 .ve
363
364 Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
365 deallocates the memory for the structure itself\:
366 .vb
367 typedef struct MyPetscObject_s *MyPetscObject;
368 struct MyPetscObject_s
369 {
370 _p_PetscObject hdr;
371 PetscInt *foo;
372 PetscScalar *bar;
373 };
374
375 // assume obj is created/initialized elsewhere...
376 MyPetscObject obj;
377
378 // OK, should dispose of all dynamically allocated resources before calling
379 // PetscHeaderDestroy()
380 PetscFree(obj->foo);
381
382 // OK, dispose of obj
383 PetscHeaderDestroy(&obj);
384
385 // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
386 // obj->bar is potentially leaked!
387 PetscFree(obj->bar);
388 .ve
389
390 .seealso: `PetscObject`, `PetscHeaderCreate()`
391 M*/
392 #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)
393
394 PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject, PetscBool);
395 PETSC_INTERN PetscErrorCode PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
396 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
397 PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
398 PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, PetscCtx ctx);
399 PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);
400
401 PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
402 PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
403 PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
404
405 /* Code shared between C and Fortran */
406 PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscInt);
407
408 #if PetscDefined(HAVE_SETJMP_H)
409 PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
410 #else
411 #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
412 #endif
413
414 #if defined(PETSC_CLANG_STATIC_ANALYZER)
415 template <typename T>
416 extern void PetscValidHeaderSpecificType(T, PetscClassId, int, const char[]);
417 template <typename T>
418 extern void PetscValidHeaderSpecific(T, PetscClassId, int);
419 template <typename T>
420 extern void PetscValidHeader(T, int);
421 template <typename T>
PetscAssertPointer(T,int)422 extern void PetscAssertPointer(T, int)
423 {
424 }
425 template <typename T>
426 extern void PetscValidFunction(T, int);
427 #else
428 // Macros to test if a PETSc object is valid and if pointers are valid
429 #if PetscDefined(USE_DEBUG)
430 /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
431 #define PetscValidHeaderSpecificType(h, ck, arg, t) \
432 do { \
433 PetscBool _7_same; \
434 PetscValidHeaderSpecific(h, ck, arg); \
435 PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
436 PetscCheck(_7_same, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong subtype object:Parameter # %d must have implementation %s it is %s", arg, t, ((PetscObject)(h))->type_name); \
437 } while (0)
438
439 #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
440 do { \
441 PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
442 PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
443 } while (0)
444
445 #define PetscValidHeaderSpecific(h, ck, arg) \
446 do { \
447 PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
448 if (((PetscObject)(h))->classid != ck) { \
449 PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
450 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
451 } \
452 } while (0)
453
454 #define PetscValidHeader(h, arg) \
455 do { \
456 PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
457 PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
458 PetscCheck(((PetscObject)(h))->classid >= PETSC_SMALLEST_CLASSID && ((PetscObject)(h))->classid <= PETSC_LARGEST_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Invalid type of object: Parameter # %d", arg); \
459 } while (0)
460
461 #if defined(__cplusplus)
462 #include <type_traits> // std::decay
463
464 namespace Petsc
465 {
466
467 namespace util
468 {
469
470 template <typename T>
471 struct PetscAssertPointerImpl {
typePetscAssertPointerImpl472 PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
stringPetscAssertPointerImpl473 PETSC_NODISCARD static constexpr const char *string() noexcept { return "memory"; }
474 };
475
476 #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
477 template <> \
478 struct PetscAssertPointerImpl<T *> { \
479 PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
480 PETSC_NODISCARD static constexpr const char *string() noexcept { return PetscStringize(T); } \
481 }; \
482 template <> \
483 struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
484 template <> \
485 struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
486 template <> \
487 struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
488
489 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
490 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
491 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
492 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
493 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
494 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
495 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
496 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
497 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
498 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
499 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
500 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
501 #if defined(PETSC_HAVE_COMPLEX)
502 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
503 #endif
504
505 #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
506
507 } // namespace util
508
509 } // namespace Petsc
510
511 #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
512 #define PetscAssertPointer_String(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
513
514 #elif PETSC_C_VERSION >= 11
515 #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
516
517 #if PetscDefined(HAVE_COMPLEX)
518 #define PETSC_GENERIC_CV_COMPLEX(result) , PETSC_GENERIC_CV(PetscComplex, result)
519 #else
520 #define PETSC_GENERIC_CV_COMPLEX(result)
521 #endif
522
523 #define PetscAssertPointer_PetscDataType(h) \
524 _Generic((h), \
525 default: PETSC_CHAR, \
526 PETSC_GENERIC_CV( char, PETSC_CHAR), \
527 PETSC_GENERIC_CV( signed char, PETSC_CHAR), \
528 PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
529 PETSC_GENERIC_CV( short, PETSC_SHORT), \
530 PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
531 PETSC_GENERIC_CV( float, PETSC_FLOAT), \
532 PETSC_GENERIC_CV( double, PETSC_DOUBLE), \
533 PETSC_GENERIC_CV( int32_t, PETSC_INT32), \
534 PETSC_GENERIC_CV( uint32_t, PETSC_INT32), \
535 PETSC_GENERIC_CV( int64_t, PETSC_INT64), \
536 PETSC_GENERIC_CV( uint64_t, PETSC_INT64) \
537 PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
538
539 #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
540
541 #if PetscDefined(HAVE_COMPLEX)
542 #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX , PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
543 #else
544 #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
545 #endif
546
547 #define PetscAssertPointer_String(h) \
548 _Generic((h), \
549 default: "memory", \
550 PETSC_GENERIC_CV_STRINGIZE(char), \
551 PETSC_GENERIC_CV_STRINGIZE(signed char), \
552 PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
553 PETSC_GENERIC_CV_STRINGIZE(short), \
554 PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
555 PETSC_GENERIC_CV_STRINGIZE(float), \
556 PETSC_GENERIC_CV_STRINGIZE(double), \
557 PETSC_GENERIC_CV_STRINGIZE(int32_t), \
558 PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
559 PETSC_GENERIC_CV_STRINGIZE(int64_t), \
560 PETSC_GENERIC_CV_STRINGIZE(uint64_t) \
561 PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
562 #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
563 #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
564 #define PetscAssertPointer_String(h) "memory"
565 #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
566 #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
567 #define PetscValidFunction(f, arg) PetscCheck((f), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Function Pointer: Parameter # %d", arg)
568 #else // PetscDefined(USE_DEBUG)
569 #define PetscValidHeaderSpecific(h, ck, arg) \
570 do { \
571 (void)(h); \
572 } while (0)
573 #define PetscValidHeaderSpecificType(h, ck, arg, t) \
574 do { \
575 (void)(h); \
576 } while (0)
577 #define PetscValidHeader(h, arg) \
578 do { \
579 (void)(h); \
580 } while (0)
581 #define PetscAssertPointer(h, arg) \
582 do { \
583 (void)(h); \
584 } while (0)
585 #define PetscValidFunction(h, arg) \
586 do { \
587 (void)(h); \
588 } while (0)
589 #endif // PetscDefined(USE_DEBUG)
590 #endif // PETSC_CLANG_STATIC_ANALYZER
591
592 #define PetscValidPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
593 #define PetscValidCharPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
594 #define PetscValidIntPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
595 #define PetscValidInt64Pointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
596 #define PetscValidCountPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
597 #define PetscValidBoolPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
598 #define PetscValidScalarPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
599 #define PetscValidRealPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
600
601 #define PetscSorted(n, idx, sorted) \
602 do { \
603 (sorted) = PETSC_TRUE; \
604 for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
605 if ((idx)[_i_] < (idx)[_i_ - 1]) { \
606 (sorted) = PETSC_FALSE; \
607 break; \
608 } \
609 } \
610 } while (0)
611
612 #if !defined(PETSC_CLANG_STATIC_ANALYZER)
613 #if !defined(PETSC_USE_DEBUG)
614
615 #define PetscCheckSameType(a, arga, b, argb) \
616 do { \
617 (void)(a); \
618 (void)(b); \
619 } while (0)
620 #define PetscCheckTypeName(a, type) \
621 do { \
622 (void)(a); \
623 } while (0)
624 #define PetscCheckTypeNames(a, type1, type2) \
625 do { \
626 (void)(a); \
627 } while (0)
628 #define PetscValidType(a, arg) \
629 do { \
630 (void)(a); \
631 } while (0)
632 #define PetscCheckSameComm(a, arga, b, argb) \
633 do { \
634 (void)(a); \
635 (void)(b); \
636 } while (0)
637 #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
638 do { \
639 (void)(a); \
640 (void)(b); \
641 } while (0)
642 #define PetscValidLogicalCollectiveScalar(a, b, arg) \
643 do { \
644 (void)(a); \
645 (void)(b); \
646 } while (0)
647 #define PetscValidLogicalCollectiveReal(a, b, arg) \
648 do { \
649 (void)(a); \
650 (void)(b); \
651 } while (0)
652 #define PetscValidLogicalCollectiveInt(a, b, arg) \
653 do { \
654 (void)(a); \
655 (void)(b); \
656 } while (0)
657 #define PetscValidLogicalCollectiveIntComm(a, b, arg) \
658 do { \
659 (void)(a); \
660 (void)(b); \
661 } while (0)
662 #define PetscValidLogicalCollectiveCount(a, b, arg) \
663 do { \
664 (void)(a); \
665 (void)(b); \
666 } while (0)
667 #define PetscValidLogicalCollectiveMPIInt(a, b, arg) \
668 do { \
669 (void)(a); \
670 (void)(b); \
671 } while (0)
672 #define PetscValidLogicalCollectiveBool(a, b, arg) \
673 do { \
674 (void)(a); \
675 (void)(b); \
676 } while (0)
677 #define PetscValidLogicalCollectiveEnum(a, b, arg) \
678 do { \
679 (void)(a); \
680 (void)(b); \
681 } while (0)
682 #define PetscCheckSorted(n, idx) \
683 do { \
684 (void)(n); \
685 (void)(idx); \
686 } while (0)
687
688 #else
689
690 /*
691 This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
692 member associated with the string type_name that can be quickly compared.
693
694 **Do not swap this macro to compare string type_name!**
695
696 This macro is used incorrectly in the code. Many places that do not need identity of the
697 types incorrectly call this check and would need to be fixed if this macro is enabled.
698 */
699 #if 0
700 #define PetscCheckSameType(a, arga, b, argb) \
701 do { \
702 PetscBool pcst_type_eq_ = PETSC_TRUE; \
703 PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
704 PetscCheck(pcst_type_eq_, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMETYPE, "Objects not of same type : Argument # % d and % d, % s != % s ", arga, argb, ((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name); \
705 } while (0)
706 #else
707 #define PetscCheckSameType(a, arga, b, argb) \
708 do { \
709 (void)(a); \
710 (void)(b); \
711 } while (0)
712 #endif
713
714 /*
715 Check type_name
716 */
717 #define PetscCheckTypeName(a, type) \
718 do { \
719 PetscBool _7_match; \
720 PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
721 PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
722 } while (0)
723
724 #define PetscCheckTypeNames(a, type1, type2) \
725 do { \
726 PetscBool _7_match; \
727 PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
728 PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
729 } while (0)
730
731 /*
732 Use this macro to check if the type is set
733 */
734 #define PetscValidType(a, arg) PetscCheck(((PetscObject)(a))->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "%s object's type is not set: Argument # %d", ((PetscObject)(a))->class_name, arg)
735
736 /*
737 Sometimes object must live on same communicator to inter-operate
738 */
739 #define PetscCheckSameComm(a, arga, b, argb) \
740 do { \
741 PetscMPIInt _7_flag; \
742 PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
743 PetscCheck(_7_flag == MPI_CONGRUENT || _7_flag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "Different communicators in the two objects: Argument # %d and %d flag %d", arga, argb, _7_flag); \
744 } while (0)
745
746 #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
747 do { \
748 PetscCheckSameType(a, arga, b, argb); \
749 PetscCheckSameComm(a, arga, b, argb); \
750 } while (0)
751
752 #define PetscValidLogicalCollectiveScalar(a, b, arg) \
753 do { \
754 PetscScalar b0 = (b); \
755 PetscReal b1[5]; \
756 if (PetscIsNanScalar(b0)) { \
757 b1[4] = 1; \
758 } else { \
759 b1[4] = 0; \
760 }; \
761 b1[0] = -PetscRealPart(b0); \
762 b1[1] = PetscRealPart(b0); \
763 b1[2] = -PetscImaginaryPart(b0); \
764 b1[3] = PetscImaginaryPart(b0); \
765 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
766 PetscCheck(b1[4] > 0 || (PetscEqualReal(-b1[0], b1[1]) && PetscEqualReal(-b1[2], b1[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
767 } while (0)
768
769 #define PetscValidLogicalCollectiveReal(a, b, arg) \
770 do { \
771 PetscReal b0 = (b), b1[3]; \
772 if (PetscIsNanReal(b0)) { \
773 b1[2] = 1; \
774 } else { \
775 b1[2] = 0; \
776 }; \
777 b1[0] = -b0; \
778 b1[1] = b0; \
779 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
780 PetscCheck(b1[2] > 0 || PetscEqualReal(-b1[0], b1[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
781 } while (0)
782
783 #define PetscValidLogicalCollectiveInt(a, b, arg) \
784 do { \
785 PetscInt b0 = (b), b1[2]; \
786 b1[0] = -b0; \
787 b1[1] = b0; \
788 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
789 PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
790 } while (0)
791
792 #define PetscValidLogicalCollectiveIntComm(a, b, arg) \
793 do { \
794 PetscInt b1[2]; \
795 b1[0] = -b; \
796 b1[1] = b; \
797 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
798 PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
799 } while (0)
800
801 #define PetscValidLogicalCollectiveCount(a, b, arg) \
802 do { \
803 PetscCount b0 = (b), b1[2]; \
804 b1[0] = -b0; \
805 b1[1] = b0; \
806 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
807 PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
808 } while (0)
809
810 #define PetscValidLogicalCollectiveMPIInt(a, b, arg) \
811 do { \
812 PetscMPIInt b0 = (b), b1[2]; \
813 b1[0] = -b0; \
814 b1[1] = b0; \
815 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
816 PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
817 } while (0)
818
819 #define PetscValidLogicalCollectiveBool(a, b, arg) \
820 do { \
821 PetscBool b0 = (PetscBool)(b), b1[2]; \
822 b1[0] = !b0; \
823 b1[1] = b0; \
824 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
825 PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
826 } while (0)
827
828 #define PetscValidLogicalCollectiveEnum(a, b, arg) \
829 do { \
830 PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
831 b1[0] = -b0; \
832 b1[1] = b0; \
833 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
834 PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
835 } while (0)
836
837 #define PetscCheckSorted(n, idx) \
838 do { \
839 PetscBool _1_flg; \
840 PetscSorted(n, idx, _1_flg); \
841 PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
842 } while (0)
843
844 #endif
845 #else /* PETSC_CLANG_STATIC_ANALYZER */
846 template <typename Ta, typename Tb>
847 extern void PetscCheckSameType(Ta, int, Tb, int);
848 template <typename Ta, typename Tb>
849 extern void PetscCheckTypeName(Ta, Tb);
850 template <typename Ta, typename Tb, typename Tc>
851 extern void PetscCheckTypeNames(Ta, Tb, Tc);
852 template <typename T>
853 extern void PetscValidType(T, int);
854 template <typename Ta, typename Tb>
855 extern void PetscCheckSameComm(Ta, int, Tb, int);
856 template <typename Ta, typename Tb>
857 extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
858 template <typename Ta, typename Tb>
859 extern void PetscValidLogicalCollectiveScalar(Ta, Tb, int);
860 template <typename Ta, typename Tb>
861 extern void PetscValidLogicalCollectiveReal(Ta, Tb, int);
862 template <typename Ta, typename Tb>
863 extern void PetscValidLogicalCollectiveInt(Ta, Tb, int);
864 template <typename Ta, typename Tb>
865 extern void PetscValidLogicalCollectiveCount(Ta, Tb, int);
866 template <typename Ta, typename Tb>
867 extern void PetscValidLogicalCollectiveMPIInt(Ta, Tb, int);
868 template <typename Ta, typename Tb>
869 extern void PetscValidLogicalCollectiveBool(Ta, Tb, int);
870 template <typename Ta, typename Tb>
871 extern void PetscValidLogicalCollectiveEnum(Ta, Tb, int);
872 template <typename T>
873 extern void PetscCheckSorted(PetscInt, T);
874 #endif /* PETSC_CLANG_STATIC_ANALYZER */
875
876 /*MC
877 PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
878
879 Synopsis:
880 #include "petsc/private/petscimpl.h"
881 PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
882
883 Input Parameters:
884 + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
885 . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
886 . arg_types - the argument types for the method, for example, (KSP,PetscInt)
887 - args - the arguments for the method, for example, (ksp,restart))
888
889 Level: developer
890
891 Notes:
892 This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
893
894 Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
895 in the object.
896
897 .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
898 M*/
899 #define PetscTryMethod(obj, A, B, C) \
900 do { \
901 PetscErrorCode(*_7_f) B; \
902 PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
903 if (_7_f) PetscCall((*_7_f)C); \
904 } while (0)
905
906 /*MC
907 PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
908
909 Synopsis:
910 #include "petsc/private/petscimpl.h"
911 PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
912
913 Input Parameters:
914 + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
915 . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
916 . arg_types - the argument types for the method, for example, (KSP,PetscInt)
917 - args - the arguments for the method, for example, (ksp,restart))
918
919 Level: developer
920
921 Notes:
922 This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
923
924 Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
925 in the object.
926
927 .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
928 M*/
929 #define PetscUseMethod(obj, A, B, C) \
930 do { \
931 PetscErrorCode(*_7_f) B; \
932 PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
933 PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
934 PetscCall((*_7_f)C); \
935 } while (0)
936
937 /*
938 Use Microsoft traditional preprocessor.
939
940 The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
941 sets _MSVC_TRADITIONAL to zero so this code path is not used.
942
943 It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
944
945 These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
946
947 PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
948 */
949 #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
950
951 #define PetscUseTypeMethod(obj, OP, ...) \
952 do { \
953 PetscErrorCode ierr_p_; \
954 PetscStackUpdateLine; \
955 PetscCheck((obj)->ops->OP, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", PetscStringize(OP), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
956 ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
957 PetscCall(ierr_p_); \
958 } while (0)
959
960 #define PetscTryTypeMethod(obj, OP, ...) \
961 do { \
962 if ((obj)->ops->OP) { \
963 PetscErrorCode ierr_p_; \
964 PetscStackUpdateLine; \
965 ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
966 PetscCall(ierr_p_); \
967 } \
968 } while (0)
969
970 #else
971
972 /*MC
973 PetscUseTypeMethod - Call a method on a `PetscObject`, that is a function in the objects function table `obj->ops`, error if the method does not exist
974
975 Synopsis:
976 #include "petsc/private/petscimpl.h"
977 PetscUseTypeMethod(obj, method, other_args)
978
979 Input Parameters:
980 + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
981 . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
982 - other_args - the other arguments for the method, `obj` is the first argument
983
984 Level: developer
985
986 Note:
987 This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
988
989 Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
990
991 .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
992 M*/
993 #define PetscUseTypeMethod(obj, ...) \
994 do { \
995 PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
996 PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
997 PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
998 } while (0)
999
1000 /*MC
1001 PetscTryTypeMethod - Call a method on a `PetscObject`, that is a function in the objects function table `obj->ops`, skip if the method does not exist
1002
1003 Synopsis:
1004 #include "petsc/private/petscimpl.h"
1005 PetscTryTypeMethod(obj, method, other_args)
1006
1007 Input Parameters:
1008 + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
1009 . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
1010 - other_args - the other arguments for the method, `obj` is the first argument
1011
1012 Level: developer
1013
1014 Note:
1015 This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
1016
1017 Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
1018
1019 .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1020 M*/
1021 #define PetscTryTypeMethod(obj, ...) \
1022 do { \
1023 if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1024 } while (0)
1025
1026 #endif
1027
1028 /*MC
1029 PetscObjectStateIncrease - Increases the state of any `PetscObject`
1030
1031 Synopsis:
1032 #include "petsc/private/petscimpl.h"
1033 PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
1034
1035 Logically Collective
1036
1037 Input Parameter:
1038 . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1039 cast with a (PetscObject), for example,
1040 `PetscObjectStateIncrease`((`PetscObject`)mat);
1041
1042 Level: developer
1043
1044 Notes:
1045 Object state is a 64-bit integer which gets increased every time
1046 the object is changed internally. By saving and later querying the object state
1047 one can determine whether information about the object is still current.
1048 Currently, state is maintained for `Vec` and `Mat` objects.
1049
1050 This routine is mostly for internal use by PETSc; a developer need only
1051 call it after explicit access to an object's internals. Routines such
1052 as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
1053 precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
1054
1055 Routines such as `VecNorm()` can bypass the computation if the norm has already been computed and the vector's state has not changed.
1056
1057 This routine is logically collective because state equality comparison needs to be possible without communication.
1058
1059 `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
1060
1061 .seealso: `PetscObjectStateGet()`, `PetscObject`
1062 M*/
1063 #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))
1064
1065 PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1066 PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1067 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1068 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1069 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1070 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1071 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1072 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1073 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1074 PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
1075
1076 /*MC
1077 PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
1078
1079 Synopsis:
1080 #include "petsc/private/petscimpl.h"
1081 PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1082
1083 Not Collective
1084
1085 Input Parameters:
1086 + obj - the object to which data is to be attached
1087 . id - the identifier for the data
1088 - data - the data to be attached, a `PetscInt`
1089
1090 Level: developer
1091
1092 Notes:
1093 The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1094
1095 This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1096 attached with `PetscObjectCompose()`
1097
1098 .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1099 `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1100 `PetscObjectCompose()`, `PetscObjectQuery()`
1101 M*/
1102 #define PetscObjectComposedDataSetInt(obj, id, data) \
1103 ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1104
1105 /*MC
1106 PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1107
1108 Synopsis:
1109 #include "petsc/private/petscimpl.h"
1110 PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1111
1112 Not Collective
1113
1114 Input Parameters:
1115 + obj - the object from which data is to be retrieved
1116 - id - the identifier for the data
1117
1118 Output Parameters:
1119 + data - the data to be retrieved, a `PetscInt`
1120 - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1121
1122 Level: developer
1123
1124 Notes:
1125 The `data` and `flag` variables are inlined, so they are not pointers.
1126
1127 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1128 `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1129 `PetscObjectCompose()`, `PetscObjectQuery()`
1130 M*/
1131 #define PetscObjectComposedDataGetInt(obj, id, data, flag) ((PetscErrorCode)(((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1132
1133 /*MC
1134 PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1135
1136 Synopsis:
1137 #include "petsc/private/petscimpl.h"
1138 PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1139
1140 Not Collective
1141
1142 Input Parameters:
1143 + obj - the object to which data is to be attached
1144 . id - the identifier for the data
1145 - data - the data to be attached, a `PetscInt` array
1146
1147 Level: developer
1148
1149 Notes:
1150 The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1151
1152 The length of the array accessed must be known, it is not available through this API.
1153
1154 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1155 `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1156 `PetscObjectCompose()`, `PetscObjectQuery()`
1157 M*/
1158 #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1159 ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1160
1161 /*MC
1162 PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1163
1164 Synopsis:
1165 #include "petsc/private/petscimpl.h"
1166 PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1167
1168 Not Collective
1169
1170 Input Parameters:
1171 + obj - the object from which data is to be retrieved
1172 - id - the identifier for the data
1173
1174 Output Parameters:
1175 + data - the data to be retrieved, a `PetscInt` array
1176 - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1177
1178 Level: developer
1179
1180 Notes:
1181 The `data` and `flag` variables are inlined, so they are not pointers.
1182
1183 The length of the array accessed must be known, it is not available through this API.
1184
1185 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1186 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1187 `PetscObjectCompose()`, `PetscObjectQuery()`
1188 M*/
1189 #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1190 ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1191
1192 /*MC
1193 PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1194
1195 Synopsis:
1196 #include "petsc/private/petscimpl.h"
1197 PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1198
1199 Not Collective
1200
1201 Input Parameters:
1202 + obj - the object to which data is to be attached
1203 . id - the identifier for the data
1204 - data - the data to be attached, a `PetscReal`
1205
1206 Level: developer
1207
1208 Note:
1209 The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1210
1211 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1212 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1213 `PetscObjectCompose()`, `PetscObjectQuery()`
1214 M*/
1215 #define PetscObjectComposedDataSetReal(obj, id, data) \
1216 ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1217
1218 /*MC
1219 PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1220
1221 Synopsis:
1222 #include "petsc/private/petscimpl.h"
1223 PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1224
1225 Not Collective
1226
1227 Input Parameters:
1228 + obj - the object from which data is to be retrieved
1229 - id - the identifier for the data
1230
1231 Output Parameters:
1232 + data - the data to be retrieved, a `PetscReal`
1233 - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1234
1235 Level: developer
1236
1237 Note:
1238 The `data` and `flag` variables are inlined, so they are not pointers.
1239
1240 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1241 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1242 `PetscObjectCompose()`, `PetscObjectQuery()`
1243 M*/
1244 #define PetscObjectComposedDataGetReal(obj, id, data, flag) ((PetscErrorCode)(((obj)->realcomposedstate ? (data = (obj)->realcomposeddata[id], flag = (PetscBool)((obj)->realcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1245
1246 /*MC
1247 PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1248
1249 Synopsis:
1250 #include "petsc/private/petscimpl.h"
1251 PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1252
1253 Not Collective
1254
1255 Input Parameters:
1256 + obj - the object to which data is to be attached
1257 . id - the identifier for the data
1258 - data - the data to be attached
1259
1260 Level: developer
1261
1262 Notes:
1263 The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1264
1265 The length of the array accessed must be known, it is not available through this API.
1266
1267 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1268 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1269 `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1270 M*/
1271 #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1272 ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1273
1274 /*MC
1275 PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1276
1277 Synopsis:
1278 #include "petsc/private/petscimpl.h"
1279 PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1280
1281 Not Collective
1282
1283 Input Parameters:
1284 + obj - the object from which data is to be retrieved
1285 - id - the identifier for the data
1286
1287 Output Parameters:
1288 + data - the data to be retrieved, a `PetscReal` array
1289 - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1290
1291 Level: developer
1292
1293 Notes:
1294 The `data` and `flag` variables are inlined, so they are not pointers.
1295
1296 The length of the array accessed must be known, it is not available through this API.
1297
1298 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1299 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1300 `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1301 M*/
1302 #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1303 ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1304
1305 /*MC
1306 PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1307
1308 Synopsis:
1309 #include "petsc/private/petscimpl.h"
1310 PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1311
1312 Not Collective
1313
1314 Input Parameters:
1315 + obj - the object to which data is to be attached
1316 . id - the identifier for the data
1317 - data - the data to be attached, a `PetscScalar`
1318
1319 Level: developer
1320
1321 Note:
1322 The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1323
1324 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1325 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1326 `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1327 M*/
1328 #if defined(PETSC_USE_COMPLEX)
1329 #define PetscObjectComposedDataSetScalar(obj, id, data) \
1330 ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1331 #else
1332 #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1333 #endif
1334 /*MC
1335 PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1336
1337 Synopsis:
1338 #include "petsc/private/petscimpl.h"
1339 PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1340
1341 Not Collective
1342
1343 Input Parameters:
1344 + obj - the object from which data is to be retrieved
1345 - id - the identifier for the data
1346
1347 Output Parameters:
1348 + data - the data to be retrieved, a `PetscScalar`
1349 - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1350
1351 Level: developer
1352
1353 Note:
1354 The `data` and `flag` variables are inlined, so they are not pointers.
1355
1356 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1357 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1358 `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1359 M*/
1360 #if defined(PETSC_USE_COMPLEX)
1361 #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1362 ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1363 #else
1364 #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1365 #endif
1366
1367 /*MC
1368 PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1369
1370 Synopsis:
1371 #include "petsc/private/petscimpl.h"
1372 PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1373
1374 Not Collective
1375
1376 Input Parameters:
1377 + obj - the object to which data is to be attached
1378 . id - the identifier for the data
1379 - data - the data to be attached, a `PetscScalar` array
1380
1381 Level: developer
1382
1383 Notes:
1384 The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1385
1386 The length of the array accessed must be known, it is not available through this API.
1387
1388 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1389 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1390 `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1391 M*/
1392 #if defined(PETSC_USE_COMPLEX)
1393 #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1394 ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1395 #else
1396 #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1397 #endif
1398 /*MC
1399 PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1400 attached to an object
1401
1402 Synopsis:
1403 #include "petsc/private/petscimpl.h"
1404 PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1405
1406 Not Collective
1407
1408 Input Parameters:
1409 + obj - the object from which data is to be retrieved
1410 - id - the identifier for the data
1411
1412 Output Parameters:
1413 + data - the data to be retrieved, a `PetscScalar` array
1414 - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1415
1416 Level: developer
1417
1418 Notes:
1419 The `data` and `flag` variables are inlined, so they are not pointers.
1420
1421 The length of the array accessed must be known, it is not available through this API.
1422
1423 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1424 `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1425 `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1426 M*/
1427 #if defined(PETSC_USE_COMPLEX)
1428 #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1429 ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1430 #else
1431 #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1432 #endif
1433
1434 PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1435 PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1436 PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1437 PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1438 PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1439 PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1440 PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1441
1442 PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1443 PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;
1444
1445 struct PetscCommStash {
1446 struct PetscCommStash *next;
1447 MPI_Comm comm;
1448 };
1449
1450 /*
1451 PETSc communicators have this attribute, see
1452 PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1453 */
1454 typedef struct {
1455 PetscMPIInt tag; /* next free tag value */
1456 PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1457 PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1458 PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1459 struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1460 } PetscCommCounter;
1461
1462 typedef enum {
1463 STATE_BEGIN,
1464 STATE_PENDING,
1465 STATE_END
1466 } SRState;
1467
1468 typedef enum {
1469 PETSC_SR_REDUCE_SUM = 0,
1470 PETSC_SR_REDUCE_MAX = 1,
1471 PETSC_SR_REDUCE_MIN = 2
1472 } PetscSRReductionType;
1473
1474 typedef struct {
1475 MPI_Comm comm;
1476 MPI_Request request;
1477 PetscBool mix;
1478 PetscBool async;
1479 PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1480 PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1481 void **invecs; /* for debugging only, vector/memory used with each op */
1482 PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
1483 struct {
1484 PetscScalar v;
1485 PetscInt i;
1486 } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1487 SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1488 PetscMPIInt maxops; /* total amount of space we have for requests */
1489 PetscMPIInt numopsbegin; /* number of requests that have been queued in */
1490 PetscMPIInt numopsend; /* number of requests that have been gotten by user */
1491 } PetscSplitReduction;
1492
1493 PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1494 PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1495 PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1496
1497 #if defined(PETSC_HAVE_THREADSAFETY)
1498 #if defined(PETSC_HAVE_CONCURRENCYKIT)
1499 #if defined(__cplusplus)
1500 /* CK does not have extern "C" protection in their include files */
1501 extern "C" {
1502 #endif
1503 #include <ck_spinlock.h>
1504 #if defined(__cplusplus)
1505 }
1506 #endif
1507 typedef ck_spinlock_t PetscSpinlock;
1508
PetscSpinlockCreate(PetscSpinlock * ck_spinlock)1509 static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1510 {
1511 ck_spinlock_init(ck_spinlock);
1512 return PETSC_SUCCESS;
1513 }
PetscSpinlockLock(PetscSpinlock * ck_spinlock)1514 static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1515 {
1516 ck_spinlock_lock(ck_spinlock);
1517 return PETSC_SUCCESS;
1518 }
PetscSpinlockUnlock(PetscSpinlock * ck_spinlock)1519 static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1520 {
1521 ck_spinlock_unlock(ck_spinlock);
1522 return PETSC_SUCCESS;
1523 }
PetscSpinlockDestroy(PetscSpinlock * ck_spinlock)1524 static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1525 {
1526 return PETSC_SUCCESS;
1527 }
1528 #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1529 #if defined(__cplusplus)
1530 // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1531 #include <atomic>
1532 #define petsc_atomic_flag std::atomic_flag
1533 #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1534 #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_release)
1535 #else
1536 #include <stdatomic.h>
1537 #define petsc_atomic_flag atomic_flag
1538 #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1539 #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_release)
1540 #endif
1541
1542 typedef petsc_atomic_flag PetscSpinlock;
1543
PetscSpinlockCreate(PetscSpinlock * spinlock)1544 static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1545 {
1546 petsc_atomic_flag_clear(spinlock);
1547 return PETSC_SUCCESS;
1548 }
PetscSpinlockLock(PetscSpinlock * spinlock)1549 static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1550 {
1551 do {
1552 } while (petsc_atomic_flag_test_and_set(spinlock));
1553 return PETSC_SUCCESS;
1554 }
PetscSpinlockUnlock(PetscSpinlock * spinlock)1555 static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1556 {
1557 petsc_atomic_flag_clear(spinlock);
1558 return PETSC_SUCCESS;
1559 }
PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock * spinlock)1560 static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1561 {
1562 return PETSC_SUCCESS;
1563 }
1564 #undef petsc_atomic_flag_test_and_set
1565 #undef petsc_atomic_flag_clear
1566 #undef petsc_atomic_flag
1567
1568 #elif defined(PETSC_HAVE_OPENMP)
1569
1570 #include <omp.h>
1571 typedef omp_lock_t PetscSpinlock;
1572
PetscSpinlockCreate(PetscSpinlock * omp_lock)1573 static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1574 {
1575 omp_init_lock(omp_lock);
1576 return PETSC_SUCCESS;
1577 }
PetscSpinlockLock(PetscSpinlock * omp_lock)1578 static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1579 {
1580 omp_set_lock(omp_lock);
1581 return PETSC_SUCCESS;
1582 }
PetscSpinlockUnlock(PetscSpinlock * omp_lock)1583 static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1584 {
1585 omp_unset_lock(omp_lock);
1586 return PETSC_SUCCESS;
1587 }
PetscSpinlockDestroy(PetscSpinlock * omp_lock)1588 static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1589 {
1590 omp_destroy_lock(omp_lock);
1591 return PETSC_SUCCESS;
1592 }
1593 #else
1594 #if defined(__cplusplus)
1595 #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1596 #else
1597 #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1598 #endif
1599 #endif
1600
1601 #else
1602 typedef int PetscSpinlock;
1603 #define PetscSpinlockCreate(a) PETSC_SUCCESS
1604 #define PetscSpinlockLock(a) PETSC_SUCCESS
1605 #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1606 #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1607 #endif
1608
1609 #if defined(PETSC_HAVE_THREADSAFETY)
1610 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1611 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1612 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1613 PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1614 #endif
1615
1616 PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1617 PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1618 PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1619 PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1620 PETSC_EXTERN PetscBool PetscPrintFunctionList;
1621
1622 #if defined(PETSC_HAVE_ADIOS)
1623 PETSC_EXTERN int64_t Petsc_adios_group;
1624 #endif
1625
1626 #if defined(PETSC_HAVE_KOKKOS)
1627 PETSC_INTERN PetscBool PetscBeganKokkos;
1628 PETSC_EXTERN PetscBool PetscKokkosInitialized;
1629 PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1630 PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1631 #endif
1632
1633 #if defined(PETSC_HAVE_OPENMP)
1634 PETSC_EXTERN PetscInt PetscNumOMPThreads;
1635 #endif
1636
1637 struct _n_PetscObjectList {
1638 char name[256];
1639 PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1640 PetscObject obj;
1641 PetscObjectList next;
1642 };
1643
1644 /*E
1645 PetscPrecision - Precision of a real number
1646
1647 Values:
1648 + `PETSC_PRECISION_INVALID` - an invalid value
1649 . `PETSC_PRECISION_BFLOAT16` - half precision (Google Brain bfloat16)
1650 . `PETSC_PRECISION___FP16` - half precison (IEEE FP16)
1651 . `PETSC_PRECISION_SINGLE` - single precision
1652 . `PETSC_PRECISION_DOUBLE` - double precision
1653 - `PETSC_PRECISION___FLOAT128` - quadruple precision (__float128)
1654
1655 Level: intermediate
1656 E*/
1657
1658 typedef enum {
1659 PETSC_PRECISION_INVALID = 0,
1660 PETSC_PRECISION_BFLOAT16,
1661 PETSC_PRECISION___FP16,
1662 PETSC_PRECISION_SINGLE,
1663 PETSC_PRECISION_DOUBLE,
1664 PETSC_PRECISION___FLOAT128
1665 } PetscPrecision;
1666
1667 // The precision of PetscScalar and PetscReal
1668 #if defined(PETSC_USE_REAL___FP16)
1669 #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
1670 #elif defined(PETSC_USE_REAL_SINGLE)
1671 #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
1672 #elif defined(PETSC_USE_REAL_DOUBLE)
1673 #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
1674 #elif defined(PETSC_USE_REAL___FLOAT128)
1675 #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
1676 #endif
1677
1678 PETSC_EXTERN const char *const PetscPrecisionTypes[];
1679