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: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectDestroyFunction)(PetscObject *); /* force cast in next macro to NEVER use extern "C" style */
140: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectViewFunction)(PetscObject, PetscViewer);
142: /*MC
143: PetscHeaderCreate - Creates a raw PETSc object of a particular class
145: Synopsis:
146: #include <petsc/private/petscimpl.h>
147: PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
149: Input Parameters:
150: + classid - The classid associated with this object (for example `VEC_CLASSID`)
151: . class_name - String name of class; should be static (for example "Vec"), may be
152: `PETSC_NULLPTR`
153: . descr - String containing short description; should be static (for example "Vector"),
154: may be `PETSC_NULLPTR`
155: . mansec - String indicating section in manual pages; should be static (for example "Vec"),
156: may be `PETSC_NULLPTR`
157: . comm - The MPI Communicator
158: . destroy - The destroy routine for this object (for example `VecDestroy()`)
159: - view - The view routine for this object (for example `VecView()`), may be
160: `PETSC_NULLPTR`
162: Output Parameter:
163: . h - The newly created `PetscObject`
165: Level: developer
167: Notes:
168: Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
169: C/C++ structure which satisfies all of the following\:
171: 1. The first member of the structure must be a `_p_PetscObject`.
172: 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
173: - Has no virtual functions or base classes.
174: - Has only standard layout non-static members (if any).
175: - Has only standard layout base classes (if any).
177: See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
178: information.
180: Example Usage:
181: Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
182: objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
183: `<OBJECT_TYPE>View()`.
184: .vb
185: Vec v;
187: PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
188: .ve
190: It is possible to create custom `PetscObject`s, note however that they must abide by the
191: restrictions set forth above.
192: .vb
193: // OK, first member of C structure is _p_PetscObject
194: struct MyCPetscObject_s
195: {
196: _p_PetscObject header;
197: int some_data;
198: };
199: typedef struct *MyCPetscObject_s MyCPetscObject;
201: PetscErrorCode MyObjectDestroy(MyObject *);
202: PetscErrorCode MyObjectView(MyObject);
204: MyCPetscObject obj;
206: // assume MY_PETSC_CLASSID is already registered
207: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
209: // OK, only destroy function must be given, all others may be NULL
210: PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
212: // ERROR must be a single-level pointer
213: PetscHeaderCreate(&obj, ...);
214: .ve
216: Illustrating proper construction from C++\:
217: .vb
218: // ERROR, class is not standard layout, first member must be publicly accessible
219: class BadCppPetscObject
220: {
221: _p_PetscObject header;
222: };
224: // ERROR, class is not standard layout, has a virtual function and virtual inheritance
225: class BadCppPetscObject2 : virtual BaseClass
226: {
227: public:
228: _p_PetscObject header;
230: virtual void foo();
231: };
233: // ERROR, class is not standard layout! Has non-standard layout member
234: class BadCppPetscObject2
235: {
236: public:
237: _p_PetscObject header;
238: BadCppPetscObject non_standard_layout;
239: };
241: // OK, class is standard layout!
242: class GoodCppPetscObject;
243: using MyCppObject = GoodCppPetscObject *;
245: // OK, non-virtual inheritance of other standard layout class does not affect layout
246: class GoodCppPetscObject : StandardLayoutClass
247: {
248: public:
249: // OK, non standard layout member is static, does not affect layout
250: static BadCppPetscObject non_standard_layout;
252: // OK, first non-static member is _p_PetscObject
253: _p_PetscObject header;
255: // OK, non-virtual member functions do not affect class layout
256: void foo();
258: // OK, may use "member" functions for destroy and view so long as they are static
259: static PetscErrorCode destroy(MyCppObject *);
260: static PetscErrorCode view(MyCppObject);
261: };
263: // OK, usage via pointer
264: MyObject obj;
266: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
267: .ve
269: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
270: M*/
271: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
272: PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFunction)(destroy), (PetscObjectViewFunction)(view))
274: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
275: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
276: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
277: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
278: PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
280: /*MC
281: PetscHeaderDestroy - Final step in destroying a `PetscObject`
283: Synopsis:
284: #include <petsc/private/petscimpl.h>
285: PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
287: Input Parameter:
288: . h - A pointer to the header created with `PetscHeaderCreate()`
290: Level: developer
292: Notes:
293: `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
295: Example Usage:
296: .vb
297: PetscObject obj;
299: PetscHeaderCreate(obj, ...);
300: // use obj...
302: // note pointer to obj is used
303: PetscHeaderDestroy(&obj);
304: .ve
306: Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
307: deallocates the memory for the structure itself\:
308: .vb
309: typedef struct MyPetscObject_s *MyPetscObject;
310: struct MyPetscObject_s
311: {
312: _p_PetscObject hdr;
313: PetscInt *foo;
314: PetscScalar *bar;
315: };
317: // assume obj is created/initialized elsewhere...
318: MyPetscObject obj;
320: // OK, should dispose of all dynamically allocated resources before calling
321: // PetscHeaderDestroy()
322: PetscFree(obj->foo);
324: // OK, dispose of obj
325: PetscHeaderDestroy(&obj);
327: // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
328: // obj->bar is potentially leaked!
329: PetscFree(obj->bar);
330: .ve
332: .seealso: `PetscObject`, `PetscHeaderCreate()`
333: M*/
334: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)
336: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject, PetscBool);
337: PETSC_INTERN PetscErrorCode PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
338: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
339: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
340: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
341: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);
343: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
344: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
345: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
347: /* Code shared between C and Fortran */
348: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscBool, PetscInt);
350: #if PetscDefined(HAVE_SETJMP_H)
351: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
352: #else
353: #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
354: #endif
356: #if defined(PETSC_CLANG_STATIC_ANALYZER)
357: template <typename T>
359: template <typename T>
361: template <typename T>
363: template <typename T>
364: extern void PetscAssertPointer(T, int)
365: {
366: }
367: template <typename T>
369: #else
370: // Macros to test if a PETSc object is valid and if pointers are valid
371: #if PetscDefined(USE_DEBUG)
372: /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
374: do { \
375: PetscBool _7_same; \
377: PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
378: 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); \
379: } while (0)
381: #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
382: do { \
383: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
384: PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
385: } while (0)
388: do { \
389: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
390: if (((PetscObject)(h))->classid != ck) { \
391: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
392: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
393: } \
394: } while (0)
397: do { \
398: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
399: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
400: 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); \
401: } while (0)
403: #if defined(__cplusplus)
404: #include <type_traits> // std::decay
406: namespace Petsc
407: {
409: namespace util
410: {
412: template <typename T>
413: struct PetscAssertPointerImpl {
414: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
415: PETSC_NODISCARD static constexpr const char *string() noexcept { return "memory"; }
416: };
418: #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
419: template <> \
420: struct PetscAssertPointerImpl<T *> { \
421: PETSC_NODISCARD static constexpr PetscDataType type() noexcept \
422: { \
423: return PETSC_TYPE; \
424: } \
425: PETSC_NODISCARD static constexpr const char *string() noexcept \
426: { \
427: return PetscStringize(T); \
428: } \
429: }; \
430: template <> \
431: struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
432: template <> \
433: struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
434: template <> \
435: struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
437: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
438: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
439: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
440: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
441: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
442: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
443: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
444: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
445: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
446: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
447: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
448: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
449: #if !defined(PETSC_SKIP_COMPLEX)
450: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
451: #endif
453: #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
455: } // namespace util
457: } // namespace Petsc
459: #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
460: #define PetscAssertPointer_String(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
462: #elif PETSC_C_VERSION >= 11
463: #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
465: #if !PetscDefined(SKIP_COMPLEX)
466: #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
467: #else
468: #define PETSC_GENERIC_CV_COMPLEX(result)
469: #endif
471: #define PetscAssertPointer_PetscDataType(h) \
472: _Generic((h), \
473: default: PETSC_CHAR, \
474: PETSC_GENERIC_CV( char, PETSC_CHAR), \
475: PETSC_GENERIC_CV( signed char, PETSC_CHAR), \
476: PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
477: PETSC_GENERIC_CV( short, PETSC_SHORT), \
478: PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
479: PETSC_GENERIC_CV( float, PETSC_FLOAT), \
480: PETSC_GENERIC_CV( double, PETSC_DOUBLE), \
481: PETSC_GENERIC_CV( int32_t, PETSC_INT32), \
482: PETSC_GENERIC_CV( uint32_t, PETSC_INT32), \
483: PETSC_GENERIC_CV( int64_t, PETSC_INT64), \
484: PETSC_GENERIC_CV( uint64_t, PETSC_INT64), \
485: PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
487: #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
489: #if !PetscDefined(SKIP_COMPLEX)
490: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
491: #else
492: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
493: #endif
495: #define PetscAssertPointer_String(h) \
496: _Generic((h), \
497: default: "memory", \
498: PETSC_GENERIC_CV_STRINGIZE(char), \
499: PETSC_GENERIC_CV_STRINGIZE(signed char), \
500: PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
501: PETSC_GENERIC_CV_STRINGIZE(short), \
502: PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
503: PETSC_GENERIC_CV_STRINGIZE(float), \
504: PETSC_GENERIC_CV_STRINGIZE(double), \
505: PETSC_GENERIC_CV_STRINGIZE(int32_t), \
506: PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
507: PETSC_GENERIC_CV_STRINGIZE(int64_t), \
508: PETSC_GENERIC_CV_STRINGIZE(uint64_t), \
509: PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
510: #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
511: #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
512: #define PetscAssertPointer_String(h) "memory"
513: #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
514: #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
516: #else // PetscDefined(USE_DEBUG)
518: do { \
519: (void)(h); \
520: } while (0)
522: do { \
523: (void)(h); \
524: } while (0)
526: do { \
527: (void)(h); \
528: } while (0)
529: #define PetscAssertPointer(h, arg) \
530: do { \
531: (void)(h); \
532: } while (0)
534: do { \
535: (void)(h); \
536: } while (0)
537: #endif // PetscDefined(USE_DEBUG)
538: #endif // PETSC_CLANG_STATIC_ANALYZER
549: #define PetscSorted(n, idx, sorted) \
550: do { \
551: (sorted) = PETSC_TRUE; \
552: for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
553: if ((idx)[_i_] < (idx)[_i_ - 1]) { \
554: (sorted) = PETSC_FALSE; \
555: break; \
556: } \
557: } \
558: } while (0)
560: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
561: #if !defined(PETSC_USE_DEBUG)
563: #define PetscCheckSameType(a, arga, b, argb) \
564: do { \
565: (void)(a); \
566: (void)(b); \
567: } while (0)
568: #define PetscCheckTypeName(a, type) \
569: do { \
570: (void)(a); \
571: } while (0)
572: #define PetscCheckTypeNames(a, type1, type2) \
573: do { \
574: (void)(a); \
575: } while (0)
577: do { \
578: (void)(a); \
579: } while (0)
580: #define PetscCheckSameComm(a, arga, b, argb) \
581: do { \
582: (void)(a); \
583: (void)(b); \
584: } while (0)
585: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
586: do { \
587: (void)(a); \
588: (void)(b); \
589: } while (0)
591: do { \
592: (void)(a); \
593: (void)(b); \
594: } while (0)
596: do { \
597: (void)(a); \
598: (void)(b); \
599: } while (0)
601: do { \
602: (void)(a); \
603: (void)(b); \
604: } while (0)
606: do { \
607: (void)(a); \
608: (void)(b); \
609: } while (0)
611: do { \
612: (void)(a); \
613: (void)(b); \
614: } while (0)
616: do { \
617: (void)(a); \
618: (void)(b); \
619: } while (0)
620: #define PetscCheckSorted(n, idx) \
621: do { \
622: (void)(n); \
623: (void)(idx); \
624: } while (0)
626: #else
628: /*
629: This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
630: member associated with the string type_name that can be quickly compared.
632: **Do not swap this macro to compare string type_name!**
634: This macro is used incorrectly in the code. Many places that do not need identity of the
635: types incorrectly call this check and would need to be fixed if this macro is enabled.
636: */
637: #if 0
638: #define PetscCheckSameType(a, arga, b, argb) \
639: do { \
640: PetscBool pcst_type_eq_ = PETSC_TRUE; \
641: PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_)); \
642: 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); \
643: } while (0)
644: #else
645: #define PetscCheckSameType(a, arga, b, argb) \
646: do { \
647: (void)(a); \
648: (void)(b); \
649: } while (0)
650: #endif
652: /*
653: Check type_name
654: */
655: #define PetscCheckTypeName(a, type) \
656: do { \
657: PetscBool _7_match; \
658: PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
659: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", (char *)(((PetscObject)(a))->type_name), type); \
660: } while (0)
662: #define PetscCheckTypeNames(a, type1, type2) \
663: do { \
664: PetscBool _7_match; \
665: PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
666: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", (char *)(((PetscObject)(a))->type_name), type1, type2); \
667: } while (0)
669: /*
670: Use this macro to check if the type is set
671: */
674: /*
675: Sometimes object must live on same communicator to inter-operate
676: */
677: #define PetscCheckSameComm(a, arga, b, argb) \
678: do { \
679: PetscMPIInt _7_flag; \
680: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
681: 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); \
682: } while (0)
684: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
685: do { \
686: PetscCheckSameType(a, arga, b, argb); \
687: PetscCheckSameComm(a, arga, b, argb); \
688: } while (0)
691: do { \
692: PetscScalar b0 = (b); \
693: PetscReal b1[5], b2[5]; \
694: if (PetscIsNanScalar(b0)) { \
695: b1[4] = 1; \
696: } else { \
697: b1[4] = 0; \
698: }; \
699: b1[0] = -PetscRealPart(b0); \
700: b1[1] = PetscRealPart(b0); \
701: b1[2] = -PetscImaginaryPart(b0); \
702: b1[3] = PetscImaginaryPart(b0); \
703: PetscCall(MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
704: 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); \
705: } while (0)
708: do { \
709: PetscReal b0 = (b), b1[3], b2[3]; \
710: if (PetscIsNanReal(b0)) { \
711: b1[2] = 1; \
712: } else { \
713: b1[2] = 0; \
714: }; \
715: b1[0] = -b0; \
716: b1[1] = b0; \
717: PetscCall(MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
718: 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); \
719: } while (0)
722: do { \
723: PetscInt b0 = (b), b1[2], b2[2]; \
724: b1[0] = -b0; \
725: b1[1] = b0; \
726: PetscCall(MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
727: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
728: } while (0)
731: do { \
732: PetscMPIInt b0 = (b), b1[2], b2[2]; \
733: b1[0] = -b0; \
734: b1[1] = b0; \
735: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
736: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
737: } while (0)
740: do { \
741: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
742: b1[0] = -b0; \
743: b1[1] = b0; \
744: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
745: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
746: } while (0)
749: do { \
750: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
751: b1[0] = -b0; \
752: b1[1] = b0; \
753: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
754: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
755: } while (0)
757: #define PetscCheckSorted(n, idx) \
758: do { \
759: PetscBool _1_flg; \
760: PetscSorted(n, idx, _1_flg); \
761: PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
762: } while (0)
764: #endif
765: #else /* PETSC_CLANG_STATIC_ANALYZER */
766: template <typename Ta, typename Tb>
767: extern void PetscCheckSameType(Ta, int, Tb, int);
768: template <typename Ta, typename Tb>
769: extern void PetscCheckTypeName(Ta, Tb);
770: template <typename Ta, typename Tb, typename Tc>
771: extern void PetscCheckTypeNames(Ta, Tb, Tc);
772: template <typename T>
774: template <typename Ta, typename Tb>
775: extern void PetscCheckSameComm(Ta, int, Tb, int);
776: template <typename Ta, typename Tb>
777: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
778: template <typename Ta, typename Tb>
780: template <typename Ta, typename Tb>
782: template <typename Ta, typename Tb>
784: template <typename Ta, typename Tb>
786: template <typename Ta, typename Tb>
788: template <typename Ta, typename Tb>
790: template <typename T>
791: extern void PetscCheckSorted(PetscInt, T);
792: #endif /* PETSC_CLANG_STATIC_ANALYZER */
794: /*MC
795: PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
797: Synopsis:
798: #include "petsc/private/petscimpl.h"
799: PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
801: Input Parameters:
802: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
803: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
804: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
805: - args - the arguments for the method, for example, (ksp,restart))
807: Level: developer
809: Notes:
810: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
812: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
813: in the object.
815: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
816: M*/
817: #define PetscTryMethod(obj, A, B, C) \
818: do { \
819: PetscErrorCode(*_7_f) B; \
820: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
821: if (_7_f) PetscCall((*_7_f)C); \
822: } while (0)
824: /*MC
825: PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
827: Synopsis:
828: #include "petsc/private/petscimpl.h"
829: PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
831: Input Parameters:
832: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
833: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
834: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
835: - args - the arguments for the method, for example, (ksp,restart))
837: Level: developer
839: Notes:
840: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
842: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
843: in the object.
845: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
846: M*/
847: #define PetscUseMethod(obj, A, B, C) \
848: do { \
849: PetscErrorCode(*_7_f) B; \
850: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
851: PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
852: PetscCall((*_7_f)C); \
853: } while (0)
855: /*
856: Use Microsoft traditional preprocessor.
858: The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
859: sets _MSVC_TRADITIONAL to zero so this code path is not used.
861: It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
863: These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
865: PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
866: */
867: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
869: #define PetscUseTypeMethod(obj, OP, ...) \
870: do { \
871: PetscErrorCode ierr_p_; \
872: PetscStackUpdateLine; \
873: 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); \
874: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
875: PetscCall(ierr_p_); \
876: } while (0)
878: #define PetscTryTypeMethod(obj, OP, ...) \
879: do { \
880: if ((obj)->ops->OP) { \
881: PetscErrorCode ierr_p_; \
882: PetscStackUpdateLine; \
883: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
884: PetscCall(ierr_p_); \
885: } \
886: } while (0)
888: #else
890: /*MC
891: 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
893: Synopsis:
894: #include "petsc/private/petscimpl.h"
895: PetscUseTypeMethod(obj, method, other_args)
897: Input Parameters:
898: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
899: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
900: - other_args - the other arguments for the method, `obj` is the first argument
902: Level: developer
904: Note:
905: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
907: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
909: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`
910: M*/
911: #define PetscUseTypeMethod(obj, ...) \
912: do { \
913: PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
914: PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
915: PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
916: } while (0)
918: /*MC
919: 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
921: Synopsis:
922: #include "petsc/private/petscimpl.h"
923: PetscTryTypeMethod(obj, method, other_args)
925: Input Parameters:
926: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
927: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
928: - other_args - the other arguments for the method, `obj` is the first argument
930: Level: developer
932: Note:
933: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
935: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
937: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
938: M*/
939: #define PetscTryTypeMethod(obj, ...) \
940: do { \
941: if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
942: } while (0)
944: #endif
946: /*MC
947: PetscObjectStateIncrease - Increases the state of any `PetscObject`
949: Synopsis:
950: #include "petsc/private/petscimpl.h"
951: PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
953: Logically Collective
955: Input Parameter:
956: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
957: cast with a (PetscObject), for example,
958: `PetscObjectStateIncrease`((`PetscObject`)mat);
960: Level: developer
962: Notes:
963: Object state is a 64-bit integer which gets increased every time
964: the object is changed internally. By saving and later querying the object state
965: one can determine whether information about the object is still current.
966: Currently, state is maintained for `Vec` and `Mat` objects.
968: This routine is mostly for internal use by PETSc; a developer need only
969: call it after explicit access to an object's internals. Routines such
970: as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
971: precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
973: Routines such as `VecNorm()` can by-pass the computation if the norm has already been computed and the vector's state has not changed.
975: This routine is logically collective because state equality comparison needs to be possible without communication.
977: `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
979: .seealso: `PetscObjectStateGet()`, `PetscObject`
980: M*/
981: #define PetscObjectStateIncrease(obj) ((obj)->state++, PETSC_SUCCESS)
983: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
984: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
985: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
986: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
987: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
988: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
989: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
990: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
991: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
992: PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
994: /*MC
995: PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
997: Synopsis:
998: #include "petsc/private/petscimpl.h"
999: PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1001: Not Collective
1003: Input Parameters:
1004: + obj - the object to which data is to be attached
1005: . id - the identifier for the data
1006: - data - the data to be attached, a `PetscInt`
1008: Level: developer
1010: Notes:
1011: The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1013: This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1014: attached with `PetscObjectCompose()`
1016: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1017: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1018: `PetscObjectCompose()`, `PetscObjectQuery()`
1019: M*/
1020: #define PetscObjectComposedDataSetInt(obj, id, data) \
1021: ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1023: /*MC
1024: PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1026: Synopsis:
1027: #include "petsc/private/petscimpl.h"
1028: PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1030: Not Collective
1032: Input Parameters:
1033: + obj - the object from which data is to be retrieved
1034: - id - the identifier for the data
1036: Output Parameters:
1037: + data - the data to be retrieved, a `PetscInt`
1038: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1040: Level: developer
1042: Notes:
1043: The `data` and `flag` variables are inlined, so they are not pointers.
1045: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1046: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1047: `PetscObjectCompose()`, `PetscObjectQuery()`
1048: M*/
1049: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS)
1051: /*MC
1052: PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1054: Synopsis:
1055: #include "petsc/private/petscimpl.h"
1056: PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1058: Not Collective
1060: Input Parameters:
1061: + obj - the object to which data is to be attached
1062: . id - the identifier for the data
1063: - data - the data to be attached, a `PetscInt` array
1065: Level: developer
1067: Notes:
1068: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1070: The length of the array accessed must be known, it is not available through this API.
1072: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1073: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1074: `PetscObjectCompose()`, `PetscObjectQuery()`
1075: M*/
1076: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1077: ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1079: /*MC
1080: PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1082: Synopsis:
1083: #include "petsc/private/petscimpl.h"
1084: PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1086: Not Collective
1088: Input Parameters:
1089: + obj - the object from which data is to be retrieved
1090: - id - the identifier for the data
1092: Output Parameters:
1093: + data - the data to be retrieved, a `PetscInt` array
1094: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1096: Level: developer
1098: Notes:
1099: The `data` and `flag` variables are inlined, so they are not pointers.
1101: The length of the array accessed must be known, it is not available through this API.
1103: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1104: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1105: `PetscObjectCompose()`, `PetscObjectQuery()`
1106: M*/
1107: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1108: ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1110: /*MC
1111: PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1113: Synopsis:
1114: #include "petsc/private/petscimpl.h"
1115: PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1117: Not Collective
1119: Input Parameters:
1120: + obj - the object to which data is to be attached
1121: . id - the identifier for the data
1122: - data - the data to be attached, a `PetscReal`
1124: Level: developer
1126: Note:
1127: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1129: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1130: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1131: `PetscObjectCompose()`, `PetscObjectQuery()`
1132: M*/
1133: #define PetscObjectComposedDataSetReal(obj, id, data) \
1134: ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1136: /*MC
1137: PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1139: Synopsis:
1140: #include "petsc/private/petscimpl.h"
1141: PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1143: Not Collective
1145: Input Parameters:
1146: + obj - the object from which data is to be retrieved
1147: - id - the identifier for the data
1149: Output Parameters:
1150: + data - the data to be retrieved, a `PetscReal`
1151: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1153: Level: developer
1155: Note:
1156: The `data` and `flag` variables are inlined, so they are not pointers.
1158: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1159: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1160: `PetscObjectCompose()`, `PetscObjectQuery()`
1161: M*/
1162: #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))
1164: /*MC
1165: PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1167: Synopsis:
1168: #include "petsc/private/petscimpl.h"
1169: PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1171: Not Collective
1173: Input Parameters:
1174: + obj - the object to which data is to be attached
1175: . id - the identifier for the data
1176: - data - the data to be attached
1178: Level: developer
1180: Notes:
1181: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1183: The length of the array accessed must be known, it is not available through this API.
1185: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1186: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1187: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1188: M*/
1189: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1190: ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1192: /*MC
1193: PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1195: Synopsis:
1196: #include "petsc/private/petscimpl.h"
1197: PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1199: Not Collective
1201: Input Parameters:
1202: + obj - the object from which data is to be retrieved
1203: - id - the identifier for the data
1205: Output Parameters:
1206: + data - the data to be retrieved, a `PetscReal` array
1207: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1209: Level: developer
1211: Notes:
1212: The `data` and `flag` variables are inlined, so they are not pointers.
1214: The length of the array accessed must be known, it is not available through this API.
1216: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1217: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1218: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1219: M*/
1220: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1221: ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1223: /*MC
1224: PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1226: Synopsis:
1227: #include "petsc/private/petscimpl.h"
1228: PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1230: Not Collective
1232: Input Parameters:
1233: + obj - the object to which data is to be attached
1234: . id - the identifier for the data
1235: - data - the data to be attached, a `PetscScalar`
1237: Level: developer
1239: Note:
1240: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1242: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1243: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1244: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1245: M*/
1246: #if defined(PETSC_USE_COMPLEX)
1247: #define PetscObjectComposedDataSetScalar(obj, id, data) \
1248: ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1249: #else
1250: #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1251: #endif
1252: /*MC
1253: PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1255: Synopsis:
1256: #include "petsc/private/petscimpl.h"
1257: PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1259: Not Collective
1261: Input Parameters:
1262: + obj - the object from which data is to be retrieved
1263: - id - the identifier for the data
1265: Output Parameters:
1266: + data - the data to be retrieved, a `PetscScalar`
1267: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1269: Level: developer
1271: Note:
1272: The `data` and `flag` variables are inlined, so they are not pointers.
1274: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1275: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1276: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1277: M*/
1278: #if defined(PETSC_USE_COMPLEX)
1279: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1280: ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1281: #else
1282: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1283: #endif
1285: /*MC
1286: PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1288: Synopsis:
1289: #include "petsc/private/petscimpl.h"
1290: PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1292: Not Collective
1294: Input Parameters:
1295: + obj - the object to which data is to be attached
1296: . id - the identifier for the data
1297: - data - the data to be attached, a `PetscScalar` array
1299: Level: developer
1301: Notes:
1302: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1304: The length of the array accessed must be known, it is not available through this API.
1306: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1307: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1308: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1309: M*/
1310: #if defined(PETSC_USE_COMPLEX)
1311: #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1312: ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1313: #else
1314: #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1315: #endif
1316: /*MC
1317: PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1318: attached to an object
1320: Synopsis:
1321: #include "petsc/private/petscimpl.h"
1322: PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1324: Not Collective
1326: Input Parameters:
1327: + obj - the object from which data is to be retrieved
1328: - id - the identifier for the data
1330: Output Parameters:
1331: + data - the data to be retrieved, a `PetscScalar` array
1332: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1334: Level: developer
1336: Notes:
1337: The `data` and `flag` variables are inlined, so they are not pointers.
1339: The length of the array accessed must be known, it is not available through this API.
1341: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1342: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1343: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1344: M*/
1345: #if defined(PETSC_USE_COMPLEX)
1346: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1347: ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1348: #else
1349: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1350: #endif
1352: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1353: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1354: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1355: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1356: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1357: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1358: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1360: PETSC_EXTERN PetscMPIInt Petsc_SharedWD_keyval;
1361: PETSC_EXTERN PetscMPIInt Petsc_SharedTmp_keyval;
1363: struct PetscCommStash {
1364: struct PetscCommStash *next;
1365: MPI_Comm comm;
1366: };
1368: /*
1369: PETSc communicators have this attribute, see
1370: PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1371: */
1372: typedef struct {
1373: PetscMPIInt tag; /* next free tag value */
1374: PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1375: PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1376: PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1377: struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1378: } PetscCommCounter;
1380: typedef enum {
1381: STATE_BEGIN,
1382: STATE_PENDING,
1383: STATE_END
1384: } SRState;
1386: typedef enum {
1387: PETSC_SR_REDUCE_SUM = 0,
1388: PETSC_SR_REDUCE_MAX = 1,
1389: PETSC_SR_REDUCE_MIN = 2
1390: } PetscSRReductionType;
1392: typedef struct {
1393: MPI_Comm comm;
1394: MPI_Request request;
1395: PetscBool mix;
1396: PetscBool async;
1397: PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1398: PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1399: void **invecs; /* for debugging only, vector/memory used with each op */
1400: PetscInt *reducetype; /* is particular value to be summed or maxed? */
1401: struct {
1402: PetscScalar v;
1403: PetscInt i;
1404: } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1405: SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1406: PetscInt maxops; /* total amount of space we have for requests */
1407: PetscInt numopsbegin; /* number of requests that have been queued in */
1408: PetscInt numopsend; /* number of requests that have been gotten by user */
1409: } PetscSplitReduction;
1411: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1412: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1413: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1415: #if defined(PETSC_HAVE_THREADSAFETY)
1416: #if defined(PETSC_HAVE_CONCURRENCYKIT)
1417: #if defined(__cplusplus)
1418: /* CK does not have extern "C" protection in their include files */
1419: extern "C" {
1420: #endif
1421: #include <ck_spinlock.h>
1422: #if defined(__cplusplus)
1423: }
1424: #endif
1425: typedef ck_spinlock_t PetscSpinlock;
1427: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1428: {
1429: ck_spinlock_init(ck_spinlock);
1430: return PETSC_SUCCESS;
1431: }
1432: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1433: {
1434: ck_spinlock_lock(ck_spinlock);
1435: return PETSC_SUCCESS;
1436: }
1437: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1438: {
1439: ck_spinlock_unlock(ck_spinlock);
1440: return PETSC_SUCCESS;
1441: }
1442: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1443: {
1444: return PETSC_SUCCESS;
1445: }
1446: #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1447: #if defined(__cplusplus)
1448: #include <atomic>
1449: #define petsc_atomic_flag std::atomic_flag
1450: #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_relaxed)
1451: #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_relaxed)
1452: #else
1453: #include <stdatomic.h>
1454: #define petsc_atomic_flag atomic_flag
1455: #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_relaxed)
1456: #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_relaxed)
1457: #endif
1459: typedef petsc_atomic_flag PetscSpinlock;
1461: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1462: {
1463: petsc_atomic_flag_clear(spinlock);
1464: return PETSC_SUCCESS;
1465: }
1466: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1467: {
1468: do {
1469: } while (petsc_atomic_flag_test_and_set(spinlock));
1470: return PETSC_SUCCESS;
1471: }
1472: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1473: {
1474: petsc_atomic_flag_clear(spinlock);
1475: return PETSC_SUCCESS;
1476: }
1477: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1478: {
1479: return PETSC_SUCCESS;
1480: }
1481: #undef petsc_atomic_flag_test_and_set
1482: #undef petsc_atomic_flag_clear
1483: #undef petsc_atomic_flag
1485: #elif defined(PETSC_HAVE_OPENMP)
1487: #include <omp.h>
1488: typedef omp_lock_t PetscSpinlock;
1490: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1491: {
1492: omp_init_lock(omp_lock);
1493: return PETSC_SUCCESS;
1494: }
1495: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1496: {
1497: omp_set_lock(omp_lock);
1498: return PETSC_SUCCESS;
1499: }
1500: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1501: {
1502: omp_unset_lock(omp_lock);
1503: return PETSC_SUCCESS;
1504: }
1505: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1506: {
1507: omp_destroy_lock(omp_lock);
1508: return PETSC_SUCCESS;
1509: }
1510: #else
1511: #if defined(__cplusplus)
1512: #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1513: #else
1514: #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1515: #endif
1516: #endif
1518: #else
1519: typedef int PetscSpinlock;
1520: #define PetscSpinlockCreate(a) PETSC_SUCCESS
1521: #define PetscSpinlockLock(a) PETSC_SUCCESS
1522: #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1523: #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1524: #endif
1526: #if defined(PETSC_HAVE_THREADSAFETY)
1527: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1528: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1529: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1530: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1531: #endif
1533: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1534: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1535: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1536: PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1537: PETSC_EXTERN PetscBool PetscPrintFunctionList;
1539: #if defined(PETSC_HAVE_ADIOS)
1540: PETSC_EXTERN int64_t Petsc_adios_group;
1541: #endif
1543: #if defined(PETSC_HAVE_KOKKOS)
1544: PETSC_INTERN PetscBool PetscBeganKokkos;
1545: PETSC_EXTERN PetscBool PetscKokkosInitialized;
1546: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1547: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1548: #endif
1550: #if defined(PETSC_HAVE_OPENMP)
1551: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1552: #endif
1554: struct _n_PetscObjectList {
1555: char name[256];
1556: PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1557: PetscObject obj;
1558: PetscObjectList next;
1559: };