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