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: #if PetscDefined(CLANG_STATIC_ANALYZER)
10: #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
11: #else
12: #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
13: #endif
15: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
16: PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
17: PETSC_INTERN PetscErrorCode PetscStackReset(void);
18: PETSC_EXTERN 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
27: /* These are used internally by PETSc ASCII IO routines*/
28: #include <stdarg.h>
29: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);
31: /*
32: All major PETSc data structures have a common core; this is defined
33: below by PETSCHEADER.
35: PetscHeaderCreate() should be used whenever creating a PETSc structure.
36: */
38: /*
39: PetscOps: structure of core operations that all PETSc objects support.
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: */
52: typedef struct {
53: PetscErrorCode (*view)(PetscObject, PetscViewer);
54: PetscErrorCode (*destroy)(PetscObject *);
55: } PetscOps;
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
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
64: Level: developer
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()`.
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;
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 *);
84: /*S
85: PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback
87: Level: advanced
89: Notes:
90: `PetscFortranCallbackFn *` plays the role of `void *` for function pointers in the PETSc Fortran API.
92: .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
93: S*/
94: PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);
96: typedef struct {
97: PetscFortranCallbackFn *func;
98: void *ctx;
99: } PetscFortranCallback;
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 *);
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 PetscDefined(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;
159: #define PETSCHEADER(ObjectOps) \
160: _p_PetscObject hdr; \
161: ObjectOps ops[1]
163: #define PETSCFREEDHEADER -1
165: /*S
166: PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`
168: Calling Sequence:
169: . obj - the `PetscObject` to destroy
171: Level: beginner
173: Note:
174: The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.
176: .seealso: `PetscObject`, `PetscObjectDestroy()`
177: S*/
178: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);
180: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;
182: /*S
183: PetscObjectViewFn - A prototype of a function that can view a `PetscObject`
185: Calling Sequence:
186: + obj - the `PetscObject` to view
187: - v - the viewer
189: Level: beginner
191: Note:
192: The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.
194: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
195: S*/
196: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);
198: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;
200: /*MC
201: PetscHeaderCreate - Creates a raw PETSc object of a particular class
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)
207: Collective
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: It also selects the options blocks this object opens for `-help mansec`; an object with no manual
215: section has none of its blocks selected
216: . comm - The MPI Communicator
217: . destroy - The destroy routine for this object (for example `VecDestroy()`)
218: - view - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`
220: Output Parameter:
221: . h - The newly created `PetscObject`
223: Level: developer
225: Notes:
226: Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
227: C/C++ structure which satisfies all of the following\:
229: 1. The first member of the structure must be a `_p_PetscObject`.
230: 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
231: - Has no virtual functions or base classes.
232: - Has only standard layout non-static members (if any).
233: - Has only standard layout base classes (if any).
235: See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
236: information.
238: Example Usage:
239: Existing `PetscObject`s may be easily created as shown. An object of type `Name` has
240: `destroy` and `view` functions named `NameDestroy()` and `NameView()`.
241: .vb
242: Vec v;
244: PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
245: .ve
247: It is possible to create custom `PetscObject`s, note however that they must abide by the
248: restrictions set forth above.
249: .vb
250: // OK, first member of C structure is _p_PetscObject
251: struct MyCPetscObject_s
252: {
253: _p_PetscObject header;
254: int some_data;
255: };
256: typedef struct *MyCPetscObject_s MyCPetscObject;
258: PetscErrorCode MyObjectDestroy(MyObject *);
259: PetscErrorCode MyObjectView(MyObject);
261: MyCPetscObject obj;
263: // assume MY_PETSC_CLASSID is already registered
264: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
266: // OK, only destroy function must be given, all others may be NULL
267: PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
269: // ERROR must be a single-level pointer
270: PetscHeaderCreate(&obj, ...);
271: .ve
273: Illustrating proper construction from C++\:
274: .vb
275: // ERROR, class is not standard layout, first member must be publicly accessible
276: class BadCppPetscObject
277: {
278: _p_PetscObject header;
279: };
281: // ERROR, class is not standard layout, has a virtual function and virtual inheritance
282: class BadCppPetscObject2 : virtual BaseClass
283: {
284: public:
285: _p_PetscObject header;
287: virtual void foo();
288: };
290: // ERROR, class is not standard layout! Has non-standard layout member
291: class BadCppPetscObject2
292: {
293: public:
294: _p_PetscObject header;
295: BadCppPetscObject non_standard_layout;
296: };
298: // OK, class is standard layout!
299: class GoodCppPetscObject;
300: using MyCppObject = GoodCppPetscObject *;
302: // OK, non-virtual inheritance of other standard layout class does not affect layout
303: class GoodCppPetscObject : StandardLayoutClass
304: {
305: public:
306: // OK, non standard layout member is static, does not affect layout
307: static BadCppPetscObject non_standard_layout;
309: // OK, first non-static member is _p_PetscObject
310: _p_PetscObject header;
312: // OK, non-virtual member functions do not affect class layout
313: void foo();
315: // OK, may use "member" functions for destroy and view so long as they are static
316: static PetscErrorCode destroy(MyCppObject *);
317: static PetscErrorCode view(MyCppObject);
318: };
320: // OK, usage via pointer
321: MyObject obj;
323: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
324: .ve
326: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
327: M*/
328: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
329: PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))
331: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
332: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
333: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
334: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
335: PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
337: /*MC
338: PetscHeaderDestroy - Final step in destroying a `PetscObject`
340: Synopsis:
341: #include <petsc/private/petscimpl.h>
342: PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
344: Collective
346: Input Parameter:
347: . h - A pointer to the header created with `PetscHeaderCreate()`
349: Level: developer
351: Notes:
352: `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
354: Example Usage:
355: .vb
356: PetscObject obj;
358: PetscHeaderCreate(obj, ...);
359: // use obj...
361: // note pointer to obj is used
362: PetscHeaderDestroy(&obj);
363: .ve
365: Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
366: deallocates the memory for the structure itself\:
367: .vb
368: typedef struct MyPetscObject_s *MyPetscObject;
369: struct MyPetscObject_s
370: {
371: _p_PetscObject hdr;
372: PetscInt *foo;
373: PetscScalar *bar;
374: };
376: // assume obj is created/initialized elsewhere...
377: MyPetscObject obj;
379: // OK, should dispose of all dynamically allocated resources before calling
380: // PetscHeaderDestroy()
381: PetscFree(obj->foo);
383: // OK, dispose of obj
384: PetscHeaderDestroy(&obj);
386: // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
387: // obj->bar is potentially leaked!
388: PetscFree(obj->bar);
389: .ve
391: .seealso: `PetscObject`, `PetscHeaderCreate()`
392: M*/
393: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)(h))
395: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(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);
401: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
402: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
403: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
404: PETSC_INTERN PetscErrorCode PetscOptionsHelpManSecs_Internal(PetscOptions, PetscInt *, const char *const *[]);
405: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscOptionsHelpPrintable_Internal(PetscOptions, const char[], PetscBool *);
407: /* Code shared between C and Fortran */
408: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscInt);
410: #if PetscDefined(HAVE_SETJMP_H)
411: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
412: #else
413: #define PetscCheckPointer(ptr, data_type) ((ptr) ? PETSC_TRUE : PETSC_FALSE)
414: #endif
416: #if PetscDefined(CLANG_STATIC_ANALYZER)
417: template <typename T>
419: template <typename T>
421: template <typename T>
423: template <typename T>
424: extern void PetscAssertPointer(T, int)
425: {
426: }
427: template <typename T>
429: #else
430: // Macros to test if a PETSc object is valid and if pointers are valid
431: #if PetscDefined(USE_DEBUG)
432: /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
434: do { \
435: PetscBool _7_same; \
437: PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
438: 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); \
439: } while (0)
441: #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
442: do { \
443: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
444: PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
445: } while (0)
448: do { \
449: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
450: if (((PetscObject)(h))->classid != ck) { \
451: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
452: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
453: } \
454: } while (0)
457: do { \
458: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
459: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
460: 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); \
461: } while (0)
463: #if defined(__cplusplus)
464: #include <type_traits> // std::decay
466: namespace Petsc
467: {
469: namespace util
470: {
472: template <typename T>
473: struct PetscAssertPointerImpl {
474: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
475: PETSC_NODISCARD static constexpr const char *string() noexcept { return "memory"; }
476: };
478: #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
479: template <> \
480: struct PetscAssertPointerImpl<T *> { \
481: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
482: PETSC_NODISCARD static constexpr const char *string() noexcept { return PetscStringize(T); } \
483: }; \
484: template <> \
485: struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
486: template <> \
487: struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
488: template <> \
489: struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
491: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
492: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
493: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
494: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
495: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
496: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
497: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
498: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
499: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
500: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
501: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
502: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
503: #if PetscDefined(HAVE_COMPLEX)
504: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
505: #endif
507: #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
509: } // namespace util
511: } // namespace Petsc
513: #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
514: #define PetscAssertPointer_String(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
516: #elif PETSC_C_VERSION >= 11
517: #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
519: #if PetscDefined(HAVE_COMPLEX)
520: #define PETSC_GENERIC_CV_COMPLEX(result) , PETSC_GENERIC_CV(PetscComplex, result)
521: #else
522: #define PETSC_GENERIC_CV_COMPLEX(result)
523: #endif
525: #define PetscAssertPointer_PetscDataType(h) \
526: _Generic((h), \
527: default: PETSC_CHAR, \
528: PETSC_GENERIC_CV( char, PETSC_CHAR), \
529: PETSC_GENERIC_CV( signed char, PETSC_CHAR), \
530: PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
531: PETSC_GENERIC_CV( short, PETSC_SHORT), \
532: PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
533: PETSC_GENERIC_CV( float, PETSC_FLOAT), \
534: PETSC_GENERIC_CV( double, PETSC_DOUBLE), \
535: PETSC_GENERIC_CV( int32_t, PETSC_INT32), \
536: PETSC_GENERIC_CV( uint32_t, PETSC_INT32), \
537: PETSC_GENERIC_CV( int64_t, PETSC_INT64), \
538: PETSC_GENERIC_CV( uint64_t, PETSC_INT64) \
539: PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
541: #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
543: #if PetscDefined(HAVE_COMPLEX)
544: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX , PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
545: #else
546: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
547: #endif
549: #define PetscAssertPointer_String(h) \
550: _Generic((h), \
551: default: "memory", \
552: PETSC_GENERIC_CV_STRINGIZE(char), \
553: PETSC_GENERIC_CV_STRINGIZE(signed char), \
554: PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
555: PETSC_GENERIC_CV_STRINGIZE(short), \
556: PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
557: PETSC_GENERIC_CV_STRINGIZE(float), \
558: PETSC_GENERIC_CV_STRINGIZE(double), \
559: PETSC_GENERIC_CV_STRINGIZE(int32_t), \
560: PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
561: PETSC_GENERIC_CV_STRINGIZE(int64_t), \
562: PETSC_GENERIC_CV_STRINGIZE(uint64_t) \
563: PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
564: #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
565: #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
566: #define PetscAssertPointer_String(h) "memory"
567: #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
568: #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
570: #else // PetscDefined(USE_DEBUG)
572: do { \
573: (void)(h); \
574: } while (0)
576: do { \
577: (void)(h); \
578: } while (0)
580: do { \
581: (void)(h); \
582: } while (0)
583: #define PetscAssertPointer(h, arg) \
584: do { \
585: (void)(h); \
586: } while (0)
588: do { \
589: (void)(h); \
590: } while (0)
591: #endif // PetscDefined(USE_DEBUG)
592: #endif // PETSC_CLANG_STATIC_ANALYZER
603: #define PetscSorted(n, idx, sorted) \
604: do { \
605: (sorted) = PETSC_TRUE; \
606: for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
607: if ((idx)[_i_] < (idx)[_i_ - 1]) { \
608: (sorted) = PETSC_FALSE; \
609: break; \
610: } \
611: } \
612: } while (0)
614: #if !PetscDefined(CLANG_STATIC_ANALYZER)
615: #if !PetscDefined(USE_DEBUG)
617: #define PetscCheckSameType(a, arga, b, argb) \
618: do { \
619: (void)(a); \
620: (void)(b); \
621: } while (0)
622: #define PetscCheckTypeName(a, type) \
623: do { \
624: (void)(a); \
625: } while (0)
626: #define PetscCheckTypeNames(a, type1, type2) \
627: do { \
628: (void)(a); \
629: } while (0)
631: do { \
632: (void)(a); \
633: } while (0)
634: #define PetscCheckSameComm(a, arga, b, argb) \
635: do { \
636: (void)(a); \
637: (void)(b); \
638: } while (0)
639: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
640: do { \
641: (void)(a); \
642: (void)(b); \
643: } while (0)
645: do { \
646: (void)(a); \
647: (void)(b); \
648: } while (0)
650: do { \
651: (void)(a); \
652: (void)(b); \
653: } while (0)
655: do { \
656: (void)(a); \
657: (void)(b); \
658: } while (0)
660: do { \
661: (void)(a); \
662: (void)(b); \
663: } while (0)
665: do { \
666: (void)(a); \
667: (void)(b); \
668: } while (0)
670: do { \
671: (void)(a); \
672: (void)(b); \
673: } while (0)
675: do { \
676: (void)(a); \
677: (void)(b); \
678: } while (0)
680: do { \
681: (void)(a); \
682: (void)(b); \
683: } while (0)
684: #define PetscCheckSorted(n, idx) \
685: do { \
686: (void)(n); \
687: (void)(idx); \
688: } while (0)
690: #else
692: #define PetscCheckSameType(a, arga, b, argb) \
693: do { \
694: PetscBool pcst_type_eq_ = PETSC_TRUE; \
695: PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
696: 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); \
697: } while (0)
699: /*
700: Check type_name
701: */
702: #define PetscCheckTypeName(a, type) \
703: do { \
704: PetscBool _7_match; \
705: PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
706: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
707: } while (0)
709: #define PetscCheckTypeNames(a, type1, type2) \
710: do { \
711: PetscBool _7_match; \
712: PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
713: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
714: } while (0)
716: /*
717: Use this macro to check if the type is set
718: */
721: /*
722: Sometimes object must live on same communicator to inter-operate
723: */
724: #define PetscCheckSameComm(a, arga, b, argb) \
725: do { \
726: PetscMPIInt _7_flag; \
727: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
728: 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); \
729: } while (0)
731: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
732: do { \
733: PetscCheckSameType(a, arga, b, argb); \
734: PetscCheckSameComm(a, arga, b, argb); \
735: } while (0)
738: do { \
739: PetscScalar b0 = (b); \
740: PetscReal b1[5]; \
741: if (PetscIsNanScalar(b0)) { \
742: b1[4] = 1; \
743: } else { \
744: b1[4] = 0; \
745: }; \
746: b1[0] = -PetscRealPart(b0); \
747: b1[1] = PetscRealPart(b0); \
748: b1[2] = -PetscImaginaryPart(b0); \
749: b1[3] = PetscImaginaryPart(b0); \
750: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
751: 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); \
752: } while (0)
755: do { \
756: PetscReal b0 = (b), b1[3]; \
757: if (PetscIsNanReal(b0)) { \
758: b1[2] = 1; \
759: } else { \
760: b1[2] = 0; \
761: }; \
762: b1[0] = -b0; \
763: b1[1] = b0; \
764: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
765: 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); \
766: } while (0)
769: do { \
770: PetscInt b0 = (b), b1[2]; \
771: b1[0] = -b0; \
772: b1[1] = b0; \
773: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
774: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
775: } while (0)
778: do { \
779: PetscInt b1[2]; \
780: b1[0] = -(b); \
781: b1[1] = b; \
782: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
783: PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
784: } while (0)
787: do { \
788: PetscCount b0 = (b), b1[2]; \
789: b1[0] = -b0; \
790: b1[1] = b0; \
791: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
792: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
793: } while (0)
796: do { \
797: PetscMPIInt b0 = (b), b1[2]; \
798: b1[0] = -b0; \
799: b1[1] = b0; \
800: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
801: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
802: } while (0)
805: do { \
806: PetscBool b0 = (PetscBool)(b), b1[2]; \
807: b1[0] = !b0; \
808: b1[1] = b0; \
809: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
810: PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
811: } while (0)
814: do { \
815: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
816: b1[0] = -b0; \
817: b1[1] = b0; \
818: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
819: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
820: } while (0)
822: #define PetscCheckSorted(n, idx) \
823: do { \
824: PetscBool _1_flg; \
825: PetscSorted(n, idx, _1_flg); \
826: PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
827: } while (0)
829: #endif
830: #else /* PETSC_CLANG_STATIC_ANALYZER */
831: template <typename Ta, typename Tb>
832: extern void PetscCheckSameType(Ta, int, Tb, int);
833: template <typename Ta, typename Tb>
834: extern void PetscCheckTypeName(Ta, Tb);
835: template <typename Ta, typename Tb, typename Tc>
836: extern void PetscCheckTypeNames(Ta, Tb, Tc);
837: template <typename T>
839: template <typename Ta, typename Tb>
840: extern void PetscCheckSameComm(Ta, int, Tb, int);
841: template <typename Ta, typename Tb>
842: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
843: template <typename Ta, typename Tb>
845: template <typename Ta, typename Tb>
847: template <typename Ta, typename Tb>
849: template <typename Ta, typename Tb>
851: template <typename Ta, typename Tb>
853: template <typename Ta, typename Tb>
855: template <typename Ta, typename Tb>
857: template <typename T>
858: extern void PetscCheckSorted(PetscInt, T);
859: #endif /* PETSC_CLANG_STATIC_ANALYZER */
861: /*MC
862: PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
864: Synopsis:
865: #include "petsc/private/petscimpl.h"
866: PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
868: Input Parameters:
869: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
870: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
871: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
872: - args - the arguments for the method, for example, (ksp,restart))
874: Level: developer
876: Notes:
877: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
879: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
880: in the object.
882: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
883: M*/
884: #define PetscTryMethod(obj, A, B, C) \
885: do { \
886: PetscErrorCode(*_7_f) B; \
887: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
888: if (_7_f) PetscCall((*_7_f)C); \
889: } while (0)
891: /*MC
892: PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
894: Synopsis:
895: #include "petsc/private/petscimpl.h"
896: PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
898: Input Parameters:
899: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
900: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
901: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
902: - args - the arguments for the method, for example, (ksp,restart))
904: Level: developer
906: Notes:
907: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
909: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
910: in the object.
912: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
913: M*/
914: #define PetscUseMethod(obj, A, B, C) \
915: do { \
916: PetscErrorCode(*_7_f) B; \
917: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
918: PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
919: PetscCall((*_7_f)C); \
920: } while (0)
922: /*
923: Use Microsoft traditional preprocessor.
925: The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
926: sets _MSVC_TRADITIONAL to zero so this code path is not used.
928: It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
930: These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
932: PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
933: */
934: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
936: #define PetscUseTypeMethod(obj, OP, ...) \
937: do { \
938: PetscErrorCode ierr_p_; \
939: PetscStackUpdateLine; \
940: 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); \
941: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
942: PetscCall(ierr_p_); \
943: } while (0)
945: #define PetscTryTypeMethod(obj, OP, ...) \
946: do { \
947: if ((obj)->ops->OP) { \
948: PetscErrorCode ierr_p_; \
949: PetscStackUpdateLine; \
950: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
951: PetscCall(ierr_p_); \
952: } \
953: } while (0)
955: #else
957: /*MC
958: 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
960: Synopsis:
961: #include "petsc/private/petscimpl.h"
962: PetscUseTypeMethod(obj, method, ...)
964: Input Parameters:
965: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
966: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
967: - ... - the other arguments for the method, `obj` is the first argument
969: Level: developer
971: Note:
972: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
974: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
976: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
977: M*/
978: #define PetscUseTypeMethod(obj, ...) \
979: do { \
980: PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "No method %s for %s of type %s", \
981: PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)(obj))->class_name, ((PetscObject)(obj))->type_name); \
982: PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
983: } while (0)
985: /*MC
986: 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
988: Synopsis:
989: #include "petsc/private/petscimpl.h"
990: PetscTryTypeMethod(obj, method, ...)
992: Input Parameters:
993: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
994: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
995: - ... - the other arguments for the method, `obj` is the first argument
997: Level: developer
999: Note:
1000: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
1002: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
1004: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1005: M*/
1006: #define PetscTryTypeMethod(obj, ...) \
1007: do { \
1008: if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1009: } while (0)
1011: #endif
1013: /*MC
1014: PetscObjectStateIncrease - Increases the state of any `PetscObject`
1016: Synopsis:
1017: #include "petsc/private/petscimpl.h"
1018: PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
1020: Logically Collective
1022: Input Parameter:
1023: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1024: cast with a (PetscObject), for example,
1025: `PetscObjectStateIncrease`((`PetscObject`)mat);
1027: Level: developer
1029: Notes:
1030: Object state is a 64-bit integer which gets increased every time
1031: the object is changed internally. By saving and later querying the object state
1032: one can determine whether information about the object is still current.
1033: Currently, state is maintained for `Vec` and `Mat` objects.
1035: This routine is mostly for internal use by PETSc; a developer need only
1036: call it after explicit access to an object's internals. Routines such
1037: as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
1038: precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
1040: Routines such as `VecNorm()` can bypass the computation if the norm has already been computed and the vector's state has not changed.
1042: This routine is logically collective because state equality comparison needs to be possible without communication.
1044: `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
1046: .seealso: `PetscObjectStateGet()`, `PetscObject`
1047: M*/
1048: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))
1050: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1051: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1052: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1053: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1054: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1055: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1056: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1057: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1058: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1059: PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
1061: /*MC
1062: PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
1064: Synopsis:
1065: #include "petsc/private/petscimpl.h"
1066: PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1068: Not Collective
1070: Input Parameters:
1071: + obj - the object to which data is to be attached
1072: . id - the identifier for the data
1073: - data - the data to be attached, a `PetscInt`
1075: Level: developer
1077: Notes:
1078: The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1080: This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1081: attached with `PetscObjectCompose()`
1083: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1084: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1085: `PetscObjectCompose()`, `PetscObjectQuery()`
1086: M*/
1087: #define PetscObjectComposedDataSetInt(obj, id, data) \
1088: ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1090: /*MC
1091: PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1093: Synopsis:
1094: #include "petsc/private/petscimpl.h"
1095: PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1097: Not Collective
1099: Input Parameters:
1100: + obj - the object from which data is to be retrieved
1101: - id - the identifier for the data
1103: Output Parameters:
1104: + data - the data to be retrieved, a `PetscInt`
1105: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1107: Level: developer
1109: Notes:
1110: The `data` and `flag` variables are inlined, so they are not pointers.
1112: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1113: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1114: `PetscObjectCompose()`, `PetscObjectQuery()`
1115: M*/
1116: #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))
1118: /*MC
1119: PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1121: Synopsis:
1122: #include "petsc/private/petscimpl.h"
1123: PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1125: Not Collective
1127: Input Parameters:
1128: + obj - the object to which data is to be attached
1129: . id - the identifier for the data
1130: - data - the data to be attached, a `PetscInt` array
1132: Level: developer
1134: Notes:
1135: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1137: The length of the array accessed must be known, it is not available through this API.
1139: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1140: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1141: `PetscObjectCompose()`, `PetscObjectQuery()`
1142: M*/
1143: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1144: ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1146: /*MC
1147: PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1149: Synopsis:
1150: #include "petsc/private/petscimpl.h"
1151: PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1153: Not Collective
1155: Input Parameters:
1156: + obj - the object from which data is to be retrieved
1157: - id - the identifier for the data
1159: Output Parameters:
1160: + data - the data to be retrieved, a `PetscInt` array
1161: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1163: Level: developer
1165: Notes:
1166: The `data` and `flag` variables are inlined, so they are not pointers.
1168: The length of the array accessed must be known, it is not available through this API.
1170: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1171: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1172: `PetscObjectCompose()`, `PetscObjectQuery()`
1173: M*/
1174: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1175: ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1177: /*MC
1178: PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1180: Synopsis:
1181: #include "petsc/private/petscimpl.h"
1182: PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1184: Not Collective
1186: Input Parameters:
1187: + obj - the object to which data is to be attached
1188: . id - the identifier for the data
1189: - data - the data to be attached, a `PetscReal`
1191: Level: developer
1193: Note:
1194: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1196: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1197: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1198: `PetscObjectCompose()`, `PetscObjectQuery()`
1199: M*/
1200: #define PetscObjectComposedDataSetReal(obj, id, data) \
1201: ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1203: /*MC
1204: PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1206: Synopsis:
1207: #include "petsc/private/petscimpl.h"
1208: PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1210: Not Collective
1212: Input Parameters:
1213: + obj - the object from which data is to be retrieved
1214: - id - the identifier for the data
1216: Output Parameters:
1217: + data - the data to be retrieved, a `PetscReal`
1218: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1220: Level: developer
1222: Note:
1223: The `data` and `flag` variables are inlined, so they are not pointers.
1225: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1226: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1227: `PetscObjectCompose()`, `PetscObjectQuery()`
1228: M*/
1229: #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))
1231: /*MC
1232: PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1234: Synopsis:
1235: #include "petsc/private/petscimpl.h"
1236: PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1238: Not Collective
1240: Input Parameters:
1241: + obj - the object to which data is to be attached
1242: . id - the identifier for the data
1243: - data - the data to be attached
1245: Level: developer
1247: Notes:
1248: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1250: The length of the array accessed must be known, it is not available through this API.
1252: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1253: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1254: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1255: M*/
1256: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1257: ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1259: /*MC
1260: PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1262: Synopsis:
1263: #include "petsc/private/petscimpl.h"
1264: PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1266: Not Collective
1268: Input Parameters:
1269: + obj - the object from which data is to be retrieved
1270: - id - the identifier for the data
1272: Output Parameters:
1273: + data - the data to be retrieved, a `PetscReal` array
1274: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1276: Level: developer
1278: Notes:
1279: The `data` and `flag` variables are inlined, so they are not pointers.
1281: The length of the array accessed must be known, it is not available through this API.
1283: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1284: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1285: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1286: M*/
1287: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1288: ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1290: /*MC
1291: PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1293: Synopsis:
1294: #include "petsc/private/petscimpl.h"
1295: PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1297: Not Collective
1299: Input Parameters:
1300: + obj - the object to which data is to be attached
1301: . id - the identifier for the data
1302: - data - the data to be attached, a `PetscScalar`
1304: Level: developer
1306: Note:
1307: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1309: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1310: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1311: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1312: M*/
1313: #if PetscDefined(USE_COMPLEX)
1314: #define PetscObjectComposedDataSetScalar(obj, id, data) \
1315: ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1316: #else
1317: #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1318: #endif
1319: /*MC
1320: PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1322: Synopsis:
1323: #include "petsc/private/petscimpl.h"
1324: PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1326: Not Collective
1328: Input Parameters:
1329: + obj - the object from which data is to be retrieved
1330: - id - the identifier for the data
1332: Output Parameters:
1333: + data - the data to be retrieved, a `PetscScalar`
1334: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1336: Level: developer
1338: Note:
1339: The `data` and `flag` variables are inlined, so they are not pointers.
1341: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1342: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1343: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1344: M*/
1345: #if PetscDefined(USE_COMPLEX)
1346: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1347: ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1348: #else
1349: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1350: #endif
1352: /*MC
1353: PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1355: Synopsis:
1356: #include "petsc/private/petscimpl.h"
1357: PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1359: Not Collective
1361: Input Parameters:
1362: + obj - the object to which data is to be attached
1363: . id - the identifier for the data
1364: - data - the data to be attached, a `PetscScalar` array
1366: Level: developer
1368: Notes:
1369: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1371: The length of the array accessed must be known, it is not available through this API.
1373: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1374: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1375: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1376: M*/
1377: #if PetscDefined(USE_COMPLEX)
1378: #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1379: ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1380: #else
1381: #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1382: #endif
1383: /*MC
1384: PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1385: attached to an object
1387: Synopsis:
1388: #include "petsc/private/petscimpl.h"
1389: PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1391: Not Collective
1393: Input Parameters:
1394: + obj - the object from which data is to be retrieved
1395: - id - the identifier for the data
1397: Output Parameters:
1398: + data - the data to be retrieved, a `PetscScalar` array
1399: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1401: Level: developer
1403: Notes:
1404: The `data` and `flag` variables are inlined, so they are not pointers.
1406: The length of the array accessed must be known, it is not available through this API.
1408: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1409: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1410: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1411: M*/
1412: #if PetscDefined(USE_COMPLEX)
1413: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1414: ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1415: #else
1416: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1417: #endif
1419: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1420: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1421: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1422: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1423: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1424: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1425: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1427: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1428: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;
1430: struct PetscCommStash {
1431: struct PetscCommStash *next;
1432: MPI_Comm comm;
1433: };
1435: /*
1436: PETSc communicators have this attribute, see
1437: PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1438: */
1439: typedef struct {
1440: PetscMPIInt tag; /* next free tag value */
1441: PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1442: PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1443: PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1444: struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1445: } PetscCommCounter;
1447: typedef enum {
1448: STATE_BEGIN,
1449: STATE_PENDING,
1450: STATE_END
1451: } SRState;
1453: typedef enum {
1454: PETSC_SR_REDUCE_SUM = 0,
1455: PETSC_SR_REDUCE_MAX = 1,
1456: PETSC_SR_REDUCE_MIN = 2
1457: } PetscSRReductionType;
1459: typedef struct {
1460: MPI_Comm comm;
1461: MPI_Request request;
1462: PetscBool mix;
1463: PetscBool async;
1464: PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1465: PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1466: void **invecs; /* for debugging only, vector/memory used with each op */
1467: PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
1468: struct {
1469: PetscScalar v;
1470: PetscInt i;
1471: } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1472: SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1473: PetscMPIInt maxops; /* total amount of space we have for requests */
1474: PetscMPIInt numopsbegin; /* number of requests that have been queued in */
1475: PetscMPIInt numopsend; /* number of requests that have been gotten by user */
1476: } PetscSplitReduction;
1478: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1479: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1480: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1482: #if PetscDefined(HAVE_THREADSAFETY)
1483: #if PetscDefined(HAVE_CONCURRENCYKIT)
1484: #if defined(__cplusplus)
1485: /* CK does not have extern "C" protection in their include files */
1486: extern "C" {
1487: #endif
1488: #include <ck_spinlock.h>
1489: #if defined(__cplusplus)
1490: }
1491: #endif
1492: typedef ck_spinlock_t PetscSpinlock;
1494: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1495: {
1496: ck_spinlock_init(ck_spinlock);
1497: return PETSC_SUCCESS;
1498: }
1499: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1500: {
1501: ck_spinlock_lock(ck_spinlock);
1502: return PETSC_SUCCESS;
1503: }
1504: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1505: {
1506: ck_spinlock_unlock(ck_spinlock);
1507: return PETSC_SUCCESS;
1508: }
1509: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1510: {
1511: return PETSC_SUCCESS;
1512: }
1513: #elif (defined(__cplusplus) && PetscDefined(HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && PetscDefined(HAVE_STDATOMIC_H))
1514: #if defined(__cplusplus)
1515: // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1516: #include <atomic>
1517: #define petsc_atomic_flag std::atomic_flag
1518: #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1519: #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_release)
1520: #else
1521: #include <stdatomic.h>
1522: #define petsc_atomic_flag atomic_flag
1523: #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1524: #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_release)
1525: #endif
1527: typedef petsc_atomic_flag PetscSpinlock;
1529: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1530: {
1531: petsc_atomic_flag_clear(spinlock);
1532: return PETSC_SUCCESS;
1533: }
1534: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1535: {
1536: do {
1537: } while (petsc_atomic_flag_test_and_set(spinlock));
1538: return PETSC_SUCCESS;
1539: }
1540: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1541: {
1542: petsc_atomic_flag_clear(spinlock);
1543: return PETSC_SUCCESS;
1544: }
1545: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1546: {
1547: return PETSC_SUCCESS;
1548: }
1549: #undef petsc_atomic_flag_test_and_set
1550: #undef petsc_atomic_flag_clear
1551: #undef petsc_atomic_flag
1553: #elif PetscDefined(HAVE_OPENMP)
1555: #include <omp.h>
1556: typedef omp_lock_t PetscSpinlock;
1558: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1559: {
1560: omp_init_lock(omp_lock);
1561: return PETSC_SUCCESS;
1562: }
1563: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1564: {
1565: omp_set_lock(omp_lock);
1566: return PETSC_SUCCESS;
1567: }
1568: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1569: {
1570: omp_unset_lock(omp_lock);
1571: return PETSC_SUCCESS;
1572: }
1573: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1574: {
1575: omp_destroy_lock(omp_lock);
1576: return PETSC_SUCCESS;
1577: }
1578: #else
1579: #if defined(__cplusplus)
1580: #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1581: #else
1582: #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1583: #endif
1584: #endif
1586: #else
1587: typedef int PetscSpinlock;
1588: #define PetscSpinlockCreate(a) PETSC_SUCCESS
1589: #define PetscSpinlockLock(a) PETSC_SUCCESS
1590: #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1591: #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1592: #endif
1594: #if PetscDefined(HAVE_THREADSAFETY)
1595: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1596: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1597: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1598: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1599: #endif
1601: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1602: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1603: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1604: PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1605: PETSC_EXTERN PetscBool PetscPrintFunctionList;
1607: #if PetscDefined(HAVE_ADIOS)
1608: PETSC_EXTERN int64_t Petsc_adios_group;
1609: #endif
1611: #if PetscDefined(HAVE_KOKKOS)
1612: PETSC_INTERN PetscBool PetscBeganKokkos;
1613: PETSC_EXTERN PetscBool PetscKokkosInitialized;
1614: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1615: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1616: #endif
1618: #if PetscDefined(HAVE_OPENMP)
1619: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1620: #endif
1622: struct _n_PetscObjectList {
1623: char name[256];
1624: PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1625: PetscObject obj;
1626: PetscObjectList next;
1627: };
1629: /*E
1630: PetscPrecision - Precision of a real number
1632: Values:
1633: + `PETSC_PRECISION_INVALID` - an invalid value
1634: . `PETSC_PRECISION_BFLOAT16` - half precision (Google Brain bfloat16)
1635: . `PETSC_PRECISION___FP16` - half precision (IEEE FP16)
1636: . `PETSC_PRECISION_SINGLE` - single precision
1637: . `PETSC_PRECISION_DOUBLE` - double precision
1638: - `PETSC_PRECISION___FLOAT128` - quadruple precision (__float128)
1640: Level: intermediate
1641: E*/
1643: typedef enum {
1644: PETSC_PRECISION_INVALID = 0,
1645: PETSC_PRECISION_BFLOAT16,
1646: PETSC_PRECISION___FP16,
1647: PETSC_PRECISION_SINGLE,
1648: PETSC_PRECISION_DOUBLE,
1649: PETSC_PRECISION___FLOAT128
1650: } PetscPrecision;
1652: // The precision of PetscScalar and PetscReal
1653: #if PetscDefined(USE_REAL___FP16)
1654: #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
1655: #elif PetscDefined(USE_REAL_SINGLE)
1656: #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
1657: #elif PetscDefined(USE_REAL_DOUBLE)
1658: #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
1659: #elif PetscDefined(USE_REAL___FLOAT128)
1660: #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
1661: #endif
1663: PETSC_EXTERN const char *const PetscPrecisionTypes[];