Actual source code: petscimpl.h
2: /*
3: Defines the basic header of all PETSc objects.
4: */
5: #ifndef PETSCIMPL_H
6: #define PETSCIMPL_H
7: #include <petscsys.h>
9: /* SUBMANSEC = Sys */
11: #if defined(PETSC_CLANG_STATIC_ANALYZER)
12: #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
13: #else
14: #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
15: #endif
17: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
18: PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
19: PETSC_INTERN PetscErrorCode PetscStackView(FILE *);
20: PETSC_INTERN PetscErrorCode PetscStackReset(void);
21: PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
22: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
23: #else
24: #define PetscStackSetCheck(check) PETSC_SUCCESS
25: #define PetscStackView(file) PETSC_SUCCESS
26: #define PetscStackReset() PETSC_SUCCESS
27: #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
28: #define PetscStackPrint(stack, file) PETSC_SUCCESS
29: #endif
31: /* These are used internally by PETSc ASCII IO routines*/
32: #include <stdarg.h>
33: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);
35: /*
36: All major PETSc data structures have a common core; this is defined
37: below by PETSCHEADER.
39: PetscHeaderCreate() should be used whenever creating a PETSc structure.
40: */
42: /*
43: PetscOps: structure of core operations that all PETSc objects support.
45: getcomm() - Gets the object's communicator.
46: view() - Is the routine for viewing the entire PETSc object; for
47: example, MatView() is the general matrix viewing routine.
48: This is used by PetscObjectView((PetscObject)obj) to allow
49: viewing any PETSc object.
50: destroy() - Is the routine for destroying the entire PETSc object;
51: for example,MatDestroy() is the general matrix
52: destruction routine.
53: This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
54: destroying any PETSc object.
55: compose() - Associates a PETSc object with another PETSc object with a name
56: query() - Returns a different PETSc object that has been associated
57: with the first object using a name.
58: composefunction() - Attaches an a function to a PETSc object with a name.
59: queryfunction() - Requests a registered function that has been attached to a PETSc object.
60: */
62: typedef struct {
63: PetscErrorCode (*view)(PetscObject, PetscViewer);
64: PetscErrorCode (*destroy)(PetscObject *);
65: PetscErrorCode (*compose)(PetscObject, const char[], PetscObject);
66: PetscErrorCode (*query)(PetscObject, const char[], PetscObject *);
67: PetscErrorCode (*composefunction)(PetscObject, const char[], void (*)(void));
68: PetscErrorCode (*queryfunction)(PetscObject, const char[], void (**)(void));
69: } PetscOps;
71: typedef enum {
72: PETSC_FORTRAN_CALLBACK_CLASS,
73: PETSC_FORTRAN_CALLBACK_SUBTYPE,
74: PETSC_FORTRAN_CALLBACK_MAXTYPE
75: } PetscFortranCallbackType;
76: typedef size_t PetscFortranCallbackId;
77: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
78: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
79: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);
81: typedef struct {
82: void (*func)(void);
83: void *ctx;
84: } PetscFortranCallback;
86: /*
87: All PETSc objects begin with the fields defined in PETSCHEADER.
88: The PetscObject is a way of examining these fields regardless of
89: the specific object. In C++ this could be a base abstract class
90: from which all objects are derived.
91: */
92: #define PETSC_MAX_OPTIONS_HANDLER 5
93: typedef struct _p_PetscObject {
94: PetscOps bops[1];
95: PetscClassId classid;
96: MPI_Comm comm;
97: PetscObjectId id; /* this is used to compare object for identity that may no longer exist since memory addresses get recycled for new objects */
98: PetscInt refct;
99: PetscErrorCode (*non_cyclic_references)(PetscObject, PetscInt *);
100: PetscInt64 cidx;
101: PetscMPIInt tag;
102: PetscFunctionList qlist;
103: PetscObjectList olist;
104: char *class_name; /* for example, "Vec" */
105: char *description;
106: char *mansec;
107: char *type_name; /* this is the subclass, for example VECSEQ which equals "seq" */
108: char *name;
109: char *prefix;
110: PetscInt tablevel;
111: void *cpp;
112: PetscObjectState state;
113: PetscInt int_idmax, intstar_idmax;
114: PetscObjectState *intcomposedstate, *intstarcomposedstate;
115: PetscInt *intcomposeddata, **intstarcomposeddata;
116: PetscInt real_idmax, realstar_idmax;
117: PetscObjectState *realcomposedstate, *realstarcomposedstate;
118: PetscReal *realcomposeddata, **realstarcomposeddata;
119: PetscInt scalar_idmax, scalarstar_idmax;
120: PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
121: PetscScalar *scalarcomposeddata, **scalarstarcomposeddata;
122: void (**fortran_func_pointers)(void); /* 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: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectDestroyFunction)(PetscObject *); /* force cast in next macro to NEVER use extern "C" style */
149: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectViewFunction)(PetscObject, PetscViewer);
151: #define PetscHeaderInitialize_Private(h, classid, class_name, descr, mansec, comm, destroy, view) \
152: ((PetscErrorCode)(PetscHeaderCreate_Private((PetscObject)(h), classid, class_name, descr, mansec, comm, (PetscObjectDestroyFunction)(destroy), (PetscObjectViewFunction)(view)) || PetscLogObjectCreate(h)))
154: /*MC
155: PetscHeaderCreate - Creates a raw PETSc object of a particular class
157: Synopsis:
158: #include <petsc/private/petscimpl.h>
159: PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
161: Input Parameters:
162: + classid - The classid associated with this object (for example `VEC_CLASSID`)
163: . class_name - String name of class; should be static (for example "Vec"), may be
164: `PETSC_NULLPTR`
165: . descr - String containing short description; should be static (for example "Vector"),
166: may be `PETSC_NULLPTR`
167: . mansec - String indicating section in manual pages; should be static (for example "Vec"),
168: may be `PETSC_NULLPTR`
169: . comm - The MPI Communicator
170: . destroy - The destroy routine for this object (for example `VecDestroy()`)
171: - view - The view routine for this object (for example `VecView()`), may be
172: `PETSC_NULLPTR`
174: Output Parameter:
175: . h - The newly created `PetscObject`
177: Level: developer
179: Notes:
180: Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
181: C/C++ structure which satisfies all of the following\:
183: 1. The first member of the structure must be a `_p_PetscObject`.
184: 2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
185: - Has no virtual functions or base classes.
186: - Has only standard layout non-static members (if any).
187: - Has only standard layout base classes (if any).
189: See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
190: information.
192: Example Usage:
193: Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
194: objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
195: `<OBJECT_TYPE>View()`.
196: .vb
197: Vec v;
199: PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
200: .ve
202: It is possible to create custom `PetscObject`s, note however that they must abide by the
203: restrictions set forth above.
204: .vb
205: // OK, first member of C structure is _p_PetscObject
206: struct MyCPetscObject_s
207: {
208: _p_PetscObject header;
209: int some_data;
210: };
211: typedef struct *MyCPetscObject_s MyCPetscObject;
213: PetscErrorCode MyObjectDestroy(MyObject *);
214: PetscErrorCode MyObjectView(MyObject);
216: MyCPetscObject obj;
218: // assume MY_PETSC_CLASSID is already registered
219: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
221: // OK, only destroy function must be given, all others may be NULL
222: PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
224: // ERROR must be a single-level pointer
225: PetscHeaderCreate(&obj, ...);
226: .ve
228: Illustrating proper construction from C++\:
229: .vb
230: // ERROR, class is not standard layout, first member must be publicly accessible
231: class BadCppPetscObject
232: {
233: _p_PetscObject header;
234: };
236: // ERROR, class is not standard layout, has a virtual function and virtual inheritance
237: class BadCppPetscObject2 : virtual BaseClass
238: {
239: public:
240: _p_PetscObject header;
242: virtual void foo();
243: };
245: // ERROR, class is not standard layout! Has non-standard layout member
246: class BadCppPetscObject2
247: {
248: public:
249: _p_PetscObject header;
250: BadCppPetscObject non_standard_layout;
251: };
253: // OK, class is standard layout!
254: class GoodCppPetscObject;
255: using MyCppObject = GoodCppPetscObject *;
257: // OK, non-virtual inheritance of other standard layout class does not affect layout
258: class GoodCppPetscObject : StandardLayoutClass
259: {
260: public:
261: // OK, non standard layout member is static, does not affect layout
262: static BadCppPetscObject non_standard_layout;
264: // OK, first non-static member is _p_PetscObject
265: _p_PetscObject header;
267: // OK, non-virtual member functions do not affect class layout
268: void foo();
270: // OK, may use "member" functions for destroy and view so long as they are static
271: static PetscErrorCode destroy(MyCppObject *);
272: static PetscErrorCode view(MyCppObject);
273: };
275: // OK, usage via pointer
276: MyObject obj;
278: PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
279: .ve
281: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
282: M*/
283: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) ((PetscErrorCode)(PetscNew(&(h)) || PetscHeaderInitialize_Private((h), (classid), (class_name), (descr), (mansec), (comm), (destroy), (view))))
285: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
286: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
287: PETSC_INTERN PetscObjectId PetscObjectNewId_Internal(void);
289: /*MC
290: PetscHeaderDestroy - Final step in destroying a `PetscObject`
292: Synopsis:
293: #include <petsc/private/petscimpl.h>
294: PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
296: Input Parameter:
297: . h - A pointer to the header created with `PetscHeaderCreate()`
299: Level: developer
301: Notes:
302: `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
304: Example Usage:
305: .vb
306: PetscObject obj;
308: PetscHeaderCreate(obj, ...);
309: // use obj...
311: // note pointer to obj is used
312: PetscHeaderDestroy(&obj);
313: .ve
315: Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
316: deallocates the memory for the structure itself\:
317: .vb
318: typedef struct MyPetscObject_s *MyPetscObject;
319: struct MyPetscObject_s
320: {
321: _p_PetscObject hdr;
322: PetscInt *foo;
323: PetscScalar *bar;
324: };
326: // assume obj is created/initialized elsewhere...
327: MyPetscObject obj;
329: // OK, should dispose of all dynamically allocated resources before calling
330: // PetscHeaderDestroy()
331: PetscFree(obj->foo);
333: // OK, dispose of obj
334: PetscHeaderDestroy(&obj);
336: // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
337: // obj->bar is potentially leaked!
338: PetscFree(obj->bar);
339: .ve
341: .seealso: `PetscObject`, `PetscHeaderCreate()`
342: M*/
343: #define PetscHeaderDestroy(h) ((PetscErrorCode)(PetscHeaderDestroy_Private((PetscObject)(*(h)), PETSC_FALSE) || PetscFree(*(h))))
345: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject, PetscBool);
346: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
347: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
348: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
349: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);
351: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
352: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
353: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
355: /* Code shared between C and Fortran */
356: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscBool, PetscInt);
358: #if PetscDefined(HAVE_SETJMP_H)
359: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
360: #else
361: #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
362: #endif
363: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
364: /*
365: Macros to test if a PETSc object is valid and if pointers are valid
366: */
367: #if !defined(PETSC_USE_DEBUG)
370: do { \
371: (void)(h); \
372: } while (0)
374: do { \
375: (void)(h); \
376: } while (0)
378: do { \
379: (void)(h); \
380: } while (0)
382: do { \
383: (void)(h); \
384: } while (0)
386: do { \
387: (void)(h); \
388: } while (0)
390: do { \
391: (void)(h); \
392: } while (0)
394: do { \
395: (void)(h); \
396: } while (0)
398: do { \
399: (void)(h); \
400: } while (0)
402: do { \
403: (void)(h); \
404: } while (0)
406: do { \
407: (void)(h); \
408: } while (0)
410: do { \
411: (void)(h); \
412: } while (0)
414: do { \
415: (void)(h); \
416: } while (0)
418: #else
420: /* This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
422: do { \
423: PetscBool _7_same; \
425: PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
426: 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); \
427: } while (0)
430: do { \
431: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
432: PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to " PetscStringize(ptrtype) ": Argument '" PetscStringize(ptr) "' (parameter # %d)", arg); \
433: } while (0)
436: do { \
438: if (((PetscObject)(h))->classid != ck) { \
439: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
440: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
441: } \
442: } while (0)
445: do { \
447: PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
448: 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); \
449: } while (0)
461: do { \
462: PetscCheck((f), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Function Pointer: Parameter # %d", arg); \
463: } while (0)
464: #endif
465: #else /* PETSC_CLANG_STATIC_ANALYZER */
466: template <typename T>
468: template <typename T>
470: template <typename T>
472: template <typename T>
474: template <typename T>
476: template <typename T>
478: template <typename T>
480: template <typename T>
482: template <typename T>
484: template <typename T>
486: template <typename T>
488: template <typename T>
490: template <typename T>
492: #endif /* PETSC_CLANG_STATIC_ANALYZER */
494: #define PetscSorted(n, idx, sorted) \
495: do { \
496: (sorted) = PETSC_TRUE; \
497: for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
498: if ((idx)[_i_] < (idx)[_i_ - 1]) { \
499: (sorted) = PETSC_FALSE; \
500: break; \
501: } \
502: } \
503: } while (0)
505: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
506: #if !defined(PETSC_USE_DEBUG)
508: #define PetscCheckSameType(a, arga, b, argb) \
509: do { \
510: (void)(a); \
511: (void)(b); \
512: } while (0)
513: #define PetscCheckTypeName(a, type) \
514: do { \
515: (void)(a); \
516: } while (0)
517: #define PetscCheckTypeNames(a, type1, type2) \
518: do { \
519: (void)(a); \
520: } while (0)
522: do { \
523: (void)(a); \
524: } while (0)
525: #define PetscCheckSameComm(a, arga, b, argb) \
526: do { \
527: (void)(a); \
528: (void)(b); \
529: } while (0)
530: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
531: do { \
532: (void)(a); \
533: (void)(b); \
534: } while (0)
536: do { \
537: (void)(a); \
538: (void)(b); \
539: } while (0)
541: do { \
542: (void)(a); \
543: (void)(b); \
544: } while (0)
546: do { \
547: (void)(a); \
548: (void)(b); \
549: } while (0)
551: do { \
552: (void)(a); \
553: (void)(b); \
554: } while (0)
556: do { \
557: (void)(a); \
558: (void)(b); \
559: } while (0)
561: do { \
562: (void)(a); \
563: (void)(b); \
564: } while (0)
565: #define PetscCheckSorted(n, idx) \
566: do { \
567: (void)(n); \
568: (void)(idx); \
569: } while (0)
571: #else
573: /*
574: This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
575: member associated with the string type_name that can be quickly compared.
577: **Do not swap this macro to compare string type_name!**
579: This macro is used incorrectly in the code. Many places that do not need identity of the
580: types incorrectly call this check and would need to be fixed if this macro is enabled.
581: */
582: #if 0
583: #define PetscCheckSameType(a, arga, b, argb) \
584: do { \
585: PetscBool pcst_type_eq_ = PETSC_TRUE; \
586: PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_)); \
587: 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); \
588: } while (0)
589: #else
590: #define PetscCheckSameType(a, arga, b, argb) \
591: do { \
592: (void)(a); \
593: (void)(b); \
594: } while (0)
595: #endif
597: /*
598: Check type_name
599: */
600: #define PetscCheckTypeName(a, type) \
601: do { \
602: PetscBool _7_match; \
603: PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
604: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", (char *)(((PetscObject)(a))->type_name), type); \
605: } while (0)
607: #define PetscCheckTypeNames(a, type1, type2) \
608: do { \
609: PetscBool _7_match; \
610: PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
611: PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", (char *)(((PetscObject)(a))->type_name), type1, type2); \
612: } while (0)
614: /*
615: Use this macro to check if the type is set
616: */
619: /*
620: Sometimes object must live on same communicator to inter-operate
621: */
622: #define PetscCheckSameComm(a, arga, b, argb) \
623: do { \
624: PetscMPIInt _7_flag; \
625: PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
626: 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); \
627: } while (0)
629: #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
630: do { \
631: PetscCheckSameType(a, arga, b, argb); \
632: PetscCheckSameComm(a, arga, b, argb); \
633: } while (0)
636: do { \
637: PetscScalar b0 = (b); \
638: PetscReal b1[5], b2[5]; \
639: if (PetscIsNanScalar(b0)) { \
640: b1[4] = 1; \
641: } else { \
642: b1[4] = 0; \
643: }; \
644: b1[0] = -PetscRealPart(b0); \
645: b1[1] = PetscRealPart(b0); \
646: b1[2] = -PetscImaginaryPart(b0); \
647: b1[3] = PetscImaginaryPart(b0); \
648: PetscCall(MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
649: PetscCheck(b2[4] > 0 || (PetscEqualReal(-b2[0], b2[1]) && PetscEqualReal(-b2[2], b2[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
650: } while (0)
653: do { \
654: PetscReal b0 = (b), b1[3], b2[3]; \
655: if (PetscIsNanReal(b0)) { \
656: b1[2] = 1; \
657: } else { \
658: b1[2] = 0; \
659: }; \
660: b1[0] = -b0; \
661: b1[1] = b0; \
662: PetscCall(MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
663: PetscCheck(b2[2] > 0 || PetscEqualReal(-b2[0], b2[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
664: } while (0)
667: do { \
668: PetscInt b0 = (b), b1[2], b2[2]; \
669: b1[0] = -b0; \
670: b1[1] = b0; \
671: PetscCall(MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
672: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
673: } while (0)
676: do { \
677: PetscMPIInt b0 = (b), b1[2], b2[2]; \
678: b1[0] = -b0; \
679: b1[1] = b0; \
680: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
681: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
682: } while (0)
685: do { \
686: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
687: b1[0] = -b0; \
688: b1[1] = b0; \
689: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
690: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
691: } while (0)
694: do { \
695: PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
696: b1[0] = -b0; \
697: b1[1] = b0; \
698: PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
699: PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
700: } while (0)
702: #define PetscCheckSorted(n, idx) \
703: do { \
704: PetscBool _1_flg; \
705: PetscSorted(n, idx, _1_flg); \
706: PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
707: } while (0)
709: #endif
710: #else /* PETSC_CLANG_STATIC_ANALYZER */
711: template <typename Ta, typename Tb>
712: void PetscCheckSameType(Ta, int, Tb, int);
713: template <typename Ta, typename Tb>
714: void PetscCheckTypeName(Ta, Tb);
715: template <typename Ta, typename Tb, typename Tc>
716: void PetscCheckTypeName(Ta, Tb, Tc);
717: template <typename T>
719: template <typename Ta, typename Tb>
720: void PetscCheckSameComm(Ta, int, Tb, int);
721: template <typename Ta, typename Tb>
722: void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
723: template <typename Ta, typename Tb>
725: template <typename Ta, typename Tb>
727: template <typename Ta, typename Tb>
729: template <typename Ta, typename Tb>
731: template <typename Ta, typename Tb>
733: template <typename Ta, typename Tb>
735: template <typename T>
736: void PetscCheckSorted(PetscInt, T);
737: #endif /* PETSC_CLANG_STATIC_ANALYZER */
739: /*MC
740: PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
742: Synopsis:
743: #include "petsc/private/petscimpl.h"
744: PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
746: Input Parameters:
747: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
748: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
749: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
750: - args - the arguments for the method, for example, (ksp,restart))
752: Level: developer
754: Notes:
755: This does not return an error code, it is a macro that returns with an error code on error.
757: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the objects function table, the `ops` array
758: in the object.
760: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
761: M*/
762: #define PetscTryMethod(obj, A, B, C) \
763: do { \
764: PetscErrorCode(*_7_f) B; \
765: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
766: if (_7_f) PetscCall((*_7_f)C); \
767: } while (0)
769: /*MC
770: PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
772: Synopsis:
773: #include "petsc/private/petscimpl.h"
774: PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
776: Input Parameters:
777: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
778: . name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
779: . arg_types - the argument types for the method, for example, (KSP,PetscInt)
780: - args - the arguments for the method, for example, (ksp,restart))
782: Level: developer
784: Notes:
785: This does not return an error code, it is a macro that returns with an error code on error.
787: Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the objects function table, the `ops` array
788: in the object.
790: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
791: M*/
792: #define PetscUseMethod(obj, A, B, C) \
793: do { \
794: PetscErrorCode(*_7_f) B; \
795: PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
796: PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
797: PetscCall((*_7_f)C); \
798: } while (0)
800: /*
801: Use Microsoft traditional preprocessor.
803: The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
804: sets _MSVC_TRADITIONAL to zero so this code path is not used.
806: It appears the Intel Windows compiler icl does not have an equaivalent of -Zc:preprocessor
808: These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
810: PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
811: */
812: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
814: #define PetscUseTypeMethod(obj, OP, ...) \
815: do { \
816: PetscErrorCode ierr_p_; \
817: PetscStackUpdateLine; \
818: 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); \
819: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
820: PetscCall(ierr_p_); \
821: } while (0)
823: #define PetscTryTypeMethod(obj, OP, ...) \
824: do { \
825: if ((obj)->ops->OP) { \
826: PetscErrorCode ierr_p_; \
827: PetscStackUpdateLine; \
828: ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
829: PetscCall(ierr_p_); \
830: } \
831: } while (0)
833: #else
835: /*MC
836: 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
838: Synopsis:
839: #include "petsc/private/petscimpl.h"
840: PetscUseTypeMethod(obj, method, other_args)
842: Input Parameters:
843: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
844: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
845: - other_args - the other arguments for the method, `obj` is the first argument
847: Level: developer
849: Note:
850: This does not return an error code, it is a macro that returns with an error code on error.
852: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
854: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`
855: M*/
856: #define PetscUseTypeMethod(obj, ...) \
857: do { \
858: PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
859: PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
860: PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
861: } while (0)
863: /*MC
864: 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
866: Synopsis:
867: #include "petsc/private/petscimpl.h"
868: PetscTryTtype(obj, method, other_args)
870: Input Parameters:
871: + obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
872: . method - the name of the method, for example, mult for the PETSc routine `MatMult()`
873: - other_args - the other arguments for the method, `obj` is the first argument
875: Level: developer
877: Note:
878: This does not return an error code, it is a macro that returns with an error code on error.
880: Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
882: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
883: M*/
884: #define PetscTryTypeMethod(obj, ...) \
885: do { \
886: if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
887: } while (0)
889: #endif
891: /*MC
892: PetscObjectStateIncrease - Increases the state of any `PetscObject`
894: Synopsis:
895: #include "petsc/private/petscimpl.h"
896: PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
898: Logically Collective
900: Input Parameter:
901: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
902: cast with a (PetscObject), for example,
903: `PetscObjectStateIncrease`((`PetscObject`)mat);
905: Level: developer
907: Notes:
908: Object state is a 64-bit integer which gets increased every time
909: the object is changed internally. By saving and later querying the object state
910: one can determine whether information about the object is still current.
911: Currently, state is maintained for `Vec` and `Mat` objects.
913: This routine is mostly for internal use by PETSc; a developer need only
914: call it after explicit access to an object's internals. Routines such
915: as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
916: precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
918: Routines such as `VecNorm()` can by-pass the computation if the norm has already been computed and the vector's state has not changed.
920: This routine is logically collective because state equality comparison needs to be possible without communication.
922: `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
924: .seealso: `PetscObjectStateGet()`, `PetscObject`
925: M*/
926: #define PetscObjectStateIncrease(obj) ((obj)->state++, PETSC_SUCCESS)
928: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
929: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
930: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
931: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
932: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
933: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
934: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
935: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
936: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
937: PETSC_EXTERN PetscInt PetscObjectComposedDataMax;
939: /*MC
940: PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
942: Synopsis:
943: #include "petsc/private/petscimpl.h"
944: PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
946: Not Collective
948: Input Parameters:
949: + obj - the object to which data is to be attached
950: . id - the identifier for the data
951: - data - the data to be attached, a `PetscInt`
953: Level: developer
955: Notes:
956: The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
958: This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
959: attached with `PetscObjectCompose()`
961: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
962: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
963: `PetscObjectCompose()`, `PetscObjectQuery()`
964: M*/
965: #define PetscObjectComposedDataSetInt(obj, id, data) \
966: ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
968: /*MC
969: PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
971: Synopsis:
972: #include "petsc/private/petscimpl.h"
973: PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
975: Not Collective
977: Input Parameters:
978: + obj - the object from which data is to be retrieved
979: - id - the identifier for the data
981: Output Parameters:
982: + data - the data to be retrieved, a `PetscInt`
983: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
985: Level: developer
987: Notes:
988: The `data` and `flag` variables are inlined, so they are not pointers.
990: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
991: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
992: `PetscObjectCompose()`, `PetscObjectQuery()`
993: M*/
994: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS)
996: /*MC
997: PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
999: Synopsis:
1000: #include "petsc/private/petscimpl.h"
1001: PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1003: Not Collective
1005: Input Parameters:
1006: + obj - the object to which data is to be attached
1007: . id - the identifier for the data
1008: - data - the data to be attached, a `PetscInt` array
1010: Level: developer
1012: Notes:
1013: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1015: The length of the array accessed must be known, it is not available through this API.
1017: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1018: `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1019: `PetscObjectCompose()`, `PetscObjectQuery()`
1020: M*/
1021: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1022: ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1024: /*MC
1025: PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1027: Synopsis:
1028: #include "petsc/private/petscimpl.h"
1029: PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1031: Not Collective
1033: Input Parameters:
1034: + obj - the object from which data is to be retrieved
1035: - id - the identifier for the data
1037: Output Parameters:
1038: + data - the data to be retrieved, a `PetscInt` array
1039: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1041: Level: developer
1043: Notes:
1044: The `data` and `flag` variables are inlined, so they are not pointers.
1046: The length of the array accessed must be known, it is not available through this API.
1048: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1049: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1050: `PetscObjectCompose()`, `PetscObjectQuery()`
1051: M*/
1052: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1053: ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1055: /*MC
1056: PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1058: Synopsis:
1059: #include "petsc/private/petscimpl.h"
1060: PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1062: Not Collective
1064: Input Parameters:
1065: + obj - the object to which data is to be attached
1066: . id - the identifier for the data
1067: - data - the data to be attached, a `PetscReal`
1069: Level: developer
1071: Note:
1072: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1074: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1075: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1076: `PetscObjectCompose()`, `PetscObjectQuery()`
1077: M*/
1078: #define PetscObjectComposedDataSetReal(obj, id, data) \
1079: ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1081: /*MC
1082: PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1084: Synopsis:
1085: #include "petsc/private/petscimpl.h"
1086: PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1088: Not Collective
1090: Input Parameters:
1091: + obj - the object from which data is to be retrieved
1092: - id - the identifier for the data
1094: Output Parameters:
1095: + data - the data to be retrieved, a `PetscReal`
1096: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1098: Level: developer
1100: Note:
1101: The `data` and `flag` variables are inlined, so they are not pointers.
1103: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1104: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1105: `PetscObjectCompose()`, `PetscObjectQuery()`
1106: M*/
1107: #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))
1109: /*MC
1110: PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1112: Synopsis:
1113: #include "petsc/private/petscimpl.h"
1114: PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1116: Not Collective
1118: Input Parameters:
1119: + obj - the object to which data is to be attached
1120: . id - the identifier for the data
1121: - data - the data to be attached
1123: Level: developer
1125: Notes:
1126: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1128: The length of the array accessed must be known, it is not available through this API.
1130: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1131: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1132: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1133: M*/
1134: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1135: ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1137: /*MC
1138: PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1140: Synopsis:
1141: #include "petsc/private/petscimpl.h"
1142: PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1144: Not Collective
1146: Input Parameters:
1147: + obj - the object from which data is to be retrieved
1148: - id - the identifier for the data
1150: Output Parameters:
1151: + data - the data to be retrieved, a `PetscReal` array
1152: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1154: Level: developer
1156: Notes:
1157: The `data` and `flag` variables are inlined, so they are not pointers.
1159: The length of the array accessed must be known, it is not available through this API.
1161: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1162: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1163: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1164: M*/
1165: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1166: ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1168: /*MC
1169: PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1171: Synopsis:
1172: #include "petsc/private/petscimpl.h"
1173: PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1175: Not Collective
1177: Input Parameters:
1178: + obj - the object to which data is to be attached
1179: . id - the identifier for the data
1180: - data - the data to be attached, a `PetscScalar`
1182: Level: developer
1184: Note:
1185: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1187: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1188: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1189: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1190: M*/
1191: #if defined(PETSC_USE_COMPLEX)
1192: #define PetscObjectComposedDataSetScalar(obj, id, data) \
1193: ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1194: #else
1195: #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1196: #endif
1197: /*MC
1198: PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1200: Synopsis:
1201: #include "petsc/private/petscimpl.h"
1202: PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1204: Not Collective
1206: Input Parameters:
1207: + obj - the object from which data is to be retrieved
1208: - id - the identifier for the data
1210: Output Parameters:
1211: + data - the data to be retrieved, a `PetscScalar`
1212: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1214: Level: developer
1216: Note:
1217: The `data` and `flag` variables are inlined, so they are not pointers.
1219: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1220: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1221: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1222: M*/
1223: #if defined(PETSC_USE_COMPLEX)
1224: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1225: ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1226: #else
1227: #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1228: #endif
1230: /*MC
1231: PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1233: Synopsis:
1234: #include "petsc/private/petscimpl.h"
1235: PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1237: Not Collective
1239: Input Parameters:
1240: + obj - the object to which data is to be attached
1241: . id - the identifier for the data
1242: - data - the data to be attached, a `PetscScalar` array
1244: Level: developer
1246: Notes:
1247: The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1249: The length of the array accessed must be known, it is not available through this API.
1251: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1252: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1253: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1254: M*/
1255: #if defined(PETSC_USE_COMPLEX)
1256: #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1257: ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1258: #else
1259: #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1260: #endif
1261: /*MC
1262: PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1263: attached to an object
1265: Synopsis:
1266: #include "petsc/private/petscimpl.h"
1267: PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1269: Not Collective
1271: Input Parameters:
1272: + obj - the object from which data is to be retrieved
1273: - id - the identifier for the data
1275: Output Parameters:
1276: + data - the data to be retrieved, a `PetscScalar` array
1277: - flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1279: Level: developer
1281: Notes:
1282: The `data` and `flag` variables are inlined, so they are not pointers.
1284: The length of the array accessed must be known, it is not available through this API.
1286: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1287: `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1288: `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1289: M*/
1290: #if defined(PETSC_USE_COMPLEX)
1291: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1292: ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1293: #else
1294: #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1295: #endif
1297: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1298: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1299: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1300: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1301: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1302: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1303: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1305: PETSC_EXTERN PetscMPIInt Petsc_SharedWD_keyval;
1306: PETSC_EXTERN PetscMPIInt Petsc_SharedTmp_keyval;
1308: struct PetscCommStash {
1309: struct PetscCommStash *next;
1310: MPI_Comm comm;
1311: };
1313: /*
1314: PETSc communicators have this attribute, see
1315: PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1316: */
1317: typedef struct {
1318: PetscMPIInt tag; /* next free tag value */
1319: PetscInt refcount; /* number of references, communicator can be freed when this reaches 0 */
1320: PetscInt namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1321: PetscMPIInt *iflags; /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1322: struct PetscCommStash *comms; /* communicators available for PETSc to pass off to other packages */
1323: } PetscCommCounter;
1325: typedef enum {
1326: STATE_BEGIN,
1327: STATE_PENDING,
1328: STATE_END
1329: } SRState;
1331: typedef enum {
1332: PETSC_SR_REDUCE_SUM = 0,
1333: PETSC_SR_REDUCE_MAX = 1,
1334: PETSC_SR_REDUCE_MIN = 2
1335: } PetscSRReductionType;
1337: typedef struct {
1338: MPI_Comm comm;
1339: MPI_Request request;
1340: PetscBool mix;
1341: PetscBool async;
1342: PetscScalar *lvalues; /* this are the reduced values before call to MPI_Allreduce() */
1343: PetscScalar *gvalues; /* values after call to MPI_Allreduce() */
1344: void **invecs; /* for debugging only, vector/memory used with each op */
1345: PetscInt *reducetype; /* is particular value to be summed or maxed? */
1346: struct {
1347: PetscScalar v;
1348: PetscInt i;
1349: } *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1350: SRState state; /* are we calling xxxBegin() or xxxEnd()? */
1351: PetscInt maxops; /* total amount of space we have for requests */
1352: PetscInt numopsbegin; /* number of requests that have been queued in */
1353: PetscInt numopsend; /* number of requests that have been gotten by user */
1354: } PetscSplitReduction;
1356: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1357: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1358: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1360: #if defined(PETSC_HAVE_THREADSAFETY)
1361: #if defined(PETSC_HAVE_CONCURRENCYKIT)
1362: #if defined(__cplusplus)
1363: /* CK does not have extern "C" protection in their include files */
1364: extern "C" {
1365: #endif
1366: #include <ck_spinlock.h>
1367: #if defined(__cplusplus)
1368: }
1369: #endif
1370: typedef ck_spinlock_t PetscSpinlock;
1372: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1373: {
1374: ck_spinlock_init(ck_spinlock);
1375: return PETSC_SUCCESS;
1376: }
1377: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1378: {
1379: ck_spinlock_lock(ck_spinlock);
1380: return PETSC_SUCCESS;
1381: }
1382: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1383: {
1384: ck_spinlock_unlock(ck_spinlock);
1385: return PETSC_SUCCESS;
1386: }
1387: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1388: {
1389: return PETSC_SUCCESS;
1390: }
1391: #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1392: #if defined(__cplusplus)
1393: #include <atomic>
1394: #define petsc_atomic_flag std::atomic_flag
1395: #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_relaxed)
1396: #define petsc_atomic_flag_clear(p) std::atomic_flag_clear_explicit(p, std::memory_order_relaxed)
1397: #else
1398: #include <stdatomic.h>
1399: #define petsc_atomic_flag atomic_flag
1400: #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_relaxed)
1401: #define petsc_atomic_flag_clear(p) atomic_flag_clear_explicit(p, memory_order_relaxed)
1402: #endif
1404: typedef petsc_atomic_flag PetscSpinlock;
1406: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1407: {
1408: petsc_atomic_flag_clear(spinlock);
1409: return PETSC_SUCCESS;
1410: }
1411: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1412: {
1413: do {
1414: } while (petsc_atomic_flag_test_and_set(spinlock));
1415: return PETSC_SUCCESS;
1416: }
1417: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1418: {
1419: petsc_atomic_flag_clear(spinlock);
1420: return PETSC_SUCCESS;
1421: }
1422: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *spinlock)
1423: {
1424: return PETSC_SUCCESS;
1425: }
1426: #undef petsc_atomic_flag_test_and_set
1427: #undef petsc_atomic_flag_clear
1428: #undef petsc_atomic_flag
1430: #elif defined(PETSC_HAVE_OPENMP)
1432: #include <omp.h>
1433: typedef omp_lock_t PetscSpinlock;
1435: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1436: {
1437: omp_init_lock(omp_lock);
1438: return PETSC_SUCCESS;
1439: }
1440: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1441: {
1442: omp_set_lock(omp_lock);
1443: return PETSC_SUCCESS;
1444: }
1445: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1446: {
1447: omp_unset_lock(omp_lock);
1448: return PETSC_SUCCESS;
1449: }
1450: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1451: {
1452: omp_destroy_lock(omp_lock);
1453: return PETSC_SUCCESS;
1454: }
1455: #else
1456: #if defined(__cplusplus)
1457: #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1458: #else
1459: #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1460: #endif
1461: #endif
1463: #else
1464: typedef int PetscSpinlock;
1465: #define PetscSpinlockCreate(a) PETSC_SUCCESS
1466: #define PetscSpinlockLock(a) PETSC_SUCCESS
1467: #define PetscSpinlockUnlock(a) PETSC_SUCCESS
1468: #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1469: #endif
1471: #if defined(PETSC_HAVE_THREADSAFETY)
1472: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1473: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1474: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1475: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1476: #endif
1478: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1479: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1480: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1481: PETSC_EXTERN PetscBool use_gpu_aware_mpi;
1482: PETSC_EXTERN PetscBool PetscPrintFunctionList;
1484: #if defined(PETSC_HAVE_ADIOS)
1485: PETSC_EXTERN int64_t Petsc_adios_group;
1486: #endif
1488: #if defined(PETSC_HAVE_KOKKOS)
1489: PETSC_INTERN PetscBool PetscBeganKokkos;
1490: PETSC_EXTERN PetscBool PetscKokkosInitialized;
1491: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1492: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1493: #endif
1495: #if defined(PETSC_HAVE_OPENMP)
1496: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1497: #endif
1499: #endif /* PETSCIMPL_H */