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: PetscBool persistent;
131: } _p_PetscObject;
133: #define PETSCHEADER(ObjectOps) \
134: _p_PetscObject hdr; \
135: ObjectOps ops[1]
137: #define PETSCFREEDHEADER -1
139: /*S
140: PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`
142: Calling Sequence:
143: . obj - the `PetscObject` to destroy
145: Level: beginner
147: Note:
148: The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.
150: .seealso: `PetscObject`, `PetscObjectDestroy()`
151: S*/
152: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode(PetscObjectDestroyFn)(PetscObject *obj);
154: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;
156: /*S
157: PetscObjectViewFn - A prototype of a function that can view a `PetscObject`
159: Calling Sequence:
160: + obj - the `PetscObject` to view
161: - v - the viewer
163: Level: beginner
165: Note:
166: The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.
168: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
169: S*/
170: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode(PetscObjectViewFn)(PetscObject obj, PetscViewer v);
172: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;
174: /*MC
175: PetscHeaderCreate - Creates a raw PETSc object of a particular class
177: Synopsis:
178: #include <petsc/private/petscimpl.h>
179: PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn * destroy, PetscObjectViewFn * view)
181: Input Parameters:
182: + classid - The classid associated with this object (for example `VEC_CLASSID`)
183: . class_name - String name of class; should be static (for example "Vec"), may be
184: `PETSC_NULLPTR`
185: . descr - String containing short description; should be static (for example "Vector"),
186: may be `PETSC_NULLPTR`
187: . mansec - String indicating section in manual pages; should be static (for example "Vec"),
188: may be `PETSC_NULLPTR`
189: . comm - The MPI Communicator
190: . destroy - The destroy routine for this object (for example `VecDestroy()`)
191: - view - The view routine for this object (for example `VecView()`), may be
192: `PETSC_NULLPTR`
194: Output Parameter:
195: . h - The newly created `PetscObject`
197: Level: developer
199: Notes:
200: Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
201: C/C++ structure which satisfies all of the following\:
203: 1. The first member of the structure must be a `_p_PetscObject`.
204: 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
205: - Has no virtual functions or base classes.
206: - Has only standard layout non-static members (if any).
207: - Has only standard layout base classes (if any).
209: See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
210: information.
212: Example Usage:
213: Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
214: objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
215: `<OBJECT_TYPE>View()`.
216: .vb
217: Vec v;
219: PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
220: .ve
222: It is possible to create custom `PetscObject`s, note however that they must abide by the
223: restrictions set forth above.
224: .vb
225: // OK, first member of C structure is _p_PetscObject
226: struct MyCPetscObject_s
227: {
228: _p_PetscObject header;
229: int some_data;
230: };
231: typedef struct *MyCPetscObject_s MyCPetscObject;
233: PetscErrorCode MyObjectDestroy(MyObject *);
234: PetscErrorCode MyObjectView(MyObject);
236: MyCPetscObject obj;
238: // assume MY_PETSC_CLASSID is already registered
239: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
241: // OK, only destroy function must be given, all others may be NULL
242: PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
244: // ERROR must be a single-level pointer
245: PetscHeaderCreate(&obj, ...);
246: .ve
248: Illustrating proper construction from C++\:
249: .vb
250: // ERROR, class is not standard layout, first member must be publicly accessible
251: class BadCppPetscObject
252: {
253: _p_PetscObject header;
254: };
256: // ERROR, class is not standard layout, has a virtual function and virtual inheritance
257: class BadCppPetscObject2 : virtual BaseClass
258: {
259: public:
260: _p_PetscObject header;
262: virtual void foo();
263: };
265: // ERROR, class is not standard layout! Has non-standard layout member
266: class BadCppPetscObject2
267: {
268: public:
269: _p_PetscObject header;
270: BadCppPetscObject non_standard_layout;
271: };
273: // OK, class is standard layout!
274: class GoodCppPetscObject;
275: using MyCppObject = GoodCppPetscObject *;
277: // OK, non-virtual inheritance of other standard layout class does not affect layout
278: class GoodCppPetscObject : StandardLayoutClass
279: {
280: public:
281: // OK, non standard layout member is static, does not affect layout
282: static BadCppPetscObject non_standard_layout;
284: // OK, first non-static member is _p_PetscObject
285: _p_PetscObject header;
287: // OK, non-virtual member functions do not affect class layout
288: void foo();
290: // OK, may use "member" functions for destroy and view so long as they are static
291: static PetscErrorCode destroy(MyCppObject *);
292: static PetscErrorCode view(MyCppObject);
293: };
295: // OK, usage via pointer
296: MyObject obj;
298: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
299: .ve
301: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
302: M*/
303: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
304: PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))
306: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
307: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
308: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
309: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
310: PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
312: /*MC
313: PetscHeaderDestroy - Final step in destroying a `PetscObject`
315: Synopsis:
316: #include <petsc/private/petscimpl.h>
317: PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
319: Input Parameter:
320: . h - A pointer to the header created with `PetscHeaderCreate()`
322: Level: developer
324: Notes:
325: `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
327: Example Usage:
328: .vb
329: PetscObject obj;
331: PetscHeaderCreate(obj, ...);
332: // use obj...
334: // note pointer to obj is used
335: PetscHeaderDestroy(&obj);
336: .ve
338: Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
339: deallocates the memory for the structure itself\:
340: .vb
341: typedef struct MyPetscObject_s *MyPetscObject;
342: struct MyPetscObject_s
343: {
344: _p_PetscObject hdr;
345: PetscInt *foo;
346: PetscScalar *bar;
347: };
349: // assume obj is created/initialized elsewhere...
350: MyPetscObject obj;
352: // OK, should dispose of all dynamically allocated resources before calling
353: // PetscHeaderDestroy()
354: PetscFree(obj->foo);
356: // OK, dispose of obj
357: PetscHeaderDestroy(&obj);
359: // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
360: // obj->bar is potentially leaked!
361: PetscFree(obj->bar);
362: .ve
364: .seealso: `PetscObject`, `PetscHeaderCreate()`
365: M*/
366: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)
368: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject, PetscBool);
369: PETSC_INTERN PetscErrorCode PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
370: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
371: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
372: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
373: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);
375: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
376: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
377: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
379: /* Code shared between C and Fortran */
380: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscBool, PetscInt);
382: #if PetscDefined(HAVE_SETJMP_H)
383: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
384: #else
385: #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
386: #endif
388: #if defined(PETSC_CLANG_STATIC_ANALYZER)
389: template <typename T>
391: template <typename T>
393: template <typename T>
395: template <typename T>
396: extern void PetscAssertPointer(T, int)
397: {
398: }
399: template <typename T>
401: #else
402: // Macros to test if a PETSc object is valid and if pointers are valid
403: #if PetscDefined(USE_DEBUG)
404: /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
406: do { \
407: PetscBool _7_same; \
409: PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
410: 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); \
411: } while (0)
413: #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
414: do { \
415: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
416: PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
417: } while (0)
420: do { \
421: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
422: if (((PetscObject)(h))->classid != ck) { \
423: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
424: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
425: } \
426: } while (0)
429: do { \
430: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
431: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
432: 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); \
433: } while (0)
435: #if defined(__cplusplus)
436: #include <type_traits> // std::decay
438: namespace Petsc
439: {
441: namespace util
442: {
444: template <typename T>
445: struct PetscAssertPointerImpl {
446: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
447: PETSC_NODISCARD static constexpr const char *string() noexcept { return "memory"; }
448: };
450: #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
451: template <> \
452: struct PetscAssertPointerImpl<T *> { \
453: PETSC_NODISCARD static constexpr PetscDataType type() noexcept \
454: { \
455: return PETSC_TYPE; \
456: } \
457: PETSC_NODISCARD static constexpr const char *string() noexcept \
458: { \
459: return PetscStringize(T); \
460: } \
461: }; \
462: template <> \
463: struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
464: template <> \
465: struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
466: template <> \
467: struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
469: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
470: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
471: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
472: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
473: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
474: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
475: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
476: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
477: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
478: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
479: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
480: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
481: #if defined(PETSC_HAVE_COMPLEX)
482: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
483: #endif
485: #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
487: } // namespace util
489: } // namespace Petsc
491: #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
492: #define PetscAssertPointer_String(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
494: #elif PETSC_C_VERSION >= 11
495: #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
497: #if PetscDefined(HAVE_COMPLEX)
498: #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
499: #else
500: #define PETSC_GENERIC_CV_COMPLEX(result)
501: #endif
503: #define PetscAssertPointer_PetscDataType(h) \
504: _Generic((h), \
505: default: PETSC_CHAR, \
506: PETSC_GENERIC_CV( char, PETSC_CHAR), \
507: PETSC_GENERIC_CV( signed char, PETSC_CHAR), \
508: PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
509: PETSC_GENERIC_CV( short, PETSC_SHORT), \
510: PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
511: PETSC_GENERIC_CV( float, PETSC_FLOAT), \
512: PETSC_GENERIC_CV( double, PETSC_DOUBLE), \
513: PETSC_GENERIC_CV( int32_t, PETSC_INT32), \
514: PETSC_GENERIC_CV( uint32_t, PETSC_INT32), \
515: PETSC_GENERIC_CV( int64_t, PETSC_INT64), \
516: PETSC_GENERIC_CV( uint64_t, PETSC_INT64), \
517: PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
519: #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
521: #if PetscDefined(HAVE_COMPLEX)
522: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
523: #else
524: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
525: #endif
527: #define PetscAssertPointer_String(h) \
528: _Generic((h), \
529: default: "memory", \
530: PETSC_GENERIC_CV_STRINGIZE(char), \
531: PETSC_GENERIC_CV_STRINGIZE(signed char), \
532: PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
533: PETSC_GENERIC_CV_STRINGIZE(short), \
534: PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
535: PETSC_GENERIC_CV_STRINGIZE(float), \
536: PETSC_GENERIC_CV_STRINGIZE(double), \
537: PETSC_GENERIC_CV_STRINGIZE(int32_t), \
538: PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
539: PETSC_GENERIC_CV_STRINGIZE(int64_t), \
540: PETSC_GENERIC_CV_STRINGIZE(uint64_t), \
541: PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
542: #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
543: #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
544: #define PetscAssertPointer_String(h) "memory"
545: #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
546: #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
548: #else // PetscDefined(USE_DEBUG)
550: do { \
551: (void)(h); \
552: } while (0)
554: do { \
555: (void)(h); \
556: } while (0)
558: do { \
559: (void)(h); \
560: } while (0)
561: #define PetscAssertPointer(h, arg) \
562: do { \
563: (void)(h); \
564: } while (0)
566: do { \
567: (void)(h); \
568: } while (0)
569: #endif // PetscDefined(USE_DEBUG)
570: #endif // PETSC_CLANG_STATIC_ANALYZER
581: #define PetscSorted(n, idx, sorted) \
582: do { \
583: (sorted) = PETSC_TRUE; \
584: for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
585: if ((idx)[_i_] < (idx)[_i_ - 1]) { \
586: (sorted) = PETSC_FALSE; \
587: break; \
588: } \
589: } \
590: } while (0)
592: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
593: #if !defined(PETSC_USE_DEBUG)
595: #define PetscCheckSameType(a, arga, b, argb) \
596: do { \
597: (void)(a); \
598: (void)(b); \
599: } while (0)
600: #define PetscCheckTypeName(a, type) \
601: do { \
602: (void)(a); \
603: } while (0)
604: #define PetscCheckTypeNames(a, type1, type2) \
605: do { \
606: (void)(a); \
607: } while (0)
609: do { \
610: (void)(a); \
611: } while (0)
612: #define PetscCheckSameComm(a, arga, b, argb) \
613: do { \
614: (void)(a); \
615: (void)(b); \
616: } while (0)
617: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
618: do { \
619: (void)(a); \
620: (void)(b); \
621: } while (0)
623: do { \
624: (void)(a); \
625: (void)(b); \
626: } while (0)
628: do { \
629: (void)(a); \
630: (void)(b); \
631: } while (0)
633: do { \
634: (void)(a); \
635: (void)(b); \
636: } while (0)
638: do { \
639: (void)(a); \
640: (void)(b); \
641: } while (0)
643: do { \
644: (void)(a); \
645: (void)(b); \
646: } while (0)
648: do { \
649: (void)(a); \
650: (void)(b); \
651: } while (0)
652: #define PetscCheckSorted(n, idx) \
653: do { \
654: (void)(n); \
655: (void)(idx); \
656: } while (0)
658: #else
660: /*
661: This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
662: member associated with the string type_name that can be quickly compared.
664: **Do not swap this macro to compare string type_name!**
666: This macro is used incorrectly in the code. Many places that do not need identity of the
667: types incorrectly call this check and would need to be fixed if this macro is enabled.
668: */
669: #if 0
670: #define PetscCheckSameType(a, arga, b, argb) \
671: do { \
672: PetscBool pcst_type_eq_ = PETSC_TRUE; \
673: PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
674: 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); \
675: } while (0)
676: #else
677: #define PetscCheckSameType(a, arga, b, argb) \
678: do { \
679: (void)(a); \
680: (void)(b); \
681: } while (0)
682: #endif
684: /*
685: Check type_name
686: */
687: #define PetscCheckTypeName(a, type) \
688: do { \
689: PetscBool _7_match; \
690: PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
691: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", (char *)(((PetscObject)(a))->type_name), type); \
692: } while (0)
694: #define PetscCheckTypeNames(a, type1, type2) \
695: do { \
696: PetscBool _7_match; \
697: PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
698: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", (char *)(((PetscObject)(a))->type_name), type1, type2); \
699: } while (0)
701: /*
702: Use this macro to check if the type is set
703: */
706: /*
707: Sometimes object must live on same communicator to inter-operate
708: */
709: #define PetscCheckSameComm(a, arga, b, argb) \
710: do { \
711: PetscMPIInt _7_flag; \
712: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
713: 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); \
714: } while (0)
716: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
717: do { \
718: PetscCheckSameType(a, arga, b, argb); \
719: PetscCheckSameComm(a, arga, b, argb); \
720: } while (0)
723: do { \
724: PetscScalar b0 = (b); \
725: PetscReal b1[5], b2[5]; \
726: if (PetscIsNanScalar(b0)) { \
727: b1[4] = 1; \
728: } else { \
729: b1[4] = 0; \
730: }; \
731: b1[0] = -PetscRealPart(b0); \
732: b1[1] = PetscRealPart(b0); \
733: b1[2] = -PetscImaginaryPart(b0); \
734: b1[3] = PetscImaginaryPart(b0); \
735: PetscCall(MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
736: PetscCheck(b2[4] > 0 || (PetscEqualReal(-b2[0], b2[1]) && PetscEqualReal(-b2[2], b2[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
737: } while (0)
740: do { \
741: PetscReal b0 = (b), b1[3], b2[3]; \
742: if (PetscIsNanReal(b0)) { \
743: b1[2] = 1; \
744: } else { \
745: b1[2] = 0; \
746: }; \
747: b1[0] = -b0; \
748: b1[1] = b0; \
749: PetscCall(MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
750: PetscCheck(b2[2] > 0 || PetscEqualReal(-b2[0], b2[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
751: } while (0)
754: do { \
755: PetscInt b0 = (b), b1[2], b2[2]; \
756: b1[0] = -b0; \
757: b1[1] = b0; \
758: PetscCall(MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
759: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
760: } while (0)
763: do { \
764: PetscMPIInt b0 = (b), b1[2], b2[2]; \
765: b1[0] = -b0; \
766: b1[1] = b0; \
767: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
768: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
769: } while (0)
772: do { \
773: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
774: b1[0] = -b0; \
775: b1[1] = b0; \
776: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
777: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
778: } while (0)
781: do { \
782: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
783: b1[0] = -b0; \
784: b1[1] = b0; \
785: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
786: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
787: } while (0)
789: #define PetscCheckSorted(n, idx) \
790: do { \
791: PetscBool _1_flg; \
792: PetscSorted(n, idx, _1_flg); \
793: PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
794: } while (0)
796: #endif
797: #else /* PETSC_CLANG_STATIC_ANALYZER */
798: template <typename Ta, typename Tb>
799: extern void PetscCheckSameType(Ta, int, Tb, int);
800: template <typename Ta, typename Tb>
801: extern void PetscCheckTypeName(Ta, Tb);
802: template <typename Ta, typename Tb, typename Tc>
803: extern void PetscCheckTypeNames(Ta, Tb, Tc);
804: template <typename T>
806: template <typename Ta, typename Tb>
807: extern void PetscCheckSameComm(Ta, int, Tb, int);
808: template <typename Ta, typename Tb>
809: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
810: template <typename Ta, typename Tb>
812: template <typename Ta, typename Tb>
814: template <typename Ta, typename Tb>
816: template <typename Ta, typename Tb>
818: template <typename Ta, typename Tb>
820: template <typename Ta, typename Tb>
822: template <typename T>
823: extern void PetscCheckSorted(PetscInt, T);
824: #endif /* PETSC_CLANG_STATIC_ANALYZER */
826: /*MC
827: PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
829: Synopsis:
830: #include "petsc/private/petscimpl.h"
831: PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
833: Input Parameters:
834: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
835: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
836: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
837: - args - the arguments for the method, for example, (ksp,restart))
839: Level: developer
841: Notes:
842: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
844: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
845: in the object.
847: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
848: M*/
849: #define PetscTryMethod(obj, A, B, C) \
850: do { \
851: PetscErrorCode(*_7_f) B; \
852: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
853: if (_7_f) PetscCall((*_7_f)C); \
854: } while (0)
856: /*MC
857: PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
859: Synopsis:
860: #include "petsc/private/petscimpl.h"
861: PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
863: Input Parameters:
864: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
865: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
866: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
867: - args - the arguments for the method, for example, (ksp,restart))
869: Level: developer
871: Notes:
872: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
874: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
875: in the object.
877: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
878: M*/
879: #define PetscUseMethod(obj, A, B, C) \
880: do { \
881: PetscErrorCode(*_7_f) B; \
882: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
883: PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
884: PetscCall((*_7_f)C); \
885: } while (0)
887: /*
888: Use Microsoft traditional preprocessor.
890: The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
891: sets _MSVC_TRADITIONAL to zero so this code path is not used.
893: It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
895: These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
897: PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
898: */
899: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
901: #define PetscUseTypeMethod(obj, OP, ...) \
902: do { \
903: PetscErrorCode ierr_p_; \
904: PetscStackUpdateLine; \
905: 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); \
906: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
907: PetscCall(ierr_p_); \
908: } while (0)
910: #define PetscTryTypeMethod(obj, OP, ...) \
911: do { \
912: if ((obj)->ops->OP) { \
913: PetscErrorCode ierr_p_; \
914: PetscStackUpdateLine; \
915: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
916: PetscCall(ierr_p_); \
917: } \
918: } while (0)
920: #else
922: /*MC
923: 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
925: Synopsis:
926: #include "petsc/private/petscimpl.h"
927: PetscUseTypeMethod(obj, method, other_args)
929: Input Parameters:
930: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
931: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
932: - other_args - the other arguments for the method, `obj` is the first argument
934: Level: developer
936: Note:
937: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
939: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
941: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
942: M*/
943: #define PetscUseTypeMethod(obj, ...) \
944: do { \
945: PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
946: PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
947: PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
948: } while (0)
950: /*MC
951: 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
953: Synopsis:
954: #include "petsc/private/petscimpl.h"
955: PetscTryTypeMethod(obj, method, other_args)
957: Input Parameters:
958: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
959: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
960: - other_args - the other arguments for the method, `obj` is the first argument
962: Level: developer
964: Note:
965: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
967: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
969: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
970: M*/
971: #define PetscTryTypeMethod(obj, ...) \
972: do { \
973: if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
974: } while (0)
976: #endif
978: /*MC
979: PetscObjectStateIncrease - Increases the state of any `PetscObject`
981: Synopsis:
982: #include "petsc/private/petscimpl.h"
983: PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
985: Logically Collective
987: Input Parameter:
988: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
989: cast with a (PetscObject), for example,
990: `PetscObjectStateIncrease`((`PetscObject`)mat);
992: Level: developer
994: Notes:
995: Object state is a 64-bit integer which gets increased every time
996: the object is changed internally. By saving and later querying the object state
997: one can determine whether information about the object is still current.
998: Currently, state is maintained for `Vec` and `Mat` objects.
1000: This routine is mostly for internal use by PETSc; a developer need only
1001: call it after explicit access to an object's internals. Routines such
1002: as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
1003: precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
1005: Routines such as `VecNorm()` can by-pass the computation if the norm has already been computed and the vector's state has not changed.
1007: This routine is logically collective because state equality comparison needs to be possible without communication.
1009: `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
1011: .seealso: `PetscObjectStateGet()`, `PetscObject`
1012: M*/
1013: #define PetscObjectStateIncrease(obj) ((obj)->state++, PETSC_SUCCESS)
1015: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1016: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1017: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1018: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1019: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1020: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1021: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1022: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1023: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1024: PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
1026: /*MC
1027: PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
1029: Synopsis:
1030: #include "petsc/private/petscimpl.h"
1031: PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1033: Not Collective
1035: Input Parameters:
1036: + obj - the object to which data is to be attached
1037: . id - the identifier for the data
1038: - data - the data to be attached, a `PetscInt`
1040: Level: developer
1042: Notes:
1043: The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1045: This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1046: attached with `PetscObjectCompose()`
1048: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1049: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1050: `PetscObjectCompose()`, `PetscObjectQuery()`
1051: M*/
1052: #define PetscObjectComposedDataSetInt(obj, id, data) \
1053: ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1055: /*MC
1056: PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1058: Synopsis:
1059: #include "petsc/private/petscimpl.h"
1060: PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1062: Not Collective
1064: Input Parameters:
1065: + obj - the object from which data is to be retrieved
1066: - id - the identifier for the data
1068: Output Parameters:
1069: + data - the data to be retrieved, a `PetscInt`
1070: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1072: Level: developer
1074: Notes:
1075: The `data` and `flag` variables are inlined, so they are not pointers.
1077: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1078: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1079: `PetscObjectCompose()`, `PetscObjectQuery()`
1080: M*/
1081: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS)
1083: /*MC
1084: PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1086: Synopsis:
1087: #include "petsc/private/petscimpl.h"
1088: PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1090: Not Collective
1092: Input Parameters:
1093: + obj - the object to which data is to be attached
1094: . id - the identifier for the data
1095: - data - the data to be attached, a `PetscInt` array
1097: Level: developer
1099: Notes:
1100: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1102: The length of the array accessed must be known, it is not available through this API.
1104: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1105: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1106: `PetscObjectCompose()`, `PetscObjectQuery()`
1107: M*/
1108: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1109: ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1111: /*MC
1112: PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1114: Synopsis:
1115: #include "petsc/private/petscimpl.h"
1116: PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1118: Not Collective
1120: Input Parameters:
1121: + obj - the object from which data is to be retrieved
1122: - id - the identifier for the data
1124: Output Parameters:
1125: + data - the data to be retrieved, a `PetscInt` array
1126: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1128: Level: developer
1130: Notes:
1131: The `data` and `flag` variables are inlined, so they are not pointers.
1133: The length of the array accessed must be known, it is not available through this API.
1135: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1136: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1137: `PetscObjectCompose()`, `PetscObjectQuery()`
1138: M*/
1139: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1140: ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1142: /*MC
1143: PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1145: Synopsis:
1146: #include "petsc/private/petscimpl.h"
1147: PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1149: Not Collective
1151: Input Parameters:
1152: + obj - the object to which data is to be attached
1153: . id - the identifier for the data
1154: - data - the data to be attached, a `PetscReal`
1156: Level: developer
1158: Note:
1159: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1161: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1162: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1163: `PetscObjectCompose()`, `PetscObjectQuery()`
1164: M*/
1165: #define PetscObjectComposedDataSetReal(obj, id, data) \
1166: ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1168: /*MC
1169: PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1171: Synopsis:
1172: #include "petsc/private/petscimpl.h"
1173: PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1175: Not Collective
1177: Input Parameters:
1178: + obj - the object from which data is to be retrieved
1179: - id - the identifier for the data
1181: Output Parameters:
1182: + data - the data to be retrieved, a `PetscReal`
1183: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1185: Level: developer
1187: Note:
1188: The `data` and `flag` variables are inlined, so they are not pointers.
1190: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1191: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1192: `PetscObjectCompose()`, `PetscObjectQuery()`
1193: M*/
1194: #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))
1196: /*MC
1197: PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1199: Synopsis:
1200: #include "petsc/private/petscimpl.h"
1201: PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1203: Not Collective
1205: Input Parameters:
1206: + obj - the object to which data is to be attached
1207: . id - the identifier for the data
1208: - data - the data to be attached
1210: Level: developer
1212: Notes:
1213: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1215: The length of the array accessed must be known, it is not available through this API.
1217: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1218: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1219: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1220: M*/
1221: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1222: ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1224: /*MC
1225: PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1227: Synopsis:
1228: #include "petsc/private/petscimpl.h"
1229: PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1231: Not Collective
1233: Input Parameters:
1234: + obj - the object from which data is to be retrieved
1235: - id - the identifier for the data
1237: Output Parameters:
1238: + data - the data to be retrieved, a `PetscReal` array
1239: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1241: Level: developer
1243: Notes:
1244: The `data` and `flag` variables are inlined, so they are not pointers.
1246: The length of the array accessed must be known, it is not available through this API.
1248: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1249: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1250: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1251: M*/
1252: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1253: ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1255: /*MC
1256: PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1258: Synopsis:
1259: #include "petsc/private/petscimpl.h"
1260: PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1262: Not Collective
1264: Input Parameters:
1265: + obj - the object to which data is to be attached
1266: . id - the identifier for the data
1267: - data - the data to be attached, a `PetscScalar`
1269: Level: developer
1271: Note:
1272: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1274: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1275: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1276: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1277: M*/
1278: #if defined(PETSC_USE_COMPLEX)
1279: #define PetscObjectComposedDataSetScalar(obj, id, data) \
1280: ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1281: #else
1282: #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1283: #endif
1284: /*MC
1285: PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1287: Synopsis:
1288: #include "petsc/private/petscimpl.h"
1289: PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1291: Not Collective
1293: Input Parameters:
1294: + obj - the object from which data is to be retrieved
1295: - id - the identifier for the data
1297: Output Parameters:
1298: + data - the data to be retrieved, a `PetscScalar`
1299: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1301: Level: developer
1303: Note:
1304: The `data` and `flag` variables are inlined, so they are not pointers.
1306: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1307: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1308: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1309: M*/
1310: #if defined(PETSC_USE_COMPLEX)
1311: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1312: ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1313: #else
1314: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1315: #endif
1317: /*MC
1318: PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1320: Synopsis:
1321: #include "petsc/private/petscimpl.h"
1322: PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1324: Not Collective
1326: Input Parameters:
1327: + obj - the object to which data is to be attached
1328: . id - the identifier for the data
1329: - data - the data to be attached, a `PetscScalar` array
1331: Level: developer
1333: Notes:
1334: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1336: The length of the array accessed must be known, it is not available through this API.
1338: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1339: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1340: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1341: M*/
1342: #if defined(PETSC_USE_COMPLEX)
1343: #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1344: ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1345: #else
1346: #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1347: #endif
1348: /*MC
1349: PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1350: attached to an object
1352: Synopsis:
1353: #include "petsc/private/petscimpl.h"
1354: PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1356: Not Collective
1358: Input Parameters:
1359: + obj - the object from which data is to be retrieved
1360: - id - the identifier for the data
1362: Output Parameters:
1363: + data - the data to be retrieved, a `PetscScalar` array
1364: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1366: Level: developer
1368: Notes:
1369: The `data` and `flag` variables are inlined, so they are not pointers.
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()`, `PetscObjectComposedDataSetScalarstar()`
1376: M*/
1377: #if defined(PETSC_USE_COMPLEX)
1378: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1379: ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1380: #else
1381: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1382: #endif
1384: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1385: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1386: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1387: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1388: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1389: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1390: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1392: PETSC_EXTERN PetscMPIInt Petsc_SharedWD_keyval;
1393: PETSC_EXTERN PetscMPIInt Petsc_SharedTmp_keyval;
1395: struct PetscCommStash {
1396: struct PetscCommStash *next;
1397: MPI_Comm comm;
1398: };
1400: /*
1401: PETSc communicators have this attribute, see
1402: PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1403: */
1404: typedef struct {
1405: PetscMPIInt tag; /* next free tag value */
1406: PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1407: PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1408: PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1409: struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1410: } PetscCommCounter;
1412: typedef enum {
1413: STATE_BEGIN,
1414: STATE_PENDING,
1415: STATE_END
1416: } SRState;
1418: typedef enum {
1419: PETSC_SR_REDUCE_SUM = 0,
1420: PETSC_SR_REDUCE_MAX = 1,
1421: PETSC_SR_REDUCE_MIN = 2
1422: } PetscSRReductionType;
1424: typedef struct {
1425: MPI_Comm comm;
1426: MPI_Request request;
1427: PetscBool mix;
1428: PetscBool async;
1429: PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1430: PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1431: void **invecs; /* for debugging only, vector/memory used with each op */
1432: PetscInt *reducetype; /* is particular value to be summed or maxed? */
1433: struct {
1434: PetscScalar v;
1435: PetscInt i;
1436: } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1437: SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1438: PetscInt maxops; /* total amount of space we have for requests */
1439: PetscInt numopsbegin; /* number of requests that have been queued in */
1440: PetscInt numopsend; /* number of requests that have been gotten by user */
1441: } PetscSplitReduction;
1443: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1444: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1445: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1447: #if defined(PETSC_HAVE_THREADSAFETY)
1448: #if defined(PETSC_HAVE_CONCURRENCYKIT)
1449: #if defined(__cplusplus)
1450: /* CK does not have extern "C" protection in their include files */
1451: extern "C" {
1452: #endif
1453: #include <ck_spinlock.h>
1454: #if defined(__cplusplus)
1455: }
1456: #endif
1457: typedef ck_spinlock_t PetscSpinlock;
1459: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1460: {
1461: ck_spinlock_init(ck_spinlock);
1462: return PETSC_SUCCESS;
1463: }
1464: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1465: {
1466: ck_spinlock_lock(ck_spinlock);
1467: return PETSC_SUCCESS;
1468: }
1469: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1470: {
1471: ck_spinlock_unlock(ck_spinlock);
1472: return PETSC_SUCCESS;
1473: }
1474: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1475: {
1476: return PETSC_SUCCESS;
1477: }
1478: #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1479: #if defined(__cplusplus)
1480: // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1481: #include <atomic>
1482: #define petsc_atomic_flag std::atomic_flag
1483: #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1484: #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_release)
1485: #else
1486: #include <stdatomic.h>
1487: #define petsc_atomic_flag atomic_flag
1488: #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1489: #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_release)
1490: #endif
1492: typedef petsc_atomic_flag PetscSpinlock;
1494: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1495: {
1496: petsc_atomic_flag_clear(spinlock);
1497: return PETSC_SUCCESS;
1498: }
1499: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1500: {
1501: do {
1502: } while (petsc_atomic_flag_test_and_set(spinlock));
1503: return PETSC_SUCCESS;
1504: }
1505: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1506: {
1507: petsc_atomic_flag_clear(spinlock);
1508: return PETSC_SUCCESS;
1509: }
1510: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1511: {
1512: return PETSC_SUCCESS;
1513: }
1514: #undef petsc_atomic_flag_test_and_set
1515: #undef petsc_atomic_flag_clear
1516: #undef petsc_atomic_flag
1518: #elif defined(PETSC_HAVE_OPENMP)
1520: #include <omp.h>
1521: typedef omp_lock_t PetscSpinlock;
1523: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1524: {
1525: omp_init_lock(omp_lock);
1526: return PETSC_SUCCESS;
1527: }
1528: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1529: {
1530: omp_set_lock(omp_lock);
1531: return PETSC_SUCCESS;
1532: }
1533: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1534: {
1535: omp_unset_lock(omp_lock);
1536: return PETSC_SUCCESS;
1537: }
1538: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1539: {
1540: omp_destroy_lock(omp_lock);
1541: return PETSC_SUCCESS;
1542: }
1543: #else
1544: #if defined(__cplusplus)
1545: #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1546: #else
1547: #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1548: #endif
1549: #endif
1551: #else
1552: typedef int PetscSpinlock;
1553: #define PetscSpinlockCreate(a) PETSC_SUCCESS
1554: #define PetscSpinlockLock(a) PETSC_SUCCESS
1555: #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1556: #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1557: #endif
1559: #if defined(PETSC_HAVE_THREADSAFETY)
1560: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1561: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1562: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1563: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1564: #endif
1566: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1567: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1568: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1569: PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1570: PETSC_EXTERN PetscBool PetscPrintFunctionList;
1572: #if defined(PETSC_HAVE_ADIOS)
1573: PETSC_EXTERN int64_t Petsc_adios_group;
1574: #endif
1576: #if defined(PETSC_HAVE_KOKKOS)
1577: PETSC_INTERN PetscBool PetscBeganKokkos;
1578: PETSC_EXTERN PetscBool PetscKokkosInitialized;
1579: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1580: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1581: #endif
1583: #if defined(PETSC_HAVE_OPENMP)
1584: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1585: #endif
1587: struct _n_PetscObjectList {
1588: char name[256];
1589: PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1590: PetscObject obj;
1591: PetscObjectList next;
1592: };