Actual source code: petscdevicetypes.h
1: #ifndef PETSCDEVICETYPES_H
2: #define PETSCDEVICETYPES_H
4: #include <petscsys.h>
6: // Some overzealous older gcc versions warn that the comparisons below are always true. Neat
7: // that it can detect this, but the tautology *is* the point of the static_assert()!
8: #if defined(__GNUC__) && __GNUC__ >= 6 && !PetscDefined(HAVE_WINDOWS_COMPILERS)
9: #define PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 1
10: #else
11: #define PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 0
12: #endif
14: /* SUBMANSEC = Sys */
16: /*E
17: PetscMemType - Memory type of a pointer
19: Level: intermediate
21: Notes:
22: `PETSC_MEMTYPE_KOKKOS` depends on the Kokkos backend configuration
24: Developer Notes:
25: This enum uses a function (`PetscMemTypeToString()`) to convert to string representation so
26: cannot be used in `PetscOptionsEnum()`.
28: Developer Note:
29: Encoding of the bitmask in binary: xxxxyyyz
30: .vb
31: z = 0 - Host memory
32: z = 1 - Device memory
33: yyy = 000 - CUDA-related memory
34: yyy = 001 - HIP-related memory
35: yyy = 010 - SYCL-related memory
36: xxxxyyy1 = 0000,0001 - CUDA memory
37: xxxxyyy1 = 0001,0001 - CUDA NVSHMEM memory
38: xxxxyyy1 = 0000,0011 - HIP memory
39: xxxxyyy1 = 0000,0101 - SYCL memory
40: .ve
42: Other types of memory, e.g., CUDA managed memory, can be added when needed.
44: .seealso: `PetscMemTypeToString()`, `VecGetArrayAndMemType()`,
45: `PetscSFBcastWithMemTypeBegin()`, `PetscSFReduceWithMemTypeBegin()`
46: E*/
47: typedef enum {
48: PETSC_MEMTYPE_HOST = 0,
49: PETSC_MEMTYPE_DEVICE = 0x01,
50: PETSC_MEMTYPE_CUDA = 0x01,
51: PETSC_MEMTYPE_NVSHMEM = 0x11,
52: PETSC_MEMTYPE_HIP = 0x03,
53: PETSC_MEMTYPE_SYCL = 0x05,
54: } PetscMemType;
55: #if PetscDefined(HAVE_CUDA)
56: #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_CUDA
57: #elif PetscDefined(HAVE_HIP)
58: #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_HIP
59: #elif PetscDefined(HAVE_SYCL)
60: #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_SYCL
61: #else
62: #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_HOST
63: #endif
65: #define PetscMemTypeHost(m) (((m)&0x1) == PETSC_MEMTYPE_HOST)
66: #define PetscMemTypeDevice(m) (((m)&0x1) == PETSC_MEMTYPE_DEVICE)
67: #define PetscMemTypeCUDA(m) (((m)&0xF) == PETSC_MEMTYPE_CUDA)
68: #define PetscMemTypeHIP(m) (((m)&0xF) == PETSC_MEMTYPE_HIP)
69: #define PetscMemTypeSYCL(m) (((m)&0xF) == PETSC_MEMTYPE_SYCL)
70: #define PetscMemTypeNVSHMEM(m) ((m) == PETSC_MEMTYPE_NVSHMEM)
72: #if defined(__cplusplus)
73: #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
74: #pragma GCC diagnostic push
75: #pragma GCC diagnostic ignored "-Wtautological-compare"
76: #endif
77: static_assert(PetscMemTypeHost(PETSC_MEMTYPE_HOST), "");
78: static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_DEVICE), "");
79: static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_CUDA), "");
80: static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_HIP), "");
81: static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_SYCL), "");
82: static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_NVSHMEM), "");
84: static_assert(!PetscMemTypeDevice(PETSC_MEMTYPE_HOST), "");
85: static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_DEVICE), "");
86: static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_CUDA), "");
87: static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_HIP), "");
88: static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_SYCL), "");
89: static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_NVSHMEM), "");
91: static_assert(PetscMemTypeCUDA(PETSC_MEMTYPE_CUDA), "");
92: static_assert(PetscMemTypeCUDA(PETSC_MEMTYPE_NVSHMEM), "");
93: #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
94: #pragma GCC diagnostic pop
95: #endif
96: #endif // __cplusplus
98: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscMemTypeToString(PetscMemType mtype)
99: {
100: #ifdef __cplusplus
101: static_assert(PETSC_MEMTYPE_CUDA == PETSC_MEMTYPE_DEVICE, "");
102: #endif
103: #define PETSC_CASE_NAME(v) \
104: case v: \
105: return PetscStringize(v)
107: switch (mtype) {
108: PETSC_CASE_NAME(PETSC_MEMTYPE_HOST);
109: /* PETSC_CASE_NAME(PETSC_MEMTYPE_DEVICE); same as PETSC_MEMTYPE_CUDA */
110: PETSC_CASE_NAME(PETSC_MEMTYPE_CUDA);
111: PETSC_CASE_NAME(PETSC_MEMTYPE_NVSHMEM);
112: PETSC_CASE_NAME(PETSC_MEMTYPE_HIP);
113: PETSC_CASE_NAME(PETSC_MEMTYPE_SYCL);
114: }
115: PetscUnreachable();
116: return "invalid";
117: #undef PETSC_CASE_NAME
118: }
120: #define PETSC_OFFLOAD_VECKOKKOS_DEPRECATED PETSC_OFFLOAD_VECKOKKOS PETSC_DEPRECATED_ENUM("Use PETSC_OFFLOAD_KOKKOS (since version 3.17.0)")
122: /*E
123: PetscOffloadMask - indicates which memory (CPU, GPU, or none) contains valid data
125: Values:
126: + `PETSC_OFFLOAD_UNALLOCATED` - no memory contains valid matrix entries; NEVER used for vectors
127: . `PETSC_OFFLOAD_GPU` - GPU has valid vector/matrix entries
128: . `PETSC_OFFLOAD_CPU` - CPU has valid vector/matrix entries
129: . `PETSC_OFFLOAD_BOTH` - Both GPU and CPU have valid vector/matrix entries and they match
130: - `PETSC_OFFLOAD_KOKKOS` - Reserved for Kokkos matrix and vector. It means the offload is managed by Kokkos, thus this flag itself cannot tell you where the valid data is.
132: Level: developer
134: Developer Notes:
135: This enum uses a function (`PetscOffloadMaskToString()`) to convert to string representation so
136: cannot be used in `PetscOptionsEnum()`.
138: .seealso: `PetscOffloadMaskToString()`, `PetscOffloadMaskToMemType()`, `PetscOffloadMaskToDeviceCopyMode()`
139: E*/
140: typedef enum {
141: PETSC_OFFLOAD_UNALLOCATED = 0x0,
142: PETSC_OFFLOAD_CPU = 0x1,
143: PETSC_OFFLOAD_GPU = 0x2,
144: PETSC_OFFLOAD_BOTH = 0x3,
145: PETSC_OFFLOAD_VECKOKKOS_DEPRECATED = 0x100,
146: PETSC_OFFLOAD_KOKKOS = 0x100
147: } PetscOffloadMask;
149: #define PetscOffloadUnallocated(m) ((m) == PETSC_OFFLOAD_UNALLOCATED)
150: #define PetscOffloadHost(m) (((m)&PETSC_OFFLOAD_CPU) == PETSC_OFFLOAD_CPU)
151: #define PetscOffloadDevice(m) (((m)&PETSC_OFFLOAD_GPU) == PETSC_OFFLOAD_GPU)
152: #define PetscOffloadBoth(m) ((m) == PETSC_OFFLOAD_BOTH)
154: #if defined(__cplusplus)
155: #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
156: #pragma GCC diagnostic push
157: #pragma GCC diagnostic ignored "-Wtautological-compare"
158: #endif
159: static_assert(!PetscOffloadHost(PETSC_OFFLOAD_UNALLOCATED), "");
160: static_assert(PetscOffloadHost(PETSC_OFFLOAD_BOTH), "");
161: static_assert(!PetscOffloadHost(PETSC_OFFLOAD_GPU), "");
162: static_assert(PetscOffloadHost(PETSC_OFFLOAD_BOTH), "");
163: static_assert(!PetscOffloadHost(PETSC_OFFLOAD_KOKKOS), "");
165: static_assert(!PetscOffloadDevice(PETSC_OFFLOAD_UNALLOCATED), "");
166: static_assert(!PetscOffloadDevice(PETSC_OFFLOAD_CPU), "");
167: static_assert(PetscOffloadDevice(PETSC_OFFLOAD_GPU), "");
168: static_assert(PetscOffloadDevice(PETSC_OFFLOAD_BOTH), "");
169: static_assert(!PetscOffloadDevice(PETSC_OFFLOAD_KOKKOS), "");
171: static_assert(PetscOffloadBoth(PETSC_OFFLOAD_BOTH), "");
172: static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_CPU), "");
173: static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_GPU), "");
174: static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_GPU), "");
175: static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_KOKKOS), "");
176: #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
177: #pragma GCC diagnostic pop
178: #endif
179: #endif // __cplusplus
181: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscOffloadMaskToString(PetscOffloadMask mask)
182: {
183: #define PETSC_CASE_RETURN(v) \
184: case v: \
185: return PetscStringize(v)
187: switch (mask) {
188: PETSC_CASE_RETURN(PETSC_OFFLOAD_UNALLOCATED);
189: PETSC_CASE_RETURN(PETSC_OFFLOAD_CPU);
190: PETSC_CASE_RETURN(PETSC_OFFLOAD_GPU);
191: PETSC_CASE_RETURN(PETSC_OFFLOAD_BOTH);
192: PETSC_CASE_RETURN(PETSC_OFFLOAD_KOKKOS);
193: }
194: PetscUnreachable();
195: return "invalid";
196: #undef PETSC_CASE_RETURN
197: }
199: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 PetscMemType PetscOffloadMaskToMemType(PetscOffloadMask mask)
200: {
201: switch (mask) {
202: case PETSC_OFFLOAD_UNALLOCATED:
203: case PETSC_OFFLOAD_CPU:
204: return PETSC_MEMTYPE_HOST;
205: case PETSC_OFFLOAD_GPU:
206: case PETSC_OFFLOAD_BOTH:
207: return PETSC_MEMTYPE_DEVICE;
208: case PETSC_OFFLOAD_KOKKOS:
209: return PETSC_MEMTYPE_KOKKOS;
210: }
211: PetscUnreachable();
212: return PETSC_MEMTYPE_HOST;
213: }
215: /*E
216: PetscDeviceInitType - Initialization strategy for `PetscDevice`
218: Values:
219: + `PETSC_DEVICE_INIT_NONE` - PetscDevice is never initialized
220: . `PETSC_DEVICE_INIT_LAZY` - PetscDevice is initialized on demand
221: - `PETSC_DEVICE_INIT_EAGER` - PetscDevice is initialized as soon as possible
223: Level: beginner
225: Notes:
226: `PETSC_DEVICE_INIT_NONE` implies that any initialization of `PetscDevice` is disallowed and
227: doing so results in an error. Useful to ensure that no accelerator is used in a program.
229: .seealso: `PetscDevice`, `PetscDeviceType`, `PetscDeviceInitialize()`,
230: `PetscDeviceInitialized()`, `PetscDeviceCreate()`
231: E*/
232: typedef enum {
233: PETSC_DEVICE_INIT_NONE,
234: PETSC_DEVICE_INIT_LAZY,
235: PETSC_DEVICE_INIT_EAGER
236: } PetscDeviceInitType;
237: PETSC_EXTERN const char *const PetscDeviceInitTypes[];
239: /*E
240: PetscDeviceType - Kind of accelerator device backend
242: Values:
243: + `PETSC_DEVICE_HOST` - Host, no accelerator backend found
244: . `PETSC_DEVICE_CUDA` - CUDA enabled GPU
245: . `PETSC_DEVICE_HIP` - ROCM/HIP enabled GPU
246: . `PETSC_DEVICE_SYCL` - SYCL enabled device
247: - `PETSC_DEVICE_MAX` - Always 1 greater than the largest valid `PetscDeviceType`, invalid type, do not use
249: Level: beginner
251: Notes:
252: One can also use the `PETSC_DEVICE_DEFAULT()` routine to get the current default `PetscDeviceType`.
254: .seealso: `PetscDevice`, `PetscDeviceInitType`, `PetscDeviceCreate()`, `PETSC_DEVICE_DEFAULT()`
255: E*/
256: typedef enum {
257: PETSC_DEVICE_HOST,
258: PETSC_DEVICE_CUDA,
259: PETSC_DEVICE_HIP,
260: PETSC_DEVICE_SYCL,
261: PETSC_DEVICE_MAX
262: } PetscDeviceType;
263: PETSC_EXTERN const char *const PetscDeviceTypes[];
265: /*E
266: PetscDeviceAttribute - Attribute detailing a property or feature of a `PetscDevice`
268: Values:
269: + `PETSC_DEVICE_ATTR_SIZE_T_SHARED_MEM_PER_BLOCK` - The maximum amount of shared memory per block in a device kernel
270: - `PETSC_DEVICE_ATTR_MAX` - Invalid attribute, do not use
272: Level: beginner
274: .seealso: `PetscDevice`, `PetscDeviceGetAttribute()`
275: E*/
276: typedef enum {
277: PETSC_DEVICE_ATTR_SIZE_T_SHARED_MEM_PER_BLOCK,
278: PETSC_DEVICE_ATTR_MAX
279: } PetscDeviceAttribute;
280: PETSC_EXTERN const char *const PetscDeviceAttributes[];
282: /*S
283: PetscDevice - Object to manage an accelerator "device" (usually a GPU)
285: Level: beginner
287: Notes:
288: This object is used to house configuration and state of a device, but does not offer any
289: ability to interact with or drive device computation. This functionality is facilitated
290: instead by the `PetscDeviceContext` object.
292: .seealso: `PetscDeviceType`, `PetscDeviceInitType`, `PetscDeviceCreate()`,
293: `PetscDeviceConfigure()`, `PetscDeviceDestroy()`, `PetscDeviceContext`,
294: `PetscDeviceContextSetDevice()`, `PetscDeviceContextGetDevice()`, `PetscDeviceGetAttribute()`
295: S*/
296: typedef struct _n_PetscDevice *PetscDevice;
298: /*E
299: PetscStreamType - Stream blocking mode, indicates how a stream implementation will interact
300: with the default `NULL` stream, which is usually blocking.
302: Values:
303: + `PETSC_STREAM_GLOBAL_BLOCKING` - Alias for `NULL` stream. Any stream of this type will block the host for all other streams to finish work before starting its operations.
304: . `PETSC_STREAM_DEFAULT_BLOCKING` - Stream will act independent of other streams, but will still be blocked by actions on the `NULL` stream.
305: . `PETSC_STREAM_GLOBAL_NONBLOCKING` - Stream is truly asynchronous, and is blocked by nothing, not even the `NULL` stream.
306: - `PETSC_STREAM_MAX` - Always 1 greater than the largest `PetscStreamType`, do not use
308: Level: intermediate
310: .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextGetStreamType()`
311: E*/
312: typedef enum {
313: PETSC_STREAM_GLOBAL_BLOCKING,
314: PETSC_STREAM_DEFAULT_BLOCKING,
315: PETSC_STREAM_GLOBAL_NONBLOCKING,
316: PETSC_STREAM_MAX
317: } PetscStreamType;
318: PETSC_EXTERN const char *const PetscStreamTypes[];
320: /*E
321: PetscDeviceContextJoinMode - Describes the type of join operation to perform in
322: `PetscDeviceContextJoin()`
324: Values:
325: + `PETSC_DEVICE_CONTEXT_JOIN_DESTROY` - Destroy all incoming sub-contexts after join.
326: . `PETSC_DEVICE_CONTEXT_JOIN_SYNC` - Synchronize incoming sub-contexts after join.
327: - `PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC` - Do not synchronize incoming sub-contexts after join.
329: Level: beginner
331: .seealso: `PetscDeviceContext`, `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`
332: E*/
333: typedef enum {
334: PETSC_DEVICE_CONTEXT_JOIN_DESTROY,
335: PETSC_DEVICE_CONTEXT_JOIN_SYNC,
336: PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC
337: } PetscDeviceContextJoinMode;
338: PETSC_EXTERN const char *const PetscDeviceContextJoinModes[];
340: /*S
341: PetscDeviceContext - Container to manage stream dependencies and the various solver handles
342: for asynchronous device compute.
344: Level: beginner
346: .seealso: `PetscDevice`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`,
347: `PetscDeviceContextDestroy()`, `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`
348: S*/
349: typedef struct _p_PetscDeviceContext *PetscDeviceContext;
351: /*E
352: PetscDeviceCopyMode - Describes the copy direction of a device-aware `memcpy`
354: Values:
355: + `PETSC_DEVICE_COPY_HTOH` - Copy from host memory to host memory
356: . `PETSC_DEVICE_COPY_DTOH` - Copy from device memory to host memory
357: . `PETSC_DEVICE_COPY_HTOD` - Copy from host memory to device memory
358: . `PETSC_DEVICE_COPY_DTOD` - Copy from device memory to device memory
359: - `PETSC_DEVICE_COPY_AUTO` - Infer the copy direction from the pointers
361: Level: beginner
363: .seealso: `PetscDeviceArrayCopy()`, `PetscDeviceMemcpy()`
364: E*/
365: typedef enum {
366: PETSC_DEVICE_COPY_HTOH,
367: PETSC_DEVICE_COPY_DTOH,
368: PETSC_DEVICE_COPY_HTOD,
369: PETSC_DEVICE_COPY_DTOD,
370: PETSC_DEVICE_COPY_AUTO,
371: } PetscDeviceCopyMode;
372: PETSC_EXTERN const char *const PetscDeviceCopyModes[];
374: PETSC_NODISCARD static inline PetscDeviceCopyMode PetscOffloadMaskToDeviceCopyMode(PetscOffloadMask dest, PetscOffloadMask src)
375: {
376: PetscDeviceCopyMode mode;
378: PetscFunctionBegin;
379: PetscAssertAbort(dest != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot copy to unallocated");
380: PetscAssertAbort(src != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot copy from unallocated");
382: if (PetscOffloadDevice(dest)) {
383: mode = PetscOffloadHost(src) ? PETSC_DEVICE_COPY_HTOD : PETSC_DEVICE_COPY_DTOD;
384: } else {
385: mode = PetscOffloadHost(src) ? PETSC_DEVICE_COPY_HTOH : PETSC_DEVICE_COPY_DTOH;
386: }
387: PetscFunctionReturn(mode);
388: }
390: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 PetscDeviceCopyMode PetscMemTypeToDeviceCopyMode(PetscMemType dest, PetscMemType src)
391: {
392: if (PetscMemTypeHost(dest)) {
393: return PetscMemTypeHost(src) ? PETSC_DEVICE_COPY_HTOH : PETSC_DEVICE_COPY_DTOH;
394: } else {
395: return PetscMemTypeDevice(src) ? PETSC_DEVICE_COPY_DTOD : PETSC_DEVICE_COPY_HTOD;
396: }
397: }
399: /*E
400: PetscMemoryAccessMode - Describes the intended usage of a memory region
402: Values:
403: + `PETSC_MEMORY_ACCESS_READ` - Read only
404: . `PETSC_MEMORY_ACCESS_WRITE` - Write only
405: - `PETSC_MEMORY_ACCESS_READ_WRITE` - Read and write
407: Level: beginner
409: Notes:
410: This `enum` is a bitmask with the following encoding (assuming 2 bit)\:
412: .vb
413: PETSC_MEMORY_ACCESS_READ = 0b01
414: PETSC_MEMORY_ACCESS_WRITE = 0b10
415: PETSC_MEMORY_ACCESS_READ_WRITE = 0b11
417: // consequently
418: PETSC_MEMORY_ACCESS_READ | PETSC_MEMORY_ACCESS_WRITE = PETSC_MEMORY_ACCESS_READ_WRITE
419: .ve
421: The following convenience macros are also provided\:
423: + `PetscMemoryAccessRead(mode)` - `true` if `mode` is any kind of read, `false` otherwise
424: - `PetscMemoryAccessWrite(mode)` - `true` if `mode` is any kind of write, `false` otherwise
426: Developer Notes:
427: This enum uses a function (`PetscMemoryAccessModeToString()`) to convert values to string
428: representation, so cannot be used in `PetscOptionsEnum()`.
430: .seealso: `PetscMemoryAccessModeToString()`, `PetscDevice`, `PetscDeviceContext`
431: E*/
432: typedef enum {
433: PETSC_MEMORY_ACCESS_READ = 0x1, // 01
434: PETSC_MEMORY_ACCESS_WRITE = 0x2, // 10
435: PETSC_MEMORY_ACCESS_READ_WRITE = 0x3, // 11
436: } PetscMemoryAccessMode;
438: #define PetscMemoryAccessRead(m) (((m)&PETSC_MEMORY_ACCESS_READ) == PETSC_MEMORY_ACCESS_READ)
439: #define PetscMemoryAccessWrite(m) (((m)&PETSC_MEMORY_ACCESS_WRITE) == PETSC_MEMORY_ACCESS_WRITE)
441: #if defined(__cplusplus)
442: #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
443: #pragma GCC diagnostic push
444: #pragma GCC diagnostic ignored "-Wtautological-compare"
445: #endif
446: static_assert(PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_READ), "");
447: static_assert(PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_READ_WRITE), "");
448: static_assert(!PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_WRITE), "");
449: static_assert(PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_WRITE), "");
450: static_assert(PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_READ_WRITE), "");
451: static_assert(!PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_READ), "");
452: static_assert((PETSC_MEMORY_ACCESS_READ | PETSC_MEMORY_ACCESS_WRITE) == PETSC_MEMORY_ACCESS_READ_WRITE, "");
453: #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
454: #pragma GCC diagnostic pop
455: #endif
456: #endif
458: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscMemoryAccessModeToString(PetscMemoryAccessMode mode)
459: {
460: #define PETSC_CASE_RETURN(v) \
461: case v: \
462: return PetscStringize(v)
464: switch (mode) {
465: PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_READ);
466: PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_WRITE);
467: PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_READ_WRITE);
468: }
469: PetscUnreachable();
470: return "invalid";
471: #undef PETSC_CASE_RETURN
472: }
474: #undef PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
476: #endif /* PETSCDEVICETYPES_H */