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 44ea61e9acSJeremy L Thompson This predefined constant is passed as the \ref CeedRequest argument to interfaces when the caller wishes for the operation to be performed 45dfdf5a53Sjeremylt immediately. 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 66ea61e9acSJeremy 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 679fd66db6SSebastian Grimberg order that it is submitted to the device. 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 /** 867a982d89SJeremy L. Thompson @brief Wait for a CeedRequest to complete. 87dfdf5a53Sjeremylt 887a982d89SJeremy L. Thompson Calling CeedRequestWait on a NULL request is a no-op. 897a982d89SJeremy L. Thompson 907a982d89SJeremy L. Thompson @param req Address of 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 1126a406739SJeremy L Thompson Note: Backends should call `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". 116ea61e9acSJeremy L Thompson @param[in] init Initialization function called by CeedInit() when the backend is selected to drive the requested resource. 117ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 118ea61e9acSJeremy L Thompson Lower values are preferred in case the resource requested by 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) { 1256574a04fSJeremy L Thompson CeedCheck(num_backends < sizeof(backends) / sizeof(backends[0]), NULL, CEED_ERROR_MAJOR, "Too many backends"); 1266a406739SJeremy L Thompson 1276a406739SJeremy L Thompson strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN); 1286a406739SJeremy L Thompson backends[num_backends].prefix[CEED_MAX_RESOURCE_LEN - 1] = 0; 1296a406739SJeremy L Thompson backends[num_backends].init = init; 1306a406739SJeremy L Thompson backends[num_backends].priority = priority; 1316a406739SJeremy L Thompson num_backends++; 1326a406739SJeremy L Thompson return CEED_ERROR_SUCCESS; 1336a406739SJeremy L Thompson } 1346a406739SJeremy L Thompson 1357a982d89SJeremy L. Thompson /// @} 136d7b241e6Sjeremylt 1377a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1387a982d89SJeremy L. Thompson /// Ceed Backend API 1397a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1407a982d89SJeremy L. Thompson /// @addtogroup CeedBackend 1417a982d89SJeremy L. Thompson /// @{ 142d7b241e6Sjeremylt 143b11c1e72Sjeremylt /** 1443f21f6b1SJeremy L Thompson @brief Return value of CEED_DEBUG environment variable 14560f9e2d6SJeremy L Thompson 146ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 14760f9e2d6SJeremy L Thompson 1483f21f6b1SJeremy L Thompson @return boolean value: true - debugging mode enabled 1493f21f6b1SJeremy L Thompson false - debugging mode disabled 15060f9e2d6SJeremy L Thompson 15160f9e2d6SJeremy L Thompson @ref Backend 15260f9e2d6SJeremy L Thompson **/ 153fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 1542b730f8bSJeremy L Thompson bool CeedDebugFlag(const Ceed ceed) { return ceed->is_debug; } 155fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 15660f9e2d6SJeremy L Thompson 15760f9e2d6SJeremy L Thompson /** 1583f21f6b1SJeremy L Thompson @brief Return value of CEED_DEBUG environment variable 15960f9e2d6SJeremy L Thompson 1603f21f6b1SJeremy L Thompson @return boolean value: true - debugging mode enabled 1613f21f6b1SJeremy L Thompson false - debugging mode disabled 1623f21f6b1SJeremy L Thompson 1633f21f6b1SJeremy L Thompson @ref Backend 1643f21f6b1SJeremy L Thompson **/ 1653f21f6b1SJeremy L Thompson // LCOV_EXCL_START 1661c66c397SJeremy L Thompson bool CeedDebugFlagEnv(void) { return getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); } 1673f21f6b1SJeremy L Thompson // LCOV_EXCL_STOP 1683f21f6b1SJeremy L Thompson 1693f21f6b1SJeremy L Thompson /** 1703f21f6b1SJeremy L Thompson @brief Print debugging information in color 1713f21f6b1SJeremy L Thompson 17260f9e2d6SJeremy L Thompson @param color Color to print 17360f9e2d6SJeremy L Thompson @param format Printing format 17460f9e2d6SJeremy L Thompson 17560f9e2d6SJeremy L Thompson @ref Backend 17660f9e2d6SJeremy L Thompson **/ 177fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 1783f21f6b1SJeremy L Thompson void CeedDebugImpl256(const unsigned char color, const char *format, ...) { 17960f9e2d6SJeremy L Thompson va_list args; 18060f9e2d6SJeremy L Thompson va_start(args, format); 18160f9e2d6SJeremy L Thompson fflush(stdout); 1822b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[38;5;%dm", color); 18360f9e2d6SJeremy L Thompson vfprintf(stdout, format, args); 1842b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[m"); 18560f9e2d6SJeremy L Thompson fprintf(stdout, "\n"); 18660f9e2d6SJeremy L Thompson fflush(stdout); 18760f9e2d6SJeremy L Thompson va_end(args); 18860f9e2d6SJeremy L Thompson } 189fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 19060f9e2d6SJeremy L Thompson 19160f9e2d6SJeremy L Thompson /** 192b11c1e72Sjeremylt @brief Allocate an array on the host; use CeedMalloc() 193b11c1e72Sjeremylt 194ea61e9acSJeremy L Thompson Memory usage can be tracked by the library. 195ea61e9acSJeremy L Thompson This ensures sufficient alignment for vectorization and should be used for large allocations. 196b11c1e72Sjeremylt 197ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 198ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 199ea61e9acSJeremy L Thompson @param[out] p Address of pointer to hold the result. 200b11c1e72Sjeremylt 201b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 202b11c1e72Sjeremylt 203b11c1e72Sjeremylt @sa CeedFree() 204dfdf5a53Sjeremylt 2057a982d89SJeremy L. Thompson @ref Backend 206b11c1e72Sjeremylt **/ 207d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 208d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n * unit); 2096574a04fSJeremy L Thompson CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "posix_memalign failed to allocate %zd members of size %zd\n", n, unit); 210e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 211d7b241e6Sjeremylt } 212d7b241e6Sjeremylt 213b11c1e72Sjeremylt /** 214b11c1e72Sjeremylt @brief Allocate a cleared (zeroed) array on the host; use CeedCalloc() 215b11c1e72Sjeremylt 216b11c1e72Sjeremylt Memory usage can be tracked by the library. 217b11c1e72Sjeremylt 218ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 219ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 220ea61e9acSJeremy L Thompson @param[out] p Address of pointer to hold the result. 221b11c1e72Sjeremylt 222b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 223b11c1e72Sjeremylt 224b11c1e72Sjeremylt @sa CeedFree() 225dfdf5a53Sjeremylt 2267a982d89SJeremy L. Thompson @ref Backend 227b11c1e72Sjeremylt **/ 228d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 229d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 2306574a04fSJeremy L Thompson CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "calloc failed to allocate %zd members of size %zd\n", n, unit); 231e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 232d7b241e6Sjeremylt } 233d7b241e6Sjeremylt 234b11c1e72Sjeremylt /** 235b11c1e72Sjeremylt @brief Reallocate an array on the host; use CeedRealloc() 236b11c1e72Sjeremylt 237b11c1e72Sjeremylt Memory usage can be tracked by the library. 238b11c1e72Sjeremylt 239ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 240ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 241ea61e9acSJeremy L Thompson @param[out] p Address of pointer to hold the result. 242b11c1e72Sjeremylt 243b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 244b11c1e72Sjeremylt 245b11c1e72Sjeremylt @sa CeedFree() 246dfdf5a53Sjeremylt 2477a982d89SJeremy L. Thompson @ref Backend 248b11c1e72Sjeremylt **/ 249d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 250d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n * unit); 2516574a04fSJeremy L Thompson CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "realloc failed to allocate %zd members of size %zd\n", n, unit); 252e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 253d7b241e6Sjeremylt } 254d7b241e6Sjeremylt 255f7e22acaSJeremy L Thompson /** 256f7e22acaSJeremy L Thompson @brief Allocate a cleared string buffer on the host 257f7e22acaSJeremy L Thompson 258f7e22acaSJeremy L Thompson Memory usage can be tracked by the library. 259f7e22acaSJeremy L Thompson 260ea61e9acSJeremy L Thompson @param[in] source Pointer to string to be copied 261ea61e9acSJeremy L Thompson @param[out] copy Pointer to variable to hold newly allocated string copy 262f7e22acaSJeremy L Thompson 263f7e22acaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 264f7e22acaSJeremy L Thompson 265f7e22acaSJeremy L Thompson @sa CeedFree() 266f7e22acaSJeremy L Thompson 267f7e22acaSJeremy L Thompson @ref Backend 268f7e22acaSJeremy L Thompson **/ 269f7e22acaSJeremy L Thompson int CeedStringAllocCopy(const char *source, char **copy) { 270f7e22acaSJeremy L Thompson size_t len = strlen(source); 2712b730f8bSJeremy L Thompson CeedCall(CeedCalloc(len + 1, copy)); 272d602d780SJeremy L Thompson memcpy(*copy, source, len); 273f7e22acaSJeremy L Thompson return CEED_ERROR_SUCCESS; 274f7e22acaSJeremy L Thompson } 275f7e22acaSJeremy L Thompson 27634138859Sjeremylt /** Free memory allocated using CeedMalloc() or CeedCalloc() 27734138859Sjeremylt 278ea61e9acSJeremy L Thompson @param[in,out] p address of pointer to memory. 279ea61e9acSJeremy 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 280ea61e9acSJeremy L Thompson pointer. 28134138859Sjeremylt **/ 282d7b241e6Sjeremylt int CeedFree(void *p) { 283d7b241e6Sjeremylt free(*(void **)p); 284d7b241e6Sjeremylt *(void **)p = NULL; 285e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 286d7b241e6Sjeremylt } 287d7b241e6Sjeremylt 288d7b241e6Sjeremylt /** 2897a982d89SJeremy L. Thompson @brief Register a Ceed backend 290d7b241e6Sjeremylt 291ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 292ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 293ea61e9acSJeremy L Thompson @param[in] init Initialization function called by CeedInit() when the backend is selected to drive the requested resource. 294ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 295ea61e9acSJeremy L Thompson Lower values are preferred in case the resource requested by CeedInit() has non-unique best prefix match. 296b11c1e72Sjeremylt 297b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 298dfdf5a53Sjeremylt 2997a982d89SJeremy L. Thompson @ref Backend 300b11c1e72Sjeremylt **/ 3012b730f8bSJeremy L Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 30210243053SJeremy L Thompson CeedDebugEnv("Backend Register: %s", prefix); 3036a406739SJeremy L Thompson CeedRegisterImpl(prefix, init, priority); 304e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 305d7b241e6Sjeremylt } 306d7b241e6Sjeremylt 307b11c1e72Sjeremylt /** 30860f9e2d6SJeremy L Thompson @brief Return debugging status flag 30960f9e2d6SJeremy L Thompson 310ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get debugging flag 311ea61e9acSJeremy L Thompson @param[out] is_debug Variable to store debugging flag 31260f9e2d6SJeremy L Thompson 31360f9e2d6SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 31460f9e2d6SJeremy L Thompson 315d1d35e2fSjeremylt @ref Backend 31660f9e2d6SJeremy L Thompson **/ 317d1d35e2fSjeremylt int CeedIsDebug(Ceed ceed, bool *is_debug) { 3183f21f6b1SJeremy L Thompson *is_debug = ceed->is_debug; 319e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 32060f9e2d6SJeremy L Thompson } 32160f9e2d6SJeremy L Thompson 32260f9e2d6SJeremy L Thompson /** 323bc246734SJeremy L Thompson @brief Get the root of the requested resource 324bc246734SJeremy L Thompson 325bc246734SJeremy L Thompson @param[in] ceed Ceed context to get resource name of 326bc246734SJeremy L Thompson @param[in] resource ull user specified resource 3271c66c397SJeremy L Thompson @param[in] delineator Delineator to break resource_root and resource_spec 328bc246734SJeremy L Thompson @param[out] resource_root Variable to store resource root 329bc246734SJeremy L Thompson 330bc246734SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 331bc246734SJeremy L Thompson 332bc246734SJeremy L Thompson @ref Backend 333bc246734SJeremy L Thompson **/ 334bc246734SJeremy L Thompson int CeedGetResourceRoot(Ceed ceed, const char *resource, const char *delineator, char **resource_root) { 335bc246734SJeremy L Thompson char *device_spec = strstr(resource, delineator); 336bc246734SJeremy L Thompson size_t resource_root_len = device_spec ? (size_t)(device_spec - resource) + 1 : strlen(resource) + 1; 3371c66c397SJeremy L Thompson 338bc246734SJeremy L Thompson CeedCall(CeedCalloc(resource_root_len, resource_root)); 339bc246734SJeremy L Thompson memcpy(*resource_root, resource, resource_root_len - 1); 340bc246734SJeremy L Thompson return CEED_ERROR_SUCCESS; 341bc246734SJeremy L Thompson } 342bc246734SJeremy L Thompson 343bc246734SJeremy L Thompson /** 3447a982d89SJeremy L. Thompson @brief Retrieve a parent Ceed context 3457a982d89SJeremy L. Thompson 346ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve parent of 3477a982d89SJeremy L. Thompson @param[out] parent Address to save the parent to 3487a982d89SJeremy L. Thompson 3497a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3507a982d89SJeremy L. Thompson 3517a982d89SJeremy L. Thompson @ref Backend 3527a982d89SJeremy L. Thompson **/ 3537a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 3547a982d89SJeremy L. Thompson if (ceed->parent) { 3552b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed->parent, parent)); 356e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3577a982d89SJeremy L. Thompson } 3587a982d89SJeremy L. Thompson *parent = ceed; 359e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3607a982d89SJeremy L. Thompson } 3617a982d89SJeremy L. Thompson 3627a982d89SJeremy L. Thompson /** 3637a982d89SJeremy L. Thompson @brief Retrieve a delegate Ceed context 3647a982d89SJeremy L. Thompson 365ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve delegate of 3667a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 3677a982d89SJeremy L. Thompson 3687a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3697a982d89SJeremy L. Thompson 3707a982d89SJeremy L. Thompson @ref Backend 3717a982d89SJeremy L. Thompson **/ 3727a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 3737a982d89SJeremy L. Thompson *delegate = ceed->delegate; 374e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3757a982d89SJeremy L. Thompson } 3767a982d89SJeremy L. Thompson 3777a982d89SJeremy L. Thompson /** 3787a982d89SJeremy L. Thompson @brief Set a delegate Ceed context 3797a982d89SJeremy L. Thompson 380ea61e9acSJeremy L Thompson This function allows a Ceed context to set a delegate Ceed context. 381ea61e9acSJeremy L Thompson All backend implementations default to the delegate Ceed context, unless overridden. 3827a982d89SJeremy L. Thompson 383ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to set delegate of 3847a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 3857a982d89SJeremy L. Thompson 3867a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3877a982d89SJeremy L. Thompson 3887a982d89SJeremy L. Thompson @ref Backend 3897a982d89SJeremy L. Thompson **/ 3907a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) { 3917a982d89SJeremy L. Thompson ceed->delegate = delegate; 3927a982d89SJeremy L. Thompson delegate->parent = ceed; 393e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3947a982d89SJeremy L. Thompson } 3957a982d89SJeremy L. Thompson 3967a982d89SJeremy L. Thompson /** 3977a982d89SJeremy L. Thompson @brief Retrieve a delegate Ceed context for a specific object type 3987a982d89SJeremy L. Thompson 399ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve delegate of 4007a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 401d1d35e2fSjeremylt @param[in] obj_name Name of the object type to retrieve delegate for 4027a982d89SJeremy L. Thompson 4037a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4047a982d89SJeremy L. Thompson 4057a982d89SJeremy L. Thompson @ref Backend 4067a982d89SJeremy L. Thompson **/ 407d1d35e2fSjeremylt int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *obj_name) { 4087a982d89SJeremy L. Thompson // Check for object delegate 4092b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) { 410d1d35e2fSjeremylt if (!strcmp(obj_name, ceed->obj_delegates->obj_name)) { 411d1d35e2fSjeremylt *delegate = ceed->obj_delegates->delegate; 412e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4137a982d89SJeremy L. Thompson } 4142b730f8bSJeremy L Thompson } 4157a982d89SJeremy L. Thompson 4167a982d89SJeremy L. Thompson // Use default delegate if no object delegate 4172b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, delegate)); 418e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4197a982d89SJeremy L. Thompson } 4207a982d89SJeremy L. Thompson 4217a982d89SJeremy L. Thompson /** 4227a982d89SJeremy L. Thompson @brief Set a delegate Ceed context for a specific object type 4237a982d89SJeremy L. Thompson 424ea61e9acSJeremy L Thompson This function allows a Ceed context to set a delegate Ceed context for a given type of Ceed object. 425ea61e9acSJeremy L Thompson All backend implementations default to the delegate Ceed context for this object. 4261c66c397SJeremy L Thompson For example, CeedSetObjectDelegate(ceed, refceed, "Basis") uses delegate implementations for all CeedBasis backend functions. 4277a982d89SJeremy L. Thompson 428ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context to set delegate of 4291c66c397SJeremy L Thompson @param[in] delegate Ceed context to use for delegation 430d1d35e2fSjeremylt @param[in] obj_name Name of the object type to set delegate for 4317a982d89SJeremy L. Thompson 4327a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4337a982d89SJeremy L. Thompson 4347a982d89SJeremy L. Thompson @ref Backend 4357a982d89SJeremy L. Thompson **/ 436d1d35e2fSjeremylt int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *obj_name) { 437d1d35e2fSjeremylt CeedInt count = ceed->obj_delegate_count; 4387a982d89SJeremy L. Thompson 4397a982d89SJeremy L. Thompson // Malloc or Realloc 4407a982d89SJeremy L. Thompson if (count) { 4412b730f8bSJeremy L Thompson CeedCall(CeedRealloc(count + 1, &ceed->obj_delegates)); 4427a982d89SJeremy L. Thompson } else { 4432b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->obj_delegates)); 4447a982d89SJeremy L. Thompson } 445d1d35e2fSjeremylt ceed->obj_delegate_count++; 4467a982d89SJeremy L. Thompson 4477a982d89SJeremy L. Thompson // Set object delegate 448d1d35e2fSjeremylt ceed->obj_delegates[count].delegate = delegate; 4492b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(obj_name, &ceed->obj_delegates[count].obj_name)); 4507a982d89SJeremy L. Thompson 4517a982d89SJeremy L. Thompson // Set delegate parent 4527a982d89SJeremy L. Thompson delegate->parent = ceed; 453e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4547a982d89SJeremy L. Thompson } 4557a982d89SJeremy L. Thompson 4567a982d89SJeremy L. Thompson /** 4577a982d89SJeremy L. Thompson @brief Get the fallback resource for CeedOperators 4587a982d89SJeremy L. Thompson 459ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 4607a982d89SJeremy L. Thompson @param[out] resource Variable to store fallback resource 4617a982d89SJeremy L. Thompson 4627a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4637a982d89SJeremy L. Thompson 4647a982d89SJeremy L. Thompson @ref Backend 4657a982d89SJeremy L. Thompson **/ 466363aefefSSebastian Grimberg int CeedGetOperatorFallbackResource(Ceed ceed, const char **resource) { 467d1d35e2fSjeremylt *resource = (const char *)ceed->op_fallback_resource; 468e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4697a982d89SJeremy L. Thompson } 4707a982d89SJeremy L. Thompson 4717a982d89SJeremy L. Thompson /** 4728687e1d4SJeremy L Thompson @brief Get the fallback Ceed for CeedOperators 4738687e1d4SJeremy L Thompson 474ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 4758687e1d4SJeremy L Thompson @param[out] fallback_ceed Variable to store fallback Ceed 4768687e1d4SJeremy L Thompson 4778687e1d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 4788687e1d4SJeremy L Thompson 4798687e1d4SJeremy L Thompson @ref Backend 4808687e1d4SJeremy L Thompson **/ 4818687e1d4SJeremy L Thompson int CeedGetOperatorFallbackCeed(Ceed ceed, Ceed *fallback_ceed) { 482d04bbc78SJeremy L Thompson if (ceed->has_valid_op_fallback_resource) { 48323d4529eSJeremy L Thompson CeedDebug256(ceed, CEED_DEBUG_COLOR_SUCCESS, "---------- CeedOperator Fallback ----------\n"); 4842b730f8bSJeremy L Thompson CeedDebug(ceed, "Getting fallback from %s to %s\n", ceed->resource, ceed->op_fallback_resource); 485d04bbc78SJeremy L Thompson } 4868687e1d4SJeremy L Thompson 487d04bbc78SJeremy L Thompson // Create fallback Ceed if uninitalized 488d04bbc78SJeremy L Thompson if (!ceed->op_fallback_ceed && ceed->has_valid_op_fallback_resource) { 48913f886e9SJeremy L Thompson CeedDebug(ceed, "Creating fallback Ceed"); 490d04bbc78SJeremy L Thompson 4918687e1d4SJeremy L Thompson Ceed fallback_ceed; 492d04bbc78SJeremy L Thompson const char *fallback_resource; 493d04bbc78SJeremy L Thompson 494363aefefSSebastian Grimberg CeedCall(CeedGetOperatorFallbackResource(ceed, &fallback_resource)); 4952b730f8bSJeremy L Thompson CeedCall(CeedInit(fallback_resource, &fallback_ceed)); 4968687e1d4SJeremy L Thompson fallback_ceed->op_fallback_parent = ceed; 4978687e1d4SJeremy L Thompson fallback_ceed->Error = ceed->Error; 4988687e1d4SJeremy L Thompson ceed->op_fallback_ceed = fallback_ceed; 4998687e1d4SJeremy L Thompson } 5008687e1d4SJeremy L Thompson *fallback_ceed = ceed->op_fallback_ceed; 5018687e1d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 5028687e1d4SJeremy L Thompson } 5038687e1d4SJeremy L Thompson 5048687e1d4SJeremy L Thompson /** 505ea61e9acSJeremy L Thompson @brief Set the fallback resource for CeedOperators. 5064385fb7fSSebastian Grimberg 507ea61e9acSJeremy L Thompson The current resource, if any, is freed by calling this function. 508ea61e9acSJeremy L Thompson This string is freed upon the destruction of the Ceed context. 5097a982d89SJeremy L. Thompson 510ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context 511ea61e9acSJeremy L Thompson @param[in] resource Fallback resource to set 5127a982d89SJeremy L. Thompson 5137a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5147a982d89SJeremy L. Thompson 5157a982d89SJeremy L. Thompson @ref Backend 5167a982d89SJeremy L. Thompson **/ 5177a982d89SJeremy L. Thompson int CeedSetOperatorFallbackResource(Ceed ceed, const char *resource) { 5187a982d89SJeremy L. Thompson // Free old 5192b730f8bSJeremy L Thompson CeedCall(CeedFree(&ceed->op_fallback_resource)); 5207a982d89SJeremy L. Thompson 5217a982d89SJeremy L. Thompson // Set new 5222b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(resource, (char **)&ceed->op_fallback_resource)); 523d04bbc78SJeremy L Thompson 524d04bbc78SJeremy L Thompson // Check validity 5252b730f8bSJeremy L Thompson ceed->has_valid_op_fallback_resource = ceed->op_fallback_resource && ceed->resource && strcmp(ceed->op_fallback_resource, ceed->resource); 526e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5277a982d89SJeremy L. Thompson } 5287a982d89SJeremy L. Thompson 5297a982d89SJeremy L. Thompson /** 5309525855cSJeremy L Thompson @brief Flag Ceed context as deterministic 5319525855cSJeremy L Thompson 532ea61e9acSJeremy L Thompson @param[in] ceed Ceed to flag as deterministic 53396b902e2Sjeremylt @param[out] is_deterministic Deterministic status to set 5349525855cSJeremy L Thompson 5359525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 5369525855cSJeremy L Thompson 5379525855cSJeremy L Thompson @ref Backend 5389525855cSJeremy L Thompson **/ 539d1d35e2fSjeremylt int CeedSetDeterministic(Ceed ceed, bool is_deterministic) { 540d1d35e2fSjeremylt ceed->is_deterministic = is_deterministic; 541e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5429525855cSJeremy L Thompson } 5439525855cSJeremy L Thompson 5449525855cSJeremy L Thompson /** 5457a982d89SJeremy L. Thompson @brief Set a backend function 5467a982d89SJeremy L. Thompson 547ea61e9acSJeremy L Thompson This function is used for a backend to set the function associated with the Ceed objects. 548ea61e9acSJeremy L Thompson For example, CeedSetBackendFunction(ceed, "Ceed", ceed, "VectorCreate", BackendVectorCreate) sets the backend implementation of 'CeedVectorCreate' 5499fd66db6SSebastian Grimberg and CeedSetBackendFunction(ceed, "Basis", basis, "Apply", BackendBasisApply) sets the backend implementation of 'CeedBasisApply'. 5509fd66db6SSebastian Grimberg Note, the prefix 'Ceed' is not required for the object type ("Basis" vs "CeedBasis"). 5517a982d89SJeremy L. Thompson 552ea61e9acSJeremy L Thompson @param[in] ceed Ceed context for error handling 553ea61e9acSJeremy L Thompson @param[in] type Type of Ceed object to set function for 5547a982d89SJeremy L. Thompson @param[out] object Ceed object to set function for 555ea61e9acSJeremy L Thompson @param[in] func_name Name of function to set 556ea61e9acSJeremy L Thompson @param[in] f Function to set 5577a982d89SJeremy L. Thompson 5587a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5597a982d89SJeremy L. Thompson 5607a982d89SJeremy L. Thompson @ref Backend 5617a982d89SJeremy L. Thompson **/ 5622b730f8bSJeremy L Thompson int CeedSetBackendFunction(Ceed ceed, const char *type, void *object, const char *func_name, int (*f)()) { 563d1d35e2fSjeremylt char lookup_name[CEED_MAX_RESOURCE_LEN + 1] = ""; 5647a982d89SJeremy L. Thompson 5657a982d89SJeremy L. Thompson // Build lookup name 5662b730f8bSJeremy L Thompson if (strcmp(type, "Ceed")) strncat(lookup_name, "Ceed", CEED_MAX_RESOURCE_LEN); 567d1d35e2fSjeremylt strncat(lookup_name, type, CEED_MAX_RESOURCE_LEN); 568d1d35e2fSjeremylt strncat(lookup_name, func_name, CEED_MAX_RESOURCE_LEN); 5697a982d89SJeremy L. Thompson 5707a982d89SJeremy L. Thompson // Find and use offset 5712b730f8bSJeremy L Thompson for (CeedInt i = 0; ceed->f_offsets[i].func_name; i++) { 572d1d35e2fSjeremylt if (!strcmp(ceed->f_offsets[i].func_name, lookup_name)) { 573d1d35e2fSjeremylt size_t offset = ceed->f_offsets[i].offset; 5747a982d89SJeremy L. Thompson int (**fpointer)(void) = (int (**)(void))((char *)object + offset); // *NOPAD* 5751c66c397SJeremy L Thompson 5767a982d89SJeremy L. Thompson *fpointer = f; 577e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5787a982d89SJeremy L. Thompson } 5792b730f8bSJeremy L Thompson } 5807a982d89SJeremy L. Thompson 5817a982d89SJeremy L. Thompson // LCOV_EXCL_START 5822b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Requested function '%s' was not found for CEED object '%s'", func_name, type); 5837a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5847a982d89SJeremy L. Thompson } 5857a982d89SJeremy L. Thompson 5867a982d89SJeremy L. Thompson /** 5877a982d89SJeremy L. Thompson @brief Retrieve backend data for a Ceed context 5887a982d89SJeremy L. Thompson 589ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve data of 5907a982d89SJeremy L. Thompson @param[out] data Address to save data to 5917a982d89SJeremy L. Thompson 5927a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5937a982d89SJeremy L. Thompson 5947a982d89SJeremy L. Thompson @ref Backend 5957a982d89SJeremy L. Thompson **/ 596777ff853SJeremy L Thompson int CeedGetData(Ceed ceed, void *data) { 597777ff853SJeremy L Thompson *(void **)data = ceed->data; 598e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5997a982d89SJeremy L. Thompson } 6007a982d89SJeremy L. Thompson 6017a982d89SJeremy L. Thompson /** 6027a982d89SJeremy L. Thompson @brief Set backend data for a Ceed context 6037a982d89SJeremy L. Thompson 604ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context to set data of 605ea61e9acSJeremy L Thompson @param[in] data Address of data to set 6067a982d89SJeremy L. Thompson 6077a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson @ref Backend 6107a982d89SJeremy L. Thompson **/ 611777ff853SJeremy L Thompson int CeedSetData(Ceed ceed, void *data) { 612777ff853SJeremy L Thompson ceed->data = data; 613e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6147a982d89SJeremy L. Thompson } 6157a982d89SJeremy L. Thompson 61634359f16Sjeremylt /** 61734359f16Sjeremylt @brief Increment the reference counter for a Ceed context 61834359f16Sjeremylt 619ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context to increment the reference counter 62034359f16Sjeremylt 62134359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 62234359f16Sjeremylt 62334359f16Sjeremylt @ref Backend 62434359f16Sjeremylt **/ 6259560d06aSjeremylt int CeedReference(Ceed ceed) { 62634359f16Sjeremylt ceed->ref_count++; 62734359f16Sjeremylt return CEED_ERROR_SUCCESS; 62834359f16Sjeremylt } 62934359f16Sjeremylt 6307a982d89SJeremy L. Thompson /// @} 6317a982d89SJeremy L. Thompson 6327a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 6337a982d89SJeremy L. Thompson /// Ceed Public API 6347a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 6357a982d89SJeremy L. Thompson /// @addtogroup CeedUser 6367a982d89SJeremy L. Thompson /// @{ 6377a982d89SJeremy L. Thompson 6387a982d89SJeremy L. Thompson /** 63992ee7d1cSjeremylt @brief Get the list of available resource names for Ceed contexts 6404385fb7fSSebastian Grimberg 641ea61e9acSJeremy L Thompson Note: The caller is responsible for `free()`ing the resources and priorities arrays, but should not `free()` the contents of the resources 642ea61e9acSJeremy L Thompson array. 64322e44211Sjeremylt 64492ee7d1cSjeremylt @param[out] n Number of available resources 64592ee7d1cSjeremylt @param[out] resources List of available resource names 64622e44211Sjeremylt @param[out] priorities Resource name prioritization values, lower is better 64722e44211Sjeremylt 64822e44211Sjeremylt @return An error code: 0 - success, otherwise - failure 64922e44211Sjeremylt 65022e44211Sjeremylt @ref User 65122e44211Sjeremylt **/ 65222e44211Sjeremylt // LCOV_EXCL_START 6532b730f8bSJeremy L Thompson int CeedRegistryGetList(size_t *n, char ***const resources, CeedInt **priorities) { 654d0c91ce9Sjeremylt *n = 0; 6559ff86846Sjeremylt *resources = malloc(num_backends * sizeof(**resources)); 6566574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 6579ff86846Sjeremylt if (priorities) { 6589ff86846Sjeremylt *priorities = malloc(num_backends * sizeof(**priorities)); 6596574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 6609ff86846Sjeremylt } 66122e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 662d0c91ce9Sjeremylt // Only report compiled backends 663d0c91ce9Sjeremylt if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) { 66422e44211Sjeremylt *resources[i] = backends[i].prefix; 6659ff86846Sjeremylt if (priorities) *priorities[i] = backends[i].priority; 666d0c91ce9Sjeremylt *n += 1; 667d0c91ce9Sjeremylt } 668d0c91ce9Sjeremylt } 6696574a04fSJeremy L Thompson CeedCheck(*n, NULL, CEED_ERROR_MAJOR, "No backends installed"); 670d0c91ce9Sjeremylt *resources = realloc(*resources, *n * sizeof(**resources)); 6716574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 672d0c91ce9Sjeremylt if (priorities) { 673d0c91ce9Sjeremylt *priorities = realloc(*priorities, *n * sizeof(**priorities)); 6746574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 67522e44211Sjeremylt } 67622e44211Sjeremylt return CEED_ERROR_SUCCESS; 67745f1e315Sjeremylt } 67822e44211Sjeremylt // LCOV_EXCL_STOP 67922e44211Sjeremylt 68022e44211Sjeremylt /** 681d79b80ecSjeremylt @brief Initialize a \ref Ceed context to use the specified resource. 6824385fb7fSSebastian Grimberg 683ea61e9acSJeremy L Thompson Note: Prefixing the resource with "help:" (e.g. "help:/cpu/self") will result in CeedInt printing the current libCEED version number and a 684ea61e9acSJeremy L Thompson list of current available backend resources to stderr. 685b11c1e72Sjeremylt 686ea61e9acSJeremy L Thompson @param[in] resource Resource to use, e.g., "/cpu/self" 687ea61e9acSJeremy L Thompson @param[out] ceed The library context 688b11c1e72Sjeremylt @sa CeedRegister() CeedDestroy() 689b11c1e72Sjeremylt 690b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 691dfdf5a53Sjeremylt 6927a982d89SJeremy L. Thompson @ref User 693b11c1e72Sjeremylt **/ 694d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 6952b730f8bSJeremy L Thompson size_t match_len = 0, match_index = UINT_MAX, match_priority = CEED_MAX_BACKEND_PRIORITY, priority; 696d7b241e6Sjeremylt 697fe2413ffSjeremylt // Find matching backend 6986574a04fSJeremy L Thompson CeedCheck(resource, NULL, CEED_ERROR_MAJOR, "No resource provided"); 6992b730f8bSJeremy L Thompson CeedCall(CeedRegisterAll()); 70013873f79Sjeremylt 70122e44211Sjeremylt // Check for help request 70222e44211Sjeremylt const char *help_prefix = "help"; 7032b730f8bSJeremy L Thompson size_t match_help = 0; 7042b730f8bSJeremy L Thompson while (match_help < 4 && resource[match_help] == help_prefix[match_help]) match_help++; 70522e44211Sjeremylt if (match_help == 4) { 7062b730f8bSJeremy L Thompson fprintf(stderr, "libCEED version: %d.%d%d%s\n", CEED_VERSION_MAJOR, CEED_VERSION_MINOR, CEED_VERSION_PATCH, 70722e44211Sjeremylt CEED_VERSION_RELEASE ? "" : "+development"); 70892ee7d1cSjeremylt fprintf(stderr, "Available backend resources:\n"); 70922e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 710d0c91ce9Sjeremylt // Only report compiled backends 7112b730f8bSJeremy L Thompson if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) fprintf(stderr, " %s\n", backends[i].prefix); 71222e44211Sjeremylt } 71322e44211Sjeremylt fflush(stderr); 71422e44211Sjeremylt match_help = 5; // Delineating character expected 71522e44211Sjeremylt } else { 71622e44211Sjeremylt match_help = 0; 71722e44211Sjeremylt } 71822e44211Sjeremylt 719ea61e9acSJeremy L Thompson // Find best match, computed as number of matching characters from requested resource stem 7202b730f8bSJeremy L Thompson size_t stem_length = 0; 7212b730f8bSJeremy L Thompson while (resource[stem_length + match_help] && resource[stem_length + match_help] != ':') stem_length++; 722d7b241e6Sjeremylt for (size_t i = 0; i < num_backends; i++) { 7232b730f8bSJeremy L Thompson size_t n = 0; 724d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 7252b730f8bSJeremy L Thompson while (prefix[n] && prefix[n] == resource[n + match_help]) n++; 726d7b241e6Sjeremylt priority = backends[i].priority; 727d1d35e2fSjeremylt if (n > match_len || (n == match_len && match_priority > priority)) { 728d1d35e2fSjeremylt match_len = n; 729d1d35e2fSjeremylt match_priority = priority; 730f7e22acaSJeremy L Thompson match_index = i; 731d7b241e6Sjeremylt } 732d7b241e6Sjeremylt } 7339c9a0587SLeila Ghaffari // Using Levenshtein distance to find closest match 7349c9a0587SLeila Ghaffari if (match_len <= 1 || match_len != stem_length) { 735203015caSLeila Ghaffari // LCOV_EXCL_START 7369c9a0587SLeila Ghaffari size_t lev_dis = UINT_MAX; 737f7e22acaSJeremy L Thompson size_t lev_index = UINT_MAX, lev_priority = CEED_MAX_BACKEND_PRIORITY; 7389c9a0587SLeila Ghaffari for (size_t i = 0; i < num_backends; i++) { 7399c9a0587SLeila Ghaffari const char *prefix = backends[i].prefix; 7409c9a0587SLeila Ghaffari size_t prefix_length = strlen(backends[i].prefix); 7419c9a0587SLeila Ghaffari size_t min_len = (prefix_length < stem_length) ? prefix_length : stem_length; 742092904ddSLeila Ghaffari size_t column[min_len + 1]; 743092904ddSLeila Ghaffari for (size_t j = 0; j <= min_len; j++) column[j] = j; 7449c9a0587SLeila Ghaffari for (size_t j = 1; j <= min_len; j++) { 7459c9a0587SLeila Ghaffari column[0] = j; 7469c9a0587SLeila Ghaffari for (size_t k = 1, last_diag = j - 1; k <= min_len; k++) { 747092904ddSLeila Ghaffari size_t old_diag = column[k]; 7489c9a0587SLeila Ghaffari size_t min_1 = (column[k] < column[k - 1]) ? column[k] + 1 : column[k - 1] + 1; 7499c9a0587SLeila Ghaffari size_t min_2 = last_diag + (resource[k - 1] == prefix[j - 1] ? 0 : 1); 7509c9a0587SLeila Ghaffari column[k] = (min_1 < min_2) ? min_1 : min_2; 7519c9a0587SLeila Ghaffari last_diag = old_diag; 7529c9a0587SLeila Ghaffari } 7539c9a0587SLeila Ghaffari } 7549c9a0587SLeila Ghaffari size_t n = column[min_len]; 7559c9a0587SLeila Ghaffari priority = backends[i].priority; 7562b730f8bSJeremy L Thompson if (n < lev_dis || (n == lev_dis && lev_priority > priority)) { 7579c9a0587SLeila Ghaffari lev_dis = n; 7589c9a0587SLeila Ghaffari lev_priority = priority; 759f7e22acaSJeremy L Thompson lev_index = i; 7609c9a0587SLeila Ghaffari } 7619c9a0587SLeila Ghaffari } 762f7e22acaSJeremy L Thompson const char *prefix_lev = backends[lev_index].prefix; 7632b730f8bSJeremy L Thompson size_t lev_length = 0; 7642b730f8bSJeremy L Thompson while (prefix_lev[lev_length] && prefix_lev[lev_length] != '\0') lev_length++; 7659c9a0587SLeila Ghaffari size_t m = (lev_length < stem_length) ? lev_length : stem_length; 7666574a04fSJeremy L Thompson if (lev_dis + 1 >= m) return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s", resource); 7676574a04fSJeremy L Thompson else return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s\nClosest match: %s", resource, backends[lev_index].prefix); 768203015caSLeila Ghaffari // LCOV_EXCL_STOP 7699c9a0587SLeila Ghaffari } 770fe2413ffSjeremylt 771fe2413ffSjeremylt // Setup Ceed 7722b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, ceed)); 7732b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &(*ceed)->jit_source_roots)); 774bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 7752b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 7762b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "exit")) (*ceed)->Error = CeedErrorExit; 7772b730f8bSJeremy L Thompson else if (!strcmp(ceed_error_handler, "store")) (*ceed)->Error = CeedErrorStore; 7782b730f8bSJeremy L Thompson else (*ceed)->Error = CeedErrorAbort; 779d1d35e2fSjeremylt memcpy((*ceed)->err_msg, "No error message stored", 24); 780d1d35e2fSjeremylt (*ceed)->ref_count = 1; 781d7b241e6Sjeremylt (*ceed)->data = NULL; 782fe2413ffSjeremylt 783fe2413ffSjeremylt // Set lookup table 784d1d35e2fSjeremylt FOffset f_offsets[] = { 7856e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 7865ae360d4SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, SetStream), 7876e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 7886e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 789f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 7906e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 791*3ac8f562SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateAtPoints), 7926e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 7936e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 7946e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 79550c301a5SRezgar Shakeri CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv), 796c4e3f59bSSebastian Grimberg CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl), 7976e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 7986e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 799777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate), 8006e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 8016e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 8029c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasValidArray), 8039c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType), 8046e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 8056a6c615bSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, TakeArray), 8066e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 807f48ed27dSnbeams CEED_FTABLE_ENTRY(CeedVector, SyncArray), 8086e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 8096e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 8109c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite), 8116e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 8126e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 813547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 814e0dd3b27Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Scale), 8150f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, AXPY), 8165fb68f37SKaren (Ren) Stengel CEED_FTABLE_ENTRY(CeedVector, AXPBY), 8170f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, PointwiseMult), 818d99fa3c5SJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, Reciprocal), 8196e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 8206e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 821f30b1135SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnsigned), 8227c1dbaffSSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnoriented), 823*3ac8f562SJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyAtPoints), 8246e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 825bd33150aSjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets), 82677d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetOrientations), 82777d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetCurlOrientations), 8286e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 8296e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 830c8c3fa7dSJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAtPoints), 8316e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 8326e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 8336e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 8346e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 8358c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction), 8368c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction), 8376e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 8389c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData), 8399c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType), 840777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData), 841891038deSjeremylt CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData), 842777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData), 84328bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead), 844777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData), 84528bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead), 8462e64a2b9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy), 847777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy), 84880ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction), 84970a7ffb3SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate), 85080ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal), 8519e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal), 85280ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal), 8539e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal), 854e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic), 855e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble), 856cefa2673SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle), 857713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 8586e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 859250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 860cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 861250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 8626e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 8636e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 8646e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 8651dfeef1dSjeremylt }; 866fe2413ffSjeremylt 8672b730f8bSJeremy L Thompson CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets)); 868d1d35e2fSjeremylt memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets)); 869fe2413ffSjeremylt 8705107b09fSJeremy L Thompson // Set fallback for advanced CeedOperator functions 871ca735530SJeremy L Thompson const char fallback_resource[] = ""; 872ca735530SJeremy L Thompson CeedCall(CeedSetOperatorFallbackResource(*ceed, fallback_resource)); 8735107b09fSJeremy L Thompson 87460f9e2d6SJeremy L Thompson // Record env variables CEED_DEBUG or DBG 8751c66c397SJeremy L Thompson (*ceed)->is_debug = getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); 87660f9e2d6SJeremy L Thompson 87722e44211Sjeremylt // Copy resource prefix, if backend setup successful 8782b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource)); 879ee5a26f2SJeremy L Thompson 880ee5a26f2SJeremy L Thompson // Set default JiT source root 881ea61e9acSJeremy L Thompson // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent 8822b730f8bSJeremy L Thompson CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault)); 883ee5a26f2SJeremy L Thompson 884d04bbc78SJeremy L Thompson // Backend specific setup 8852b730f8bSJeremy L Thompson CeedCall(backends[match_index].init(&resource[match_help], *ceed)); 886e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 887d7b241e6Sjeremylt } 888d7b241e6Sjeremylt 889d7b241e6Sjeremylt /** 8905ae360d4SJeremy L Thompson @brief Set the GPU stream for a Ceed context 8915ae360d4SJeremy L Thompson 8925ae360d4SJeremy L Thompson @param[in,out] ceed Ceed context to set the stream 8935ae360d4SJeremy L Thompson @param[in] handle Handle to GPU stream 8945ae360d4SJeremy L Thompson 8955ae360d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 8965ae360d4SJeremy L Thompson 8975ae360d4SJeremy L Thompson @ref User 8985ae360d4SJeremy L Thompson **/ 8995ae360d4SJeremy L Thompson int CeedSetStream(Ceed ceed, void *handle) { 9005ae360d4SJeremy L Thompson CeedCheck(handle, ceed, CEED_ERROR_INCOMPATIBLE, "Stream handle must be non-null"); 9019ffb25e0SJames Wright if (ceed->SetStream) { 9025ae360d4SJeremy L Thompson CeedCall(ceed->SetStream(ceed, handle)); 9039ffb25e0SJames Wright } else { 9049ffb25e0SJames Wright Ceed delegate; 9059ffb25e0SJames Wright CeedCall(CeedGetDelegate(ceed, &delegate)); 9065ae360d4SJeremy L Thompson 90728ce3d2aSJeremy L Thompson if (delegate) CeedCall(CeedSetStream(delegate, handle)); 90828ce3d2aSJeremy L Thompson else return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support setting stream"); 9099ffb25e0SJames Wright } 9105ae360d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 9115ae360d4SJeremy L Thompson } 9125ae360d4SJeremy L Thompson 9135ae360d4SJeremy L Thompson /** 914ea61e9acSJeremy L Thompson @brief Copy the pointer to a Ceed context. 9154385fb7fSSebastian Grimberg 916512bb800SJeremy L Thompson Both pointers should be destroyed with `CeedDestroy()`. 917512bb800SJeremy L Thompson 918512bb800SJeremy 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. 919512bb800SJeremy L Thompson This Ceed context will be destroyed if `ceed_copy` is the only reference to this Ceed context. 9209560d06aSjeremylt 921ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to copy reference to 922ea61e9acSJeremy L Thompson @param[in,out] ceed_copy Variable to store copied reference 9239560d06aSjeremylt 9249560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 9259560d06aSjeremylt 9269560d06aSjeremylt @ref User 9279560d06aSjeremylt **/ 9289560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) { 9292b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 9302b730f8bSJeremy L Thompson CeedCall(CeedDestroy(ceed_copy)); 9319560d06aSjeremylt *ceed_copy = ceed; 9329560d06aSjeremylt return CEED_ERROR_SUCCESS; 9339560d06aSjeremylt } 9349560d06aSjeremylt 9359560d06aSjeremylt /** 9367a982d89SJeremy L. Thompson @brief Get the full resource name for a Ceed context 9372f86a920SJeremy L Thompson 938ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get resource name of 9397a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 9402f86a920SJeremy L Thompson 9412f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9422f86a920SJeremy L Thompson 9437a982d89SJeremy L. Thompson @ref User 9445107b09fSJeremy L Thompson **/ 9457a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 9467a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 947e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9485107b09fSJeremy L Thompson } 9495107b09fSJeremy L Thompson 9505107b09fSJeremy L Thompson /** 951d79b80ecSjeremylt @brief Return Ceed context preferred memory type 952c907536fSjeremylt 953ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get preferred memory type of 954d1d35e2fSjeremylt @param[out] mem_type Address to save preferred memory type to 955c907536fSjeremylt 956c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 957c907536fSjeremylt 9587a982d89SJeremy L. Thompson @ref User 959c907536fSjeremylt **/ 960d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) { 961c907536fSjeremylt if (ceed->GetPreferredMemType) { 9622b730f8bSJeremy L Thompson CeedCall(ceed->GetPreferredMemType(mem_type)); 963c907536fSjeremylt } else { 964c263cd57Sjeremylt Ceed delegate; 9652b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, &delegate)); 966c263cd57Sjeremylt 967c263cd57Sjeremylt if (delegate) { 9682b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(delegate, mem_type)); 969c263cd57Sjeremylt } else { 970d1d35e2fSjeremylt *mem_type = CEED_MEM_HOST; 971c907536fSjeremylt } 972c263cd57Sjeremylt } 973e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 974c907536fSjeremylt } 975c907536fSjeremylt 976c907536fSjeremylt /** 9779525855cSJeremy L Thompson @brief Get deterministic status of Ceed 9789525855cSJeremy L Thompson 9799525855cSJeremy L Thompson @param[in] ceed Ceed 980d1d35e2fSjeremylt @param[out] is_deterministic Variable to store deterministic status 9819525855cSJeremy L Thompson 9829525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9839525855cSJeremy L Thompson 9849525855cSJeremy L Thompson @ref User 9859525855cSJeremy L Thompson **/ 986d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) { 987d1d35e2fSjeremylt *is_deterministic = ceed->is_deterministic; 988e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9899525855cSJeremy L Thompson } 9909525855cSJeremy L Thompson 9919525855cSJeremy L Thompson /** 992ee5a26f2SJeremy L Thompson @brief Set additional JiT source root for Ceed 993ee5a26f2SJeremy L Thompson 994ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed 995ee5a26f2SJeremy L Thompson @param[in] jit_source_root Absolute path to additional JiT source directory 996ee5a26f2SJeremy L Thompson 997ee5a26f2SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 998ee5a26f2SJeremy L Thompson 999ee5a26f2SJeremy L Thompson @ref User 1000ee5a26f2SJeremy L Thompson **/ 1001ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) { 10026155f12fSJeremy L Thompson Ceed ceed_parent; 1003ee5a26f2SJeremy L Thompson 10042b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 10056155f12fSJeremy L Thompson 10066155f12fSJeremy L Thompson CeedInt index = ceed_parent->num_jit_source_roots; 1007ee5a26f2SJeremy L Thompson size_t path_length = strlen(jit_source_root); 10081c66c397SJeremy L Thompson 10092b730f8bSJeremy L Thompson CeedCall(CeedRealloc(index + 1, &ceed_parent->jit_source_roots)); 10102b730f8bSJeremy L Thompson CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index])); 1011d602d780SJeremy L Thompson memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length); 10126155f12fSJeremy L Thompson ceed_parent->num_jit_source_roots++; 1013ee5a26f2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1014ee5a26f2SJeremy L Thompson } 1015ee5a26f2SJeremy L Thompson 1016ee5a26f2SJeremy L Thompson /** 10170a0da059Sjeremylt @brief View a Ceed 10180a0da059Sjeremylt 10190a0da059Sjeremylt @param[in] ceed Ceed to view 10200a0da059Sjeremylt @param[in] stream Filestream to write to 10210a0da059Sjeremylt 10220a0da059Sjeremylt @return An error code: 0 - success, otherwise - failure 10230a0da059Sjeremylt 10240a0da059Sjeremylt @ref User 10250a0da059Sjeremylt **/ 10260a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) { 1027d1d35e2fSjeremylt CeedMemType mem_type; 10280a0da059Sjeremylt 10292b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 10300a0da059Sjeremylt 10312b730f8bSJeremy L Thompson fprintf(stream, 10322b730f8bSJeremy L Thompson "Ceed\n" 10330a0da059Sjeremylt " Ceed Resource: %s\n" 10340a0da059Sjeremylt " Preferred MemType: %s\n", 1035d1d35e2fSjeremylt ceed->resource, CeedMemTypes[mem_type]); 1036e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 10370a0da059Sjeremylt } 10380a0da059Sjeremylt 10390a0da059Sjeremylt /** 1040b11c1e72Sjeremylt @brief Destroy a Ceed context 1041d7b241e6Sjeremylt 1042ea61e9acSJeremy L Thompson @param[in,out] ceed Address of Ceed context to destroy 1043b11c1e72Sjeremylt 1044b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1045dfdf5a53Sjeremylt 10467a982d89SJeremy L. Thompson @ref User 1047b11c1e72Sjeremylt **/ 1048d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 1049ad6481ceSJeremy L Thompson if (!*ceed || --(*ceed)->ref_count > 0) { 1050ad6481ceSJeremy L Thompson *ceed = NULL; 1051ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1052ad6481ceSJeremy L Thompson } 10532b730f8bSJeremy L Thompson if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate)); 10540ace9bf2Sjeremylt 1055d1d35e2fSjeremylt if ((*ceed)->obj_delegate_count > 0) { 105692ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) { 10572b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate))); 10582b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name)); 1059aefd8378Sjeremylt } 10602b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates)); 1061aefd8378Sjeremylt } 10620ace9bf2Sjeremylt 10632b730f8bSJeremy L Thompson if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed)); 10640ace9bf2Sjeremylt 106592ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) { 10662b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots[i])); 1067032e71eaSJeremy L Thompson } 10682b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots)); 1069032e71eaSJeremy L Thompson 10702b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->f_offsets)); 10712b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->resource)); 10722b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed)); 10732b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->op_fallback_resource)); 10742b730f8bSJeremy L Thompson CeedCall(CeedFree(ceed)); 1075e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1076d7b241e6Sjeremylt } 1077d7b241e6Sjeremylt 1078f9982c62SWill Pazner // LCOV_EXCL_START 1079f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) { 10802b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args); 10812b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorFormat(ceed->op_fallback_parent, format, args); 108278464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 108378464608Sjeremylt vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args); // NOLINT 1084d1d35e2fSjeremylt return ceed->err_msg; 1085f9982c62SWill Pazner } 1086f9982c62SWill Pazner // LCOV_EXCL_STOP 1087f9982c62SWill Pazner 10887a982d89SJeremy L. Thompson /** 10897a982d89SJeremy L. Thompson @brief Error handling implementation; use \ref CeedError instead. 10907a982d89SJeremy L. Thompson 10917a982d89SJeremy L. Thompson @ref Developer 10927a982d89SJeremy L. Thompson **/ 10932b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) { 10947a982d89SJeremy L. Thompson va_list args; 1095d1d35e2fSjeremylt int ret_val; 10961c66c397SJeremy L Thompson 10977a982d89SJeremy L. Thompson va_start(args, format); 10987a982d89SJeremy L. Thompson if (ceed) { 1099d1d35e2fSjeremylt ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args); 11007a982d89SJeremy L. Thompson } else { 1101b0d62198Sjeremylt // LCOV_EXCL_START 1102477729cfSJeremy L Thompson const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 11032b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 11042b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "return")) ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args); 1105477729cfSJeremy L Thompson else 1106477729cfSJeremy L Thompson // This function will not return 1107d1d35e2fSjeremylt ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args); 11087a982d89SJeremy L. Thompson } 11097a982d89SJeremy L. Thompson va_end(args); 1110d1d35e2fSjeremylt return ret_val; 1111b0d62198Sjeremylt // LCOV_EXCL_STOP 11127a982d89SJeremy L. Thompson } 11137a982d89SJeremy L. Thompson 1114477729cfSJeremy L Thompson /** 1115477729cfSJeremy L Thompson @brief Error handler that returns without printing anything. 1116477729cfSJeremy L Thompson 1117477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1118477729cfSJeremy L Thompson 1119477729cfSJeremy L Thompson @ref Developer 1120477729cfSJeremy L Thompson **/ 1121477729cfSJeremy L Thompson // LCOV_EXCL_START 11222b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1123d1d35e2fSjeremylt return err_code; 1124477729cfSJeremy L Thompson } 1125477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1126477729cfSJeremy L Thompson 1127477729cfSJeremy L Thompson /** 1128ea61e9acSJeremy L Thompson @brief Error handler that stores the error message for future use and returns the error. 1129477729cfSJeremy L Thompson 1130477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1131477729cfSJeremy L Thompson 1132477729cfSJeremy L Thompson @ref Developer 1133477729cfSJeremy L Thompson **/ 1134477729cfSJeremy L Thompson // LCOV_EXCL_START 11352b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 11362b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args); 11372b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorStore(ceed->op_fallback_parent, filename, line_no, func, err_code, format, args); 1138477729cfSJeremy L Thompson 1139477729cfSJeremy L Thompson // Build message 11401c66c397SJeremy L Thompson int len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%s:%d in %s(): ", filename, line_no, func); 114178464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 114278464608Sjeremylt vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args); // NOLINT 1143d1d35e2fSjeremylt return err_code; 1144477729cfSJeremy L Thompson } 1145477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1146477729cfSJeremy L Thompson 1147477729cfSJeremy L Thompson /** 1148477729cfSJeremy L Thompson @brief Error handler that prints to stderr and aborts 1149477729cfSJeremy L Thompson 1150477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1151477729cfSJeremy L Thompson 1152477729cfSJeremy L Thompson @ref Developer 1153477729cfSJeremy L Thompson **/ 1154477729cfSJeremy L Thompson // LCOV_EXCL_START 11552b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1156d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 1157f9982c62SWill Pazner vfprintf(stderr, format, *args); 1158477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1159477729cfSJeremy L Thompson abort(); 1160d1d35e2fSjeremylt return err_code; 1161477729cfSJeremy L Thompson } 1162477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1163477729cfSJeremy L Thompson 1164477729cfSJeremy L Thompson /** 1165477729cfSJeremy L Thompson @brief Error handler that prints to stderr and exits 1166477729cfSJeremy L Thompson 1167477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1168477729cfSJeremy L Thompson 1169ea61e9acSJeremy L Thompson In contrast to CeedErrorAbort(), this exits without a signal, so atexit() handlers (e.g., as used by gcov) are run. 1170477729cfSJeremy L Thompson 1171477729cfSJeremy L Thompson @ref Developer 1172477729cfSJeremy L Thompson **/ 11732b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1174d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 117578464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 117678464608Sjeremylt vfprintf(stderr, format, *args); // NOLINT 1177477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1178d1d35e2fSjeremylt exit(err_code); 1179d1d35e2fSjeremylt return err_code; 1180477729cfSJeremy L Thompson } 1181477729cfSJeremy L Thompson 1182477729cfSJeremy L Thompson /** 1183477729cfSJeremy L Thompson @brief Set error handler 1184477729cfSJeremy L Thompson 1185ea61e9acSJeremy L Thompson A default error handler is set in CeedInit(). 1186ea61e9acSJeremy L Thompson Use this function to change the error handler to CeedErrorReturn(), CeedErrorAbort(), or a user-defined error handler. 1187477729cfSJeremy L Thompson 1188477729cfSJeremy L Thompson @ref Developer 1189477729cfSJeremy L Thompson **/ 1190d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) { 1191d1d35e2fSjeremylt ceed->Error = handler; 1192d1d35e2fSjeremylt if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler); 11932b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler); 1194e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1195477729cfSJeremy L Thompson } 1196477729cfSJeremy L Thompson 1197477729cfSJeremy L Thompson /** 1198477729cfSJeremy L Thompson @brief Get error message 1199477729cfSJeremy L Thompson 1200ea61e9acSJeremy L Thompson The error message is only stored when using the error handler CeedErrorStore() 1201477729cfSJeremy L Thompson 1202ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve error message 1203d1d35e2fSjeremylt @param[out] err_msg Char pointer to hold error message 1204477729cfSJeremy L Thompson 1205477729cfSJeremy L Thompson @ref Developer 1206477729cfSJeremy L Thompson **/ 1207d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) { 12082b730f8bSJeremy L Thompson if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg); 12092b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedGetErrorMessage(ceed->op_fallback_parent, err_msg); 1210d1d35e2fSjeremylt *err_msg = ceed->err_msg; 1211e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1212477729cfSJeremy L Thompson } 1213477729cfSJeremy L Thompson 1214477729cfSJeremy L Thompson /** 1215477729cfSJeremy L Thompson @brief Restore error message 1216477729cfSJeremy L Thompson 1217ea61e9acSJeremy L Thompson The error message is only stored when using the error handler CeedErrorStore() 1218477729cfSJeremy L Thompson 1219ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to restore error message 1220d1d35e2fSjeremylt @param[out] err_msg Char pointer that holds error message 1221477729cfSJeremy L Thompson 1222477729cfSJeremy L Thompson @ref Developer 1223477729cfSJeremy L Thompson **/ 1224d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) { 12252b730f8bSJeremy L Thompson if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg); 12262b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedResetErrorMessage(ceed->op_fallback_parent, err_msg); 1227d1d35e2fSjeremylt *err_msg = NULL; 1228d1d35e2fSjeremylt memcpy(ceed->err_msg, "No error message stored", 24); 1229e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1230477729cfSJeremy L Thompson } 1231477729cfSJeremy L Thompson 12321070991dSJed Brown /** 12331070991dSJed Brown @brief Get libCEED library version info 12341070991dSJed Brown 1235ea61e9acSJeremy L Thompson libCEED version numbers have the form major.minor.patch. 1236ea61e9acSJeremy L Thompson Non-release versions may contain unstable interfaces. 12371070991dSJed Brown 12381070991dSJed Brown @param[out] major Major version of the library 12391070991dSJed Brown @param[out] minor Minor version of the library 12401070991dSJed Brown @param[out] patch Patch (subminor) version of the library 12411070991dSJed Brown @param[out] release True for releases; false for development branches. 12421070991dSJed Brown 12431070991dSJed Brown The caller may pass NULL for any arguments that are not needed. 12441070991dSJed Brown 12451070991dSJed Brown @sa CEED_VERSION_GE() 12461070991dSJed Brown 12471070991dSJed Brown @ref Developer 12481070991dSJed Brown */ 12491070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) { 12501070991dSJed Brown if (major) *major = CEED_VERSION_MAJOR; 12511070991dSJed Brown if (minor) *minor = CEED_VERSION_MINOR; 12521070991dSJed Brown if (patch) *patch = CEED_VERSION_PATCH; 12531070991dSJed Brown if (release) *release = CEED_VERSION_RELEASE; 12541070991dSJed Brown return 0; 12551070991dSJed Brown } 12561070991dSJed Brown 125780a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) { 125880a9ef05SNatalie Beams *scalar_type = CEED_SCALAR_TYPE; 125980a9ef05SNatalie Beams return 0; 126080a9ef05SNatalie Beams } 126180a9ef05SNatalie Beams 1262d7b241e6Sjeremylt /// @} 1263