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_EXTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
19: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
20: #else
21: #define PetscStackSetCheck(check) PETSC_SUCCESS
22: #define PetscStackReset() PETSC_SUCCESS
23: #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
24: #define PetscStackPrint(stack, file) PETSC_SUCCESS
25: #endif
27: /* These are used internally by PETSc ASCII IO routines*/
28: #include <stdarg.h>
29: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);
31: /*
32: All major PETSc data structures have a common core; this is defined
33: below by PETSCHEADER.
35: PetscHeaderCreate() should be used whenever creating a PETSc structure.
36: */
38: /*
39: PetscOps: structure of core operations that all PETSc objects support.
41: view() - Is the routine for viewing the entire PETSc object; for
42: example, MatView() is the general matrix viewing routine.
43: This is used by PetscObjectView((PetscObject)obj) to allow
44: viewing any PETSc object.
45: destroy() - Is the routine for destroying the entire PETSc object;
46: for example,MatDestroy() is the general matrix
47: destruction routine.
48: This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
49: destroying any PETSc object.
50: */
52: typedef struct {
53: PetscErrorCode (*view)(PetscObject, PetscViewer);
54: PetscErrorCode (*destroy)(PetscObject *);
55: } PetscOps;
57: /*E
58: PetscFortranCallbackType - Indicates if a Fortran callback stored in a `PetscObject` is associated with the class or the current particular type of the object
60: Values:
61: + `PETSC_FORTRAN_CALLBACK_CLASS` - the callback is associated with the class
62: - `PETSC_FORTRAN_CALLBACK_SUBTYPE` - the callback is associated with the current particular subtype
64: Level: developer
66: Developer Note:
67: The two sets of callbacks are stored in different arrays in the `PetscObject` because the `PETSC_FORTRAN_CALLBACK_SUBTYPE` callbacks must
68: be removed whenever the type of the object is changed (because they are not appropriate for other types). The removal is done in
69: `PetscObjectChangeTypeName()`.
71: .seealso: `PetscFortranCallbackFn`, `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`, `PetscObjectChangeTypeName()`
72: E*/
73: typedef enum {
74: PETSC_FORTRAN_CALLBACK_CLASS,
75: PETSC_FORTRAN_CALLBACK_SUBTYPE,
76: PETSC_FORTRAN_CALLBACK_MAXTYPE
77: } PetscFortranCallbackType;
79: typedef size_t PetscFortranCallbackId;
80: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
81: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
82: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);
84: /*S
85: PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback
87: Level: advanced
89: Notes:
90: `PetscFortranCallbackFn *` plays the role of `void *` for function pointers in the PETSc Fortran API.
92: .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
93: S*/
94: PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);
96: typedef struct {
97: PetscFortranCallbackFn *func;
98: void *ctx;
99: } PetscFortranCallback;
101: /*
102: All PETSc objects begin with the fields defined in PETSCHEADER.
103: The PetscObject is a way of examining these fields regardless of
104: the specific object. In C++ this could be a base abstract class
105: from which all objects are derived.
106: */
107: #define PETSC_MAX_OPTIONS_HANDLER 5
108: typedef struct _p_PetscObject {
109: PetscOps bops[1];
110: PetscClassId classid;
111: MPI_Comm comm;
112: PetscObjectId id; /* this is used to compare object for identity that may no longer exist since memory addresses get recycled for new objects */
113: PetscInt refct;
114: PetscErrorCode (*non_cyclic_references)(PetscObject, PetscInt *);
115: PetscInt64 cidx;
116: PetscMPIInt tag;
117: PetscFunctionList qlist;
118: PetscObjectList olist;
119: char *class_name; /* for example, "Vec" */
120: char *description;
121: char *mansec;
122: char *type_name; /* this is the subclass, for example VECSEQ which equals "seq" */
123: char *name;
124: char *prefix;
125: PetscInt tablevel;
126: void *cpp;
127: PetscObjectState state;
128: PetscInt int_idmax, intstar_idmax;
129: PetscObjectState *intcomposedstate, *intstarcomposedstate;
130: PetscInt *intcomposeddata, **intstarcomposeddata;
131: PetscInt real_idmax, realstar_idmax;
132: PetscObjectState *realcomposedstate, *realstarcomposedstate;
133: PetscReal *realcomposeddata, **realstarcomposeddata;
134: #if PetscDefined(USE_COMPLEX)
135: PetscInt scalar_idmax, scalarstar_idmax;
136: PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
137: PetscScalar *scalarcomposeddata, **scalarstarcomposeddata;
138: #endif
139: PetscFortranCallbackFn **fortran_func_pointers; /* used by Fortran interface functions to stash user provided Fortran functions */
140: PetscFortranCallbackId num_fortran_func_pointers; /* number of Fortran function pointers allocated */
141: PetscFortranCallback *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
142: PetscFortranCallbackId num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
143: void *python_context;
144: PetscErrorCode (*python_destroy)(void *);
146: PetscInt noptionhandler;
147: PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems, PetscCtx);
148: PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscCtxRt);
149: void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
150: #if defined(PETSC_HAVE_SAWS)
151: PetscBool amsmem; /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
152: PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
153: #endif
154: PetscOptions options; /* options database used, NULL means default */
155: PetscBool optionsprinted;
156: PetscBool donotPetscObjectPrintClassNamePrefixType;
157: } _p_PetscObject;
159: #define PETSCHEADER(ObjectOps) \
160: _p_PetscObject hdr; \
161: ObjectOps ops[1]
163: #define PETSCFREEDHEADER -1
165: /*S
166: PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`
168: Calling Sequence:
169: . obj - the `PetscObject` to destroy
171: Level: beginner
173: Note:
174: The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.
176: .seealso: `PetscObject`, `PetscObjectDestroy()`
177: S*/
178: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);
180: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;
182: /*S
183: PetscObjectViewFn - A prototype of a function that can view a `PetscObject`
185: Calling Sequence:
186: + obj - the `PetscObject` to view
187: - v - the viewer
189: Level: beginner
191: Note:
192: The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.
194: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
195: S*/
196: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);
198: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;
200: /*MC
201: PetscHeaderCreate - Creates a raw PETSc object of a particular class
203: Synopsis:
204: #include <petsc/private/petscimpl.h>
205: PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn * destroy, PetscObjectViewFn * view)
207: Collective
209: Input Parameters:
210: + classid - The classid associated with this object (for example `VEC_CLASSID`)
211: . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
212: . descr - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
213: . mansec - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`
214: . comm - The MPI Communicator
215: . destroy - The destroy routine for this object (for example `VecDestroy()`)
216: - view - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`
218: Output Parameter:
219: . h - The newly created `PetscObject`
221: Level: developer
223: Notes:
224: Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
225: C/C++ structure which satisfies all of the following\:
227: 1. The first member of the structure must be a `_p_PetscObject`.
228: 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
229: - Has no virtual functions or base classes.
230: - Has only standard layout non-static members (if any).
231: - Has only standard layout base classes (if any).
233: See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
234: information.
236: Example Usage:
237: Existing `PetscObject`s may be easily created as shown. An object of type `Name` has
238: `destroy` and `view` functions named `NameDestroy()` and `NameView()`.
239: .vb
240: Vec v;
242: PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
243: .ve
245: It is possible to create custom `PetscObject`s, note however that they must abide by the
246: restrictions set forth above.
247: .vb
248: // OK, first member of C structure is _p_PetscObject
249: struct MyCPetscObject_s
250: {
251: _p_PetscObject header;
252: int some_data;
253: };
254: typedef struct *MyCPetscObject_s MyCPetscObject;
256: PetscErrorCode MyObjectDestroy(MyObject *);
257: PetscErrorCode MyObjectView(MyObject);
259: MyCPetscObject obj;
261: // assume MY_PETSC_CLASSID is already registered
262: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
264: // OK, only destroy function must be given, all others may be NULL
265: PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
267: // ERROR must be a single-level pointer
268: PetscHeaderCreate(&obj, ...);
269: .ve
271: Illustrating proper construction from C++\:
272: .vb
273: // ERROR, class is not standard layout, first member must be publicly accessible
274: class BadCppPetscObject
275: {
276: _p_PetscObject header;
277: };
279: // ERROR, class is not standard layout, has a virtual function and virtual inheritance
280: class BadCppPetscObject2 : virtual BaseClass
281: {
282: public:
283: _p_PetscObject header;
285: virtual void foo();
286: };
288: // ERROR, class is not standard layout! Has non-standard layout member
289: class BadCppPetscObject2
290: {
291: public:
292: _p_PetscObject header;
293: BadCppPetscObject non_standard_layout;
294: };
296: // OK, class is standard layout!
297: class GoodCppPetscObject;
298: using MyCppObject = GoodCppPetscObject *;
300: // OK, non-virtual inheritance of other standard layout class does not affect layout
301: class GoodCppPetscObject : StandardLayoutClass
302: {
303: public:
304: // OK, non standard layout member is static, does not affect layout
305: static BadCppPetscObject non_standard_layout;
307: // OK, first non-static member is _p_PetscObject
308: _p_PetscObject header;
310: // OK, non-virtual member functions do not affect class layout
311: void foo();
313: // OK, may use "member" functions for destroy and view so long as they are static
314: static PetscErrorCode destroy(MyCppObject *);
315: static PetscErrorCode view(MyCppObject);
316: };
318: // OK, usage via pointer
319: MyObject obj;
321: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
322: .ve
324: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
325: M*/
326: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
327: PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))
329: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
330: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
331: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
332: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
333: PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
335: /*MC
336: PetscHeaderDestroy - Final step in destroying a `PetscObject`
338: Synopsis:
339: #include <petsc/private/petscimpl.h>
340: PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
342: Collective
344: Input Parameter:
345: . h - A pointer to the header created with `PetscHeaderCreate()`
347: Level: developer
349: Notes:
350: `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
352: Example Usage:
353: .vb
354: PetscObject obj;
356: PetscHeaderCreate(obj, ...);
357: // use obj...
359: // note pointer to obj is used
360: PetscHeaderDestroy(&obj);
361: .ve
363: Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
364: deallocates the memory for the structure itself\:
365: .vb
366: typedef struct MyPetscObject_s *MyPetscObject;
367: struct MyPetscObject_s
368: {
369: _p_PetscObject hdr;
370: PetscInt *foo;
371: PetscScalar *bar;
372: };
374: // assume obj is created/initialized elsewhere...
375: MyPetscObject obj;
377: // OK, should dispose of all dynamically allocated resources before calling
378: // PetscHeaderDestroy()
379: PetscFree(obj->foo);
381: // OK, dispose of obj
382: PetscHeaderDestroy(&obj);
384: // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
385: // obj->bar is potentially leaked!
386: PetscFree(obj->bar);
387: .ve
389: .seealso: `PetscObject`, `PetscHeaderCreate()`
390: M*/
391: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)
393: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject, PetscBool);
394: PETSC_INTERN PetscErrorCode PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
395: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
396: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
397: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, PetscCtx ctx);
398: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);
400: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
401: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
402: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
404: /* Code shared between C and Fortran */
405: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscInt);
407: #if PetscDefined(HAVE_SETJMP_H)
408: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
409: #else
410: #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
411: #endif
413: #if defined(PETSC_CLANG_STATIC_ANALYZER)
414: template <typename T>
416: template <typename T>
418: template <typename T>
420: template <typename T>
421: extern void PetscAssertPointer(T, int)
422: {
423: }
424: template <typename T>
426: #else
427: // Macros to test if a PETSc object is valid and if pointers are valid
428: #if PetscDefined(USE_DEBUG)
429: /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
431: do { \
432: PetscBool _7_same; \
434: PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
435: 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); \
436: } while (0)
438: #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
439: do { \
440: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
441: PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
442: } while (0)
445: do { \
446: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
447: if (((PetscObject)(h))->classid != ck) { \
448: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
449: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
450: } \
451: } while (0)
454: do { \
455: PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
456: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
457: 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); \
458: } while (0)
460: #if defined(__cplusplus)
461: #include <type_traits> // std::decay
463: namespace Petsc
464: {
466: namespace util
467: {
469: template <typename T>
470: struct PetscAssertPointerImpl {
471: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
472: PETSC_NODISCARD static constexpr const char *string() noexcept { return "memory"; }
473: };
475: #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
476: template <> \
477: struct PetscAssertPointerImpl<T *> { \
478: PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
479: PETSC_NODISCARD static constexpr const char *string() noexcept { return PetscStringize(T); } \
480: }; \
481: template <> \
482: struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
483: template <> \
484: struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
485: template <> \
486: struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
488: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
489: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
490: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
491: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
492: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
493: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
494: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
495: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
496: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
497: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
498: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
499: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
500: #if defined(PETSC_HAVE_COMPLEX)
501: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
502: #endif
504: #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
506: } // namespace util
508: } // namespace Petsc
510: #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
511: #define PetscAssertPointer_String(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
513: #elif PETSC_C_VERSION >= 11
514: #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
516: #if PetscDefined(HAVE_COMPLEX)
517: #define PETSC_GENERIC_CV_COMPLEX(result) , PETSC_GENERIC_CV(PetscComplex, result)
518: #else
519: #define PETSC_GENERIC_CV_COMPLEX(result)
520: #endif
522: #define PetscAssertPointer_PetscDataType(h) \
523: _Generic((h), \
524: default: PETSC_CHAR, \
525: PETSC_GENERIC_CV( char, PETSC_CHAR), \
526: PETSC_GENERIC_CV( signed char, PETSC_CHAR), \
527: PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
528: PETSC_GENERIC_CV( short, PETSC_SHORT), \
529: PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
530: PETSC_GENERIC_CV( float, PETSC_FLOAT), \
531: PETSC_GENERIC_CV( double, PETSC_DOUBLE), \
532: PETSC_GENERIC_CV( int32_t, PETSC_INT32), \
533: PETSC_GENERIC_CV( uint32_t, PETSC_INT32), \
534: PETSC_GENERIC_CV( int64_t, PETSC_INT64), \
535: PETSC_GENERIC_CV( uint64_t, PETSC_INT64) \
536: PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
538: #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
540: #if PetscDefined(HAVE_COMPLEX)
541: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX , PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
542: #else
543: #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
544: #endif
546: #define PetscAssertPointer_String(h) \
547: _Generic((h), \
548: default: "memory", \
549: PETSC_GENERIC_CV_STRINGIZE(char), \
550: PETSC_GENERIC_CV_STRINGIZE(signed char), \
551: PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
552: PETSC_GENERIC_CV_STRINGIZE(short), \
553: PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
554: PETSC_GENERIC_CV_STRINGIZE(float), \
555: PETSC_GENERIC_CV_STRINGIZE(double), \
556: PETSC_GENERIC_CV_STRINGIZE(int32_t), \
557: PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
558: PETSC_GENERIC_CV_STRINGIZE(int64_t), \
559: PETSC_GENERIC_CV_STRINGIZE(uint64_t) \
560: PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
561: #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
562: #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
563: #define PetscAssertPointer_String(h) "memory"
564: #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
565: #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
567: #else // PetscDefined(USE_DEBUG)
569: do { \
570: (void)(h); \
571: } while (0)
573: do { \
574: (void)(h); \
575: } while (0)
577: do { \
578: (void)(h); \
579: } while (0)
580: #define PetscAssertPointer(h, arg) \
581: do { \
582: (void)(h); \
583: } while (0)
585: do { \
586: (void)(h); \
587: } while (0)
588: #endif // PetscDefined(USE_DEBUG)
589: #endif // PETSC_CLANG_STATIC_ANALYZER
600: #define PetscSorted(n, idx, sorted) \
601: do { \
602: (sorted) = PETSC_TRUE; \
603: for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
604: if ((idx)[_i_] < (idx)[_i_ - 1]) { \
605: (sorted) = PETSC_FALSE; \
606: break; \
607: } \
608: } \
609: } while (0)
611: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
612: #if !defined(PETSC_USE_DEBUG)
614: #define PetscCheckSameType(a, arga, b, argb) \
615: do { \
616: (void)(a); \
617: (void)(b); \
618: } while (0)
619: #define PetscCheckTypeName(a, type) \
620: do { \
621: (void)(a); \
622: } while (0)
623: #define PetscCheckTypeNames(a, type1, type2) \
624: do { \
625: (void)(a); \
626: } while (0)
628: do { \
629: (void)(a); \
630: } while (0)
631: #define PetscCheckSameComm(a, arga, b, argb) \
632: do { \
633: (void)(a); \
634: (void)(b); \
635: } while (0)
636: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
637: do { \
638: (void)(a); \
639: (void)(b); \
640: } while (0)
642: do { \
643: (void)(a); \
644: (void)(b); \
645: } while (0)
647: do { \
648: (void)(a); \
649: (void)(b); \
650: } while (0)
652: do { \
653: (void)(a); \
654: (void)(b); \
655: } while (0)
657: do { \
658: (void)(a); \
659: (void)(b); \
660: } while (0)
662: do { \
663: (void)(a); \
664: (void)(b); \
665: } while (0)
667: do { \
668: (void)(a); \
669: (void)(b); \
670: } while (0)
672: do { \
673: (void)(a); \
674: (void)(b); \
675: } while (0)
677: do { \
678: (void)(a); \
679: (void)(b); \
680: } while (0)
681: #define PetscCheckSorted(n, idx) \
682: do { \
683: (void)(n); \
684: (void)(idx); \
685: } while (0)
687: #else
689: /*
690: This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
691: member associated with the string type_name that can be quickly compared.
693: **Do not swap this macro to compare string type_name!**
695: This macro is used incorrectly in the code. Many places that do not need identity of the
696: types incorrectly call this check and would need to be fixed if this macro is enabled.
697: */
698: #if 0
699: #define PetscCheckSameType(a, arga, b, argb) \
700: do { \
701: PetscBool pcst_type_eq_ = PETSC_TRUE; \
702: PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
703: 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); \
704: } while (0)
705: #else
706: #define PetscCheckSameType(a, arga, b, argb) \
707: do { \
708: (void)(a); \
709: (void)(b); \
710: } while (0)
711: #endif
713: /*
714: Check type_name
715: */
716: #define PetscCheckTypeName(a, type) \
717: do { \
718: PetscBool _7_match; \
719: PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
720: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
721: } while (0)
723: #define PetscCheckTypeNames(a, type1, type2) \
724: do { \
725: PetscBool _7_match; \
726: PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
727: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
728: } while (0)
730: /*
731: Use this macro to check if the type is set
732: */
735: /*
736: Sometimes object must live on same communicator to inter-operate
737: */
738: #define PetscCheckSameComm(a, arga, b, argb) \
739: do { \
740: PetscMPIInt _7_flag; \
741: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
742: 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); \
743: } while (0)
745: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
746: do { \
747: PetscCheckSameType(a, arga, b, argb); \
748: PetscCheckSameComm(a, arga, b, argb); \
749: } while (0)
752: do { \
753: PetscScalar b0 = (b); \
754: PetscReal b1[5]; \
755: if (PetscIsNanScalar(b0)) { \
756: b1[4] = 1; \
757: } else { \
758: b1[4] = 0; \
759: }; \
760: b1[0] = -PetscRealPart(b0); \
761: b1[1] = PetscRealPart(b0); \
762: b1[2] = -PetscImaginaryPart(b0); \
763: b1[3] = PetscImaginaryPart(b0); \
764: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
765: 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); \
766: } while (0)
769: do { \
770: PetscReal b0 = (b), b1[3]; \
771: if (PetscIsNanReal(b0)) { \
772: b1[2] = 1; \
773: } else { \
774: b1[2] = 0; \
775: }; \
776: b1[0] = -b0; \
777: b1[1] = b0; \
778: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
779: 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); \
780: } while (0)
783: do { \
784: PetscInt b0 = (b), b1[2]; \
785: b1[0] = -b0; \
786: b1[1] = b0; \
787: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
788: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
789: } while (0)
792: do { \
793: PetscInt b1[2]; \
794: b1[0] = -b; \
795: b1[1] = b; \
796: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
797: PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
798: } while (0)
801: do { \
802: PetscCount b0 = (b), b1[2]; \
803: b1[0] = -b0; \
804: b1[1] = b0; \
805: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
806: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
807: } while (0)
810: do { \
811: PetscMPIInt b0 = (b), b1[2]; \
812: b1[0] = -b0; \
813: b1[1] = b0; \
814: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
815: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
816: } while (0)
819: do { \
820: PetscBool b0 = (PetscBool)(b), b1[2]; \
821: b1[0] = !b0; \
822: b1[1] = b0; \
823: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
824: PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
825: } while (0)
828: do { \
829: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
830: b1[0] = -b0; \
831: b1[1] = b0; \
832: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
833: PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
834: } while (0)
836: #define PetscCheckSorted(n, idx) \
837: do { \
838: PetscBool _1_flg; \
839: PetscSorted(n, idx, _1_flg); \
840: PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
841: } while (0)
843: #endif
844: #else /* PETSC_CLANG_STATIC_ANALYZER */
845: template <typename Ta, typename Tb>
846: extern void PetscCheckSameType(Ta, int, Tb, int);
847: template <typename Ta, typename Tb>
848: extern void PetscCheckTypeName(Ta, Tb);
849: template <typename Ta, typename Tb, typename Tc>
850: extern void PetscCheckTypeNames(Ta, Tb, Tc);
851: template <typename T>
853: template <typename Ta, typename Tb>
854: extern void PetscCheckSameComm(Ta, int, Tb, int);
855: template <typename Ta, typename Tb>
856: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
857: template <typename Ta, typename Tb>
859: template <typename Ta, typename Tb>
861: template <typename Ta, typename Tb>
863: template <typename Ta, typename Tb>
865: template <typename Ta, typename Tb>
867: template <typename Ta, typename Tb>
869: template <typename Ta, typename Tb>
871: template <typename T>
872: extern void PetscCheckSorted(PetscInt, T);
873: #endif /* PETSC_CLANG_STATIC_ANALYZER */
875: /*MC
876: PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
878: Synopsis:
879: #include "petsc/private/petscimpl.h"
880: PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
882: Input Parameters:
883: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
884: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
885: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
886: - args - the arguments for the method, for example, (ksp,restart))
888: Level: developer
890: Notes:
891: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
893: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
894: in the object.
896: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
897: M*/
898: #define PetscTryMethod(obj, A, B, C) \
899: do { \
900: PetscErrorCode(*_7_f) B; \
901: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
902: if (_7_f) PetscCall((*_7_f)C); \
903: } while (0)
905: /*MC
906: PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
908: Synopsis:
909: #include "petsc/private/petscimpl.h"
910: PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
912: Input Parameters:
913: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
914: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
915: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
916: - args - the arguments for the method, for example, (ksp,restart))
918: Level: developer
920: Notes:
921: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
923: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
924: in the object.
926: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
927: M*/
928: #define PetscUseMethod(obj, A, B, C) \
929: do { \
930: PetscErrorCode(*_7_f) B; \
931: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
932: PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
933: PetscCall((*_7_f)C); \
934: } while (0)
936: /*
937: Use Microsoft traditional preprocessor.
939: The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
940: sets _MSVC_TRADITIONAL to zero so this code path is not used.
942: It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
944: These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
946: PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
947: */
948: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
950: #define PetscUseTypeMethod(obj, OP, ...) \
951: do { \
952: PetscErrorCode ierr_p_; \
953: PetscStackUpdateLine; \
954: 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); \
955: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
956: PetscCall(ierr_p_); \
957: } while (0)
959: #define PetscTryTypeMethod(obj, OP, ...) \
960: do { \
961: if ((obj)->ops->OP) { \
962: PetscErrorCode ierr_p_; \
963: PetscStackUpdateLine; \
964: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
965: PetscCall(ierr_p_); \
966: } \
967: } while (0)
969: #else
971: /*MC
972: 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
974: Synopsis:
975: #include "petsc/private/petscimpl.h"
976: PetscUseTypeMethod(obj, method, other_args)
978: Input Parameters:
979: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
980: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
981: - other_args - the other arguments for the method, `obj` is the first argument
983: Level: developer
985: Note:
986: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
988: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
990: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
991: M*/
992: #define PetscUseTypeMethod(obj, ...) \
993: do { \
994: PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
995: PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
996: PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
997: } while (0)
999: /*MC
1000: 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
1002: Synopsis:
1003: #include "petsc/private/petscimpl.h"
1004: PetscTryTypeMethod(obj, method, other_args)
1006: Input Parameters:
1007: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
1008: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
1009: - other_args - the other arguments for the method, `obj` is the first argument
1011: Level: developer
1013: Note:
1014: This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
1016: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
1018: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1019: M*/
1020: #define PetscTryTypeMethod(obj, ...) \
1021: do { \
1022: if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1023: } while (0)
1025: #endif
1027: /*MC
1028: PetscObjectStateIncrease - Increases the state of any `PetscObject`
1030: Synopsis:
1031: #include "petsc/private/petscimpl.h"
1032: PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
1034: Logically Collective
1036: Input Parameter:
1037: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1038: cast with a (PetscObject), for example,
1039: `PetscObjectStateIncrease`((`PetscObject`)mat);
1041: Level: developer
1043: Notes:
1044: Object state is a 64-bit integer which gets increased every time
1045: the object is changed internally. By saving and later querying the object state
1046: one can determine whether information about the object is still current.
1047: Currently, state is maintained for `Vec` and `Mat` objects.
1049: This routine is mostly for internal use by PETSc; a developer need only
1050: call it after explicit access to an object's internals. Routines such
1051: as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
1052: precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
1054: Routines such as `VecNorm()` can bypass the computation if the norm has already been computed and the vector's state has not changed.
1056: This routine is logically collective because state equality comparison needs to be possible without communication.
1058: `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
1060: .seealso: `PetscObjectStateGet()`, `PetscObject`
1061: M*/
1062: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))
1064: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1065: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1066: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1067: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1068: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1069: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1070: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1071: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1072: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1073: PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
1075: /*MC
1076: PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
1078: Synopsis:
1079: #include "petsc/private/petscimpl.h"
1080: PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1082: Not Collective
1084: Input Parameters:
1085: + obj - the object to which data is to be attached
1086: . id - the identifier for the data
1087: - data - the data to be attached, a `PetscInt`
1089: Level: developer
1091: Notes:
1092: The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1094: This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1095: attached with `PetscObjectCompose()`
1097: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1098: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1099: `PetscObjectCompose()`, `PetscObjectQuery()`
1100: M*/
1101: #define PetscObjectComposedDataSetInt(obj, id, data) \
1102: ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1104: /*MC
1105: PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1107: Synopsis:
1108: #include "petsc/private/petscimpl.h"
1109: PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1111: Not Collective
1113: Input Parameters:
1114: + obj - the object from which data is to be retrieved
1115: - id - the identifier for the data
1117: Output Parameters:
1118: + data - the data to be retrieved, a `PetscInt`
1119: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1121: Level: developer
1123: Notes:
1124: The `data` and `flag` variables are inlined, so they are not pointers.
1126: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1127: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1128: `PetscObjectCompose()`, `PetscObjectQuery()`
1129: M*/
1130: #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))
1132: /*MC
1133: PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1135: Synopsis:
1136: #include "petsc/private/petscimpl.h"
1137: PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1139: Not Collective
1141: Input Parameters:
1142: + obj - the object to which data is to be attached
1143: . id - the identifier for the data
1144: - data - the data to be attached, a `PetscInt` array
1146: Level: developer
1148: Notes:
1149: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1151: The length of the array accessed must be known, it is not available through this API.
1153: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1154: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1155: `PetscObjectCompose()`, `PetscObjectQuery()`
1156: M*/
1157: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1158: ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1160: /*MC
1161: PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1163: Synopsis:
1164: #include "petsc/private/petscimpl.h"
1165: PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1167: Not Collective
1169: Input Parameters:
1170: + obj - the object from which data is to be retrieved
1171: - id - the identifier for the data
1173: Output Parameters:
1174: + data - the data to be retrieved, a `PetscInt` array
1175: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1177: Level: developer
1179: Notes:
1180: The `data` and `flag` variables are inlined, so they are not pointers.
1182: The length of the array accessed must be known, it is not available through this API.
1184: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1185: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1186: `PetscObjectCompose()`, `PetscObjectQuery()`
1187: M*/
1188: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1189: ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1191: /*MC
1192: PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1194: Synopsis:
1195: #include "petsc/private/petscimpl.h"
1196: PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1198: Not Collective
1200: Input Parameters:
1201: + obj - the object to which data is to be attached
1202: . id - the identifier for the data
1203: - data - the data to be attached, a `PetscReal`
1205: Level: developer
1207: Note:
1208: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1210: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1211: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1212: `PetscObjectCompose()`, `PetscObjectQuery()`
1213: M*/
1214: #define PetscObjectComposedDataSetReal(obj, id, data) \
1215: ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1217: /*MC
1218: PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1220: Synopsis:
1221: #include "petsc/private/petscimpl.h"
1222: PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1224: Not Collective
1226: Input Parameters:
1227: + obj - the object from which data is to be retrieved
1228: - id - the identifier for the data
1230: Output Parameters:
1231: + data - the data to be retrieved, a `PetscReal`
1232: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1234: Level: developer
1236: Note:
1237: The `data` and `flag` variables are inlined, so they are not pointers.
1239: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1240: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1241: `PetscObjectCompose()`, `PetscObjectQuery()`
1242: M*/
1243: #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))
1245: /*MC
1246: PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1248: Synopsis:
1249: #include "petsc/private/petscimpl.h"
1250: PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1252: Not Collective
1254: Input Parameters:
1255: + obj - the object to which data is to be attached
1256: . id - the identifier for the data
1257: - data - the data to be attached
1259: Level: developer
1261: Notes:
1262: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1264: The length of the array accessed must be known, it is not available through this API.
1266: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1267: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1268: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1269: M*/
1270: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1271: ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1273: /*MC
1274: PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1276: Synopsis:
1277: #include "petsc/private/petscimpl.h"
1278: PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1280: Not Collective
1282: Input Parameters:
1283: + obj - the object from which data is to be retrieved
1284: - id - the identifier for the data
1286: Output Parameters:
1287: + data - the data to be retrieved, a `PetscReal` array
1288: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1290: Level: developer
1292: Notes:
1293: The `data` and `flag` variables are inlined, so they are not pointers.
1295: The length of the array accessed must be known, it is not available through this API.
1297: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1298: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1299: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1300: M*/
1301: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1302: ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1304: /*MC
1305: PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1307: Synopsis:
1308: #include "petsc/private/petscimpl.h"
1309: PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1311: Not Collective
1313: Input Parameters:
1314: + obj - the object to which data is to be attached
1315: . id - the identifier for the data
1316: - data - the data to be attached, a `PetscScalar`
1318: Level: developer
1320: Note:
1321: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1323: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1324: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1325: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1326: M*/
1327: #if defined(PETSC_USE_COMPLEX)
1328: #define PetscObjectComposedDataSetScalar(obj, id, data) \
1329: ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1330: #else
1331: #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1332: #endif
1333: /*MC
1334: PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1336: Synopsis:
1337: #include "petsc/private/petscimpl.h"
1338: PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1340: Not Collective
1342: Input Parameters:
1343: + obj - the object from which data is to be retrieved
1344: - id - the identifier for the data
1346: Output Parameters:
1347: + data - the data to be retrieved, a `PetscScalar`
1348: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1350: Level: developer
1352: Note:
1353: The `data` and `flag` variables are inlined, so they are not pointers.
1355: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1356: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1357: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1358: M*/
1359: #if defined(PETSC_USE_COMPLEX)
1360: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1361: ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1362: #else
1363: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1364: #endif
1366: /*MC
1367: PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1369: Synopsis:
1370: #include "petsc/private/petscimpl.h"
1371: PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1373: Not Collective
1375: Input Parameters:
1376: + obj - the object to which data is to be attached
1377: . id - the identifier for the data
1378: - data - the data to be attached, a `PetscScalar` array
1380: Level: developer
1382: Notes:
1383: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1385: The length of the array accessed must be known, it is not available through this API.
1387: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1388: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1389: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1390: M*/
1391: #if defined(PETSC_USE_COMPLEX)
1392: #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1393: ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1394: #else
1395: #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1396: #endif
1397: /*MC
1398: PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1399: attached to an object
1401: Synopsis:
1402: #include "petsc/private/petscimpl.h"
1403: PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1405: Not Collective
1407: Input Parameters:
1408: + obj - the object from which data is to be retrieved
1409: - id - the identifier for the data
1411: Output Parameters:
1412: + data - the data to be retrieved, a `PetscScalar` array
1413: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1415: Level: developer
1417: Notes:
1418: The `data` and `flag` variables are inlined, so they are not pointers.
1420: The length of the array accessed must be known, it is not available through this API.
1422: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1423: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1424: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1425: M*/
1426: #if defined(PETSC_USE_COMPLEX)
1427: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1428: ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1429: #else
1430: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1431: #endif
1433: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1434: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1435: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1436: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1437: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1438: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1439: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1441: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1442: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;
1444: struct PetscCommStash {
1445: struct PetscCommStash *next;
1446: MPI_Comm comm;
1447: };
1449: /*
1450: PETSc communicators have this attribute, see
1451: PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1452: */
1453: typedef struct {
1454: PetscMPIInt tag; /* next free tag value */
1455: PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1456: PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1457: PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1458: struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1459: } PetscCommCounter;
1461: typedef enum {
1462: STATE_BEGIN,
1463: STATE_PENDING,
1464: STATE_END
1465: } SRState;
1467: typedef enum {
1468: PETSC_SR_REDUCE_SUM = 0,
1469: PETSC_SR_REDUCE_MAX = 1,
1470: PETSC_SR_REDUCE_MIN = 2
1471: } PetscSRReductionType;
1473: typedef struct {
1474: MPI_Comm comm;
1475: MPI_Request request;
1476: PetscBool mix;
1477: PetscBool async;
1478: PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1479: PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1480: void **invecs; /* for debugging only, vector/memory used with each op */
1481: PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
1482: struct {
1483: PetscScalar v;
1484: PetscInt i;
1485: } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1486: SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1487: PetscMPIInt maxops; /* total amount of space we have for requests */
1488: PetscMPIInt numopsbegin; /* number of requests that have been queued in */
1489: PetscMPIInt numopsend; /* number of requests that have been gotten by user */
1490: } PetscSplitReduction;
1492: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1493: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1494: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1496: #if defined(PETSC_HAVE_THREADSAFETY)
1497: #if defined(PETSC_HAVE_CONCURRENCYKIT)
1498: #if defined(__cplusplus)
1499: /* CK does not have extern "C" protection in their include files */
1500: extern "C" {
1501: #endif
1502: #include <ck_spinlock.h>
1503: #if defined(__cplusplus)
1504: }
1505: #endif
1506: typedef ck_spinlock_t PetscSpinlock;
1508: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1509: {
1510: ck_spinlock_init(ck_spinlock);
1511: return PETSC_SUCCESS;
1512: }
1513: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1514: {
1515: ck_spinlock_lock(ck_spinlock);
1516: return PETSC_SUCCESS;
1517: }
1518: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1519: {
1520: ck_spinlock_unlock(ck_spinlock);
1521: return PETSC_SUCCESS;
1522: }
1523: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1524: {
1525: return PETSC_SUCCESS;
1526: }
1527: #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1528: #if defined(__cplusplus)
1529: // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1530: #include <atomic>
1531: #define petsc_atomic_flag std::atomic_flag
1532: #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1533: #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_release)
1534: #else
1535: #include <stdatomic.h>
1536: #define petsc_atomic_flag atomic_flag
1537: #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1538: #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_release)
1539: #endif
1541: typedef petsc_atomic_flag PetscSpinlock;
1543: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1544: {
1545: petsc_atomic_flag_clear(spinlock);
1546: return PETSC_SUCCESS;
1547: }
1548: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1549: {
1550: do {
1551: } while (petsc_atomic_flag_test_and_set(spinlock));
1552: return PETSC_SUCCESS;
1553: }
1554: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1555: {
1556: petsc_atomic_flag_clear(spinlock);
1557: return PETSC_SUCCESS;
1558: }
1559: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1560: {
1561: return PETSC_SUCCESS;
1562: }
1563: #undef petsc_atomic_flag_test_and_set
1564: #undef petsc_atomic_flag_clear
1565: #undef petsc_atomic_flag
1567: #elif defined(PETSC_HAVE_OPENMP)
1569: #include <omp.h>
1570: typedef omp_lock_t PetscSpinlock;
1572: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1573: {
1574: omp_init_lock(omp_lock);
1575: return PETSC_SUCCESS;
1576: }
1577: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1578: {
1579: omp_set_lock(omp_lock);
1580: return PETSC_SUCCESS;
1581: }
1582: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1583: {
1584: omp_unset_lock(omp_lock);
1585: return PETSC_SUCCESS;
1586: }
1587: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1588: {
1589: omp_destroy_lock(omp_lock);
1590: return PETSC_SUCCESS;
1591: }
1592: #else
1593: #if defined(__cplusplus)
1594: #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1595: #else
1596: #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1597: #endif
1598: #endif
1600: #else
1601: typedef int PetscSpinlock;
1602: #define PetscSpinlockCreate(a) PETSC_SUCCESS
1603: #define PetscSpinlockLock(a) PETSC_SUCCESS
1604: #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1605: #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1606: #endif
1608: #if defined(PETSC_HAVE_THREADSAFETY)
1609: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1610: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1611: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1612: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1613: #endif
1615: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1616: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1617: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1618: PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1619: PETSC_EXTERN PetscBool PetscPrintFunctionList;
1621: #if defined(PETSC_HAVE_ADIOS)
1622: PETSC_EXTERN int64_t Petsc_adios_group;
1623: #endif
1625: #if defined(PETSC_HAVE_KOKKOS)
1626: PETSC_INTERN PetscBool PetscBeganKokkos;
1627: PETSC_EXTERN PetscBool PetscKokkosInitialized;
1628: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1629: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1630: #endif
1632: #if defined(PETSC_HAVE_OPENMP)
1633: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1634: #endif
1636: struct _n_PetscObjectList {
1637: char name[256];
1638: PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1639: PetscObject obj;
1640: PetscObjectList next;
1641: };
1643: /*E
1644: PetscPrecision - Precision of a real number
1646: Values:
1647: + `PETSC_PRECISION_INVALID` - an invalid value
1648: . `PETSC_PRECISION_BFLOAT16` - half precision (Google Brain bfloat16)
1649: . `PETSC_PRECISION___FP16` - half precison (IEEE FP16)
1650: . `PETSC_PRECISION_SINGLE` - single precision
1651: . `PETSC_PRECISION_DOUBLE` - double precision
1652: - `PETSC_PRECISION___FLOAT128` - quadruple precision (__float128)
1654: Level: intermediate
1655: E*/
1657: typedef enum {
1658: PETSC_PRECISION_INVALID = 0,
1659: PETSC_PRECISION_BFLOAT16,
1660: PETSC_PRECISION___FP16,
1661: PETSC_PRECISION_SINGLE,
1662: PETSC_PRECISION_DOUBLE,
1663: PETSC_PRECISION___FLOAT128
1664: } PetscPrecision;
1666: // The precision of PetscScalar and PetscReal
1667: #if defined(PETSC_USE_REAL___FP16)
1668: #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
1669: #elif defined(PETSC_USE_REAL_SINGLE)
1670: #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
1671: #elif defined(PETSC_USE_REAL_DOUBLE)
1672: #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
1673: #elif defined(PETSC_USE_REAL___FLOAT128)
1674: #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
1675: #endif
1677: PETSC_EXTERN const char *const PetscPrecisionTypes[];