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 PetscStackReset(void);
18: PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
19: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
20: #else
21: #define PetscStackSetCheck(check) PETSC_SUCCESS
22: #define PetscStackReset() PETSC_SUCCESS
23: #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
24: #define PetscStackPrint(stack, file) PETSC_SUCCESS
25: #endif
27: /* These are used internally by PETSc ASCII IO routines*/
28: #include <stdarg.h>
29: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);
31: /*
32: All major PETSc data structures have a common core; this is defined
33: below by PETSCHEADER.
35: PetscHeaderCreate() should be used whenever creating a PETSc structure.
36: */
38: /*
39: PetscOps: structure of core operations that all PETSc objects support.
41: view() - Is the routine for viewing the entire PETSc object; for
42: example, MatView() is the general matrix viewing routine.
43: This is used by PetscObjectView((PetscObject)obj) to allow
44: viewing any PETSc object.
45: destroy() - Is the routine for destroying the entire PETSc object;
46: for example,MatDestroy() is the general matrix
47: destruction routine.
48: This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
49: destroying any PETSc object.
50: */
52: typedef struct {
53: PetscErrorCode (*view)(PetscObject, PetscViewer);
54: PetscErrorCode (*destroy)(PetscObject *);
55: } PetscOps;
57: typedef enum {
58: PETSC_FORTRAN_CALLBACK_CLASS,
59: PETSC_FORTRAN_CALLBACK_SUBTYPE,
60: PETSC_FORTRAN_CALLBACK_MAXTYPE
61: } PetscFortranCallbackType;
62: typedef size_t PetscFortranCallbackId;
63: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
64: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
65: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);
67: /*S
68: PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback
70: Level: advanced
72: Notes:
73: `PetscFortranCallbackFn *` plays the role of `void *` for function pointers in the PETSc Fortran API.
75: .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
76: S*/
77: PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);
79: typedef struct {
80: PetscFortranCallbackFn *func;
81: void *ctx;
82: } PetscFortranCallback;
84: /*
85: All PETSc objects begin with the fields defined in PETSCHEADER.
86: The PetscObject is a way of examining these fields regardless of
87: the specific object. In C++ this could be a base abstract class
88: from which all objects are derived.
89: */
90: #define PETSC_MAX_OPTIONS_HANDLER 5
91: typedef struct _p_PetscObject {
92: PetscOps bops[1];
93: PetscClassId classid;
94: MPI_Comm comm;
95: PetscObjectId id; /* this is used to compare object for identity that may no longer exist since memory addresses get recycled for new objects */
96: PetscInt refct;
97: PetscErrorCode (*non_cyclic_references)(PetscObject, PetscInt *);
98: PetscInt64 cidx;
99: PetscMPIInt tag;
100: PetscFunctionList qlist;
101: PetscObjectList olist;
102: char *class_name; /* for example, "Vec" */
103: char *description;
104: char *mansec;
105: char *type_name; /* this is the subclass, for example VECSEQ which equals "seq" */
106: char *name;
107: char *prefix;
108: PetscInt tablevel;
109: void *cpp;
110: PetscObjectState state;
111: PetscInt int_idmax, intstar_idmax;
112: PetscObjectState *intcomposedstate, *intstarcomposedstate;
113: PetscInt *intcomposeddata, **intstarcomposeddata;
114: PetscInt real_idmax, realstar_idmax;
115: PetscObjectState *realcomposedstate, *realstarcomposedstate;
116: PetscReal *realcomposeddata, **realstarcomposeddata;
117: #if PetscDefined(USE_COMPLEX)
118: PetscInt scalar_idmax, scalarstar_idmax;
119: PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
120: PetscScalar *scalarcomposeddata, **scalarstarcomposeddata;
121: #endif
122: PetscFortranCallbackFn **fortran_func_pointers; /* used by Fortran interface functions to stash user provided Fortran functions */
123: PetscFortranCallbackId num_fortran_func_pointers; /* number of Fortran function pointers allocated */
124: PetscFortranCallback *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
125: PetscFortranCallbackId num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
126: void *python_context;
127: PetscErrorCode (*python_destroy)(void *);
129: PetscInt noptionhandler;
130: PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems, void *);
131: PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, void *);
132: void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
133: #if defined(PETSC_HAVE_SAWS)
134: PetscBool amsmem; /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
135: PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
136: #endif
137: PetscOptions options; /* options database used, NULL means default */
138: PetscBool optionsprinted;
139: PetscBool donotPetscObjectPrintClassNamePrefixType;
140: } _p_PetscObject;
142: #define PETSCHEADER(ObjectOps) \
143: _p_PetscObject hdr; \
144: ObjectOps ops[1]
146: #define PETSCFREEDHEADER -1
148: /*S
149: PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`
151: Calling Sequence:
152: . obj - the `PetscObject` to destroy
154: Level: beginner
156: Note:
157: The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.
159: .seealso: `PetscObject`, `PetscObjectDestroy()`
160: S*/
161: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);
163: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;
165: /*S
166: PetscObjectViewFn - A prototype of a function that can view a `PetscObject`
168: Calling Sequence:
169: + obj - the `PetscObject` to view
170: - v - the viewer
172: Level: beginner
174: Note:
175: The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.
177: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
178: S*/
179: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);
181: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;
183: /*MC
184: PetscHeaderCreate - Creates a raw PETSc object of a particular class
186: Synopsis:
187: #include <petsc/private/petscimpl.h>
188: PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn * destroy, PetscObjectViewFn * view)
190: Collective
192: Input Parameters:
193: + classid - The classid associated with this object (for example `VEC_CLASSID`)
194: . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
195: . descr - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
196: . mansec - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`
197: . comm - The MPI Communicator
198: . destroy - The destroy routine for this object (for example `VecDestroy()`)
199: - view - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`
201: Output Parameter:
202: . h - The newly created `PetscObject`
204: Level: developer
206: Notes:
207: Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
208: C/C++ structure which satisfies all of the following\:
210: 1. The first member of the structure must be a `_p_PetscObject`.
211: 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
212: - Has no virtual functions or base classes.
213: - Has only standard layout non-static members (if any).
214: - Has only standard layout base classes (if any).
216: See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
217: information.
219: Example Usage:
220: Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
221: objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
222: `<OBJECT_TYPE>View()`.
223: .vb
224: Vec v;
226: PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
227: .ve
229: It is possible to create custom `PetscObject`s, note however that they must abide by the
230: restrictions set forth above.
231: .vb
232: // OK, first member of C structure is _p_PetscObject
233: struct MyCPetscObject_s
234: {
235: _p_PetscObject header;
236: int some_data;
237: };
238: typedef struct *MyCPetscObject_s MyCPetscObject;
240: PetscErrorCode MyObjectDestroy(MyObject *);
241: PetscErrorCode MyObjectView(MyObject);
243: MyCPetscObject obj;
245: // assume MY_PETSC_CLASSID is already registered
246: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
248: // OK, only destroy function must be given, all others may be NULL
249: PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
251: // ERROR must be a single-level pointer
252: PetscHeaderCreate(&obj, ...);
253: .ve
255: Illustrating proper construction from C++\:
256: .vb
257: // ERROR, class is not standard layout, first member must be publicly accessible
258: class BadCppPetscObject
259: {
260: _p_PetscObject header;
261: };
263: // ERROR, class is not standard layout, has a virtual function and virtual inheritance
264: class BadCppPetscObject2 : virtual BaseClass
265: {
266: public:
267: _p_PetscObject header;
269: virtual void foo();
270: };
272: // ERROR, class is not standard layout! Has non-standard layout member
273: class BadCppPetscObject2
274: {
275: public:
276: _p_PetscObject header;
277: BadCppPetscObject non_standard_layout;
278: };
280: // OK, class is standard layout!
281: class GoodCppPetscObject;
282: using MyCppObject = GoodCppPetscObject *;
284: // OK, non-virtual inheritance of other standard layout class does not affect layout
285: class GoodCppPetscObject : StandardLayoutClass
286: {
287: public:
288: // OK, non standard layout member is static, does not affect layout
289: static BadCppPetscObject non_standard_layout;
291: // OK, first non-static member is _p_PetscObject
292: _p_PetscObject header;
294: // OK, non-virtual member functions do not affect class layout
295: void foo();
297: // OK, may use "member" functions for destroy and view so long as they are static
298: static PetscErrorCode destroy(MyCppObject *);
299: static PetscErrorCode view(MyCppObject);
300: };
302: // OK, usage via pointer
303: MyObject obj;
305: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
306: .ve
308: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
309: M*/
310: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
311: PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))
313: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
314: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
315: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
316: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
317: PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
319: /*MC
320: PetscHeaderDestroy - Final step in destroying a `PetscObject`
322: Synopsis:
323: #include <petsc/private/petscimpl.h>
324: PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
326: Collective
328: Input Parameter:
329: . h - A pointer to the header created with `PetscHeaderCreate()`
331: Level: developer
333: Notes:
334: `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
336: Example Usage:
337: .vb
338: PetscObject obj;
340: PetscHeaderCreate(obj, ...);
341: // use obj...
343: // note pointer to obj is used
344: PetscHeaderDestroy(&obj);
345: .ve
347: Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
348: deallocates the memory for the structure itself\:
349: .vb
350: typedef struct MyPetscObject_s *MyPetscObject;
351: struct MyPetscObject_s
352: {
353: _p_PetscObject hdr;
354: PetscInt *foo;
355: PetscScalar *bar;
356: };
358: // assume obj is created/initialized elsewhere...
359: MyPetscObject obj;
361: // OK, should dispose of all dynamically allocated resources before calling
362: // PetscHeaderDestroy()
363: PetscFree(obj->foo);
365: // OK, dispose of obj
366: PetscHeaderDestroy(&obj);
368: // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
369: // obj->bar is potentially leaked!
370: PetscFree(obj->bar);
371: .ve
373: .seealso: `PetscObject`, `PetscHeaderCreate()`
374: M*/
375: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)
377: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject, PetscBool);
378: PETSC_INTERN PetscErrorCode PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
379: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
380: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
381: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, void *ctx);
382: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);
384: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
385: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
386: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
388: /* Code shared between C and Fortran */
389: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscInt);
391: #if PetscDefined(HAVE_SETJMP_H)
392: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
393: #else
394: #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
395: #endif
397: #if defined(PETSC_CLANG_STATIC_ANALYZER)
398: template <typename T>
400: template <typename T>
402: template <typename T>
404: template <typename T>
405: extern void PetscAssertPointer(T, int)
406: {
407: }
408: template <typename T>
410: #else
411: // Macros to test if a PETSc object is valid and if pointers are valid
412: #if PetscDefined(USE_DEBUG)
413: /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
415: do { \
416: PetscBool _7_same; \
418: PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
419: 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); \
420: } while (0)
422: #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
423: do { \
424: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
425: PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
426: } while (0)
429: do { \
430: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
431: if (((PetscObject)(h))->classid != ck) { \
432: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
433: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
434: } \
435: } while (0)
438: do { \
439: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
440: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
441: 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); \
442: } while (0)
444: #if defined(__cplusplus)
445: #include <type_traits> // std::decay
447: namespace Petsc
448: {
450: namespace util
451: {
453: template <typename T>
454: struct PetscAssertPointerImpl {
455: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
456: PETSC_NODISCARD static constexpr const char *string() noexcept { return "memory"; }
457: };
459: #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
460: template <> \
461: struct PetscAssertPointerImpl<T *> { \
462: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
463: PETSC_NODISCARD static constexpr const char *string() noexcept { return PetscStringize(T); } \
464: }; \
465: template <> \
466: struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
467: template <> \
468: struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
469: template <> \
470: struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
472: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
473: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
474: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
475: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
476: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
477: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
478: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
479: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
480: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
481: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
482: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
483: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
484: #if defined(PETSC_HAVE_COMPLEX)
485: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
486: #endif
488: #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
490: } // namespace util
492: } // namespace Petsc
494: #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
495: #define PetscAssertPointer_String(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
497: #elif PETSC_C_VERSION >= 11
498: #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
500: #if PetscDefined(HAVE_COMPLEX)
501: #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
502: #else
503: #define PETSC_GENERIC_CV_COMPLEX(result)
504: #endif
506: #define PetscAssertPointer_PetscDataType(h) \
507: _Generic((h), \
508: default: PETSC_CHAR, \
509: PETSC_GENERIC_CV( char, PETSC_CHAR), \
510: PETSC_GENERIC_CV( signed char, PETSC_CHAR), \
511: PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
512: PETSC_GENERIC_CV( short, PETSC_SHORT), \
513: PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
514: PETSC_GENERIC_CV( float, PETSC_FLOAT), \
515: PETSC_GENERIC_CV( double, PETSC_DOUBLE), \
516: PETSC_GENERIC_CV( int32_t, PETSC_INT32), \
517: PETSC_GENERIC_CV( uint32_t, PETSC_INT32), \
518: PETSC_GENERIC_CV( int64_t, PETSC_INT64), \
519: PETSC_GENERIC_CV( uint64_t, PETSC_INT64), \
520: PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
522: #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
524: #if PetscDefined(HAVE_COMPLEX)
525: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
526: #else
527: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
528: #endif
530: #define PetscAssertPointer_String(h) \
531: _Generic((h), \
532: default: "memory", \
533: PETSC_GENERIC_CV_STRINGIZE(char), \
534: PETSC_GENERIC_CV_STRINGIZE(signed char), \
535: PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
536: PETSC_GENERIC_CV_STRINGIZE(short), \
537: PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
538: PETSC_GENERIC_CV_STRINGIZE(float), \
539: PETSC_GENERIC_CV_STRINGIZE(double), \
540: PETSC_GENERIC_CV_STRINGIZE(int32_t), \
541: PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
542: PETSC_GENERIC_CV_STRINGIZE(int64_t), \
543: PETSC_GENERIC_CV_STRINGIZE(uint64_t), \
544: PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
545: #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
546: #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
547: #define PetscAssertPointer_String(h) "memory"
548: #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
549: #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
551: #else // PetscDefined(USE_DEBUG)
553: do { \
554: (void)(h); \
555: } while (0)
557: do { \
558: (void)(h); \
559: } while (0)
561: do { \
562: (void)(h); \
563: } while (0)
564: #define PetscAssertPointer(h, arg) \
565: do { \
566: (void)(h); \
567: } while (0)
569: do { \
570: (void)(h); \
571: } while (0)
572: #endif // PetscDefined(USE_DEBUG)
573: #endif // PETSC_CLANG_STATIC_ANALYZER
584: #define PetscSorted(n, idx, sorted) \
585: do { \
586: (sorted) = PETSC_TRUE; \
587: for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
588: if ((idx)[_i_] < (idx)[_i_ - 1]) { \
589: (sorted) = PETSC_FALSE; \
590: break; \
591: } \
592: } \
593: } while (0)
595: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
596: #if !defined(PETSC_USE_DEBUG)
598: #define PetscCheckSameType(a, arga, b, argb) \
599: do { \
600: (void)(a); \
601: (void)(b); \
602: } while (0)
603: #define PetscCheckTypeName(a, type) \
604: do { \
605: (void)(a); \
606: } while (0)
607: #define PetscCheckTypeNames(a, type1, type2) \
608: do { \
609: (void)(a); \
610: } while (0)
612: do { \
613: (void)(a); \
614: } while (0)
615: #define PetscCheckSameComm(a, arga, b, argb) \
616: do { \
617: (void)(a); \
618: (void)(b); \
619: } while (0)
620: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
621: do { \
622: (void)(a); \
623: (void)(b); \
624: } while (0)
626: do { \
627: (void)(a); \
628: (void)(b); \
629: } while (0)
631: do { \
632: (void)(a); \
633: (void)(b); \
634: } while (0)
636: do { \
637: (void)(a); \
638: (void)(b); \
639: } while (0)
641: do { \
642: (void)(a); \
643: (void)(b); \
644: } while (0)
646: do { \
647: (void)(a); \
648: (void)(b); \
649: } while (0)
651: do { \
652: (void)(a); \
653: (void)(b); \
654: } while (0)
656: do { \
657: (void)(a); \
658: (void)(b); \
659: } while (0)
661: do { \
662: (void)(a); \
663: (void)(b); \
664: } while (0)
665: #define PetscCheckSorted(n, idx) \
666: do { \
667: (void)(n); \
668: (void)(idx); \
669: } while (0)
671: #else
673: /*
674: This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
675: member associated with the string type_name that can be quickly compared.
677: **Do not swap this macro to compare string type_name!**
679: This macro is used incorrectly in the code. Many places that do not need identity of the
680: types incorrectly call this check and would need to be fixed if this macro is enabled.
681: */
682: #if 0
683: #define PetscCheckSameType(a, arga, b, argb) \
684: do { \
685: PetscBool pcst_type_eq_ = PETSC_TRUE; \
686: PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
687: 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); \
688: } while (0)
689: #else
690: #define PetscCheckSameType(a, arga, b, argb) \
691: do { \
692: (void)(a); \
693: (void)(b); \
694: } while (0)
695: #endif
697: /*
698: Check type_name
699: */
700: #define PetscCheckTypeName(a, type) \
701: do { \
702: PetscBool _7_match; \
703: PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
704: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
705: } while (0)
707: #define PetscCheckTypeNames(a, type1, type2) \
708: do { \
709: PetscBool _7_match; \
710: PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
711: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
712: } while (0)
714: /*
715: Use this macro to check if the type is set
716: */
719: /*
720: Sometimes object must live on same communicator to inter-operate
721: */
722: #define PetscCheckSameComm(a, arga, b, argb) \
723: do { \
724: PetscMPIInt _7_flag; \
725: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
726: 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); \
727: } while (0)
729: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
730: do { \
731: PetscCheckSameType(a, arga, b, argb); \
732: PetscCheckSameComm(a, arga, b, argb); \
733: } while (0)
736: do { \
737: PetscScalar b0 = (b); \
738: PetscReal b1[5]; \
739: if (PetscIsNanScalar(b0)) { \
740: b1[4] = 1; \
741: } else { \
742: b1[4] = 0; \
743: }; \
744: b1[0] = -PetscRealPart(b0); \
745: b1[1] = PetscRealPart(b0); \
746: b1[2] = -PetscImaginaryPart(b0); \
747: b1[3] = PetscImaginaryPart(b0); \
748: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
749: PetscCheck(b1[4] > 0 || (PetscEqualReal(-b1[0], b1[1]) && PetscEqualReal(-b1[2], b1[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
750: } while (0)
753: do { \
754: PetscReal b0 = (b), b1[3]; \
755: if (PetscIsNanReal(b0)) { \
756: b1[2] = 1; \
757: } else { \
758: b1[2] = 0; \
759: }; \
760: b1[0] = -b0; \
761: b1[1] = b0; \
762: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
763: PetscCheck(b1[2] > 0 || PetscEqualReal(-b1[0], b1[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
764: } while (0)
767: do { \
768: PetscInt b0 = (b), b1[2]; \
769: b1[0] = -b0; \
770: b1[1] = b0; \
771: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
772: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
773: } while (0)
776: do { \
777: PetscInt b1[2]; \
778: b1[0] = -b; \
779: b1[1] = b; \
780: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
781: PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
782: } while (0)
785: do { \
786: PetscCount b0 = (b), b1[2]; \
787: b1[0] = -b0; \
788: b1[1] = b0; \
789: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
790: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
791: } while (0)
794: do { \
795: PetscMPIInt b0 = (b), b1[2]; \
796: b1[0] = -b0; \
797: b1[1] = b0; \
798: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
799: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
800: } while (0)
803: do { \
804: PetscBool b0 = (PetscBool)(b), b1[2]; \
805: b1[0] = !b0; \
806: b1[1] = b0; \
807: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
808: PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
809: } while (0)
812: do { \
813: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
814: b1[0] = -b0; \
815: b1[1] = b0; \
816: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
817: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
818: } while (0)
820: #define PetscCheckSorted(n, idx) \
821: do { \
822: PetscBool _1_flg; \
823: PetscSorted(n, idx, _1_flg); \
824: PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
825: } while (0)
827: #endif
828: #else /* PETSC_CLANG_STATIC_ANALYZER */
829: template <typename Ta, typename Tb>
830: extern void PetscCheckSameType(Ta, int, Tb, int);
831: template <typename Ta, typename Tb>
832: extern void PetscCheckTypeName(Ta, Tb);
833: template <typename Ta, typename Tb, typename Tc>
834: extern void PetscCheckTypeNames(Ta, Tb, Tc);
835: template <typename T>
837: template <typename Ta, typename Tb>
838: extern void PetscCheckSameComm(Ta, int, Tb, int);
839: template <typename Ta, typename Tb>
840: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
841: template <typename Ta, typename Tb>
843: template <typename Ta, typename Tb>
845: template <typename Ta, typename Tb>
847: template <typename Ta, typename Tb>
849: template <typename Ta, typename Tb>
851: template <typename Ta, typename Tb>
853: template <typename Ta, typename Tb>
855: template <typename T>
856: extern void PetscCheckSorted(PetscInt, T);
857: #endif /* PETSC_CLANG_STATIC_ANALYZER */
859: /*MC
860: PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
862: Synopsis:
863: #include "petsc/private/petscimpl.h"
864: PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
866: Input Parameters:
867: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
868: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
869: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
870: - args - the arguments for the method, for example, (ksp,restart))
872: Level: developer
874: Notes:
875: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
877: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
878: in the object.
880: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
881: M*/
882: #define PetscTryMethod(obj, A, B, C) \
883: do { \
884: PetscErrorCode(*_7_f) B; \
885: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
886: if (_7_f) PetscCall((*_7_f)C); \
887: } while (0)
889: /*MC
890: PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
892: Synopsis:
893: #include "petsc/private/petscimpl.h"
894: PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
896: Input Parameters:
897: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
898: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
899: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
900: - args - the arguments for the method, for example, (ksp,restart))
902: Level: developer
904: Notes:
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 `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
908: in the object.
910: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
911: M*/
912: #define PetscUseMethod(obj, A, B, C) \
913: do { \
914: PetscErrorCode(*_7_f) B; \
915: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
916: PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
917: PetscCall((*_7_f)C); \
918: } while (0)
920: /*
921: Use Microsoft traditional preprocessor.
923: The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
924: sets _MSVC_TRADITIONAL to zero so this code path is not used.
926: It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
928: These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
930: PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
931: */
932: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
934: #define PetscUseTypeMethod(obj, OP, ...) \
935: do { \
936: PetscErrorCode ierr_p_; \
937: PetscStackUpdateLine; \
938: 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); \
939: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
940: PetscCall(ierr_p_); \
941: } while (0)
943: #define PetscTryTypeMethod(obj, OP, ...) \
944: do { \
945: if ((obj)->ops->OP) { \
946: PetscErrorCode ierr_p_; \
947: PetscStackUpdateLine; \
948: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
949: PetscCall(ierr_p_); \
950: } \
951: } while (0)
953: #else
955: /*MC
956: 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
958: Synopsis:
959: #include "petsc/private/petscimpl.h"
960: PetscUseTypeMethod(obj, method, other_args)
962: Input Parameters:
963: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
964: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
965: - other_args - the other arguments for the method, `obj` is the first argument
967: Level: developer
969: Note:
970: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
972: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
974: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
975: M*/
976: #define PetscUseTypeMethod(obj, ...) \
977: do { \
978: PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
979: PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
980: PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
981: } while (0)
983: /*MC
984: 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
986: Synopsis:
987: #include "petsc/private/petscimpl.h"
988: PetscTryTypeMethod(obj, method, other_args)
990: Input Parameters:
991: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
992: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
993: - other_args - the other arguments for the method, `obj` is the first argument
995: Level: developer
997: Note:
998: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
1000: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
1002: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1003: M*/
1004: #define PetscTryTypeMethod(obj, ...) \
1005: do { \
1006: if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1007: } while (0)
1009: #endif
1011: /*MC
1012: PetscObjectStateIncrease - Increases the state of any `PetscObject`
1014: Synopsis:
1015: #include "petsc/private/petscimpl.h"
1016: PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
1018: Logically Collective
1020: Input Parameter:
1021: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1022: cast with a (PetscObject), for example,
1023: `PetscObjectStateIncrease`((`PetscObject`)mat);
1025: Level: developer
1027: Notes:
1028: Object state is a 64-bit integer which gets increased every time
1029: the object is changed internally. By saving and later querying the object state
1030: one can determine whether information about the object is still current.
1031: Currently, state is maintained for `Vec` and `Mat` objects.
1033: This routine is mostly for internal use by PETSc; a developer need only
1034: call it after explicit access to an object's internals. Routines such
1035: as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
1036: precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
1038: Routines such as `VecNorm()` can bypass the computation if the norm has already been computed and the vector's state has not changed.
1040: This routine is logically collective because state equality comparison needs to be possible without communication.
1042: `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
1044: .seealso: `PetscObjectStateGet()`, `PetscObject`
1045: M*/
1046: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))
1048: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1049: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1050: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1051: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1052: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1053: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1054: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1055: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1056: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1057: PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
1059: /*MC
1060: PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
1062: Synopsis:
1063: #include "petsc/private/petscimpl.h"
1064: PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1066: Not Collective
1068: Input Parameters:
1069: + obj - the object to which data is to be attached
1070: . id - the identifier for the data
1071: - data - the data to be attached, a `PetscInt`
1073: Level: developer
1075: Notes:
1076: The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1078: This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1079: attached with `PetscObjectCompose()`
1081: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1082: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1083: `PetscObjectCompose()`, `PetscObjectQuery()`
1084: M*/
1085: #define PetscObjectComposedDataSetInt(obj, id, data) \
1086: ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1088: /*MC
1089: PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1091: Synopsis:
1092: #include "petsc/private/petscimpl.h"
1093: PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1095: Not Collective
1097: Input Parameters:
1098: + obj - the object from which data is to be retrieved
1099: - id - the identifier for the data
1101: Output Parameters:
1102: + data - the data to be retrieved, a `PetscInt`
1103: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1105: Level: developer
1107: Notes:
1108: The `data` and `flag` variables are inlined, so they are not pointers.
1110: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1111: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1112: `PetscObjectCompose()`, `PetscObjectQuery()`
1113: M*/
1114: #define PetscObjectComposedDataGetInt(obj, id, data, flag) ((PetscErrorCode)(((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1116: /*MC
1117: PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1119: Synopsis:
1120: #include "petsc/private/petscimpl.h"
1121: PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1123: Not Collective
1125: Input Parameters:
1126: + obj - the object to which data is to be attached
1127: . id - the identifier for the data
1128: - data - the data to be attached, a `PetscInt` array
1130: Level: developer
1132: Notes:
1133: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1135: The length of the array accessed must be known, it is not available through this API.
1137: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1138: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1139: `PetscObjectCompose()`, `PetscObjectQuery()`
1140: M*/
1141: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1142: ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1144: /*MC
1145: PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1147: Synopsis:
1148: #include "petsc/private/petscimpl.h"
1149: PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1151: Not Collective
1153: Input Parameters:
1154: + obj - the object from which data is to be retrieved
1155: - id - the identifier for the data
1157: Output Parameters:
1158: + data - the data to be retrieved, a `PetscInt` array
1159: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1161: Level: developer
1163: Notes:
1164: The `data` and `flag` variables are inlined, so they are not pointers.
1166: The length of the array accessed must be known, it is not available through this API.
1168: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1169: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1170: `PetscObjectCompose()`, `PetscObjectQuery()`
1171: M*/
1172: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1173: ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1175: /*MC
1176: PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1178: Synopsis:
1179: #include "petsc/private/petscimpl.h"
1180: PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1182: Not Collective
1184: Input Parameters:
1185: + obj - the object to which data is to be attached
1186: . id - the identifier for the data
1187: - data - the data to be attached, a `PetscReal`
1189: Level: developer
1191: Note:
1192: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1194: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1195: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1196: `PetscObjectCompose()`, `PetscObjectQuery()`
1197: M*/
1198: #define PetscObjectComposedDataSetReal(obj, id, data) \
1199: ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1201: /*MC
1202: PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1204: Synopsis:
1205: #include "petsc/private/petscimpl.h"
1206: PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1208: Not Collective
1210: Input Parameters:
1211: + obj - the object from which data is to be retrieved
1212: - id - the identifier for the data
1214: Output Parameters:
1215: + data - the data to be retrieved, a `PetscReal`
1216: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1218: Level: developer
1220: Note:
1221: The `data` and `flag` variables are inlined, so they are not pointers.
1223: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1224: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1225: `PetscObjectCompose()`, `PetscObjectQuery()`
1226: M*/
1227: #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))
1229: /*MC
1230: PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1232: Synopsis:
1233: #include "petsc/private/petscimpl.h"
1234: PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1236: Not Collective
1238: Input Parameters:
1239: + obj - the object to which data is to be attached
1240: . id - the identifier for the data
1241: - data - the data to be attached
1243: Level: developer
1245: Notes:
1246: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1248: The length of the array accessed must be known, it is not available through this API.
1250: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1251: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1252: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1253: M*/
1254: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1255: ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1257: /*MC
1258: PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1260: Synopsis:
1261: #include "petsc/private/petscimpl.h"
1262: PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1264: Not Collective
1266: Input Parameters:
1267: + obj - the object from which data is to be retrieved
1268: - id - the identifier for the data
1270: Output Parameters:
1271: + data - the data to be retrieved, a `PetscReal` array
1272: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1274: Level: developer
1276: Notes:
1277: The `data` and `flag` variables are inlined, so they are not pointers.
1279: The length of the array accessed must be known, it is not available through this API.
1281: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1282: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1283: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1284: M*/
1285: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1286: ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1288: /*MC
1289: PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1291: Synopsis:
1292: #include "petsc/private/petscimpl.h"
1293: PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1295: Not Collective
1297: Input Parameters:
1298: + obj - the object to which data is to be attached
1299: . id - the identifier for the data
1300: - data - the data to be attached, a `PetscScalar`
1302: Level: developer
1304: Note:
1305: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1307: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1308: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1309: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1310: M*/
1311: #if defined(PETSC_USE_COMPLEX)
1312: #define PetscObjectComposedDataSetScalar(obj, id, data) \
1313: ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1314: #else
1315: #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1316: #endif
1317: /*MC
1318: PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1320: Synopsis:
1321: #include "petsc/private/petscimpl.h"
1322: PetscErrorCode PetscObjectComposedDataGetScalar(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`
1332: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1334: Level: developer
1336: Note:
1337: The `data` and `flag` variables are inlined, so they are not pointers.
1339: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1340: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1341: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1342: M*/
1343: #if defined(PETSC_USE_COMPLEX)
1344: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1345: ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1346: #else
1347: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1348: #endif
1350: /*MC
1351: PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1353: Synopsis:
1354: #include "petsc/private/petscimpl.h"
1355: PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1357: Not Collective
1359: Input Parameters:
1360: + obj - the object to which data is to be attached
1361: . id - the identifier for the data
1362: - data - the data to be attached, a `PetscScalar` array
1364: Level: developer
1366: Notes:
1367: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1369: The length of the array accessed must be known, it is not available through this API.
1371: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1372: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1373: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1374: M*/
1375: #if defined(PETSC_USE_COMPLEX)
1376: #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1377: ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1378: #else
1379: #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1380: #endif
1381: /*MC
1382: PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1383: attached to an object
1385: Synopsis:
1386: #include "petsc/private/petscimpl.h"
1387: PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1389: Not Collective
1391: Input Parameters:
1392: + obj - the object from which data is to be retrieved
1393: - id - the identifier for the data
1395: Output Parameters:
1396: + data - the data to be retrieved, a `PetscScalar` array
1397: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1399: Level: developer
1401: Notes:
1402: The `data` and `flag` variables are inlined, so they are not pointers.
1404: The length of the array accessed must be known, it is not available through this API.
1406: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1407: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1408: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1409: M*/
1410: #if defined(PETSC_USE_COMPLEX)
1411: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1412: ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1413: #else
1414: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1415: #endif
1417: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1418: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1419: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1420: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1421: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1422: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1423: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1425: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1426: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;
1428: struct PetscCommStash {
1429: struct PetscCommStash *next;
1430: MPI_Comm comm;
1431: };
1433: /*
1434: PETSc communicators have this attribute, see
1435: PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1436: */
1437: typedef struct {
1438: PetscMPIInt tag; /* next free tag value */
1439: PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1440: PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1441: PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1442: struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1443: } PetscCommCounter;
1445: typedef enum {
1446: STATE_BEGIN,
1447: STATE_PENDING,
1448: STATE_END
1449: } SRState;
1451: typedef enum {
1452: PETSC_SR_REDUCE_SUM = 0,
1453: PETSC_SR_REDUCE_MAX = 1,
1454: PETSC_SR_REDUCE_MIN = 2
1455: } PetscSRReductionType;
1457: typedef struct {
1458: MPI_Comm comm;
1459: MPI_Request request;
1460: PetscBool mix;
1461: PetscBool async;
1462: PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1463: PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1464: void **invecs; /* for debugging only, vector/memory used with each op */
1465: PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
1466: struct {
1467: PetscScalar v;
1468: PetscInt i;
1469: } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1470: SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1471: PetscMPIInt maxops; /* total amount of space we have for requests */
1472: PetscMPIInt numopsbegin; /* number of requests that have been queued in */
1473: PetscMPIInt numopsend; /* number of requests that have been gotten by user */
1474: } PetscSplitReduction;
1476: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1477: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1478: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1480: #if defined(PETSC_HAVE_THREADSAFETY)
1481: #if defined(PETSC_HAVE_CONCURRENCYKIT)
1482: #if defined(__cplusplus)
1483: /* CK does not have extern "C" protection in their include files */
1484: extern "C" {
1485: #endif
1486: #include <ck_spinlock.h>
1487: #if defined(__cplusplus)
1488: }
1489: #endif
1490: typedef ck_spinlock_t PetscSpinlock;
1492: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1493: {
1494: ck_spinlock_init(ck_spinlock);
1495: return PETSC_SUCCESS;
1496: }
1497: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1498: {
1499: ck_spinlock_lock(ck_spinlock);
1500: return PETSC_SUCCESS;
1501: }
1502: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1503: {
1504: ck_spinlock_unlock(ck_spinlock);
1505: return PETSC_SUCCESS;
1506: }
1507: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1508: {
1509: return PETSC_SUCCESS;
1510: }
1511: #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1512: #if defined(__cplusplus)
1513: // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1514: #include <atomic>
1515: #define petsc_atomic_flag std::atomic_flag
1516: #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1517: #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_release)
1518: #else
1519: #include <stdatomic.h>
1520: #define petsc_atomic_flag atomic_flag
1521: #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1522: #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_release)
1523: #endif
1525: typedef petsc_atomic_flag PetscSpinlock;
1527: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1528: {
1529: petsc_atomic_flag_clear(spinlock);
1530: return PETSC_SUCCESS;
1531: }
1532: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1533: {
1534: do {
1535: } while (petsc_atomic_flag_test_and_set(spinlock));
1536: return PETSC_SUCCESS;
1537: }
1538: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1539: {
1540: petsc_atomic_flag_clear(spinlock);
1541: return PETSC_SUCCESS;
1542: }
1543: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1544: {
1545: return PETSC_SUCCESS;
1546: }
1547: #undef petsc_atomic_flag_test_and_set
1548: #undef petsc_atomic_flag_clear
1549: #undef petsc_atomic_flag
1551: #elif defined(PETSC_HAVE_OPENMP)
1553: #include <omp.h>
1554: typedef omp_lock_t PetscSpinlock;
1556: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1557: {
1558: omp_init_lock(omp_lock);
1559: return PETSC_SUCCESS;
1560: }
1561: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1562: {
1563: omp_set_lock(omp_lock);
1564: return PETSC_SUCCESS;
1565: }
1566: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1567: {
1568: omp_unset_lock(omp_lock);
1569: return PETSC_SUCCESS;
1570: }
1571: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1572: {
1573: omp_destroy_lock(omp_lock);
1574: return PETSC_SUCCESS;
1575: }
1576: #else
1577: #if defined(__cplusplus)
1578: #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1579: #else
1580: #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1581: #endif
1582: #endif
1584: #else
1585: typedef int PetscSpinlock;
1586: #define PetscSpinlockCreate(a) PETSC_SUCCESS
1587: #define PetscSpinlockLock(a) PETSC_SUCCESS
1588: #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1589: #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1590: #endif
1592: #if defined(PETSC_HAVE_THREADSAFETY)
1593: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1594: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1595: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1596: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1597: #endif
1599: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1600: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1601: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1602: PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1603: PETSC_EXTERN PetscBool PetscPrintFunctionList;
1605: #if defined(PETSC_HAVE_ADIOS)
1606: PETSC_EXTERN int64_t Petsc_adios_group;
1607: #endif
1609: #if defined(PETSC_HAVE_KOKKOS)
1610: PETSC_INTERN PetscBool PetscBeganKokkos;
1611: PETSC_EXTERN PetscBool PetscKokkosInitialized;
1612: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1613: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1614: #endif
1616: #if defined(PETSC_HAVE_OPENMP)
1617: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1618: #endif
1620: struct _n_PetscObjectList {
1621: char name[256];
1622: PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1623: PetscObject obj;
1624: PetscObjectList next;
1625: };