xref: /petsc/include/petsc/private/petscimpl.h (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1 /*
2     Defines the basic header of all PETSc objects.
3 */
4 #pragma once
5 #include <petscsys.h>
6 
7 /* SUBMANSEC = Sys */
8 
9 #if defined(PETSC_CLANG_STATIC_ANALYZER)
10   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
11 #else
12   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
13 #endif
14 
15 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
16 PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
17 PETSC_INTERN PetscErrorCode PetscStackReset(void);
18 PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
19 PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
20 #else
21   #define PetscStackSetCheck(check)         PETSC_SUCCESS
22   #define PetscStackReset()                 PETSC_SUCCESS
23   #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
24   #define PetscStackPrint(stack, file)      PETSC_SUCCESS
25 #endif
26 
27 /* These are used internally by PETSc ASCII IO routines*/
28 #include <stdarg.h>
29 PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);
30 
31 /*
32    All major PETSc data structures have a common core; this is defined
33    below by PETSCHEADER.
34 
35    PetscHeaderCreate() should be used whenever creating a PETSc structure.
36 */
37 
38 /*
39    PetscOps: structure of core operations that all PETSc objects support.
40 
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 */
51 
52 typedef struct {
53   PetscErrorCode (*view)(PetscObject, PetscViewer);
54   PetscErrorCode (*destroy)(PetscObject *);
55 } PetscOps;
56 
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
59 
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
63 
64   Level: developer
65 
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()`.
70 
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;
78 
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 *);
83 
84 /*S
85   PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback
86 
87   Level: advanced
88 
89   Notes:
90   `PetscFortranCallbackFn *` plays the role of `void *` for function pointers in the PETSc Fortran API.
91 
92 .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
93 S*/
94 PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);
95 
96 typedef struct {
97   PetscFortranCallbackFn *func;
98   void                   *ctx;
99 } PetscFortranCallback;
100 
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 *);
145 
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;
158 
159 #define PETSCHEADER(ObjectOps) \
160   _p_PetscObject hdr; \
161   ObjectOps      ops[1]
162 
163 #define PETSCFREEDHEADER -1
164 
165 /*S
166   PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`
167 
168   Calling Sequence:
169 . obj - the `PetscObject` to destroy
170 
171   Level: beginner
172 
173   Note:
174   The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.
175 
176 .seealso: `PetscObject`, `PetscObjectDestroy()`
177 S*/
178 PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);
179 
180 PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;
181 
182 /*S
183   PetscObjectViewFn - A prototype of a function that can view a `PetscObject`
184 
185   Calling Sequence:
186 + obj - the `PetscObject` to view
187 - v - the viewer
188 
189   Level: beginner
190 
191   Note:
192   The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.
193 
194 .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
195 S*/
196 PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);
197 
198 PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;
199 
200 /*MC
201     PetscHeaderCreate - Creates a raw PETSc object of a particular class
202 
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)
206 
207   Collective
208 
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`
217 
218   Output Parameter:
219 . h - The newly created `PetscObject`
220 
221   Level: developer
222 
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\:
226 
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).
232 
233      See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
234      information.
235 
236   Example Usage:
237   Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
238   objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
239   `<OBJECT_TYPE>View()`.
240 .vb
241   Vec v;
242 
243   PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
244 .ve
245 
246   It is possible to create custom `PetscObject`s, note however that they must abide by the
247   restrictions set forth above.
248 .vb
249   // OK, first member of C structure is _p_PetscObject
250   struct MyCPetscObject_s
251   {
252     _p_PetscObject header;
253     int            some_data;
254   };
255   typedef struct *MyCPetscObject_s MyCPetscObject;
256 
257   PetscErrorCode MyObjectDestroy(MyObject *);
258   PetscErrorCode MyObjectView(MyObject);
259 
260   MyCPetscObject obj;
261 
262   // assume MY_PETSC_CLASSID is already registered
263   PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);
264 
265   // OK, only destroy function must be given, all others may be NULL
266   PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);
267 
268   // ERROR must be a single-level pointer
269   PetscHeaderCreate(&obj, ...);
270 .ve
271 
272   Illustrating proper construction from C++\:
273 .vb
274   // ERROR, class is not standard layout, first member must be publicly accessible
275   class BadCppPetscObject
276   {
277     _p_PetscObject header;
278   };
279 
280   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
281   class BadCppPetscObject2 : virtual BaseClass
282   {
283   public:
284     _p_PetscObject header;
285 
286     virtual void foo();
287   };
288 
289   // ERROR, class is not standard layout! Has non-standard layout member
290   class BadCppPetscObject2
291   {
292   public:
293     _p_PetscObject    header;
294     BadCppPetscObject non_standard_layout;
295   };
296 
297   // OK, class is standard layout!
298   class GoodCppPetscObject;
299   using MyCppObject = GoodCppPetscObject *;
300 
301   // OK, non-virtual inheritance of other standard layout class does not affect layout
302   class GoodCppPetscObject : StandardLayoutClass
303   {
304   public:
305     // OK, non standard layout member is static, does not affect layout
306     static BadCppPetscObject non_standard_layout;
307 
308     // OK, first non-static member is _p_PetscObject
309     _p_PetscObject header;
310 
311      // OK, non-virtual member functions do not affect class layout
312     void foo();
313 
314     // OK, may use "member" functions for destroy and view so long as they are static
315     static PetscErrorCode destroy(MyCppObject *);
316     static PetscErrorCode view(MyCppObject);
317   };
318 
319   // OK, usage via pointer
320   MyObject obj;
321 
322   PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
323 .ve
324 
325 .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
326 M*/
327 #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
328   PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))
329 
330 PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
331 PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
332 PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
333 PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
334 PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);
335 
336 /*MC
337   PetscHeaderDestroy - Final step in destroying a `PetscObject`
338 
339   Synopsis:
340   #include <petsc/private/petscimpl.h>
341   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)
342 
343   Collective
344 
345   Input Parameter:
346 . h - A pointer to the header created with `PetscHeaderCreate()`
347 
348   Level: developer
349 
350   Notes:
351   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.
352 
353   Example Usage:
354 .vb
355   PetscObject obj;
356 
357   PetscHeaderCreate(obj, ...);
358   // use obj...
359 
360   // note pointer to obj is used
361   PetscHeaderDestroy(&obj);
362 .ve
363 
364   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
365   deallocates the memory for the structure itself\:
366 .vb
367   typedef struct MyPetscObject_s *MyPetscObject;
368   struct MyPetscObject_s
369   {
370     _p_PetscObject  hdr;
371     PetscInt       *foo;
372     PetscScalar    *bar;
373   };
374 
375   // assume obj is created/initialized elsewhere...
376   MyPetscObject obj;
377 
378   // OK, should dispose of all dynamically allocated resources before calling
379   // PetscHeaderDestroy()
380   PetscFree(obj->foo);
381 
382   // OK, dispose of obj
383   PetscHeaderDestroy(&obj);
384 
385   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
386   // obj->bar is potentially leaked!
387   PetscFree(obj->bar);
388 .ve
389 
390 .seealso: `PetscObject`, `PetscHeaderCreate()`
391 M*/
392 #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)
393 
394 PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
395 PETSC_INTERN PetscErrorCode                PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
396 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
397 PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
398 PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, PetscCtx ctx);
399 PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);
400 
401 PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
402 PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
403 PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
404 
405 /* Code shared between C and Fortran */
406 PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscInt);
407 
408 #if PetscDefined(HAVE_SETJMP_H)
409 PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
410 #else
411   #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
412 #endif
413 
414 #if defined(PETSC_CLANG_STATIC_ANALYZER)
415 template <typename T>
416 extern void PetscValidHeaderSpecificType(T, PetscClassId, int, const char[]);
417 template <typename T>
418 extern void PetscValidHeaderSpecific(T, PetscClassId, int);
419 template <typename T>
420 extern void PetscValidHeader(T, int);
421 template <typename T>
PetscAssertPointer(T,int)422 extern void PetscAssertPointer(T, int)
423 {
424 }
425 template <typename T>
426 extern void PetscValidFunction(T, int);
427 #else
428   // Macros to test if a PETSc object is valid and if pointers are valid
429   #if PetscDefined(USE_DEBUG)
430     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
431     #define PetscValidHeaderSpecificType(h, ck, arg, t) \
432       do { \
433         PetscBool _7_same; \
434         PetscValidHeaderSpecific(h, ck, arg); \
435         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
436         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); \
437       } while (0)
438 
439     #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
440       do { \
441         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
442         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
443       } while (0)
444 
445     #define PetscValidHeaderSpecific(h, ck, arg) \
446       do { \
447         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
448         if (((PetscObject)(h))->classid != ck) { \
449           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
450           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
451         } \
452       } while (0)
453 
454     #define PetscValidHeader(h, arg) \
455       do { \
456         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
457         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
458         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); \
459       } while (0)
460 
461     #if defined(__cplusplus)
462       #include <type_traits> // std::decay
463 
464 namespace Petsc
465 {
466 
467 namespace util
468 {
469 
470 template <typename T>
471 struct PetscAssertPointerImpl {
typePetscAssertPointerImpl472   PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
stringPetscAssertPointerImpl473   PETSC_NODISCARD static constexpr const char   *string() noexcept { return "memory"; }
474 };
475 
476       #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
477         template <> \
478         struct PetscAssertPointerImpl<T *> { \
479           PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
480           PETSC_NODISCARD static constexpr const char   *string() noexcept { return PetscStringize(T); } \
481         }; \
482         template <> \
483         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
484         template <> \
485         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
486         template <> \
487         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }
488 
489 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
490 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
491 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
492 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
493 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
494 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
495 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
496 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
497 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
498 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
499 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
500 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
501       #if defined(PETSC_HAVE_COMPLEX)
502 PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
503       #endif
504 
505       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION
506 
507 } // namespace util
508 
509 } // namespace Petsc
510 
511       #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
512       #define PetscAssertPointer_String(h)        ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()
513 
514     #elif PETSC_C_VERSION >= 11
515       #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result
516 
517       #if PetscDefined(HAVE_COMPLEX)
518         #define PETSC_GENERIC_CV_COMPLEX(result) , PETSC_GENERIC_CV(PetscComplex, result)
519       #else
520         #define PETSC_GENERIC_CV_COMPLEX(result)
521       #endif
522 
523       #define PetscAssertPointer_PetscDataType(h) \
524         _Generic((h), \
525           default: PETSC_CHAR, \
526           PETSC_GENERIC_CV(          char, PETSC_CHAR), \
527           PETSC_GENERIC_CV(   signed char, PETSC_CHAR), \
528           PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
529           PETSC_GENERIC_CV(         short, PETSC_SHORT), \
530           PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
531           PETSC_GENERIC_CV(         float, PETSC_FLOAT), \
532           PETSC_GENERIC_CV(        double, PETSC_DOUBLE), \
533           PETSC_GENERIC_CV(       int32_t, PETSC_INT32), \
534           PETSC_GENERIC_CV(      uint32_t, PETSC_INT32), \
535           PETSC_GENERIC_CV(       int64_t, PETSC_INT64), \
536           PETSC_GENERIC_CV(      uint64_t, PETSC_INT64) \
537           PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))
538 
539       #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))
540 
541       #if PetscDefined(HAVE_COMPLEX)
542         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX , PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
543       #else
544         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
545       #endif
546 
547       #define PetscAssertPointer_String(h) \
548         _Generic((h), \
549           default: "memory", \
550           PETSC_GENERIC_CV_STRINGIZE(char), \
551           PETSC_GENERIC_CV_STRINGIZE(signed char), \
552           PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
553           PETSC_GENERIC_CV_STRINGIZE(short), \
554           PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
555           PETSC_GENERIC_CV_STRINGIZE(float), \
556           PETSC_GENERIC_CV_STRINGIZE(double), \
557           PETSC_GENERIC_CV_STRINGIZE(int32_t), \
558           PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
559           PETSC_GENERIC_CV_STRINGIZE(int64_t), \
560           PETSC_GENERIC_CV_STRINGIZE(uint64_t) \
561           PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
562     #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
563       #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
564       #define PetscAssertPointer_String(h)        "memory"
565     #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
566     #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
567     #define PetscValidFunction(f, arg) PetscCheck((f), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Function Pointer: Parameter # %d", arg)
568   #else // PetscDefined(USE_DEBUG)
569     #define PetscValidHeaderSpecific(h, ck, arg) \
570       do { \
571         (void)(h); \
572       } while (0)
573     #define PetscValidHeaderSpecificType(h, ck, arg, t) \
574       do { \
575         (void)(h); \
576       } while (0)
577     #define PetscValidHeader(h, arg) \
578       do { \
579         (void)(h); \
580       } while (0)
581     #define PetscAssertPointer(h, arg) \
582       do { \
583         (void)(h); \
584       } while (0)
585     #define PetscValidFunction(h, arg) \
586       do { \
587         (void)(h); \
588       } while (0)
589   #endif // PetscDefined(USE_DEBUG)
590 #endif   // PETSC_CLANG_STATIC_ANALYZER
591 
592 #define PetscValidPointer(h, arg)       PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
593 #define PetscValidCharPointer(h, arg)   PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
594 #define PetscValidIntPointer(h, arg)    PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
595 #define PetscValidInt64Pointer(h, arg)  PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
596 #define PetscValidCountPointer(h, arg)  PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
597 #define PetscValidBoolPointer(h, arg)   PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
598 #define PetscValidScalarPointer(h, arg) PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
599 #define PetscValidRealPointer(h, arg)   PETSC_DEPRECATED_MACRO(3, 20, 0, "PetscAssertPointer()", ) PetscAssertPointer(h, arg)
600 
601 #define PetscSorted(n, idx, sorted) \
602   do { \
603     (sorted) = PETSC_TRUE; \
604     for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
605       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
606         (sorted) = PETSC_FALSE; \
607         break; \
608       } \
609     } \
610   } while (0)
611 
612 #if !defined(PETSC_CLANG_STATIC_ANALYZER)
613   #if !defined(PETSC_USE_DEBUG)
614 
615     #define PetscCheckSameType(a, arga, b, argb) \
616       do { \
617         (void)(a); \
618         (void)(b); \
619       } while (0)
620     #define PetscCheckTypeName(a, type) \
621       do { \
622         (void)(a); \
623       } while (0)
624     #define PetscCheckTypeNames(a, type1, type2) \
625       do { \
626         (void)(a); \
627       } while (0)
628     #define PetscValidType(a, arg) \
629       do { \
630         (void)(a); \
631       } while (0)
632     #define PetscCheckSameComm(a, arga, b, argb) \
633       do { \
634         (void)(a); \
635         (void)(b); \
636       } while (0)
637     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
638       do { \
639         (void)(a); \
640         (void)(b); \
641       } while (0)
642     #define PetscValidLogicalCollectiveScalar(a, b, arg) \
643       do { \
644         (void)(a); \
645         (void)(b); \
646       } while (0)
647     #define PetscValidLogicalCollectiveReal(a, b, arg) \
648       do { \
649         (void)(a); \
650         (void)(b); \
651       } while (0)
652     #define PetscValidLogicalCollectiveInt(a, b, arg) \
653       do { \
654         (void)(a); \
655         (void)(b); \
656       } while (0)
657     #define PetscValidLogicalCollectiveIntComm(a, b, arg) \
658       do { \
659         (void)(a); \
660         (void)(b); \
661       } while (0)
662     #define PetscValidLogicalCollectiveCount(a, b, arg) \
663       do { \
664         (void)(a); \
665         (void)(b); \
666       } while (0)
667     #define PetscValidLogicalCollectiveMPIInt(a, b, arg) \
668       do { \
669         (void)(a); \
670         (void)(b); \
671       } while (0)
672     #define PetscValidLogicalCollectiveBool(a, b, arg) \
673       do { \
674         (void)(a); \
675         (void)(b); \
676       } while (0)
677     #define PetscValidLogicalCollectiveEnum(a, b, arg) \
678       do { \
679         (void)(a); \
680         (void)(b); \
681       } while (0)
682     #define PetscCheckSorted(n, idx) \
683       do { \
684         (void)(n); \
685         (void)(idx); \
686       } while (0)
687 
688   #else
689 
690     /*
691   This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
692   member associated with the string type_name that can be quickly compared.
693 
694   **Do not swap this macro to compare string type_name!**
695 
696   This macro is used incorrectly in the code. Many places that do not need identity of the
697   types incorrectly call this check and would need to be fixed if this macro is enabled.
698 */
699     #if 0
700       #define PetscCheckSameType(a, arga, b, argb) \
701         do { \
702           PetscBool pcst_type_eq_ = PETSC_TRUE; \
703           PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
704           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); \
705         } while (0)
706     #else
707       #define PetscCheckSameType(a, arga, b, argb) \
708         do { \
709           (void)(a); \
710           (void)(b); \
711         } while (0)
712     #endif
713 
714     /*
715     Check type_name
716 */
717     #define PetscCheckTypeName(a, type) \
718       do { \
719         PetscBool _7_match; \
720         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
721         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
722       } while (0)
723 
724     #define PetscCheckTypeNames(a, type1, type2) \
725       do { \
726         PetscBool _7_match; \
727         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
728         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
729       } while (0)
730 
731     /*
732    Use this macro to check if the type is set
733 */
734     #define PetscValidType(a, arg) PetscCheck(((PetscObject)(a))->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "%s object's type is not set: Argument # %d", ((PetscObject)(a))->class_name, arg)
735 
736     /*
737    Sometimes object must live on same communicator to inter-operate
738 */
739     #define PetscCheckSameComm(a, arga, b, argb) \
740       do { \
741         PetscMPIInt _7_flag; \
742         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
743         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); \
744       } while (0)
745 
746     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
747       do { \
748         PetscCheckSameType(a, arga, b, argb); \
749         PetscCheckSameComm(a, arga, b, argb); \
750       } while (0)
751 
752     #define PetscValidLogicalCollectiveScalar(a, b, arg) \
753       do { \
754         PetscScalar b0 = (b); \
755         PetscReal   b1[5]; \
756         if (PetscIsNanScalar(b0)) { \
757           b1[4] = 1; \
758         } else { \
759           b1[4] = 0; \
760         }; \
761         b1[0] = -PetscRealPart(b0); \
762         b1[1] = PetscRealPart(b0); \
763         b1[2] = -PetscImaginaryPart(b0); \
764         b1[3] = PetscImaginaryPart(b0); \
765         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
766         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); \
767       } while (0)
768 
769     #define PetscValidLogicalCollectiveReal(a, b, arg) \
770       do { \
771         PetscReal b0 = (b), b1[3]; \
772         if (PetscIsNanReal(b0)) { \
773           b1[2] = 1; \
774         } else { \
775           b1[2] = 0; \
776         }; \
777         b1[0] = -b0; \
778         b1[1] = b0; \
779         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
780         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); \
781       } while (0)
782 
783     #define PetscValidLogicalCollectiveInt(a, b, arg) \
784       do { \
785         PetscInt b0 = (b), b1[2]; \
786         b1[0]       = -b0; \
787         b1[1]       = b0; \
788         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
789         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
790       } while (0)
791 
792     #define PetscValidLogicalCollectiveIntComm(a, b, arg) \
793       do { \
794         PetscInt b1[2]; \
795         b1[0] = -b; \
796         b1[1] = b; \
797         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
798         PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
799       } while (0)
800 
801     #define PetscValidLogicalCollectiveCount(a, b, arg) \
802       do { \
803         PetscCount b0 = (b), b1[2]; \
804         b1[0]         = -b0; \
805         b1[1]         = b0; \
806         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
807         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
808       } while (0)
809 
810     #define PetscValidLogicalCollectiveMPIInt(a, b, arg) \
811       do { \
812         PetscMPIInt b0 = (b), b1[2]; \
813         b1[0]          = -b0; \
814         b1[1]          = b0; \
815         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
816         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
817       } while (0)
818 
819     #define PetscValidLogicalCollectiveBool(a, b, arg) \
820       do { \
821         PetscBool b0 = (PetscBool)(b), b1[2]; \
822         b1[0]        = !b0; \
823         b1[1]        = b0; \
824         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
825         PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
826       } while (0)
827 
828     #define PetscValidLogicalCollectiveEnum(a, b, arg) \
829       do { \
830         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
831         b1[0]          = -b0; \
832         b1[1]          = b0; \
833         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
834         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
835       } while (0)
836 
837     #define PetscCheckSorted(n, idx) \
838       do { \
839         PetscBool _1_flg; \
840         PetscSorted(n, idx, _1_flg); \
841         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
842       } while (0)
843 
844   #endif
845 #else  /* PETSC_CLANG_STATIC_ANALYZER */
846 template <typename Ta, typename Tb>
847 extern void PetscCheckSameType(Ta, int, Tb, int);
848 template <typename Ta, typename Tb>
849 extern void PetscCheckTypeName(Ta, Tb);
850 template <typename Ta, typename Tb, typename Tc>
851 extern void PetscCheckTypeNames(Ta, Tb, Tc);
852 template <typename T>
853 extern void PetscValidType(T, int);
854 template <typename Ta, typename Tb>
855 extern void PetscCheckSameComm(Ta, int, Tb, int);
856 template <typename Ta, typename Tb>
857 extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
858 template <typename Ta, typename Tb>
859 extern void PetscValidLogicalCollectiveScalar(Ta, Tb, int);
860 template <typename Ta, typename Tb>
861 extern void PetscValidLogicalCollectiveReal(Ta, Tb, int);
862 template <typename Ta, typename Tb>
863 extern void PetscValidLogicalCollectiveInt(Ta, Tb, int);
864 template <typename Ta, typename Tb>
865 extern void PetscValidLogicalCollectiveCount(Ta, Tb, int);
866 template <typename Ta, typename Tb>
867 extern void PetscValidLogicalCollectiveMPIInt(Ta, Tb, int);
868 template <typename Ta, typename Tb>
869 extern void PetscValidLogicalCollectiveBool(Ta, Tb, int);
870 template <typename Ta, typename Tb>
871 extern void PetscValidLogicalCollectiveEnum(Ta, Tb, int);
872 template <typename T>
873 extern void PetscCheckSorted(PetscInt, T);
874 #endif /* PETSC_CLANG_STATIC_ANALYZER */
875 
876 /*MC
877    PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.
878 
879   Synopsis:
880    #include "petsc/private/petscimpl.h"
881    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
882 
883    Input Parameters:
884 +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
885 .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
886 .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
887 -   args - the arguments for the method, for example, (ksp,restart))
888 
889    Level: developer
890 
891    Notes:
892    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
893 
894    Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
895    in the object.
896 
897 .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
898 M*/
899 #define PetscTryMethod(obj, A, B, C) \
900   do { \
901     PetscErrorCode(*_7_f) B; \
902     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
903     if (_7_f) PetscCall((*_7_f)C); \
904   } while (0)
905 
906 /*MC
907    PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.
908 
909   Synopsis:
910    #include "petsc/private/petscimpl.h"
911    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))
912 
913    Input Parameters:
914 +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
915 .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
916 .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
917 -   args - the arguments for the method, for example, (ksp,restart))
918 
919    Level: developer
920 
921    Notes:
922    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
923 
924    Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
925    in the object.
926 
927 .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
928 M*/
929 #define PetscUseMethod(obj, A, B, C) \
930   do { \
931     PetscErrorCode(*_7_f) B; \
932     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
933     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
934     PetscCall((*_7_f)C); \
935   } while (0)
936 
937 /*
938   Use Microsoft traditional preprocessor.
939 
940   The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
941   sets  _MSVC_TRADITIONAL to zero so this code path is not used.
942 
943   It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor
944 
945   These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist
946 
947   PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
948 */
949 #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)
950 
951   #define PetscUseTypeMethod(obj, OP, ...) \
952     do { \
953       PetscErrorCode ierr_p_; \
954       PetscStackUpdateLine; \
955       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); \
956       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
957       PetscCall(ierr_p_); \
958     } while (0)
959 
960   #define PetscTryTypeMethod(obj, OP, ...) \
961     do { \
962       if ((obj)->ops->OP) { \
963         PetscErrorCode ierr_p_; \
964         PetscStackUpdateLine; \
965         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
966         PetscCall(ierr_p_); \
967       } \
968     } while (0)
969 
970 #else
971 
972   /*MC
973    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 
975   Synopsis:
976    #include "petsc/private/petscimpl.h"
977    PetscUseTypeMethod(obj, method, other_args)
978 
979    Input Parameters:
980 +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
981 .   method - the name of the method, for example, mult for the PETSc routine `MatMult()`
982 -   other_args - the other arguments for the method, `obj` is the first argument
983 
984    Level: developer
985 
986    Note:
987    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
988 
989    Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
990 
991 .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
992 M*/
993   #define PetscUseTypeMethod(obj, ...) \
994     do { \
995       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
996                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
997       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
998     } while (0)
999 
1000   /*MC
1001    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 
1003   Synopsis:
1004    #include "petsc/private/petscimpl.h"
1005    PetscTryTypeMethod(obj, method, other_args)
1006 
1007    Input Parameters:
1008 +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
1009 .   method - the name of the method, for example, mult for the PETSc routine `MatMult()`
1010 -   other_args - the other arguments for the method, `obj` is the first argument
1011 
1012    Level: developer
1013 
1014    Note:
1015    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.
1016 
1017    Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`
1018 
1019 .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1020 M*/
1021   #define PetscTryTypeMethod(obj, ...) \
1022     do { \
1023       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1024     } while (0)
1025 
1026 #endif
1027 
1028 /*MC
1029    PetscObjectStateIncrease - Increases the state of any `PetscObject`
1030 
1031    Synopsis:
1032    #include "petsc/private/petscimpl.h"
1033    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
1034 
1035    Logically Collective
1036 
1037    Input Parameter:
1038 .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1039          cast with a (PetscObject), for example,
1040          `PetscObjectStateIncrease`((`PetscObject`)mat);
1041 
1042    Level: developer
1043 
1044    Notes:
1045    Object state is a 64-bit integer which gets increased every time
1046    the object is changed internally. By saving and later querying the object state
1047    one can determine whether information about the object is still current.
1048    Currently, state is maintained for `Vec` and `Mat` objects.
1049 
1050    This routine is mostly for internal use by PETSc; a developer need only
1051    call it after explicit access to an object's internals. Routines such
1052    as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
1053    precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.
1054 
1055    Routines such as `VecNorm()` can bypass the computation if the norm has already been computed and the vector's state has not changed.
1056 
1057    This routine is logically collective because state equality comparison needs to be possible without communication.
1058 
1059    `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.
1060 
1061 .seealso: `PetscObjectStateGet()`, `PetscObject`
1062 M*/
1063 #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))
1064 
1065 PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1066 PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1067 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1068 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1069 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1070 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1071 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1072 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1073 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1074 PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;
1075 
1076 /*MC
1077    PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`
1078 
1079    Synopsis:
1080    #include "petsc/private/petscimpl.h"
1081    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)
1082 
1083    Not Collective
1084 
1085    Input Parameters:
1086 +  obj - the object to which data is to be attached
1087 .  id - the identifier for the data
1088 -  data - the data to  be attached, a `PetscInt`
1089 
1090    Level: developer
1091 
1092    Notes:
1093    The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`
1094 
1095    This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1096    attached with `PetscObjectCompose()`
1097 
1098 .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1099           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1100           `PetscObjectCompose()`, `PetscObjectQuery()`
1101 M*/
1102 #define PetscObjectComposedDataSetInt(obj, id, data) \
1103   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1104 
1105 /*MC
1106    PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`
1107 
1108    Synopsis:
1109    #include "petsc/private/petscimpl.h"
1110    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)
1111 
1112    Not Collective
1113 
1114    Input Parameters:
1115 +  obj - the object from which data is to be retrieved
1116 -  id - the identifier for the data
1117 
1118    Output Parameters:
1119 +  data - the data to be retrieved, a `PetscInt`
1120 -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1121 
1122    Level: developer
1123 
1124    Notes:
1125    The `data` and `flag` variables are inlined, so they are not pointers.
1126 
1127 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1128           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1129           `PetscObjectCompose()`, `PetscObjectQuery()`
1130 M*/
1131 #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 
1133 /*MC
1134    PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`
1135 
1136    Synopsis:
1137    #include "petsc/private/petscimpl.h"
1138    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)
1139 
1140    Not Collective
1141 
1142    Input Parameters:
1143 +  obj - the object to which data is to be attached
1144 .  id - the identifier for the data
1145 -  data - the data to  be attached, a `PetscInt` array
1146 
1147    Level: developer
1148 
1149    Notes:
1150    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1151 
1152    The length of the array accessed must be known, it is not available through this API.
1153 
1154 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1155           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1156           `PetscObjectCompose()`, `PetscObjectQuery()`
1157 M*/
1158 #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1159   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1160 
1161 /*MC
1162    PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`
1163 
1164    Synopsis:
1165    #include "petsc/private/petscimpl.h"
1166    PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)
1167 
1168    Not Collective
1169 
1170    Input Parameters:
1171 +  obj - the object from which data is to be retrieved
1172 -  id - the identifier for the data
1173 
1174    Output Parameters:
1175 +  data - the data to be retrieved, a `PetscInt` array
1176 -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1177 
1178    Level: developer
1179 
1180    Notes:
1181    The `data` and `flag` variables are inlined, so they are not pointers.
1182 
1183    The length of the array accessed must be known, it is not available through this API.
1184 
1185 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1186           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1187           `PetscObjectCompose()`, `PetscObjectQuery()`
1188 M*/
1189 #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1190   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1191 
1192 /*MC
1193    PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`
1194 
1195    Synopsis:
1196    #include "petsc/private/petscimpl.h"
1197    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)
1198 
1199    Not Collective
1200 
1201    Input Parameters:
1202 +  obj - the object to which data is to be attached
1203 .  id - the identifier for the data
1204 -  data - the data to  be attached, a `PetscReal`
1205 
1206    Level: developer
1207 
1208    Note:
1209    The `data` identifier can be determined through a call to  `PetscObjectComposedDataRegister()`
1210 
1211 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1212           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1213           `PetscObjectCompose()`, `PetscObjectQuery()`
1214 M*/
1215 #define PetscObjectComposedDataSetReal(obj, id, data) \
1216   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1217 
1218 /*MC
1219    PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`
1220 
1221    Synopsis:
1222    #include "petsc/private/petscimpl.h"
1223    PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)
1224 
1225    Not Collective
1226 
1227    Input Parameters:
1228 +  obj - the object from which data is to be retrieved
1229 -  id - the identifier for the data
1230 
1231    Output Parameters:
1232 +  data - the data to be retrieved, a `PetscReal`
1233 -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1234 
1235    Level: developer
1236 
1237    Note:
1238    The `data` and `flag` variables are inlined, so they are not pointers.
1239 
1240 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1241           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1242           `PetscObjectCompose()`, `PetscObjectQuery()`
1243 M*/
1244 #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 
1246 /*MC
1247    PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`
1248 
1249    Synopsis:
1250    #include "petsc/private/petscimpl.h"
1251    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)
1252 
1253    Not Collective
1254 
1255    Input Parameters:
1256 +  obj - the object to which data is to be attached
1257 .  id - the identifier for the data
1258 -  data - the data to  be attached
1259 
1260    Level: developer
1261 
1262    Notes:
1263    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1264 
1265    The length of the array accessed must be known, it is not available through this API.
1266 
1267 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1268           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1269           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1270 M*/
1271 #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1272   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1273 
1274 /*MC
1275    PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`
1276 
1277    Synopsis:
1278    #include "petsc/private/petscimpl.h"
1279    PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)
1280 
1281    Not Collective
1282 
1283    Input Parameters:
1284 +  obj - the object from which data is to be retrieved
1285 -  id - the identifier for the data
1286 
1287    Output Parameters:
1288 +  data - the data to be retrieved, a `PetscReal` array
1289 -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1290 
1291    Level: developer
1292 
1293    Notes:
1294    The `data` and `flag` variables are inlined, so they are not pointers.
1295 
1296    The length of the array accessed must be known, it is not available through this API.
1297 
1298 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1299           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1300           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1301 M*/
1302 #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1303   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1304 
1305 /*MC
1306    PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`
1307 
1308    Synopsis:
1309    #include "petsc/private/petscimpl.h"
1310    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)
1311 
1312    Not Collective
1313 
1314    Input Parameters:
1315 +  obj - the object to which data is to be attached
1316 .  id - the identifier for the data
1317 -  data - the data to  be attached, a `PetscScalar`
1318 
1319    Level: developer
1320 
1321    Note:
1322    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1323 
1324 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1325           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1326           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1327 M*/
1328 #if defined(PETSC_USE_COMPLEX)
1329   #define PetscObjectComposedDataSetScalar(obj, id, data) \
1330     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1331 #else
1332   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1333 #endif
1334 /*MC
1335    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`
1336 
1337    Synopsis:
1338    #include "petsc/private/petscimpl.h"
1339    PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)
1340 
1341    Not Collective
1342 
1343    Input Parameters:
1344 +  obj - the object from which data is to be retrieved
1345 -  id - the identifier for the data
1346 
1347    Output Parameters:
1348 +  data - the data to be retrieved, a `PetscScalar`
1349 -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1350 
1351    Level: developer
1352 
1353    Note:
1354    The `data` and `flag` variables are inlined, so they are not pointers.
1355 
1356 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1357           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1358           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1359 M*/
1360 #if defined(PETSC_USE_COMPLEX)
1361   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1362     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1363 #else
1364   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1365 #endif
1366 
1367 /*MC
1368    PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`
1369 
1370    Synopsis:
1371    #include "petsc/private/petscimpl.h"
1372    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)
1373 
1374    Not Collective
1375 
1376    Input Parameters:
1377 +  obj - the object to which data is to be attached
1378 .  id - the identifier for the data
1379 -  data - the data to  be attached, a `PetscScalar` array
1380 
1381    Level: developer
1382 
1383    Notes:
1384    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`
1385 
1386    The length of the array accessed must be known, it is not available through this API.
1387 
1388 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1389           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1390           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1391 M*/
1392 #if defined(PETSC_USE_COMPLEX)
1393   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1394     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1395 #else
1396   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1397 #endif
1398 /*MC
1399    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1400    attached to an object
1401 
1402    Synopsis:
1403    #include "petsc/private/petscimpl.h"
1404    PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)
1405 
1406    Not Collective
1407 
1408    Input Parameters:
1409 +  obj - the object from which data is to be retrieved
1410 -  id - the identifier for the data
1411 
1412    Output Parameters:
1413 +  data - the data to be retrieved, a `PetscScalar` array
1414 -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise
1415 
1416    Level: developer
1417 
1418    Notes:
1419    The `data` and `flag` variables are inlined, so they are not pointers.
1420 
1421    The length of the array accessed must be known, it is not available through this API.
1422 
1423 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1424           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1425           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1426 M*/
1427 #if defined(PETSC_USE_COMPLEX)
1428   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1429     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1430 #else
1431   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1432 #endif
1433 
1434 PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1435 PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1436 PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1437 PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1438 PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1439 PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1440 PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;
1441 
1442 PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1443 PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;
1444 
1445 struct PetscCommStash {
1446   struct PetscCommStash *next;
1447   MPI_Comm               comm;
1448 };
1449 
1450 /*
1451   PETSc communicators have this attribute, see
1452   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1453 */
1454 typedef struct {
1455   PetscMPIInt            tag;       /* next free tag value */
1456   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1457   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1458   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1459   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1460 } PetscCommCounter;
1461 
1462 typedef enum {
1463   STATE_BEGIN,
1464   STATE_PENDING,
1465   STATE_END
1466 } SRState;
1467 
1468 typedef enum {
1469   PETSC_SR_REDUCE_SUM = 0,
1470   PETSC_SR_REDUCE_MAX = 1,
1471   PETSC_SR_REDUCE_MIN = 2
1472 } PetscSRReductionType;
1473 
1474 typedef struct {
1475   MPI_Comm              comm;
1476   MPI_Request           request;
1477   PetscBool             mix;
1478   PetscBool             async;
1479   PetscScalar          *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
1480   PetscScalar          *gvalues;    /* values after call to MPI_Allreduce() */
1481   void                **invecs;     /* for debugging only, vector/memory used with each op */
1482   PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
1483   struct {
1484     PetscScalar v;
1485     PetscInt    i;
1486   }          *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1487   SRState     state;                     /* are we calling xxxBegin() or xxxEnd()? */
1488   PetscMPIInt maxops;                    /* total amount of space we have for requests */
1489   PetscMPIInt numopsbegin;               /* number of requests that have been queued in */
1490   PetscMPIInt numopsend;                 /* number of requests that have been gotten by user */
1491 } PetscSplitReduction;
1492 
1493 PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1494 PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1495 PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);
1496 
1497 #if defined(PETSC_HAVE_THREADSAFETY)
1498   #if defined(PETSC_HAVE_CONCURRENCYKIT)
1499     #if defined(__cplusplus)
1500 /*  CK does not have extern "C" protection in their include files */
1501 extern "C" {
1502     #endif
1503     #include <ck_spinlock.h>
1504     #if defined(__cplusplus)
1505 }
1506     #endif
1507 typedef ck_spinlock_t PetscSpinlock;
1508 
PetscSpinlockCreate(PetscSpinlock * ck_spinlock)1509 static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1510 {
1511   ck_spinlock_init(ck_spinlock);
1512   return PETSC_SUCCESS;
1513 }
PetscSpinlockLock(PetscSpinlock * ck_spinlock)1514 static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1515 {
1516   ck_spinlock_lock(ck_spinlock);
1517   return PETSC_SUCCESS;
1518 }
PetscSpinlockUnlock(PetscSpinlock * ck_spinlock)1519 static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1520 {
1521   ck_spinlock_unlock(ck_spinlock);
1522   return PETSC_SUCCESS;
1523 }
PetscSpinlockDestroy(PetscSpinlock * ck_spinlock)1524 static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1525 {
1526   return PETSC_SUCCESS;
1527 }
1528   #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1529     #if defined(__cplusplus)
1530       // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1531       #include <atomic>
1532       #define petsc_atomic_flag                 std::atomic_flag
1533       #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1534       #define petsc_atomic_flag_clear(p)        std::atomic_flag_clear_explicit(p, std::memory_order_release)
1535     #else
1536       #include <stdatomic.h>
1537       #define petsc_atomic_flag                 atomic_flag
1538       #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1539       #define petsc_atomic_flag_clear(p)        atomic_flag_clear_explicit(p, memory_order_release)
1540     #endif
1541 
1542 typedef petsc_atomic_flag PetscSpinlock;
1543 
PetscSpinlockCreate(PetscSpinlock * spinlock)1544 static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1545 {
1546   petsc_atomic_flag_clear(spinlock);
1547   return PETSC_SUCCESS;
1548 }
PetscSpinlockLock(PetscSpinlock * spinlock)1549 static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1550 {
1551   do {
1552   } while (petsc_atomic_flag_test_and_set(spinlock));
1553   return PETSC_SUCCESS;
1554 }
PetscSpinlockUnlock(PetscSpinlock * spinlock)1555 static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1556 {
1557   petsc_atomic_flag_clear(spinlock);
1558   return PETSC_SUCCESS;
1559 }
PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock * spinlock)1560 static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1561 {
1562   return PETSC_SUCCESS;
1563 }
1564     #undef petsc_atomic_flag_test_and_set
1565     #undef petsc_atomic_flag_clear
1566     #undef petsc_atomic_flag
1567 
1568   #elif defined(PETSC_HAVE_OPENMP)
1569 
1570     #include <omp.h>
1571 typedef omp_lock_t PetscSpinlock;
1572 
PetscSpinlockCreate(PetscSpinlock * omp_lock)1573 static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1574 {
1575   omp_init_lock(omp_lock);
1576   return PETSC_SUCCESS;
1577 }
PetscSpinlockLock(PetscSpinlock * omp_lock)1578 static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1579 {
1580   omp_set_lock(omp_lock);
1581   return PETSC_SUCCESS;
1582 }
PetscSpinlockUnlock(PetscSpinlock * omp_lock)1583 static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1584 {
1585   omp_unset_lock(omp_lock);
1586   return PETSC_SUCCESS;
1587 }
PetscSpinlockDestroy(PetscSpinlock * omp_lock)1588 static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1589 {
1590   omp_destroy_lock(omp_lock);
1591   return PETSC_SUCCESS;
1592 }
1593   #else
1594     #if defined(__cplusplus)
1595       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1596     #else
1597       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1598     #endif
1599   #endif
1600 
1601 #else
1602 typedef int PetscSpinlock;
1603   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
1604   #define PetscSpinlockLock(a)    PETSC_SUCCESS
1605   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
1606   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1607 #endif
1608 
1609 #if defined(PETSC_HAVE_THREADSAFETY)
1610 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1611 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1612 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1613 PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1614 #endif
1615 
1616 PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1617 PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1618 PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1619 PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1620 PETSC_EXTERN PetscBool     PetscPrintFunctionList;
1621 
1622 #if defined(PETSC_HAVE_ADIOS)
1623 PETSC_EXTERN int64_t Petsc_adios_group;
1624 #endif
1625 
1626 #if defined(PETSC_HAVE_KOKKOS)
1627 PETSC_INTERN PetscBool      PetscBeganKokkos;
1628 PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1629 PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1630 PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1631 #endif
1632 
1633 #if defined(PETSC_HAVE_OPENMP)
1634 PETSC_EXTERN PetscInt PetscNumOMPThreads;
1635 #endif
1636 
1637 struct _n_PetscObjectList {
1638   char            name[256];
1639   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1640   PetscObject     obj;
1641   PetscObjectList next;
1642 };
1643 
1644 /*E
1645     PetscPrecision - Precision of a real number
1646 
1647     Values:
1648 +   `PETSC_PRECISION_INVALID`     - an invalid value
1649 .   `PETSC_PRECISION_BFLOAT16`    - half precision (Google Brain bfloat16)
1650 .   `PETSC_PRECISION___FP16`      - half precison (IEEE FP16)
1651 .   `PETSC_PRECISION_SINGLE`      - single precision
1652 .   `PETSC_PRECISION_DOUBLE`      - double precision
1653 -   `PETSC_PRECISION___FLOAT128`  - quadruple precision (__float128)
1654 
1655     Level: intermediate
1656 E*/
1657 
1658 typedef enum {
1659   PETSC_PRECISION_INVALID = 0,
1660   PETSC_PRECISION_BFLOAT16,
1661   PETSC_PRECISION___FP16,
1662   PETSC_PRECISION_SINGLE,
1663   PETSC_PRECISION_DOUBLE,
1664   PETSC_PRECISION___FLOAT128
1665 } PetscPrecision;
1666 
1667 // The precision of PetscScalar and PetscReal
1668 #if defined(PETSC_USE_REAL___FP16)
1669   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
1670 #elif defined(PETSC_USE_REAL_SINGLE)
1671   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
1672 #elif defined(PETSC_USE_REAL_DOUBLE)
1673   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
1674 #elif defined(PETSC_USE_REAL___FLOAT128)
1675   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
1676 #endif
1677 
1678 PETSC_EXTERN const char *const PetscPrecisionTypes[];
1679