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