xref: /libCEED/interface/ceed.c (revision 897d47372ec59843dd923b6bfcbc02717b893aa1)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
8d7b241e6Sjeremylt #define _POSIX_C_SOURCE 200112
93d576824SJeremy L Thompson #include <ceed-impl.h>
1049aac155SJeremy L Thompson #include <ceed.h>
112b730f8bSJeremy L Thompson #include <ceed/backend.h>
12aedaa0e5Sjeremylt #include <limits.h>
13d7b241e6Sjeremylt #include <stdarg.h>
1449aac155SJeremy L Thompson #include <stdbool.h>
156e79d475Sjeremylt #include <stddef.h>
16d7b241e6Sjeremylt #include <stdio.h>
17d7b241e6Sjeremylt #include <stdlib.h>
18d7b241e6Sjeremylt #include <string.h>
19d7b241e6Sjeremylt 
20d7b241e6Sjeremylt /// @cond DOXYGEN_SKIP
21d7b241e6Sjeremylt static CeedRequest ceed_request_immediate;
22d7b241e6Sjeremylt static CeedRequest ceed_request_ordered;
23d7b241e6Sjeremylt 
24d7b241e6Sjeremylt static struct {
25d7b241e6Sjeremylt   char prefix[CEED_MAX_RESOURCE_LEN];
26d7b241e6Sjeremylt   int (*init)(const char *resource, Ceed f);
27d7b241e6Sjeremylt   unsigned int priority;
28d7b241e6Sjeremylt } backends[32];
29d7b241e6Sjeremylt static size_t num_backends;
30fe2413ffSjeremylt 
316e79d475Sjeremylt #define CEED_FTABLE_ENTRY(class, method) \
32e64bb3f3SSebastian Grimberg   { #class #method, offsetof(struct class##_private, method) }
33d7b241e6Sjeremylt /// @endcond
34d7b241e6Sjeremylt 
35d7b241e6Sjeremylt /// @file
36d7b241e6Sjeremylt /// Implementation of core components of Ceed library
377a982d89SJeremy L. Thompson 
387a982d89SJeremy L. Thompson /// @addtogroup CeedUser
39d7b241e6Sjeremylt /// @{
40d7b241e6Sjeremylt 
41dfdf5a53Sjeremylt /**
42dfdf5a53Sjeremylt   @brief Request immediate completion
43dfdf5a53Sjeremylt 
44ca94c3ddSJeremy L Thompson   This predefined constant is passed as the @ref CeedRequest argument to interfaces when the caller wishes for the operation to be performed immediately.
45ca94c3ddSJeremy L Thompson   The code
46dfdf5a53Sjeremylt 
47dfdf5a53Sjeremylt   @code
48dfdf5a53Sjeremylt     CeedOperatorApply(op, ..., CEED_REQUEST_IMMEDIATE);
49dfdf5a53Sjeremylt   @endcode
50dfdf5a53Sjeremylt 
51dfdf5a53Sjeremylt   is semantically equivalent to
52dfdf5a53Sjeremylt 
53dfdf5a53Sjeremylt   @code
54dfdf5a53Sjeremylt     CeedRequest request;
55dfdf5a53Sjeremylt     CeedOperatorApply(op, ..., &request);
56dfdf5a53Sjeremylt     CeedRequestWait(&request);
57dfdf5a53Sjeremylt   @endcode
58dfdf5a53Sjeremylt 
59dfdf5a53Sjeremylt   @sa CEED_REQUEST_ORDERED
60dfdf5a53Sjeremylt **/
61d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_IMMEDIATE = &ceed_request_immediate;
62d7b241e6Sjeremylt 
63d7b241e6Sjeremylt /**
64b11c1e72Sjeremylt   @brief Request ordered completion
65d7b241e6Sjeremylt 
66ca94c3ddSJeremy L Thompson   This predefined constant is passed as the @ref CeedRequest argument to interfaces when the caller wishes for the operation to be completed in the order that it is submitted to the device.
67ca94c3ddSJeremy L Thompson   It is typically used in a construct such as:
68d7b241e6Sjeremylt 
69d7b241e6Sjeremylt   @code
70d7b241e6Sjeremylt     CeedRequest request;
71d7b241e6Sjeremylt     CeedOperatorApply(op1, ..., CEED_REQUEST_ORDERED);
72d7b241e6Sjeremylt     CeedOperatorApply(op2, ..., &request);
73d7b241e6Sjeremylt     // other optional work
748b2d6f4aSMatthew Knepley     CeedRequestWait(&request);
75d7b241e6Sjeremylt   @endcode
76d7b241e6Sjeremylt 
77ea61e9acSJeremy L Thompson   which allows the sequence to complete asynchronously but does not start `op2` until `op1` has completed.
78d7b241e6Sjeremylt 
79ea61e9acSJeremy L Thompson   @todo The current implementation is overly strict, offering equivalent semantics to @ref CEED_REQUEST_IMMEDIATE.
80d7b241e6Sjeremylt 
81d7b241e6Sjeremylt   @sa CEED_REQUEST_IMMEDIATE
82d7b241e6Sjeremylt  */
83d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_ORDERED = &ceed_request_ordered;
84d7b241e6Sjeremylt 
85b11c1e72Sjeremylt /**
86ca94c3ddSJeremy L Thompson   @brief Wait for a @ref CeedRequest to complete.
87dfdf5a53Sjeremylt 
88ca94c3ddSJeremy L Thompson   Calling @ref CeedRequestWait() on a `NULL` request is a no-op.
897a982d89SJeremy L. Thompson 
90ca94c3ddSJeremy L Thompson   @param[in,out] req Address of @ref CeedRequest to wait for; zeroed on completion.
917a982d89SJeremy L. Thompson 
927a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
937a982d89SJeremy L. Thompson 
947a982d89SJeremy L. Thompson   @ref User
95b11c1e72Sjeremylt **/
967a982d89SJeremy L. Thompson int CeedRequestWait(CeedRequest *req) {
972b730f8bSJeremy L Thompson   if (!*req) return CEED_ERROR_SUCCESS;
982b730f8bSJeremy L Thompson   return CeedError(NULL, CEED_ERROR_UNSUPPORTED, "CeedRequestWait not implemented");
99683faae0SJed Brown }
1007a982d89SJeremy L. Thompson 
1017a982d89SJeremy L. Thompson /// @}
1027a982d89SJeremy L. Thompson 
1037a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1047a982d89SJeremy L. Thompson /// Ceed Library Internal Functions
1057a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1067a982d89SJeremy L. Thompson /// @addtogroup CeedDeveloper
1077a982d89SJeremy L. Thompson /// @{
108d7b241e6Sjeremylt 
1096a406739SJeremy L Thompson /**
1106a406739SJeremy L Thompson   @brief Register a Ceed backend internally.
1114385fb7fSSebastian Grimberg 
112ca94c3ddSJeremy L Thompson   Note: Backends should call @ref CeedRegister() instead.
1136a406739SJeremy L Thompson 
114ea61e9acSJeremy L Thompson   @param[in] prefix   Prefix of resources for this backend to respond to.
115ea61e9acSJeremy L Thompson                         For example, the reference backend responds to "/cpu/self".
116ca94c3ddSJeremy L Thompson   @param[in] init     Initialization function called by @ref CeedInit() when the backend is selected to drive the requested resource
117ea61e9acSJeremy L Thompson   @param[in] priority Integer priority.
118ca94c3ddSJeremy L Thompson                         Lower values are preferred in case the resource requested by @ref CeedInit() has non-unique best prefix match.
1196a406739SJeremy L Thompson 
1206a406739SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1216a406739SJeremy L Thompson 
1226a406739SJeremy L Thompson   @ref Developer
1236a406739SJeremy L Thompson **/
1242b730f8bSJeremy L Thompson int CeedRegisterImpl(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) {
12558c07c4fSSebastian Grimberg   int ierr = 0;
1266a406739SJeremy L Thompson 
12758c07c4fSSebastian Grimberg   CeedPragmaCritical(CeedRegisterImpl) {
12858c07c4fSSebastian Grimberg     if (num_backends < sizeof(backends) / sizeof(backends[0])) {
1296a406739SJeremy L Thompson       strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN);
1306a406739SJeremy L Thompson       backends[num_backends].prefix[CEED_MAX_RESOURCE_LEN - 1] = 0;
1316a406739SJeremy L Thompson       backends[num_backends].init                              = init;
1326a406739SJeremy L Thompson       backends[num_backends].priority                          = priority;
1336a406739SJeremy L Thompson       num_backends++;
13458c07c4fSSebastian Grimberg     } else {
13558c07c4fSSebastian Grimberg       ierr = 1;
13658c07c4fSSebastian Grimberg     }
13758c07c4fSSebastian Grimberg   }
13858c07c4fSSebastian Grimberg   // LCOV_EXCL_START
13958c07c4fSSebastian Grimberg   CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "Too many backends");
14058c07c4fSSebastian Grimberg   // LCOV_EXCL_STOP
1416a406739SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1426a406739SJeremy L Thompson }
1436a406739SJeremy L Thompson 
1447a982d89SJeremy L. Thompson /// @}
145d7b241e6Sjeremylt 
1467a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1477a982d89SJeremy L. Thompson /// Ceed Backend API
1487a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1497a982d89SJeremy L. Thompson /// @addtogroup CeedBackend
1507a982d89SJeremy L. Thompson /// @{
151d7b241e6Sjeremylt 
152b11c1e72Sjeremylt /**
153ca94c3ddSJeremy L Thompson   @brief Return value of `CEED_DEBUG` environment variable
15460f9e2d6SJeremy L Thompson 
155ca94c3ddSJeremy L Thompson   @param[in] ceed `Ceed` context
15660f9e2d6SJeremy L Thompson 
157ca94c3ddSJeremy L Thompson   @return Boolean value: true  - debugging mode enabled
1583f21f6b1SJeremy L Thompson                          false - debugging mode disabled
15960f9e2d6SJeremy L Thompson 
16060f9e2d6SJeremy L Thompson   @ref Backend
16160f9e2d6SJeremy L Thompson **/
162fc6bbcedSJeremy L Thompson // LCOV_EXCL_START
1632b730f8bSJeremy L Thompson bool CeedDebugFlag(const Ceed ceed) { return ceed->is_debug; }
164fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP
16560f9e2d6SJeremy L Thompson 
16660f9e2d6SJeremy L Thompson /**
167ca94c3ddSJeremy L Thompson   @brief Return value of `CEED_DEBUG` environment variable
16860f9e2d6SJeremy L Thompson 
169ca94c3ddSJeremy L Thompson   @return Boolean value: true  - debugging mode enabled
1703f21f6b1SJeremy L Thompson                          false - debugging mode disabled
1713f21f6b1SJeremy L Thompson 
1723f21f6b1SJeremy L Thompson   @ref Backend
1733f21f6b1SJeremy L Thompson **/
1743f21f6b1SJeremy L Thompson // LCOV_EXCL_START
1751c66c397SJeremy L Thompson bool CeedDebugFlagEnv(void) { return getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); }
1763f21f6b1SJeremy L Thompson // LCOV_EXCL_STOP
1773f21f6b1SJeremy L Thompson 
1783f21f6b1SJeremy L Thompson /**
1793f21f6b1SJeremy L Thompson   @brief Print debugging information in color
1803f21f6b1SJeremy L Thompson 
181ca94c3ddSJeremy L Thompson   @param[in] color  Color to print
182ca94c3ddSJeremy L Thompson   @param[in] format Printing format
18360f9e2d6SJeremy L Thompson 
18460f9e2d6SJeremy L Thompson   @ref Backend
18560f9e2d6SJeremy L Thompson **/
186fc6bbcedSJeremy L Thompson // LCOV_EXCL_START
1873f21f6b1SJeremy L Thompson void CeedDebugImpl256(const unsigned char color, const char *format, ...) {
18860f9e2d6SJeremy L Thompson   va_list args;
18960f9e2d6SJeremy L Thompson   va_start(args, format);
19060f9e2d6SJeremy L Thompson   fflush(stdout);
1912b730f8bSJeremy L Thompson   if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[38;5;%dm", color);
19260f9e2d6SJeremy L Thompson   vfprintf(stdout, format, args);
1932b730f8bSJeremy L Thompson   if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[m");
19460f9e2d6SJeremy L Thompson   fprintf(stdout, "\n");
19560f9e2d6SJeremy L Thompson   fflush(stdout);
19660f9e2d6SJeremy L Thompson   va_end(args);
19760f9e2d6SJeremy L Thompson }
198fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP
19960f9e2d6SJeremy L Thompson 
20060f9e2d6SJeremy L Thompson /**
201ca94c3ddSJeremy L Thompson   @brief Allocate an array on the host; use @ref CeedMalloc().
202b11c1e72Sjeremylt 
203ea61e9acSJeremy L Thompson   Memory usage can be tracked by the library.
204ea61e9acSJeremy L Thompson   This ensures sufficient alignment for vectorization and should be used for large allocations.
205b11c1e72Sjeremylt 
206ea61e9acSJeremy L Thompson   @param[in]  n    Number of units to allocate
207ea61e9acSJeremy L Thompson   @param[in]  unit Size of each unit
208ca94c3ddSJeremy L Thompson   @param[out] p    Address of pointer to hold the result
209b11c1e72Sjeremylt 
210b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
211b11c1e72Sjeremylt 
2127a982d89SJeremy L. Thompson   @ref Backend
213ca94c3ddSJeremy L Thompson 
214ca94c3ddSJeremy L Thompson   @sa CeedFree()
215b11c1e72Sjeremylt **/
216d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) {
217d7b241e6Sjeremylt   int ierr = posix_memalign((void **)p, CEED_ALIGN, n * unit);
2186574a04fSJeremy L Thompson   CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "posix_memalign failed to allocate %zd members of size %zd\n", n, unit);
219e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
220d7b241e6Sjeremylt }
221d7b241e6Sjeremylt 
222b11c1e72Sjeremylt /**
223ca94c3ddSJeremy L Thompson   @brief Allocate a cleared (zeroed) array on the host; use @ref CeedCalloc().
224b11c1e72Sjeremylt 
225b11c1e72Sjeremylt   Memory usage can be tracked by the library.
226b11c1e72Sjeremylt 
227ea61e9acSJeremy L Thompson   @param[in]  n    Number of units to allocate
228ea61e9acSJeremy L Thompson   @param[in]  unit Size of each unit
229ca94c3ddSJeremy L Thompson   @param[out] p    Address of pointer to hold the result
230b11c1e72Sjeremylt 
231b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
232b11c1e72Sjeremylt 
2337a982d89SJeremy L. Thompson   @ref Backend
234ca94c3ddSJeremy L Thompson 
235ca94c3ddSJeremy L Thompson   @sa CeedFree()
236b11c1e72Sjeremylt **/
237d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) {
238d7b241e6Sjeremylt   *(void **)p = calloc(n, unit);
2396574a04fSJeremy L Thompson   CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "calloc failed to allocate %zd members of size %zd\n", n, unit);
240e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
241d7b241e6Sjeremylt }
242d7b241e6Sjeremylt 
243b11c1e72Sjeremylt /**
244ca94c3ddSJeremy L Thompson   @brief Reallocate an array on the host; use @ref CeedRealloc().
245b11c1e72Sjeremylt 
246b11c1e72Sjeremylt   Memory usage can be tracked by the library.
247b11c1e72Sjeremylt 
248ea61e9acSJeremy L Thompson   @param[in]  n    Number of units to allocate
249ea61e9acSJeremy L Thompson   @param[in]  unit Size of each unit
250ca94c3ddSJeremy L Thompson   @param[out] p    Address of pointer to hold the result
251b11c1e72Sjeremylt 
252b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
253b11c1e72Sjeremylt 
2547a982d89SJeremy L. Thompson   @ref Backend
255ca94c3ddSJeremy L Thompson 
256ca94c3ddSJeremy L Thompson   @sa CeedFree()
257b11c1e72Sjeremylt **/
258d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) {
259d7b241e6Sjeremylt   *(void **)p = realloc(*(void **)p, n * unit);
2606574a04fSJeremy L Thompson   CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "realloc failed to allocate %zd members of size %zd\n", n, unit);
261e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
262d7b241e6Sjeremylt }
263d7b241e6Sjeremylt 
264f7e22acaSJeremy L Thompson /**
265ca94c3ddSJeremy L Thompson   @brief Allocate a cleared string buffer on the host.
266f7e22acaSJeremy L Thompson 
267f7e22acaSJeremy L Thompson   Memory usage can be tracked by the library.
268f7e22acaSJeremy L Thompson 
269ea61e9acSJeremy L Thompson   @param[in]  source Pointer to string to be copied
270ea61e9acSJeremy L Thompson   @param[out] copy   Pointer to variable to hold newly allocated string copy
271f7e22acaSJeremy L Thompson 
272f7e22acaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
273f7e22acaSJeremy L Thompson 
274f7e22acaSJeremy L Thompson   @ref Backend
275ca94c3ddSJeremy L Thompson 
276ca94c3ddSJeremy L Thompson   @sa CeedFree()
277f7e22acaSJeremy L Thompson **/
278f7e22acaSJeremy L Thompson int CeedStringAllocCopy(const char *source, char **copy) {
279f7e22acaSJeremy L Thompson   size_t len = strlen(source);
2802b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(len + 1, copy));
281d602d780SJeremy L Thompson   memcpy(*copy, source, len);
282f7e22acaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
283f7e22acaSJeremy L Thompson }
284f7e22acaSJeremy L Thompson 
285ca94c3ddSJeremy L Thompson /** Free memory allocated using @ref CeedMalloc() or @ref CeedCalloc()
28634138859Sjeremylt 
287ca94c3ddSJeremy L Thompson   @param[in,out] p Address of pointer to memory.
288ca94c3ddSJeremy L Thompson                      This argument is of type `void*` to avoid needing a cast, but is the address of the pointer (which is zeroed) rather than the pointer.
289ca94c3ddSJeremy L Thompson 
290ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
291ca94c3ddSJeremy L Thompson 
292ca94c3ddSJeremy L Thompson   @ref Backend
29334138859Sjeremylt **/
294d7b241e6Sjeremylt int CeedFree(void *p) {
295d7b241e6Sjeremylt   free(*(void **)p);
296d7b241e6Sjeremylt   *(void **)p = NULL;
297e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
298d7b241e6Sjeremylt }
299d7b241e6Sjeremylt 
300d7b241e6Sjeremylt /**
301ca94c3ddSJeremy L Thompson   @brief Register a `Ceed` backend
302d7b241e6Sjeremylt 
303ea61e9acSJeremy L Thompson   @param[in] prefix   Prefix of resources for this backend to respond to.
304ea61e9acSJeremy L Thompson                         For example, the reference backend responds to "/cpu/self".
305ca94c3ddSJeremy L Thompson   @param[in] init     Initialization function called by @ref CeedInit() when the backend is selected to drive the requested resource
306ea61e9acSJeremy L Thompson   @param[in] priority Integer priority.
307ca94c3ddSJeremy L Thompson                         Lower values are preferred in case the resource requested by @ref CeedInit() has non-unique best prefix match.
308b11c1e72Sjeremylt 
309b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
310dfdf5a53Sjeremylt 
3117a982d89SJeremy L. Thompson   @ref Backend
312b11c1e72Sjeremylt **/
3132b730f8bSJeremy L Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) {
31410243053SJeremy L Thompson   CeedDebugEnv("Backend Register: %s", prefix);
3156a406739SJeremy L Thompson   CeedRegisterImpl(prefix, init, priority);
316e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
317d7b241e6Sjeremylt }
318d7b241e6Sjeremylt 
319b11c1e72Sjeremylt /**
32060f9e2d6SJeremy L Thompson   @brief Return debugging status flag
32160f9e2d6SJeremy L Thompson 
322ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context to get debugging flag
323ea61e9acSJeremy L Thompson   @param[out] is_debug Variable to store debugging flag
32460f9e2d6SJeremy L Thompson 
32560f9e2d6SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
32660f9e2d6SJeremy L Thompson 
327d1d35e2fSjeremylt   @ref Backend
32860f9e2d6SJeremy L Thompson **/
329d1d35e2fSjeremylt int CeedIsDebug(Ceed ceed, bool *is_debug) {
3303f21f6b1SJeremy L Thompson   *is_debug = ceed->is_debug;
331e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
33260f9e2d6SJeremy L Thompson }
33360f9e2d6SJeremy L Thompson 
33460f9e2d6SJeremy L Thompson /**
335bc246734SJeremy L Thompson   @brief Get the root of the requested resource
336bc246734SJeremy L Thompson 
337ca94c3ddSJeremy L Thompson   @param[in]  ceed          `Ceed` context to get resource name of
338ca94c3ddSJeremy L Thompson   @param[in]  resource      Full user specified resource
339ca94c3ddSJeremy L Thompson   @param[in]  delineator    Delineator to break `resource_root` and `resource_spec`
340bc246734SJeremy L Thompson   @param[out] resource_root Variable to store resource root
341bc246734SJeremy L Thompson 
342bc246734SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
343bc246734SJeremy L Thompson 
344bc246734SJeremy L Thompson   @ref Backend
345bc246734SJeremy L Thompson **/
346bc246734SJeremy L Thompson int CeedGetResourceRoot(Ceed ceed, const char *resource, const char *delineator, char **resource_root) {
347bc246734SJeremy L Thompson   char  *device_spec       = strstr(resource, delineator);
348bc246734SJeremy L Thompson   size_t resource_root_len = device_spec ? (size_t)(device_spec - resource) + 1 : strlen(resource) + 1;
3491c66c397SJeremy L Thompson 
350bc246734SJeremy L Thompson   CeedCall(CeedCalloc(resource_root_len, resource_root));
351bc246734SJeremy L Thompson   memcpy(*resource_root, resource, resource_root_len - 1);
352bc246734SJeremy L Thompson   return CEED_ERROR_SUCCESS;
353bc246734SJeremy L Thompson }
354bc246734SJeremy L Thompson 
355bc246734SJeremy L Thompson /**
356ca94c3ddSJeremy L Thompson   @brief Retrieve a parent `Ceed` context
3577a982d89SJeremy L. Thompson 
358ca94c3ddSJeremy L Thompson   @param[in]  ceed   `Ceed` context to retrieve parent of
3597a982d89SJeremy L. Thompson   @param[out] parent Address to save the parent to
3607a982d89SJeremy L. Thompson 
3617a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3627a982d89SJeremy L. Thompson 
3637a982d89SJeremy L. Thompson   @ref Backend
3647a982d89SJeremy L. Thompson **/
3657a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) {
3667a982d89SJeremy L. Thompson   if (ceed->parent) {
3672b730f8bSJeremy L Thompson     CeedCall(CeedGetParent(ceed->parent, parent));
368e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3697a982d89SJeremy L. Thompson   }
3707a982d89SJeremy L. Thompson   *parent = ceed;
371e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3727a982d89SJeremy L. Thompson }
3737a982d89SJeremy L. Thompson 
3747a982d89SJeremy L. Thompson /**
375ca94c3ddSJeremy L Thompson   @brief Retrieve a delegate `Ceed` context
3767a982d89SJeremy L. Thompson 
377ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context to retrieve delegate of
3787a982d89SJeremy L. Thompson   @param[out] delegate Address to save the delegate to
3797a982d89SJeremy L. Thompson 
3807a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3817a982d89SJeremy L. Thompson 
3827a982d89SJeremy L. Thompson   @ref Backend
3837a982d89SJeremy L. Thompson **/
3847a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) {
3857a982d89SJeremy L. Thompson   *delegate = ceed->delegate;
386e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3877a982d89SJeremy L. Thompson }
3887a982d89SJeremy L. Thompson 
3897a982d89SJeremy L. Thompson /**
390ca94c3ddSJeremy L Thompson   @brief Set a delegate `Ceed` context
3917a982d89SJeremy L. Thompson 
392ca94c3ddSJeremy L Thompson   This function allows a `Ceed` context to set a delegate `Ceed` context.
393ca94c3ddSJeremy L Thompson   All backend implementations default to the delegate `Ceed` context, unless overridden.
3947a982d89SJeremy L. Thompson 
395ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context to set delegate of
3967a982d89SJeremy L. Thompson   @param[out] delegate Address to set the delegate to
3977a982d89SJeremy L. Thompson 
3987a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3997a982d89SJeremy L. Thompson 
4007a982d89SJeremy L. Thompson   @ref Backend
4017a982d89SJeremy L. Thompson **/
4027a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) {
4037a982d89SJeremy L. Thompson   ceed->delegate   = delegate;
4047a982d89SJeremy L. Thompson   delegate->parent = ceed;
405e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4067a982d89SJeremy L. Thompson }
4077a982d89SJeremy L. Thompson 
4087a982d89SJeremy L. Thompson /**
409ca94c3ddSJeremy L Thompson   @brief Retrieve a delegate `Ceed` context for a specific object type
4107a982d89SJeremy L. Thompson 
411ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context to retrieve delegate of
4127a982d89SJeremy L. Thompson   @param[out] delegate Address to save the delegate to
413d1d35e2fSjeremylt   @param[in]  obj_name Name of the object type to retrieve delegate for
4147a982d89SJeremy L. Thompson 
4157a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4167a982d89SJeremy L. Thompson 
4177a982d89SJeremy L. Thompson   @ref Backend
4187a982d89SJeremy L. Thompson **/
419d1d35e2fSjeremylt int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *obj_name) {
4207a982d89SJeremy L. Thompson   // Check for object delegate
4212b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) {
422d1d35e2fSjeremylt     if (!strcmp(obj_name, ceed->obj_delegates->obj_name)) {
423d1d35e2fSjeremylt       *delegate = ceed->obj_delegates->delegate;
424e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
4257a982d89SJeremy L. Thompson     }
4262b730f8bSJeremy L Thompson   }
4277a982d89SJeremy L. Thompson 
4287a982d89SJeremy L. Thompson   // Use default delegate if no object delegate
4292b730f8bSJeremy L Thompson   CeedCall(CeedGetDelegate(ceed, delegate));
430e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4317a982d89SJeremy L. Thompson }
4327a982d89SJeremy L. Thompson 
4337a982d89SJeremy L. Thompson /**
434ca94c3ddSJeremy L Thompson   @brief Set a delegate `Ceed` context for a specific object type
4357a982d89SJeremy L. Thompson 
436ca94c3ddSJeremy L Thompson   This function allows a `Ceed` context to set a delegate `Ceed` context for a given type of `Ceed` object.
437ca94c3ddSJeremy L Thompson   All backend implementations default to the delegate `Ceed` context for this object.
438ca94c3ddSJeremy L Thompson   For example, `CeedSetObjectDelegate(ceed, delegate, "Basis")` uses delegate implementations for all `CeedBasis` backend functions.
4397a982d89SJeremy L. Thompson 
440ca94c3ddSJeremy L Thompson   @param[in,out] ceed     `Ceed` context to set delegate of
441ca94c3ddSJeremy L Thompson   @param[in]     delegate `Ceed` context to use for delegation
442d1d35e2fSjeremylt   @param[in]     obj_name Name of the object type to set delegate for
4437a982d89SJeremy L. Thompson 
4447a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4457a982d89SJeremy L. Thompson 
4467a982d89SJeremy L. Thompson   @ref Backend
4477a982d89SJeremy L. Thompson **/
448d1d35e2fSjeremylt int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *obj_name) {
449d1d35e2fSjeremylt   CeedInt count = ceed->obj_delegate_count;
4507a982d89SJeremy L. Thompson 
4517a982d89SJeremy L. Thompson   // Malloc or Realloc
4527a982d89SJeremy L. Thompson   if (count) {
4532b730f8bSJeremy L Thompson     CeedCall(CeedRealloc(count + 1, &ceed->obj_delegates));
4547a982d89SJeremy L. Thompson   } else {
4552b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(1, &ceed->obj_delegates));
4567a982d89SJeremy L. Thompson   }
457d1d35e2fSjeremylt   ceed->obj_delegate_count++;
4587a982d89SJeremy L. Thompson 
4597a982d89SJeremy L. Thompson   // Set object delegate
460d1d35e2fSjeremylt   ceed->obj_delegates[count].delegate = delegate;
4612b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(obj_name, &ceed->obj_delegates[count].obj_name));
4627a982d89SJeremy L. Thompson 
4637a982d89SJeremy L. Thompson   // Set delegate parent
4647a982d89SJeremy L. Thompson   delegate->parent = ceed;
465e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4667a982d89SJeremy L. Thompson }
4677a982d89SJeremy L. Thompson 
4687a982d89SJeremy L. Thompson /**
469ca94c3ddSJeremy L Thompson   @brief Get the fallback resource for `CeedOperator`
4707a982d89SJeremy L. Thompson 
471ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context
4727a982d89SJeremy L. Thompson   @param[out] resource Variable to store fallback resource
4737a982d89SJeremy L. Thompson 
4747a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4757a982d89SJeremy L. Thompson 
4767a982d89SJeremy L. Thompson   @ref Backend
4777a982d89SJeremy L. Thompson **/
478363aefefSSebastian Grimberg int CeedGetOperatorFallbackResource(Ceed ceed, const char **resource) {
479d1d35e2fSjeremylt   *resource = (const char *)ceed->op_fallback_resource;
480e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4817a982d89SJeremy L. Thompson }
4827a982d89SJeremy L. Thompson 
4837a982d89SJeremy L. Thompson /**
484ca94c3ddSJeremy L Thompson   @brief Get the fallback `Ceed` for `CeedOperator`
4858687e1d4SJeremy L Thompson 
486ca94c3ddSJeremy L Thompson   @param[in]  ceed          `Ceed` context
487ca94c3ddSJeremy L Thompson   @param[out] fallback_ceed Variable to store fallback `Ceed`
4888687e1d4SJeremy L Thompson 
4898687e1d4SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4908687e1d4SJeremy L Thompson 
4918687e1d4SJeremy L Thompson   @ref Backend
4928687e1d4SJeremy L Thompson **/
4938687e1d4SJeremy L Thompson int CeedGetOperatorFallbackCeed(Ceed ceed, Ceed *fallback_ceed) {
494d04bbc78SJeremy L Thompson   if (ceed->has_valid_op_fallback_resource) {
49523d4529eSJeremy L Thompson     CeedDebug256(ceed, CEED_DEBUG_COLOR_SUCCESS, "---------- CeedOperator Fallback ----------\n");
4962b730f8bSJeremy L Thompson     CeedDebug(ceed, "Getting fallback from %s to %s\n", ceed->resource, ceed->op_fallback_resource);
497d04bbc78SJeremy L Thompson   }
4988687e1d4SJeremy L Thompson 
499d04bbc78SJeremy L Thompson   // Create fallback Ceed if uninitalized
500d04bbc78SJeremy L Thompson   if (!ceed->op_fallback_ceed && ceed->has_valid_op_fallback_resource) {
50113f886e9SJeremy L Thompson     CeedDebug(ceed, "Creating fallback Ceed");
502d04bbc78SJeremy L Thompson 
5038687e1d4SJeremy L Thompson     Ceed        fallback_ceed;
504d04bbc78SJeremy L Thompson     const char *fallback_resource;
505d04bbc78SJeremy L Thompson 
506363aefefSSebastian Grimberg     CeedCall(CeedGetOperatorFallbackResource(ceed, &fallback_resource));
5072b730f8bSJeremy L Thompson     CeedCall(CeedInit(fallback_resource, &fallback_ceed));
5088687e1d4SJeremy L Thompson     fallback_ceed->op_fallback_parent = ceed;
5098687e1d4SJeremy L Thompson     fallback_ceed->Error              = ceed->Error;
5108687e1d4SJeremy L Thompson     ceed->op_fallback_ceed            = fallback_ceed;
5118687e1d4SJeremy L Thompson   }
5128687e1d4SJeremy L Thompson   *fallback_ceed = ceed->op_fallback_ceed;
5138687e1d4SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5148687e1d4SJeremy L Thompson }
5158687e1d4SJeremy L Thompson 
5168687e1d4SJeremy L Thompson /**
517ca94c3ddSJeremy L Thompson   @brief Set the fallback resource for `CeedOperator`.
5184385fb7fSSebastian Grimberg 
519ea61e9acSJeremy L Thompson   The current resource, if any, is freed by calling this function.
520ca94c3ddSJeremy L Thompson   This string is freed upon the destruction of the `Ceed` context.
5217a982d89SJeremy L. Thompson 
522ca94c3ddSJeremy L Thompson   @param[in,out] ceed     `Ceed` context
523ea61e9acSJeremy L Thompson   @param[in]     resource Fallback resource to set
5247a982d89SJeremy L. Thompson 
5257a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5267a982d89SJeremy L. Thompson 
5277a982d89SJeremy L. Thompson   @ref Backend
5287a982d89SJeremy L. Thompson **/
5297a982d89SJeremy L. Thompson int CeedSetOperatorFallbackResource(Ceed ceed, const char *resource) {
5307a982d89SJeremy L. Thompson   // Free old
5312b730f8bSJeremy L Thompson   CeedCall(CeedFree(&ceed->op_fallback_resource));
5327a982d89SJeremy L. Thompson 
5337a982d89SJeremy L. Thompson   // Set new
5342b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(resource, (char **)&ceed->op_fallback_resource));
535d04bbc78SJeremy L Thompson 
536d04bbc78SJeremy L Thompson   // Check validity
5372b730f8bSJeremy L Thompson   ceed->has_valid_op_fallback_resource = ceed->op_fallback_resource && ceed->resource && strcmp(ceed->op_fallback_resource, ceed->resource);
538e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5397a982d89SJeremy L. Thompson }
5407a982d89SJeremy L. Thompson 
5417a982d89SJeremy L. Thompson /**
542ca94c3ddSJeremy L Thompson   @brief Flag `Ceed` context as deterministic
5439525855cSJeremy L Thompson 
544ca94c3ddSJeremy L Thompson   @param[in]  ceed             `Ceed` to flag as deterministic
54596b902e2Sjeremylt   @param[out] is_deterministic Deterministic status to set
5469525855cSJeremy L Thompson 
5479525855cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5489525855cSJeremy L Thompson 
5499525855cSJeremy L Thompson   @ref Backend
5509525855cSJeremy L Thompson **/
551d1d35e2fSjeremylt int CeedSetDeterministic(Ceed ceed, bool is_deterministic) {
552d1d35e2fSjeremylt   ceed->is_deterministic = is_deterministic;
553e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5549525855cSJeremy L Thompson }
5559525855cSJeremy L Thompson 
5569525855cSJeremy L Thompson /**
557ca94c3ddSJeremy L Thompson   @brief Set a backend function.
5587a982d89SJeremy L. Thompson 
559ea61e9acSJeremy L Thompson   This function is used for a backend to set the function associated with the Ceed objects.
560ca94c3ddSJeremy L Thompson   For example, `CeedSetBackendFunction(ceed, "Ceed", ceed, "VectorCreate", BackendVectorCreate)` sets the backend implementation of @ref CeedVectorCreate() and `CeedSetBackendFunction(ceed, "Basis", basis, "Apply", BackendBasisApply)` sets the backend implementation of @ref CeedBasisApply().
5619fd66db6SSebastian Grimberg   Note, the prefix 'Ceed' is not required for the object type ("Basis" vs "CeedBasis").
5627a982d89SJeremy L. Thompson 
563ca94c3ddSJeremy L Thompson   @param[in]  ceed      `Ceed` context for error handling
564ea61e9acSJeremy L Thompson   @param[in]  type      Type of Ceed object to set function for
5657a982d89SJeremy L. Thompson   @param[out] object    Ceed object to set function for
566ea61e9acSJeremy L Thompson   @param[in]  func_name Name of function to set
567ea61e9acSJeremy L Thompson   @param[in]  f         Function to set
5687a982d89SJeremy L. Thompson 
5697a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5707a982d89SJeremy L. Thompson 
5717a982d89SJeremy L. Thompson   @ref Backend
5727a982d89SJeremy L. Thompson **/
573*897d4737SSebastian Grimberg int CeedSetBackendFunctionImpl(Ceed ceed, const char *type, void *object, const char *func_name, void (*f)(void)) {
574d1d35e2fSjeremylt   char lookup_name[CEED_MAX_RESOURCE_LEN + 1] = "";
5757a982d89SJeremy L. Thompson 
5767a982d89SJeremy L. Thompson   // Build lookup name
5772b730f8bSJeremy L Thompson   if (strcmp(type, "Ceed")) strncat(lookup_name, "Ceed", CEED_MAX_RESOURCE_LEN);
578d1d35e2fSjeremylt   strncat(lookup_name, type, CEED_MAX_RESOURCE_LEN);
579d1d35e2fSjeremylt   strncat(lookup_name, func_name, CEED_MAX_RESOURCE_LEN);
5807a982d89SJeremy L. Thompson 
5817a982d89SJeremy L. Thompson   // Find and use offset
5822b730f8bSJeremy L Thompson   for (CeedInt i = 0; ceed->f_offsets[i].func_name; i++) {
583d1d35e2fSjeremylt     if (!strcmp(ceed->f_offsets[i].func_name, lookup_name)) {
584d1d35e2fSjeremylt       size_t offset          = ceed->f_offsets[i].offset;
5857a982d89SJeremy L. Thompson       int (**fpointer)(void) = (int (**)(void))((char *)object + offset);  // *NOPAD*
5861c66c397SJeremy L Thompson 
587*897d4737SSebastian Grimberg       *fpointer = (int (*)(void))f;
588e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
5897a982d89SJeremy L. Thompson     }
5902b730f8bSJeremy L Thompson   }
5917a982d89SJeremy L. Thompson 
5927a982d89SJeremy L. Thompson   // LCOV_EXCL_START
5932b730f8bSJeremy L Thompson   return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Requested function '%s' was not found for CEED object '%s'", func_name, type);
5947a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
5957a982d89SJeremy L. Thompson }
5967a982d89SJeremy L. Thompson 
5977a982d89SJeremy L. Thompson /**
598ca94c3ddSJeremy L Thompson   @brief Retrieve backend data for a `Ceed` context
5997a982d89SJeremy L. Thompson 
600ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` context to retrieve data of
6017a982d89SJeremy L. Thompson   @param[out] data Address to save data to
6027a982d89SJeremy L. Thompson 
6037a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6047a982d89SJeremy L. Thompson 
6057a982d89SJeremy L. Thompson   @ref Backend
6067a982d89SJeremy L. Thompson **/
607777ff853SJeremy L Thompson int CeedGetData(Ceed ceed, void *data) {
608777ff853SJeremy L Thompson   *(void **)data = ceed->data;
609e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6107a982d89SJeremy L. Thompson }
6117a982d89SJeremy L. Thompson 
6127a982d89SJeremy L. Thompson /**
613ca94c3ddSJeremy L Thompson   @brief Set backend data for a `Ceed` context
6147a982d89SJeremy L. Thompson 
615ca94c3ddSJeremy L Thompson   @param[in,out] ceed `Ceed` context to set data of
616ea61e9acSJeremy L Thompson   @param[in]     data Address of data to set
6177a982d89SJeremy L. Thompson 
6187a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6197a982d89SJeremy L. Thompson 
6207a982d89SJeremy L. Thompson   @ref Backend
6217a982d89SJeremy L. Thompson **/
622777ff853SJeremy L Thompson int CeedSetData(Ceed ceed, void *data) {
623777ff853SJeremy L Thompson   ceed->data = data;
624e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6257a982d89SJeremy L. Thompson }
6267a982d89SJeremy L. Thompson 
62734359f16Sjeremylt /**
628ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `Ceed` context
62934359f16Sjeremylt 
630ca94c3ddSJeremy L Thompson   @param[in,out] ceed `Ceed` context to increment the reference counter
63134359f16Sjeremylt 
63234359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
63334359f16Sjeremylt 
63434359f16Sjeremylt   @ref Backend
63534359f16Sjeremylt **/
6369560d06aSjeremylt int CeedReference(Ceed ceed) {
63734359f16Sjeremylt   ceed->ref_count++;
63834359f16Sjeremylt   return CEED_ERROR_SUCCESS;
63934359f16Sjeremylt }
64034359f16Sjeremylt 
6417a982d89SJeremy L. Thompson /// @}
6427a982d89SJeremy L. Thompson 
6437a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
6447a982d89SJeremy L. Thompson /// Ceed Public API
6457a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
6467a982d89SJeremy L. Thompson /// @addtogroup CeedUser
6477a982d89SJeremy L. Thompson /// @{
6487a982d89SJeremy L. Thompson 
6497a982d89SJeremy L. Thompson /**
650ca94c3ddSJeremy L Thompson   @brief Get the list of available resource names for `Ceed` contexts
6514385fb7fSSebastian Grimberg 
652ca94c3ddSJeremy L Thompson   Note: The caller is responsible for `free()`ing the resources and priorities arrays, but should not `free()` the contents of the resources array.
65322e44211Sjeremylt 
65492ee7d1cSjeremylt   @param[out] n          Number of available resources
65592ee7d1cSjeremylt   @param[out] resources  List of available resource names
65622e44211Sjeremylt   @param[out] priorities Resource name prioritization values, lower is better
65722e44211Sjeremylt 
65822e44211Sjeremylt   @return An error code: 0 - success, otherwise - failure
65922e44211Sjeremylt 
66022e44211Sjeremylt   @ref User
66122e44211Sjeremylt **/
66222e44211Sjeremylt // LCOV_EXCL_START
6632b730f8bSJeremy L Thompson int CeedRegistryGetList(size_t *n, char ***const resources, CeedInt **priorities) {
664d0c91ce9Sjeremylt   *n         = 0;
6659ff86846Sjeremylt   *resources = malloc(num_backends * sizeof(**resources));
6666574a04fSJeremy L Thompson   CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "malloc() failure");
6679ff86846Sjeremylt   if (priorities) {
6689ff86846Sjeremylt     *priorities = malloc(num_backends * sizeof(**priorities));
6696574a04fSJeremy L Thompson     CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "malloc() failure");
6709ff86846Sjeremylt   }
67122e44211Sjeremylt   for (size_t i = 0; i < num_backends; i++) {
672d0c91ce9Sjeremylt     // Only report compiled backends
673d0c91ce9Sjeremylt     if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) {
67422e44211Sjeremylt       *resources[i] = backends[i].prefix;
6759ff86846Sjeremylt       if (priorities) *priorities[i] = backends[i].priority;
676d0c91ce9Sjeremylt       *n += 1;
677d0c91ce9Sjeremylt     }
678d0c91ce9Sjeremylt   }
6796574a04fSJeremy L Thompson   CeedCheck(*n, NULL, CEED_ERROR_MAJOR, "No backends installed");
680d0c91ce9Sjeremylt   *resources = realloc(*resources, *n * sizeof(**resources));
6816574a04fSJeremy L Thompson   CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "realloc() failure");
682d0c91ce9Sjeremylt   if (priorities) {
683d0c91ce9Sjeremylt     *priorities = realloc(*priorities, *n * sizeof(**priorities));
6846574a04fSJeremy L Thompson     CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "realloc() failure");
68522e44211Sjeremylt   }
68622e44211Sjeremylt   return CEED_ERROR_SUCCESS;
68745f1e315Sjeremylt }
68822e44211Sjeremylt // LCOV_EXCL_STOP
68922e44211Sjeremylt 
69022e44211Sjeremylt /**
691ca94c3ddSJeremy L Thompson   @brief Initialize a `Ceed` context to use the specified resource.
6924385fb7fSSebastian Grimberg 
693ca94c3ddSJeremy L Thompson   Note: Prefixing the resource with "help:" (e.g. "help:/cpu/self") will result in @ref CeedInt() printing the current libCEED version number and a list of current available backend resources to `stderr`.
694b11c1e72Sjeremylt 
695ea61e9acSJeremy L Thompson   @param[in]  resource Resource to use, e.g., "/cpu/self"
696ea61e9acSJeremy L Thompson   @param[out] ceed     The library context
697b11c1e72Sjeremylt 
698b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
699dfdf5a53Sjeremylt 
7007a982d89SJeremy L. Thompson   @ref User
701ca94c3ddSJeremy L Thompson 
702ca94c3ddSJeremy L Thompson   @sa CeedRegister() CeedDestroy()
703b11c1e72Sjeremylt **/
704d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) {
7052b730f8bSJeremy L Thompson   size_t match_len = 0, match_index = UINT_MAX, match_priority = CEED_MAX_BACKEND_PRIORITY, priority;
706d7b241e6Sjeremylt 
707fe2413ffSjeremylt   // Find matching backend
7086574a04fSJeremy L Thompson   CeedCheck(resource, NULL, CEED_ERROR_MAJOR, "No resource provided");
7092b730f8bSJeremy L Thompson   CeedCall(CeedRegisterAll());
71013873f79Sjeremylt 
71122e44211Sjeremylt   // Check for help request
71222e44211Sjeremylt   const char *help_prefix = "help";
7132b730f8bSJeremy L Thompson   size_t      match_help  = 0;
7142b730f8bSJeremy L Thompson   while (match_help < 4 && resource[match_help] == help_prefix[match_help]) match_help++;
71522e44211Sjeremylt   if (match_help == 4) {
7162b730f8bSJeremy L Thompson     fprintf(stderr, "libCEED version: %d.%d%d%s\n", CEED_VERSION_MAJOR, CEED_VERSION_MINOR, CEED_VERSION_PATCH,
71722e44211Sjeremylt             CEED_VERSION_RELEASE ? "" : "+development");
71892ee7d1cSjeremylt     fprintf(stderr, "Available backend resources:\n");
71922e44211Sjeremylt     for (size_t i = 0; i < num_backends; i++) {
720d0c91ce9Sjeremylt       // Only report compiled backends
7212b730f8bSJeremy L Thompson       if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) fprintf(stderr, "  %s\n", backends[i].prefix);
72222e44211Sjeremylt     }
72322e44211Sjeremylt     fflush(stderr);
72422e44211Sjeremylt     match_help = 5;  // Delineating character expected
72522e44211Sjeremylt   } else {
72622e44211Sjeremylt     match_help = 0;
72722e44211Sjeremylt   }
72822e44211Sjeremylt 
729ea61e9acSJeremy L Thompson   // Find best match, computed as number of matching characters from requested resource stem
7302b730f8bSJeremy L Thompson   size_t stem_length = 0;
7312b730f8bSJeremy L Thompson   while (resource[stem_length + match_help] && resource[stem_length + match_help] != ':') stem_length++;
732d7b241e6Sjeremylt   for (size_t i = 0; i < num_backends; i++) {
7332b730f8bSJeremy L Thompson     size_t      n      = 0;
734d7b241e6Sjeremylt     const char *prefix = backends[i].prefix;
7352b730f8bSJeremy L Thompson     while (prefix[n] && prefix[n] == resource[n + match_help]) n++;
736d7b241e6Sjeremylt     priority = backends[i].priority;
737d1d35e2fSjeremylt     if (n > match_len || (n == match_len && match_priority > priority)) {
738d1d35e2fSjeremylt       match_len      = n;
739d1d35e2fSjeremylt       match_priority = priority;
740f7e22acaSJeremy L Thompson       match_index    = i;
741d7b241e6Sjeremylt     }
742d7b241e6Sjeremylt   }
7439c9a0587SLeila Ghaffari   // Using Levenshtein distance to find closest match
7449c9a0587SLeila Ghaffari   if (match_len <= 1 || match_len != stem_length) {
745203015caSLeila Ghaffari     // LCOV_EXCL_START
7469c9a0587SLeila Ghaffari     size_t lev_dis   = UINT_MAX;
747f7e22acaSJeremy L Thompson     size_t lev_index = UINT_MAX, lev_priority = CEED_MAX_BACKEND_PRIORITY;
7489c9a0587SLeila Ghaffari     for (size_t i = 0; i < num_backends; i++) {
7499c9a0587SLeila Ghaffari       const char *prefix        = backends[i].prefix;
7509c9a0587SLeila Ghaffari       size_t      prefix_length = strlen(backends[i].prefix);
7519c9a0587SLeila Ghaffari       size_t      min_len       = (prefix_length < stem_length) ? prefix_length : stem_length;
752092904ddSLeila Ghaffari       size_t      column[min_len + 1];
753092904ddSLeila Ghaffari       for (size_t j = 0; j <= min_len; j++) column[j] = j;
7549c9a0587SLeila Ghaffari       for (size_t j = 1; j <= min_len; j++) {
7559c9a0587SLeila Ghaffari         column[0] = j;
7569c9a0587SLeila Ghaffari         for (size_t k = 1, last_diag = j - 1; k <= min_len; k++) {
757092904ddSLeila Ghaffari           size_t old_diag = column[k];
7589c9a0587SLeila Ghaffari           size_t min_1    = (column[k] < column[k - 1]) ? column[k] + 1 : column[k - 1] + 1;
7599c9a0587SLeila Ghaffari           size_t min_2    = last_diag + (resource[k - 1] == prefix[j - 1] ? 0 : 1);
7609c9a0587SLeila Ghaffari           column[k]       = (min_1 < min_2) ? min_1 : min_2;
7619c9a0587SLeila Ghaffari           last_diag       = old_diag;
7629c9a0587SLeila Ghaffari         }
7639c9a0587SLeila Ghaffari       }
7649c9a0587SLeila Ghaffari       size_t n = column[min_len];
7659c9a0587SLeila Ghaffari       priority = backends[i].priority;
7662b730f8bSJeremy L Thompson       if (n < lev_dis || (n == lev_dis && lev_priority > priority)) {
7679c9a0587SLeila Ghaffari         lev_dis      = n;
7689c9a0587SLeila Ghaffari         lev_priority = priority;
769f7e22acaSJeremy L Thompson         lev_index    = i;
7709c9a0587SLeila Ghaffari       }
7719c9a0587SLeila Ghaffari     }
772f7e22acaSJeremy L Thompson     const char *prefix_lev = backends[lev_index].prefix;
7732b730f8bSJeremy L Thompson     size_t      lev_length = 0;
7742b730f8bSJeremy L Thompson     while (prefix_lev[lev_length] && prefix_lev[lev_length] != '\0') lev_length++;
7759c9a0587SLeila Ghaffari     size_t m = (lev_length < stem_length) ? lev_length : stem_length;
7766574a04fSJeremy L Thompson     if (lev_dis + 1 >= m) return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s", resource);
7776574a04fSJeremy L Thompson     else return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s\nClosest match: %s", resource, backends[lev_index].prefix);
778203015caSLeila Ghaffari     // LCOV_EXCL_STOP
7799c9a0587SLeila Ghaffari   }
780fe2413ffSjeremylt 
781fe2413ffSjeremylt   // Setup Ceed
7822b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, ceed));
7832b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, &(*ceed)->jit_source_roots));
784bc81ce41Sjeremylt   const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER");
7852b730f8bSJeremy L Thompson   if (!ceed_error_handler) ceed_error_handler = "abort";
7862b730f8bSJeremy L Thompson   if (!strcmp(ceed_error_handler, "exit")) (*ceed)->Error = CeedErrorExit;
7872b730f8bSJeremy L Thompson   else if (!strcmp(ceed_error_handler, "store")) (*ceed)->Error = CeedErrorStore;
7882b730f8bSJeremy L Thompson   else (*ceed)->Error = CeedErrorAbort;
789d1d35e2fSjeremylt   memcpy((*ceed)->err_msg, "No error message stored", 24);
790d1d35e2fSjeremylt   (*ceed)->ref_count = 1;
791d7b241e6Sjeremylt   (*ceed)->data      = NULL;
792fe2413ffSjeremylt 
793fe2413ffSjeremylt   // Set lookup table
794d1d35e2fSjeremylt   FOffset f_offsets[] = {
7956e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, Error),
7965ae360d4SJeremy L Thompson       CEED_FTABLE_ENTRY(Ceed, SetStream),
7976e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType),
7986e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, Destroy),
799f8902d9eSjeremylt       CEED_FTABLE_ENTRY(Ceed, VectorCreate),
8006e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate),
8013ac8f562SJeremy L Thompson       CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateAtPoints),
8026e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked),
8036e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1),
8046e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, BasisCreateH1),
80550c301a5SRezgar Shakeri       CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv),
806c4e3f59bSSebastian Grimberg       CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl),
8076e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, TensorContractCreate),
8086e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, QFunctionCreate),
809777ff853SJeremy L Thompson       CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate),
8106e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, OperatorCreate),
81148acf710SJeremy L Thompson       CEED_FTABLE_ENTRY(Ceed, OperatorCreateAtPoints),
8126e79d475Sjeremylt       CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate),
8139c774eddSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedVector, HasValidArray),
8149c774eddSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType),
8156e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, SetArray),
8166a6c615bSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedVector, TakeArray),
8176e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, SetValue),
818f48ed27dSnbeams       CEED_FTABLE_ENTRY(CeedVector, SyncArray),
8196e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, GetArray),
8206e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, GetArrayRead),
8219c774eddSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite),
8226e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, RestoreArray),
8236e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead),
824547d9b97Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, Norm),
825e0dd3b27Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, Scale),
8260f7fd0f8Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, AXPY),
8275fb68f37SKaren (Ren) Stengel       CEED_FTABLE_ENTRY(CeedVector, AXPBY),
8280f7fd0f8Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, PointwiseMult),
829d99fa3c5SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedVector, Reciprocal),
8306e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedVector, Destroy),
8316e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedElemRestriction, Apply),
832f30b1135SSebastian Grimberg       CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnsigned),
8337c1dbaffSSebastian Grimberg       CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnoriented),
83405fa913cSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyAtPointsInElement),
8356e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock),
836bd33150aSjeremylt       CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets),
83777d1c127SSebastian Grimberg       CEED_FTABLE_ENTRY(CeedElemRestriction, GetOrientations),
83877d1c127SSebastian Grimberg       CEED_FTABLE_ENTRY(CeedElemRestriction, GetCurlOrientations),
8396e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy),
8406e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedBasis, Apply),
841c8c3fa7dSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedBasis, ApplyAtPoints),
8426e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedBasis, Destroy),
8436e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedTensorContract, Apply),
8446e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedTensorContract, Destroy),
8456e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedQFunction, Apply),
8468c84ac63Sjeremylt       CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction),
8478c84ac63Sjeremylt       CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction),
8486e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedQFunction, Destroy),
8499c774eddSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData),
8509c774eddSJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType),
851777ff853SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData),
852891038deSjeremylt       CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData),
853777ff853SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData),
85428bfd0b7SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead),
855777ff853SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData),
85628bfd0b7SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead),
8572e64a2b9SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy),
858777ff853SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy),
85980ac2e43SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction),
86070a7ffb3SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate),
86180ac2e43SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal),
8629e9210b8SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal),
86380ac2e43SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal),
8649e9210b8SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal),
865e2f04181SAndrew T. Barker       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic),
866e2f04181SAndrew T. Barker       CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble),
867cefa2673SJeremy L Thompson       CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle),
868713f43c3Sjeremylt       CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse),
8696e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedOperator, Apply),
870250756a7Sjeremylt       CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite),
871cae8b89aSjeremylt       CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd),
872250756a7Sjeremylt       CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite),
8736e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian),
8746e79d475Sjeremylt       CEED_FTABLE_ENTRY(CeedOperator, Destroy),
8756e79d475Sjeremylt       {NULL, 0}  // End of lookup table - used in SetBackendFunction loop
8761dfeef1dSjeremylt   };
877fe2413ffSjeremylt 
8782b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets));
879d1d35e2fSjeremylt   memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets));
880fe2413ffSjeremylt 
8815107b09fSJeremy L Thompson   // Set fallback for advanced CeedOperator functions
882ca735530SJeremy L Thompson   const char fallback_resource[] = "";
883ca735530SJeremy L Thompson   CeedCall(CeedSetOperatorFallbackResource(*ceed, fallback_resource));
8845107b09fSJeremy L Thompson 
88560f9e2d6SJeremy L Thompson   // Record env variables CEED_DEBUG or DBG
8861c66c397SJeremy L Thompson   (*ceed)->is_debug = getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG");
88760f9e2d6SJeremy L Thompson 
88822e44211Sjeremylt   // Copy resource prefix, if backend setup successful
8892b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource));
890ee5a26f2SJeremy L Thompson 
891ee5a26f2SJeremy L Thompson   // Set default JiT source root
892ea61e9acSJeremy L Thompson   // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent
8932b730f8bSJeremy L Thompson   CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault));
894ee5a26f2SJeremy L Thompson 
895d04bbc78SJeremy L Thompson   // Backend specific setup
8962b730f8bSJeremy L Thompson   CeedCall(backends[match_index].init(&resource[match_help], *ceed));
897e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
898d7b241e6Sjeremylt }
899d7b241e6Sjeremylt 
900d7b241e6Sjeremylt /**
901ca94c3ddSJeremy L Thompson   @brief Set the GPU stream for a `Ceed` context
9025ae360d4SJeremy L Thompson 
903ca94c3ddSJeremy L Thompson   @param[in,out] ceed   `Ceed` context to set the stream
9045ae360d4SJeremy L Thompson   @param[in]     handle Handle to GPU stream
9055ae360d4SJeremy L Thompson 
9065ae360d4SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9075ae360d4SJeremy L Thompson 
9085ae360d4SJeremy L Thompson   @ref User
9095ae360d4SJeremy L Thompson **/
9105ae360d4SJeremy L Thompson int CeedSetStream(Ceed ceed, void *handle) {
911ca94c3ddSJeremy L Thompson   CeedCheck(handle, ceed, CEED_ERROR_INCOMPATIBLE, "Stream handle must be non-NULL");
9129ffb25e0SJames Wright   if (ceed->SetStream) {
9135ae360d4SJeremy L Thompson     CeedCall(ceed->SetStream(ceed, handle));
9149ffb25e0SJames Wright   } else {
9159ffb25e0SJames Wright     Ceed delegate;
9169ffb25e0SJames Wright     CeedCall(CeedGetDelegate(ceed, &delegate));
9175ae360d4SJeremy L Thompson 
91828ce3d2aSJeremy L Thompson     if (delegate) CeedCall(CeedSetStream(delegate, handle));
91928ce3d2aSJeremy L Thompson     else return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support setting stream");
9209ffb25e0SJames Wright   }
9215ae360d4SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9225ae360d4SJeremy L Thompson }
9235ae360d4SJeremy L Thompson 
9245ae360d4SJeremy L Thompson /**
925ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `Ceed` context.
9264385fb7fSSebastian Grimberg 
927ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedDestroy().
928512bb800SJeremy L Thompson 
929ca94c3ddSJeremy L Thompson   Note: If the value of `*ceed_copy` passed to this function is non-`NULL`, then it is assumed that `*ceed_copy` is a pointer to a `Ceed` context.
930ca94c3ddSJeremy L Thompson         This `Ceed` context will be destroyed if `*ceed_copy` is the only reference to this `Ceed` context.
9319560d06aSjeremylt 
932ca94c3ddSJeremy L Thompson   @param[in]     ceed      `Ceed` context to copy reference to
933ea61e9acSJeremy L Thompson   @param[in,out] ceed_copy Variable to store copied reference
9349560d06aSjeremylt 
9359560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
9369560d06aSjeremylt 
9379560d06aSjeremylt   @ref User
9389560d06aSjeremylt **/
9399560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) {
9402b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
9412b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(ceed_copy));
9429560d06aSjeremylt   *ceed_copy = ceed;
9439560d06aSjeremylt   return CEED_ERROR_SUCCESS;
9449560d06aSjeremylt }
9459560d06aSjeremylt 
9469560d06aSjeremylt /**
947ca94c3ddSJeremy L Thompson   @brief Get the full resource name for a `Ceed` context
9482f86a920SJeremy L Thompson 
949ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context to get resource name of
9507a982d89SJeremy L. Thompson   @param[out] resource Variable to store resource name
9512f86a920SJeremy L Thompson 
9522f86a920SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9532f86a920SJeremy L Thompson 
9547a982d89SJeremy L. Thompson   @ref User
9555107b09fSJeremy L Thompson **/
9567a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) {
9577a982d89SJeremy L. Thompson   *resource = (const char *)ceed->resource;
958e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9595107b09fSJeremy L Thompson }
9605107b09fSJeremy L Thompson 
9615107b09fSJeremy L Thompson /**
962ca94c3ddSJeremy L Thompson   @brief Return `Ceed` context preferred memory type
963c907536fSjeremylt 
964ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` context to get preferred memory type of
965d1d35e2fSjeremylt   @param[out] mem_type Address to save preferred memory type to
966c907536fSjeremylt 
967c907536fSjeremylt   @return An error code: 0 - success, otherwise - failure
968c907536fSjeremylt 
9697a982d89SJeremy L. Thompson   @ref User
970c907536fSjeremylt **/
971d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) {
972c907536fSjeremylt   if (ceed->GetPreferredMemType) {
9732b730f8bSJeremy L Thompson     CeedCall(ceed->GetPreferredMemType(mem_type));
974c907536fSjeremylt   } else {
975c263cd57Sjeremylt     Ceed delegate;
9762b730f8bSJeremy L Thompson     CeedCall(CeedGetDelegate(ceed, &delegate));
977c263cd57Sjeremylt 
978c263cd57Sjeremylt     if (delegate) {
9792b730f8bSJeremy L Thompson       CeedCall(CeedGetPreferredMemType(delegate, mem_type));
980c263cd57Sjeremylt     } else {
981d1d35e2fSjeremylt       *mem_type = CEED_MEM_HOST;
982c907536fSjeremylt     }
983c263cd57Sjeremylt   }
984e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
985c907536fSjeremylt }
986c907536fSjeremylt 
987c907536fSjeremylt /**
988ca94c3ddSJeremy L Thompson   @brief Get deterministic status of `Ceed` context
9899525855cSJeremy L Thompson 
990ca94c3ddSJeremy L Thompson   @param[in]  ceed             `Ceed` context
991d1d35e2fSjeremylt   @param[out] is_deterministic Variable to store deterministic status
9929525855cSJeremy L Thompson 
9939525855cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9949525855cSJeremy L Thompson 
9959525855cSJeremy L Thompson   @ref User
9969525855cSJeremy L Thompson **/
997d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) {
998d1d35e2fSjeremylt   *is_deterministic = ceed->is_deterministic;
999e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10009525855cSJeremy L Thompson }
10019525855cSJeremy L Thompson 
10029525855cSJeremy L Thompson /**
1003ca94c3ddSJeremy L Thompson   @brief Set additional JiT source root for `Ceed` context
1004ee5a26f2SJeremy L Thompson 
1005ca94c3ddSJeremy L Thompson   @param[in,out] ceed            `Ceed` context
1006ee5a26f2SJeremy L Thompson   @param[in]     jit_source_root Absolute path to additional JiT source directory
1007ee5a26f2SJeremy L Thompson 
1008ee5a26f2SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1009ee5a26f2SJeremy L Thompson 
1010ee5a26f2SJeremy L Thompson   @ref User
1011ee5a26f2SJeremy L Thompson **/
1012ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) {
10136155f12fSJeremy L Thompson   Ceed ceed_parent;
1014ee5a26f2SJeremy L Thompson 
10152b730f8bSJeremy L Thompson   CeedCall(CeedGetParent(ceed, &ceed_parent));
10166155f12fSJeremy L Thompson 
10176155f12fSJeremy L Thompson   CeedInt index       = ceed_parent->num_jit_source_roots;
1018ee5a26f2SJeremy L Thompson   size_t  path_length = strlen(jit_source_root);
10191c66c397SJeremy L Thompson 
10202b730f8bSJeremy L Thompson   CeedCall(CeedRealloc(index + 1, &ceed_parent->jit_source_roots));
10212b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index]));
1022d602d780SJeremy L Thompson   memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length);
10236155f12fSJeremy L Thompson   ceed_parent->num_jit_source_roots++;
1024ee5a26f2SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1025ee5a26f2SJeremy L Thompson }
1026ee5a26f2SJeremy L Thompson 
1027ee5a26f2SJeremy L Thompson /**
1028ca94c3ddSJeremy L Thompson   @brief View a `Ceed`
10290a0da059Sjeremylt 
1030ca94c3ddSJeremy L Thompson   @param[in] ceed   `Ceed` to view
10310a0da059Sjeremylt   @param[in] stream Filestream to write to
10320a0da059Sjeremylt 
10330a0da059Sjeremylt   @return An error code: 0 - success, otherwise - failure
10340a0da059Sjeremylt 
10350a0da059Sjeremylt   @ref User
10360a0da059Sjeremylt **/
10370a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) {
1038d1d35e2fSjeremylt   CeedMemType mem_type;
10390a0da059Sjeremylt 
10402b730f8bSJeremy L Thompson   CeedCall(CeedGetPreferredMemType(ceed, &mem_type));
10410a0da059Sjeremylt 
10422b730f8bSJeremy L Thompson   fprintf(stream,
10432b730f8bSJeremy L Thompson           "Ceed\n"
10440a0da059Sjeremylt           "  Ceed Resource: %s\n"
10450a0da059Sjeremylt           "  Preferred MemType: %s\n",
1046d1d35e2fSjeremylt           ceed->resource, CeedMemTypes[mem_type]);
1047e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10480a0da059Sjeremylt }
10490a0da059Sjeremylt 
10500a0da059Sjeremylt /**
1051ca94c3ddSJeremy L Thompson   @brief Destroy a `Ceed`
1052d7b241e6Sjeremylt 
1053ca94c3ddSJeremy L Thompson   @param[in,out] ceed Address of `Ceed` context to destroy
1054b11c1e72Sjeremylt 
1055b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1056dfdf5a53Sjeremylt 
10577a982d89SJeremy L. Thompson   @ref User
1058b11c1e72Sjeremylt **/
1059d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) {
1060ad6481ceSJeremy L Thompson   if (!*ceed || --(*ceed)->ref_count > 0) {
1061ad6481ceSJeremy L Thompson     *ceed = NULL;
1062ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1063ad6481ceSJeremy L Thompson   }
10642b730f8bSJeremy L Thompson   if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate));
10650ace9bf2Sjeremylt 
1066d1d35e2fSjeremylt   if ((*ceed)->obj_delegate_count > 0) {
106792ae7e47SJeremy L Thompson     for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) {
10682b730f8bSJeremy L Thompson       CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate)));
10692b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name));
1070aefd8378Sjeremylt     }
10712b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ceed)->obj_delegates));
1072aefd8378Sjeremylt   }
10730ace9bf2Sjeremylt 
10742b730f8bSJeremy L Thompson   if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed));
10750ace9bf2Sjeremylt 
107692ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) {
10772b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ceed)->jit_source_roots[i]));
1078032e71eaSJeremy L Thompson   }
10792b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ceed)->jit_source_roots));
1080032e71eaSJeremy L Thompson 
10812b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ceed)->f_offsets));
10822b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ceed)->resource));
10832b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed));
10842b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ceed)->op_fallback_resource));
10852b730f8bSJeremy L Thompson   CeedCall(CeedFree(ceed));
1086e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1087d7b241e6Sjeremylt }
1088d7b241e6Sjeremylt 
1089f9982c62SWill Pazner // LCOV_EXCL_START
1090f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) {
10912b730f8bSJeremy L Thompson   if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args);
10922b730f8bSJeremy L Thompson   if (ceed->op_fallback_parent) return CeedErrorFormat(ceed->op_fallback_parent, format, args);
109378464608Sjeremylt   // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized
109478464608Sjeremylt   vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args);  // NOLINT
1095d1d35e2fSjeremylt   return ceed->err_msg;
1096f9982c62SWill Pazner }
1097f9982c62SWill Pazner // LCOV_EXCL_STOP
1098f9982c62SWill Pazner 
10997a982d89SJeremy L. Thompson /**
1100ca94c3ddSJeremy L Thompson   @brief Error handling implementation; use @ref CeedError() instead.
1101ca94c3ddSJeremy L Thompson 
1102ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
11037a982d89SJeremy L. Thompson 
11047a982d89SJeremy L. Thompson   @ref Developer
11057a982d89SJeremy L. Thompson **/
11062b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) {
11077a982d89SJeremy L. Thompson   va_list args;
1108d1d35e2fSjeremylt   int     ret_val;
11091c66c397SJeremy L Thompson 
11107a982d89SJeremy L. Thompson   va_start(args, format);
11117a982d89SJeremy L. Thompson   if (ceed) {
1112d1d35e2fSjeremylt     ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args);
11137a982d89SJeremy L. Thompson   } else {
1114b0d62198Sjeremylt     // LCOV_EXCL_START
1115477729cfSJeremy L Thompson     const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER");
11162b730f8bSJeremy L Thompson     if (!ceed_error_handler) ceed_error_handler = "abort";
11172b730f8bSJeremy L Thompson     if (!strcmp(ceed_error_handler, "return")) ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args);
1118477729cfSJeremy L Thompson     else
1119477729cfSJeremy L Thompson       // This function will not return
1120d1d35e2fSjeremylt       ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args);
11217a982d89SJeremy L. Thompson   }
11227a982d89SJeremy L. Thompson   va_end(args);
1123d1d35e2fSjeremylt   return ret_val;
1124b0d62198Sjeremylt   // LCOV_EXCL_STOP
11257a982d89SJeremy L. Thompson }
11267a982d89SJeremy L. Thompson 
1127477729cfSJeremy L Thompson /**
1128477729cfSJeremy L Thompson   @brief Error handler that returns without printing anything.
1129477729cfSJeremy L Thompson 
1130ca94c3ddSJeremy L Thompson   Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior.
1131ca94c3ddSJeremy L Thompson 
1132ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1133477729cfSJeremy L Thompson 
1134477729cfSJeremy L Thompson   @ref Developer
1135477729cfSJeremy L Thompson **/
1136477729cfSJeremy L Thompson // LCOV_EXCL_START
11372b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) {
1138d1d35e2fSjeremylt   return err_code;
1139477729cfSJeremy L Thompson }
1140477729cfSJeremy L Thompson // LCOV_EXCL_STOP
1141477729cfSJeremy L Thompson 
1142477729cfSJeremy L Thompson /**
1143ea61e9acSJeremy L Thompson   @brief Error handler that stores the error message for future use and returns the error.
1144477729cfSJeremy L Thompson 
1145ca94c3ddSJeremy L Thompson   Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior.
1146ca94c3ddSJeremy L Thompson 
1147ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1148477729cfSJeremy L Thompson 
1149477729cfSJeremy L Thompson   @ref Developer
1150477729cfSJeremy L Thompson **/
1151477729cfSJeremy L Thompson // LCOV_EXCL_START
11522b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) {
11532b730f8bSJeremy L Thompson   if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args);
11542b730f8bSJeremy L Thompson   if (ceed->op_fallback_parent) return CeedErrorStore(ceed->op_fallback_parent, filename, line_no, func, err_code, format, args);
1155477729cfSJeremy L Thompson 
1156477729cfSJeremy L Thompson   // Build message
11571c66c397SJeremy L Thompson   int len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%s:%d in %s(): ", filename, line_no, func);
115878464608Sjeremylt   // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized
115978464608Sjeremylt   vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args);  // NOLINT
1160d1d35e2fSjeremylt   return err_code;
1161477729cfSJeremy L Thompson }
1162477729cfSJeremy L Thompson // LCOV_EXCL_STOP
1163477729cfSJeremy L Thompson 
1164477729cfSJeremy L Thompson /**
1165ca94c3ddSJeremy L Thompson   @brief Error handler that prints to `stderr` and aborts
1166477729cfSJeremy L Thompson 
1167ca94c3ddSJeremy L Thompson   Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior.
1168ca94c3ddSJeremy L Thompson 
1169ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1170477729cfSJeremy L Thompson 
1171477729cfSJeremy L Thompson   @ref Developer
1172477729cfSJeremy L Thompson **/
1173477729cfSJeremy L Thompson // LCOV_EXCL_START
11742b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) {
1175d1d35e2fSjeremylt   fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func);
1176f9982c62SWill Pazner   vfprintf(stderr, format, *args);
1177477729cfSJeremy L Thompson   fprintf(stderr, "\n");
1178477729cfSJeremy L Thompson   abort();
1179d1d35e2fSjeremylt   return err_code;
1180477729cfSJeremy L Thompson }
1181477729cfSJeremy L Thompson // LCOV_EXCL_STOP
1182477729cfSJeremy L Thompson 
1183477729cfSJeremy L Thompson /**
1184ca94c3ddSJeremy L Thompson   @brief Error handler that prints to `stderr` and exits.
1185477729cfSJeremy L Thompson 
1186ca94c3ddSJeremy L Thompson   Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior.
1187477729cfSJeremy L Thompson 
1188ca94c3ddSJeremy L Thompson   In contrast to @ref CeedErrorAbort(), this exits without a signal, so `atexit()` handlers (e.g., as used by gcov) are run.
1189ca94c3ddSJeremy L Thompson 
1190ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1191477729cfSJeremy L Thompson 
1192477729cfSJeremy L Thompson   @ref Developer
1193477729cfSJeremy L Thompson **/
11942b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) {
1195d1d35e2fSjeremylt   fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func);
119678464608Sjeremylt   // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized
119778464608Sjeremylt   vfprintf(stderr, format, *args);  // NOLINT
1198477729cfSJeremy L Thompson   fprintf(stderr, "\n");
1199d1d35e2fSjeremylt   exit(err_code);
1200d1d35e2fSjeremylt   return err_code;
1201477729cfSJeremy L Thompson }
1202477729cfSJeremy L Thompson 
1203477729cfSJeremy L Thompson /**
1204477729cfSJeremy L Thompson   @brief Set error handler
1205477729cfSJeremy L Thompson 
1206ca94c3ddSJeremy L Thompson   A default error handler is set in @ref CeedInit().
1207ca94c3ddSJeremy L Thompson   Use this function to change the error handler to @ref CeedErrorReturn(), @ref CeedErrorAbort(), or a user-defined error handler.
1208ca94c3ddSJeremy L Thompson 
1209ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1210477729cfSJeremy L Thompson 
1211477729cfSJeremy L Thompson   @ref Developer
1212477729cfSJeremy L Thompson **/
1213d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) {
1214d1d35e2fSjeremylt   ceed->Error = handler;
1215d1d35e2fSjeremylt   if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler);
12162b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler);
1217e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1218477729cfSJeremy L Thompson }
1219477729cfSJeremy L Thompson 
1220477729cfSJeremy L Thompson /**
1221477729cfSJeremy L Thompson   @brief Get error message
1222477729cfSJeremy L Thompson 
1223ca94c3ddSJeremy L Thompson   The error message is only stored when using the error handler @ref CeedErrorStore()
1224477729cfSJeremy L Thompson 
1225ca94c3ddSJeremy L Thompson   @param[in]  ceed    `Ceed` context to retrieve error message
1226d1d35e2fSjeremylt   @param[out] err_msg Char pointer to hold error message
1227477729cfSJeremy L Thompson 
1228ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1229ca94c3ddSJeremy L Thompson 
1230477729cfSJeremy L Thompson   @ref Developer
1231477729cfSJeremy L Thompson **/
1232d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) {
12332b730f8bSJeremy L Thompson   if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg);
12342b730f8bSJeremy L Thompson   if (ceed->op_fallback_parent) return CeedGetErrorMessage(ceed->op_fallback_parent, err_msg);
1235d1d35e2fSjeremylt   *err_msg = ceed->err_msg;
1236e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1237477729cfSJeremy L Thompson }
1238477729cfSJeremy L Thompson 
1239477729cfSJeremy L Thompson /**
1240ca94c3ddSJeremy L Thompson   @brief Restore error message.
1241477729cfSJeremy L Thompson 
1242ca94c3ddSJeremy L Thompson   The error message is only stored when using the error handler @ref CeedErrorStore().
1243477729cfSJeremy L Thompson 
1244ca94c3ddSJeremy L Thompson   @param[in]  ceed    `Ceed` context to restore error message
1245d1d35e2fSjeremylt   @param[out] err_msg Char pointer that holds error message
1246477729cfSJeremy L Thompson 
1247ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1248ca94c3ddSJeremy L Thompson 
1249477729cfSJeremy L Thompson   @ref Developer
1250477729cfSJeremy L Thompson **/
1251d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) {
12522b730f8bSJeremy L Thompson   if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg);
12532b730f8bSJeremy L Thompson   if (ceed->op_fallback_parent) return CeedResetErrorMessage(ceed->op_fallback_parent, err_msg);
1254d1d35e2fSjeremylt   *err_msg = NULL;
1255d1d35e2fSjeremylt   memcpy(ceed->err_msg, "No error message stored", 24);
1256e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1257477729cfSJeremy L Thompson }
1258477729cfSJeremy L Thompson 
12591070991dSJed Brown /**
1260ca94c3ddSJeremy L Thompson   @brief Get libCEED library version information.
12611070991dSJed Brown 
1262ea61e9acSJeremy L Thompson   libCEED version numbers have the form major.minor.patch.
1263ea61e9acSJeremy L Thompson   Non-release versions may contain unstable interfaces.
12641070991dSJed Brown 
12651070991dSJed Brown   @param[out] major   Major version of the library
12661070991dSJed Brown   @param[out] minor   Minor version of the library
12671070991dSJed Brown   @param[out] patch   Patch (subminor) version of the library
126853cbfc38SJeremy L Thompson   @param[out] release True for releases; false for development branches
12691070991dSJed Brown 
1270ca94c3ddSJeremy L Thompson   The caller may pass `NULL` for any arguments that are not needed.
12711070991dSJed Brown 
1272ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
12731070991dSJed Brown 
12741070991dSJed Brown   @ref Developer
1275ca94c3ddSJeremy L Thompson 
1276ca94c3ddSJeremy L Thompson   @sa CEED_VERSION_GE()
12771070991dSJed Brown */
12781070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) {
12791070991dSJed Brown   if (major) *major = CEED_VERSION_MAJOR;
12801070991dSJed Brown   if (minor) *minor = CEED_VERSION_MINOR;
12811070991dSJed Brown   if (patch) *patch = CEED_VERSION_PATCH;
12821070991dSJed Brown   if (release) *release = CEED_VERSION_RELEASE;
1283ca94c3ddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
12841070991dSJed Brown }
12851070991dSJed Brown 
128653cbfc38SJeremy L Thompson /**
128753cbfc38SJeremy L Thompson   @brief Get libCEED scalar type, such as F64 or F32
128853cbfc38SJeremy L Thompson 
128953cbfc38SJeremy L Thompson   @param[out] scalar_type Type of libCEED scalars
129053cbfc38SJeremy L Thompson 
1291ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1292ca94c3ddSJeremy L Thompson 
129353cbfc38SJeremy L Thompson   @ref Developer
129453cbfc38SJeremy L Thompson */
129580a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) {
129680a9ef05SNatalie Beams   *scalar_type = CEED_SCALAR_TYPE;
1297ca94c3ddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
129880a9ef05SNatalie Beams }
129980a9ef05SNatalie Beams 
1300d7b241e6Sjeremylt /// @}
1301