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) \ 32b559d91bSJed Brown { \ 33b559d91bSJed Brown #class #method, offsetof(struct class##_private, method) \ 34b559d91bSJed Brown } 35d7b241e6Sjeremylt /// @endcond 36d7b241e6Sjeremylt 37d7b241e6Sjeremylt /// @file 38d7b241e6Sjeremylt /// Implementation of core components of Ceed library 397a982d89SJeremy L. Thompson 407a982d89SJeremy L. Thompson /// @addtogroup CeedUser 41d7b241e6Sjeremylt /// @{ 42d7b241e6Sjeremylt 43dfdf5a53Sjeremylt /** 44dfdf5a53Sjeremylt @brief Request immediate completion 45dfdf5a53Sjeremylt 46ea61e9acSJeremy L Thompson This predefined constant is passed as the \ref CeedRequest argument to interfaces when the caller wishes for the operation to be performed 47dfdf5a53Sjeremylt immediately. The code 48dfdf5a53Sjeremylt 49dfdf5a53Sjeremylt @code 50dfdf5a53Sjeremylt CeedOperatorApply(op, ..., CEED_REQUEST_IMMEDIATE); 51dfdf5a53Sjeremylt @endcode 52dfdf5a53Sjeremylt 53dfdf5a53Sjeremylt is semantically equivalent to 54dfdf5a53Sjeremylt 55dfdf5a53Sjeremylt @code 56dfdf5a53Sjeremylt CeedRequest request; 57dfdf5a53Sjeremylt CeedOperatorApply(op, ..., &request); 58dfdf5a53Sjeremylt CeedRequestWait(&request); 59dfdf5a53Sjeremylt @endcode 60dfdf5a53Sjeremylt 61dfdf5a53Sjeremylt @sa CEED_REQUEST_ORDERED 62dfdf5a53Sjeremylt **/ 63d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_IMMEDIATE = &ceed_request_immediate; 64d7b241e6Sjeremylt 65d7b241e6Sjeremylt /** 66b11c1e72Sjeremylt @brief Request ordered completion 67d7b241e6Sjeremylt 68ea61e9acSJeremy 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 69ea61e9acSJeremy L Thompson order that it is submitted to the device. It is typically used in a construct such as 70d7b241e6Sjeremylt 71d7b241e6Sjeremylt @code 72d7b241e6Sjeremylt CeedRequest request; 73d7b241e6Sjeremylt CeedOperatorApply(op1, ..., CEED_REQUEST_ORDERED); 74d7b241e6Sjeremylt CeedOperatorApply(op2, ..., &request); 75d7b241e6Sjeremylt // other optional work 768b2d6f4aSMatthew Knepley CeedRequestWait(&request); 77d7b241e6Sjeremylt @endcode 78d7b241e6Sjeremylt 79ea61e9acSJeremy L Thompson which allows the sequence to complete asynchronously but does not start `op2` until `op1` has completed. 80d7b241e6Sjeremylt 81ea61e9acSJeremy L Thompson @todo The current implementation is overly strict, offering equivalent semantics to @ref CEED_REQUEST_IMMEDIATE. 82d7b241e6Sjeremylt 83d7b241e6Sjeremylt @sa CEED_REQUEST_IMMEDIATE 84d7b241e6Sjeremylt */ 85d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_ORDERED = &ceed_request_ordered; 86d7b241e6Sjeremylt 87b11c1e72Sjeremylt /** 887a982d89SJeremy L. Thompson @brief Wait for a CeedRequest to complete. 89dfdf5a53Sjeremylt 907a982d89SJeremy L. Thompson Calling CeedRequestWait on a NULL request is a no-op. 917a982d89SJeremy L. Thompson 927a982d89SJeremy L. Thompson @param req Address of CeedRequest to wait for; zeroed on completion. 937a982d89SJeremy L. Thompson 947a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 957a982d89SJeremy L. Thompson 967a982d89SJeremy L. Thompson @ref User 97b11c1e72Sjeremylt **/ 987a982d89SJeremy L. Thompson int CeedRequestWait(CeedRequest *req) { 992b730f8bSJeremy L Thompson if (!*req) return CEED_ERROR_SUCCESS; 1002b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_UNSUPPORTED, "CeedRequestWait not implemented"); 101683faae0SJed Brown } 1027a982d89SJeremy L. Thompson 1037a982d89SJeremy L. Thompson /// @} 1047a982d89SJeremy L. Thompson 1057a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1067a982d89SJeremy L. Thompson /// Ceed Library Internal Functions 1077a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1087a982d89SJeremy L. Thompson /// @addtogroup CeedDeveloper 1097a982d89SJeremy L. Thompson /// @{ 110d7b241e6Sjeremylt 1116a406739SJeremy L Thompson /** 1126a406739SJeremy L Thompson @brief Register a Ceed backend internally. 113*4385fb7fSSebastian Grimberg 1146a406739SJeremy L Thompson Note: Backends should call `CeedRegister` instead. 1156a406739SJeremy L Thompson 116ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 117ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 118ea61e9acSJeremy L Thompson @param[in] init Initialization function called by CeedInit() when the backend is selected to drive the requested resource. 119ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 120ea61e9acSJeremy L Thompson Lower values are preferred in case the resource requested by CeedInit() has non-unique best prefix match. 1216a406739SJeremy L Thompson 1226a406739SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1236a406739SJeremy L Thompson 1246a406739SJeremy L Thompson @ref Developer 1256a406739SJeremy L Thompson **/ 1262b730f8bSJeremy L Thompson int CeedRegisterImpl(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 127ecc88aebSJeremy L Thompson if (num_backends >= sizeof(backends) / sizeof(backends[0])) { 1286a406739SJeremy L Thompson // LCOV_EXCL_START 1296a406739SJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, "Too many backends"); 1306a406739SJeremy L Thompson // LCOV_EXCL_STOP 131ecc88aebSJeremy L Thompson } 1326a406739SJeremy L Thompson 1336a406739SJeremy L Thompson strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN); 1346a406739SJeremy L Thompson backends[num_backends].prefix[CEED_MAX_RESOURCE_LEN - 1] = 0; 1356a406739SJeremy L Thompson backends[num_backends].init = init; 1366a406739SJeremy L Thompson backends[num_backends].priority = priority; 1376a406739SJeremy L Thompson num_backends++; 1386a406739SJeremy L Thompson return CEED_ERROR_SUCCESS; 1396a406739SJeremy L Thompson } 1406a406739SJeremy L Thompson 1417a982d89SJeremy L. Thompson /// @} 142d7b241e6Sjeremylt 1437a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1447a982d89SJeremy L. Thompson /// Ceed Backend API 1457a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1467a982d89SJeremy L. Thompson /// @addtogroup CeedBackend 1477a982d89SJeremy L. Thompson /// @{ 148d7b241e6Sjeremylt 149b11c1e72Sjeremylt /** 1503f21f6b1SJeremy L Thompson @brief Return value of CEED_DEBUG environment variable 15160f9e2d6SJeremy L Thompson 152ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 15360f9e2d6SJeremy L Thompson 1543f21f6b1SJeremy L Thompson @return boolean value: true - debugging mode enabled 1553f21f6b1SJeremy L Thompson false - debugging mode disabled 15660f9e2d6SJeremy L Thompson 15760f9e2d6SJeremy L Thompson @ref Backend 15860f9e2d6SJeremy L Thompson **/ 159fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 1602b730f8bSJeremy L Thompson bool CeedDebugFlag(const Ceed ceed) { return ceed->is_debug; } 161fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 16260f9e2d6SJeremy L Thompson 16360f9e2d6SJeremy L Thompson /** 1643f21f6b1SJeremy L Thompson @brief Return value of CEED_DEBUG environment variable 16560f9e2d6SJeremy L Thompson 1663f21f6b1SJeremy L Thompson @return boolean value: true - debugging mode enabled 1673f21f6b1SJeremy L Thompson false - debugging mode disabled 1683f21f6b1SJeremy L Thompson 1693f21f6b1SJeremy L Thompson @ref Backend 1703f21f6b1SJeremy L Thompson **/ 1713f21f6b1SJeremy L Thompson // LCOV_EXCL_START 1722b730f8bSJeremy L Thompson bool CeedDebugFlagEnv(void) { return !!getenv("CEED_DEBUG") || !!getenv("DEBUG") || !!getenv("DBG"); } 1733f21f6b1SJeremy L Thompson // LCOV_EXCL_STOP 1743f21f6b1SJeremy L Thompson 1753f21f6b1SJeremy L Thompson /** 1763f21f6b1SJeremy L Thompson @brief Print debugging information in color 1773f21f6b1SJeremy L Thompson 17860f9e2d6SJeremy L Thompson @param color Color to print 17960f9e2d6SJeremy L Thompson @param format Printing format 18060f9e2d6SJeremy L Thompson 18160f9e2d6SJeremy L Thompson @ref Backend 18260f9e2d6SJeremy L Thompson **/ 183fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 1843f21f6b1SJeremy L Thompson void CeedDebugImpl256(const unsigned char color, const char *format, ...) { 18560f9e2d6SJeremy L Thompson va_list args; 18660f9e2d6SJeremy L Thompson va_start(args, format); 18760f9e2d6SJeremy L Thompson fflush(stdout); 1882b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[38;5;%dm", color); 18960f9e2d6SJeremy L Thompson vfprintf(stdout, format, args); 1902b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[m"); 19160f9e2d6SJeremy L Thompson fprintf(stdout, "\n"); 19260f9e2d6SJeremy L Thompson fflush(stdout); 19360f9e2d6SJeremy L Thompson va_end(args); 19460f9e2d6SJeremy L Thompson } 195fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 19660f9e2d6SJeremy L Thompson 19760f9e2d6SJeremy L Thompson /** 198b11c1e72Sjeremylt @brief Allocate an array on the host; use CeedMalloc() 199b11c1e72Sjeremylt 200ea61e9acSJeremy L Thompson Memory usage can be tracked by the library. 201ea61e9acSJeremy L Thompson This ensures sufficient alignment for vectorization and should be used for large allocations. 202b11c1e72Sjeremylt 203ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 204ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 205ea61e9acSJeremy L Thompson @param[out] p Address of pointer to hold the result. 206b11c1e72Sjeremylt 207b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 208b11c1e72Sjeremylt 209b11c1e72Sjeremylt @sa CeedFree() 210dfdf5a53Sjeremylt 2117a982d89SJeremy L. Thompson @ref Backend 212b11c1e72Sjeremylt **/ 213d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 214d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n * unit); 2152b730f8bSJeremy L Thompson if (ierr) { 216c042f62fSJeremy L Thompson // LCOV_EXCL_START 2172b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, "posix_memalign failed to allocate %zd members of size %zd\n", n, unit); 218c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 2192b730f8bSJeremy L Thompson } 220e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 221d7b241e6Sjeremylt } 222d7b241e6Sjeremylt 223b11c1e72Sjeremylt /** 224b11c1e72Sjeremylt @brief Allocate a cleared (zeroed) array on the host; use CeedCalloc() 225b11c1e72Sjeremylt 226b11c1e72Sjeremylt Memory usage can be tracked by the library. 227b11c1e72Sjeremylt 228ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 229ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 230ea61e9acSJeremy L Thompson @param[out] p Address of pointer to hold the result. 231b11c1e72Sjeremylt 232b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 233b11c1e72Sjeremylt 234b11c1e72Sjeremylt @sa CeedFree() 235dfdf5a53Sjeremylt 2367a982d89SJeremy L. Thompson @ref Backend 237b11c1e72Sjeremylt **/ 238d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 239d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 2402b730f8bSJeremy L Thompson if (n && unit && !*(void **)p) { 241c042f62fSJeremy L Thompson // LCOV_EXCL_START 2422b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, "calloc failed to allocate %zd members of size %zd\n", n, unit); 243c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 2442b730f8bSJeremy L Thompson } 245e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 246d7b241e6Sjeremylt } 247d7b241e6Sjeremylt 248b11c1e72Sjeremylt /** 249b11c1e72Sjeremylt @brief Reallocate an array on the host; use CeedRealloc() 250b11c1e72Sjeremylt 251b11c1e72Sjeremylt Memory usage can be tracked by the library. 252b11c1e72Sjeremylt 253ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 254ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 255ea61e9acSJeremy L Thompson @param[out] p Address of pointer to hold the result. 256b11c1e72Sjeremylt 257b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 258b11c1e72Sjeremylt 259b11c1e72Sjeremylt @sa CeedFree() 260dfdf5a53Sjeremylt 2617a982d89SJeremy L. Thompson @ref Backend 262b11c1e72Sjeremylt **/ 263d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 264d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n * unit); 2652b730f8bSJeremy L Thompson if (n && unit && !*(void **)p) { 266c042f62fSJeremy L Thompson // LCOV_EXCL_START 2672b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, "realloc failed to allocate %zd members of size %zd\n", n, unit); 268c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 2692b730f8bSJeremy L Thompson } 270e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 271d7b241e6Sjeremylt } 272d7b241e6Sjeremylt 273f7e22acaSJeremy L Thompson /** 274f7e22acaSJeremy L Thompson @brief Allocate a cleared string buffer on the host 275f7e22acaSJeremy L Thompson 276f7e22acaSJeremy L Thompson Memory usage can be tracked by the library. 277f7e22acaSJeremy L Thompson 278ea61e9acSJeremy L Thompson @param[in] source Pointer to string to be copied 279ea61e9acSJeremy L Thompson @param[out] copy Pointer to variable to hold newly allocated string copy 280f7e22acaSJeremy L Thompson 281f7e22acaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 282f7e22acaSJeremy L Thompson 283f7e22acaSJeremy L Thompson @sa CeedFree() 284f7e22acaSJeremy L Thompson 285f7e22acaSJeremy L Thompson @ref Backend 286f7e22acaSJeremy L Thompson **/ 287f7e22acaSJeremy L Thompson int CeedStringAllocCopy(const char *source, char **copy) { 288f7e22acaSJeremy L Thompson size_t len = strlen(source); 2892b730f8bSJeremy L Thompson CeedCall(CeedCalloc(len + 1, copy)); 290d602d780SJeremy L Thompson memcpy(*copy, source, len); 291f7e22acaSJeremy L Thompson return CEED_ERROR_SUCCESS; 292f7e22acaSJeremy L Thompson } 293f7e22acaSJeremy L Thompson 29434138859Sjeremylt /** Free memory allocated using CeedMalloc() or CeedCalloc() 29534138859Sjeremylt 296ea61e9acSJeremy L Thompson @param[in,out] p address of pointer to memory. 297ea61e9acSJeremy 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 298ea61e9acSJeremy L Thompson pointer. 29934138859Sjeremylt **/ 300d7b241e6Sjeremylt int CeedFree(void *p) { 301d7b241e6Sjeremylt free(*(void **)p); 302d7b241e6Sjeremylt *(void **)p = NULL; 303e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 304d7b241e6Sjeremylt } 305d7b241e6Sjeremylt 306d7b241e6Sjeremylt /** 3077a982d89SJeremy L. Thompson @brief Register a Ceed backend 308d7b241e6Sjeremylt 309ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 310ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 311ea61e9acSJeremy L Thompson @param[in] init Initialization function called by CeedInit() when the backend is selected to drive the requested resource. 312ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 313ea61e9acSJeremy L Thompson Lower values are preferred in case the resource requested by CeedInit() has non-unique best prefix match. 314b11c1e72Sjeremylt 315b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 316dfdf5a53Sjeremylt 3177a982d89SJeremy L. Thompson @ref Backend 318b11c1e72Sjeremylt **/ 3192b730f8bSJeremy L Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 32010243053SJeremy L Thompson CeedDebugEnv("Backend Register: %s", prefix); 3216a406739SJeremy L Thompson CeedRegisterImpl(prefix, init, priority); 322e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 323d7b241e6Sjeremylt } 324d7b241e6Sjeremylt 325b11c1e72Sjeremylt /** 32660f9e2d6SJeremy L Thompson @brief Return debugging status flag 32760f9e2d6SJeremy L Thompson 328ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get debugging flag 329ea61e9acSJeremy L Thompson @param[out] is_debug Variable to store debugging flag 33060f9e2d6SJeremy L Thompson 33160f9e2d6SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 33260f9e2d6SJeremy L Thompson 333d1d35e2fSjeremylt @ref Backend 33460f9e2d6SJeremy L Thompson **/ 335d1d35e2fSjeremylt int CeedIsDebug(Ceed ceed, bool *is_debug) { 3363f21f6b1SJeremy L Thompson *is_debug = ceed->is_debug; 337e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 33860f9e2d6SJeremy L Thompson } 33960f9e2d6SJeremy L Thompson 34060f9e2d6SJeremy L Thompson /** 3417a982d89SJeremy L. Thompson @brief Retrieve a parent Ceed context 3427a982d89SJeremy L. Thompson 343ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve parent of 3447a982d89SJeremy L. Thompson @param[out] parent Address to save the parent to 3457a982d89SJeremy L. Thompson 3467a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3477a982d89SJeremy L. Thompson 3487a982d89SJeremy L. Thompson @ref Backend 3497a982d89SJeremy L. Thompson **/ 3507a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 3517a982d89SJeremy L. Thompson if (ceed->parent) { 3522b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed->parent, parent)); 353e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3547a982d89SJeremy L. Thompson } 3557a982d89SJeremy L. Thompson *parent = ceed; 356e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3577a982d89SJeremy L. Thompson } 3587a982d89SJeremy L. Thompson 3597a982d89SJeremy L. Thompson /** 3607a982d89SJeremy L. Thompson @brief Retrieve a delegate Ceed context 3617a982d89SJeremy L. Thompson 362ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve delegate of 3637a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 3647a982d89SJeremy L. Thompson 3657a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3667a982d89SJeremy L. Thompson 3677a982d89SJeremy L. Thompson @ref Backend 3687a982d89SJeremy L. Thompson **/ 3697a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 3707a982d89SJeremy L. Thompson *delegate = ceed->delegate; 371e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3727a982d89SJeremy L. Thompson } 3737a982d89SJeremy L. Thompson 3747a982d89SJeremy L. Thompson /** 3757a982d89SJeremy L. Thompson @brief Set a delegate Ceed context 3767a982d89SJeremy L. Thompson 377ea61e9acSJeremy L Thompson This function allows a Ceed context to set a delegate Ceed context. 378ea61e9acSJeremy L Thompson All backend implementations default to the delegate Ceed context, unless overridden. 3797a982d89SJeremy L. Thompson 380ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to set delegate of 3817a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 3827a982d89SJeremy L. Thompson 3837a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3847a982d89SJeremy L. Thompson 3857a982d89SJeremy L. Thompson @ref Backend 3867a982d89SJeremy L. Thompson **/ 3877a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) { 3887a982d89SJeremy L. Thompson ceed->delegate = delegate; 3897a982d89SJeremy L. Thompson delegate->parent = ceed; 390e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3917a982d89SJeremy L. Thompson } 3927a982d89SJeremy L. Thompson 3937a982d89SJeremy L. Thompson /** 3947a982d89SJeremy L. Thompson @brief Retrieve a delegate Ceed context for a specific object type 3957a982d89SJeremy L. Thompson 396ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve delegate of 3977a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 398d1d35e2fSjeremylt @param[in] obj_name Name of the object type to retrieve delegate for 3997a982d89SJeremy L. Thompson 4007a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4017a982d89SJeremy L. Thompson 4027a982d89SJeremy L. Thompson @ref Backend 4037a982d89SJeremy L. Thompson **/ 404d1d35e2fSjeremylt int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *obj_name) { 4057a982d89SJeremy L. Thompson // Check for object delegate 4062b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) { 407d1d35e2fSjeremylt if (!strcmp(obj_name, ceed->obj_delegates->obj_name)) { 408d1d35e2fSjeremylt *delegate = ceed->obj_delegates->delegate; 409e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4107a982d89SJeremy L. Thompson } 4112b730f8bSJeremy L Thompson } 4127a982d89SJeremy L. Thompson 4137a982d89SJeremy L. Thompson // Use default delegate if no object delegate 4142b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, delegate)); 415e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4167a982d89SJeremy L. Thompson } 4177a982d89SJeremy L. Thompson 4187a982d89SJeremy L. Thompson /** 4197a982d89SJeremy L. Thompson @brief Set a delegate Ceed context for a specific object type 4207a982d89SJeremy L. Thompson 421ea61e9acSJeremy L Thompson This function allows a Ceed context to set a delegate Ceed context for a given type of Ceed object. 422ea61e9acSJeremy L Thompson All backend implementations default to the delegate Ceed context for this object. 423ea61e9acSJeremy L Thompson For example, CeedSetObjectDelegate(ceed, refceed, "Basis") uses refceed implementations for all CeedBasis backend functions. 4247a982d89SJeremy L. Thompson 425ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context to set delegate of 4267a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 427d1d35e2fSjeremylt @param[in] obj_name Name of the object type to set delegate for 4287a982d89SJeremy L. Thompson 4297a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4307a982d89SJeremy L. Thompson 4317a982d89SJeremy L. Thompson @ref Backend 4327a982d89SJeremy L. Thompson **/ 433d1d35e2fSjeremylt int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *obj_name) { 434d1d35e2fSjeremylt CeedInt count = ceed->obj_delegate_count; 4357a982d89SJeremy L. Thompson 4367a982d89SJeremy L. Thompson // Malloc or Realloc 4377a982d89SJeremy L. Thompson if (count) { 4382b730f8bSJeremy L Thompson CeedCall(CeedRealloc(count + 1, &ceed->obj_delegates)); 4397a982d89SJeremy L. Thompson } else { 4402b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->obj_delegates)); 4417a982d89SJeremy L. Thompson } 442d1d35e2fSjeremylt ceed->obj_delegate_count++; 4437a982d89SJeremy L. Thompson 4447a982d89SJeremy L. Thompson // Set object delegate 445d1d35e2fSjeremylt ceed->obj_delegates[count].delegate = delegate; 4462b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(obj_name, &ceed->obj_delegates[count].obj_name)); 4477a982d89SJeremy L. Thompson 4487a982d89SJeremy L. Thompson // Set delegate parent 4497a982d89SJeremy L. Thompson delegate->parent = ceed; 450e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4517a982d89SJeremy L. Thompson } 4527a982d89SJeremy L. Thompson 4537a982d89SJeremy L. Thompson /** 4547a982d89SJeremy L. Thompson @brief Get the fallback resource for CeedOperators 4557a982d89SJeremy L. Thompson 456ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 4577a982d89SJeremy L. Thompson @param[out] resource Variable to store fallback resource 4587a982d89SJeremy L. Thompson 4597a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4607a982d89SJeremy L. Thompson 4617a982d89SJeremy L. Thompson @ref Backend 4627a982d89SJeremy L. Thompson **/ 4637a982d89SJeremy L. Thompson int CeedGetOperatorFallbackResource(Ceed ceed, const char **resource) { 464d1d35e2fSjeremylt *resource = (const char *)ceed->op_fallback_resource; 465e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4667a982d89SJeremy L. Thompson } 4677a982d89SJeremy L. Thompson 4687a982d89SJeremy L. Thompson /** 4698687e1d4SJeremy L Thompson @brief Get the fallback Ceed for CeedOperators 4708687e1d4SJeremy L Thompson 471ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 4728687e1d4SJeremy L Thompson @param[out] fallback_ceed Variable to store fallback Ceed 4738687e1d4SJeremy L Thompson 4748687e1d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 4758687e1d4SJeremy L Thompson 4768687e1d4SJeremy L Thompson @ref Backend 4778687e1d4SJeremy L Thompson **/ 4788687e1d4SJeremy L Thompson int CeedGetOperatorFallbackCeed(Ceed ceed, Ceed *fallback_ceed) { 479d04bbc78SJeremy L Thompson if (ceed->has_valid_op_fallback_resource) { 480d04bbc78SJeremy L Thompson CeedDebug256(ceed, 1, "---------- CeedOperator Fallback ----------\n"); 4812b730f8bSJeremy L Thompson CeedDebug(ceed, "Getting fallback from %s to %s\n", ceed->resource, ceed->op_fallback_resource); 482d04bbc78SJeremy L Thompson } 4838687e1d4SJeremy L Thompson 484d04bbc78SJeremy L Thompson // Create fallback Ceed if uninitalized 485d04bbc78SJeremy L Thompson if (!ceed->op_fallback_ceed && ceed->has_valid_op_fallback_resource) { 48613f886e9SJeremy L Thompson CeedDebug(ceed, "Creating fallback Ceed"); 487d04bbc78SJeremy L Thompson 4888687e1d4SJeremy L Thompson Ceed fallback_ceed; 489d04bbc78SJeremy L Thompson const char *fallback_resource; 490d04bbc78SJeremy L Thompson 4912b730f8bSJeremy L Thompson CeedCall(CeedGetOperatorFallbackResource(ceed, &fallback_resource)); 4922b730f8bSJeremy L Thompson CeedCall(CeedInit(fallback_resource, &fallback_ceed)); 4938687e1d4SJeremy L Thompson fallback_ceed->op_fallback_parent = ceed; 4948687e1d4SJeremy L Thompson fallback_ceed->Error = ceed->Error; 4958687e1d4SJeremy L Thompson ceed->op_fallback_ceed = fallback_ceed; 4968687e1d4SJeremy L Thompson } 4978687e1d4SJeremy L Thompson *fallback_ceed = ceed->op_fallback_ceed; 4988687e1d4SJeremy L Thompson 4998687e1d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 5008687e1d4SJeremy L Thompson } 5018687e1d4SJeremy L Thompson 5028687e1d4SJeremy L Thompson /** 503ea61e9acSJeremy L Thompson @brief Set the fallback resource for CeedOperators. 504*4385fb7fSSebastian Grimberg 505ea61e9acSJeremy L Thompson The current resource, if any, is freed by calling this function. 506ea61e9acSJeremy L Thompson This string is freed upon the destruction of the Ceed context. 5077a982d89SJeremy L. Thompson 508ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context 509ea61e9acSJeremy L Thompson @param[in] resource Fallback resource to set 5107a982d89SJeremy L. Thompson 5117a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5127a982d89SJeremy L. Thompson 5137a982d89SJeremy L. Thompson @ref Backend 5147a982d89SJeremy L. Thompson **/ 5157a982d89SJeremy L. Thompson int CeedSetOperatorFallbackResource(Ceed ceed, const char *resource) { 5167a982d89SJeremy L. Thompson // Free old 5172b730f8bSJeremy L Thompson CeedCall(CeedFree(&ceed->op_fallback_resource)); 5187a982d89SJeremy L. Thompson 5197a982d89SJeremy L. Thompson // Set new 5202b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(resource, (char **)&ceed->op_fallback_resource)); 521d04bbc78SJeremy L Thompson 522d04bbc78SJeremy L Thompson // Check validity 5232b730f8bSJeremy L Thompson ceed->has_valid_op_fallback_resource = ceed->op_fallback_resource && ceed->resource && strcmp(ceed->op_fallback_resource, ceed->resource); 524d04bbc78SJeremy L Thompson 525e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5267a982d89SJeremy L. Thompson } 5277a982d89SJeremy L. Thompson 5287a982d89SJeremy L. Thompson /** 529ea61e9acSJeremy L Thompson @brief Get the parent Ceed context associated with a fallback Ceed context for a CeedOperator 5307a982d89SJeremy L. Thompson 531ea61e9acSJeremy L Thompson @param[in] ceed Ceed context 5327a982d89SJeremy L. Thompson @param[out] parent Variable to store parent Ceed context 5337a982d89SJeremy L. Thompson 5347a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5357a982d89SJeremy L. Thompson 5367a982d89SJeremy L. Thompson @ref Backend 5377a982d89SJeremy L. Thompson **/ 5387a982d89SJeremy L. Thompson int CeedGetOperatorFallbackParentCeed(Ceed ceed, Ceed *parent) { 539d1d35e2fSjeremylt *parent = ceed->op_fallback_parent; 540e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5417a982d89SJeremy L. Thompson } 5427a982d89SJeremy L. Thompson 5437a982d89SJeremy L. Thompson /** 5449525855cSJeremy L Thompson @brief Flag Ceed context as deterministic 5459525855cSJeremy L Thompson 546ea61e9acSJeremy L Thompson @param[in] ceed Ceed to flag as deterministic 54796b902e2Sjeremylt @param[out] is_deterministic Deterministic status to set 5489525855cSJeremy L Thompson 5499525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 5509525855cSJeremy L Thompson 5519525855cSJeremy L Thompson @ref Backend 5529525855cSJeremy L Thompson **/ 553d1d35e2fSjeremylt int CeedSetDeterministic(Ceed ceed, bool is_deterministic) { 554d1d35e2fSjeremylt ceed->is_deterministic = is_deterministic; 555e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5569525855cSJeremy L Thompson } 5579525855cSJeremy L Thompson 5589525855cSJeremy L Thompson /** 5597a982d89SJeremy L. Thompson @brief Set a backend function 5607a982d89SJeremy L. Thompson 561ea61e9acSJeremy L Thompson This function is used for a backend to set the function associated with the Ceed objects. 562ea61e9acSJeremy L Thompson For example, CeedSetBackendFunction(ceed, "Ceed", ceed, "VectorCreate", BackendVectorCreate) sets the backend implementation of 'CeedVectorCreate' 563ea61e9acSJeremy L Thompson and CeedSetBackendFunction(ceed, "Basis", basis, "Apply", BackendBasisApply) sets the backend implementation of 'CeedBasisApply'. Note, the prefix 564ea61e9acSJeremy L Thompson 'Ceed' is not required for the object type ("Basis" vs "CeedBasis"). 5657a982d89SJeremy L. Thompson 566ea61e9acSJeremy L Thompson @param[in] ceed Ceed context for error handling 567ea61e9acSJeremy L Thompson @param[in] type Type of Ceed object to set function for 5687a982d89SJeremy L. Thompson @param[out] object Ceed object to set function for 569ea61e9acSJeremy L Thompson @param[in] func_name Name of function to set 570ea61e9acSJeremy L Thompson @param[in] f Function to set 5717a982d89SJeremy L. Thompson 5727a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5737a982d89SJeremy L. Thompson 5747a982d89SJeremy L. Thompson @ref Backend 5757a982d89SJeremy L. Thompson **/ 5762b730f8bSJeremy L Thompson int CeedSetBackendFunction(Ceed ceed, const char *type, void *object, const char *func_name, int (*f)()) { 577d1d35e2fSjeremylt char lookup_name[CEED_MAX_RESOURCE_LEN + 1] = ""; 5787a982d89SJeremy L. Thompson 5797a982d89SJeremy L. Thompson // Build lookup name 5802b730f8bSJeremy L Thompson if (strcmp(type, "Ceed")) strncat(lookup_name, "Ceed", CEED_MAX_RESOURCE_LEN); 581d1d35e2fSjeremylt strncat(lookup_name, type, CEED_MAX_RESOURCE_LEN); 582d1d35e2fSjeremylt strncat(lookup_name, func_name, CEED_MAX_RESOURCE_LEN); 5837a982d89SJeremy L. Thompson 5847a982d89SJeremy L. Thompson // Find and use offset 5852b730f8bSJeremy L Thompson for (CeedInt i = 0; ceed->f_offsets[i].func_name; i++) { 586d1d35e2fSjeremylt if (!strcmp(ceed->f_offsets[i].func_name, lookup_name)) { 587d1d35e2fSjeremylt size_t offset = ceed->f_offsets[i].offset; 5887a982d89SJeremy L. Thompson int (**fpointer)(void) = (int (**)(void))((char *)object + offset); // *NOPAD* 5897a982d89SJeremy L. Thompson *fpointer = f; 590e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5917a982d89SJeremy L. Thompson } 5922b730f8bSJeremy L Thompson } 5937a982d89SJeremy L. Thompson 5947a982d89SJeremy L. Thompson // LCOV_EXCL_START 5952b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Requested function '%s' was not found for CEED object '%s'", func_name, type); 5967a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5977a982d89SJeremy L. Thompson } 5987a982d89SJeremy L. Thompson 5997a982d89SJeremy L. Thompson /** 6007a982d89SJeremy L. Thompson @brief Retrieve backend data for a Ceed context 6017a982d89SJeremy L. Thompson 602ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve data of 6037a982d89SJeremy L. Thompson @param[out] data Address to save data to 6047a982d89SJeremy L. Thompson 6057a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6067a982d89SJeremy L. Thompson 6077a982d89SJeremy L. Thompson @ref Backend 6087a982d89SJeremy L. Thompson **/ 609777ff853SJeremy L Thompson int CeedGetData(Ceed ceed, void *data) { 610777ff853SJeremy L Thompson *(void **)data = ceed->data; 611e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6127a982d89SJeremy L. Thompson } 6137a982d89SJeremy L. Thompson 6147a982d89SJeremy L. Thompson /** 6157a982d89SJeremy L. Thompson @brief Set backend data for a Ceed context 6167a982d89SJeremy L. Thompson 617ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context to set data of 618ea61e9acSJeremy L Thompson @param[in] data Address of data to set 6197a982d89SJeremy L. Thompson 6207a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6217a982d89SJeremy L. Thompson 6227a982d89SJeremy L. Thompson @ref Backend 6237a982d89SJeremy L. Thompson **/ 624777ff853SJeremy L Thompson int CeedSetData(Ceed ceed, void *data) { 625777ff853SJeremy L Thompson ceed->data = data; 626e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6277a982d89SJeremy L. Thompson } 6287a982d89SJeremy L. Thompson 62934359f16Sjeremylt /** 63034359f16Sjeremylt @brief Increment the reference counter for a Ceed context 63134359f16Sjeremylt 632ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed context to increment the reference counter 63334359f16Sjeremylt 63434359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 63534359f16Sjeremylt 63634359f16Sjeremylt @ref Backend 63734359f16Sjeremylt **/ 6389560d06aSjeremylt int CeedReference(Ceed ceed) { 63934359f16Sjeremylt ceed->ref_count++; 64034359f16Sjeremylt return CEED_ERROR_SUCCESS; 64134359f16Sjeremylt } 64234359f16Sjeremylt 6437a982d89SJeremy L. Thompson /// @} 6447a982d89SJeremy L. Thompson 6457a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 6467a982d89SJeremy L. Thompson /// Ceed Public API 6477a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 6487a982d89SJeremy L. Thompson /// @addtogroup CeedUser 6497a982d89SJeremy L. Thompson /// @{ 6507a982d89SJeremy L. Thompson 6517a982d89SJeremy L. Thompson /** 65292ee7d1cSjeremylt @brief Get the list of available resource names for Ceed contexts 653*4385fb7fSSebastian Grimberg 654ea61e9acSJeremy L Thompson Note: The caller is responsible for `free()`ing the resources and priorities arrays, but should not `free()` the contents of the resources 655ea61e9acSJeremy L Thompson array. 65622e44211Sjeremylt 65792ee7d1cSjeremylt @param[out] n Number of available resources 65892ee7d1cSjeremylt @param[out] resources List of available resource names 65922e44211Sjeremylt @param[out] priorities Resource name prioritization values, lower is better 66022e44211Sjeremylt 66122e44211Sjeremylt @return An error code: 0 - success, otherwise - failure 66222e44211Sjeremylt 66322e44211Sjeremylt @ref User 66422e44211Sjeremylt **/ 66522e44211Sjeremylt // LCOV_EXCL_START 6662b730f8bSJeremy L Thompson int CeedRegistryGetList(size_t *n, char ***const resources, CeedInt **priorities) { 667d0c91ce9Sjeremylt *n = 0; 6689ff86846Sjeremylt *resources = malloc(num_backends * sizeof(**resources)); 6692b730f8bSJeremy L Thompson if (!resources) return CeedError(NULL, CEED_ERROR_MAJOR, "malloc() failure"); 6709ff86846Sjeremylt if (priorities) { 6719ff86846Sjeremylt *priorities = malloc(num_backends * sizeof(**priorities)); 6722b730f8bSJeremy L Thompson if (!priorities) return CeedError(NULL, CEED_ERROR_MAJOR, "malloc() failure"); 6739ff86846Sjeremylt } 67422e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 675d0c91ce9Sjeremylt // Only report compiled backends 676d0c91ce9Sjeremylt if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) { 67722e44211Sjeremylt *resources[i] = backends[i].prefix; 6789ff86846Sjeremylt if (priorities) *priorities[i] = backends[i].priority; 679d0c91ce9Sjeremylt *n += 1; 680d0c91ce9Sjeremylt } 681d0c91ce9Sjeremylt } 6822b730f8bSJeremy L Thompson if (*n == 0) { 68378464608Sjeremylt // LCOV_EXCL_START 68478464608Sjeremylt return CeedError(NULL, CEED_ERROR_MAJOR, "No backends installed"); 68578464608Sjeremylt // LCOV_EXCL_STOP 6862b730f8bSJeremy L Thompson } 687d0c91ce9Sjeremylt *resources = realloc(*resources, *n * sizeof(**resources)); 6882b730f8bSJeremy L Thompson if (!resources) return CeedError(NULL, CEED_ERROR_MAJOR, "realloc() failure"); 689d0c91ce9Sjeremylt if (priorities) { 690d0c91ce9Sjeremylt *priorities = realloc(*priorities, *n * sizeof(**priorities)); 6912b730f8bSJeremy L Thompson if (!priorities) return CeedError(NULL, CEED_ERROR_MAJOR, "realloc() failure"); 69222e44211Sjeremylt } 69322e44211Sjeremylt return CEED_ERROR_SUCCESS; 69445f1e315Sjeremylt } 69522e44211Sjeremylt // LCOV_EXCL_STOP 69622e44211Sjeremylt 69722e44211Sjeremylt /** 698d79b80ecSjeremylt @brief Initialize a \ref Ceed context to use the specified resource. 699*4385fb7fSSebastian Grimberg 700ea61e9acSJeremy 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 701ea61e9acSJeremy L Thompson list of current available backend resources to stderr. 702b11c1e72Sjeremylt 703ea61e9acSJeremy L Thompson @param[in] resource Resource to use, e.g., "/cpu/self" 704ea61e9acSJeremy L Thompson @param[out] ceed The library context 705b11c1e72Sjeremylt @sa CeedRegister() CeedDestroy() 706b11c1e72Sjeremylt 707b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 708dfdf5a53Sjeremylt 7097a982d89SJeremy L. Thompson @ref User 710b11c1e72Sjeremylt **/ 711d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 7122b730f8bSJeremy L Thompson size_t match_len = 0, match_index = UINT_MAX, match_priority = CEED_MAX_BACKEND_PRIORITY, priority; 713d7b241e6Sjeremylt 714fe2413ffSjeremylt // Find matching backend 7152b730f8bSJeremy L Thompson if (!resource) { 71613873f79Sjeremylt // LCOV_EXCL_START 717e15f9bd0SJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, "No resource provided"); 71813873f79Sjeremylt // LCOV_EXCL_STOP 7192b730f8bSJeremy L Thompson } 7202b730f8bSJeremy L Thompson CeedCall(CeedRegisterAll()); 72113873f79Sjeremylt 72222e44211Sjeremylt // Check for help request 72322e44211Sjeremylt const char *help_prefix = "help"; 7242b730f8bSJeremy L Thompson size_t match_help = 0; 7252b730f8bSJeremy L Thompson while (match_help < 4 && resource[match_help] == help_prefix[match_help]) match_help++; 72622e44211Sjeremylt if (match_help == 4) { 7272b730f8bSJeremy L Thompson fprintf(stderr, "libCEED version: %d.%d%d%s\n", CEED_VERSION_MAJOR, CEED_VERSION_MINOR, CEED_VERSION_PATCH, 72822e44211Sjeremylt CEED_VERSION_RELEASE ? "" : "+development"); 72992ee7d1cSjeremylt fprintf(stderr, "Available backend resources:\n"); 73022e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 731d0c91ce9Sjeremylt // Only report compiled backends 7322b730f8bSJeremy L Thompson if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) fprintf(stderr, " %s\n", backends[i].prefix); 73322e44211Sjeremylt } 73422e44211Sjeremylt fflush(stderr); 73522e44211Sjeremylt match_help = 5; // Delineating character expected 73622e44211Sjeremylt } else { 73722e44211Sjeremylt match_help = 0; 73822e44211Sjeremylt } 73922e44211Sjeremylt 740ea61e9acSJeremy L Thompson // Find best match, computed as number of matching characters from requested resource stem 7412b730f8bSJeremy L Thompson size_t stem_length = 0; 7422b730f8bSJeremy L Thompson while (resource[stem_length + match_help] && resource[stem_length + match_help] != ':') stem_length++; 743d7b241e6Sjeremylt for (size_t i = 0; i < num_backends; i++) { 7442b730f8bSJeremy L Thompson size_t n = 0; 745d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 7462b730f8bSJeremy L Thompson while (prefix[n] && prefix[n] == resource[n + match_help]) n++; 747d7b241e6Sjeremylt priority = backends[i].priority; 748d1d35e2fSjeremylt if (n > match_len || (n == match_len && match_priority > priority)) { 749d1d35e2fSjeremylt match_len = n; 750d1d35e2fSjeremylt match_priority = priority; 751f7e22acaSJeremy L Thompson match_index = i; 752d7b241e6Sjeremylt } 753d7b241e6Sjeremylt } 7549c9a0587SLeila Ghaffari // Using Levenshtein distance to find closest match 7559c9a0587SLeila Ghaffari if (match_len <= 1 || match_len != stem_length) { 756203015caSLeila Ghaffari // LCOV_EXCL_START 7579c9a0587SLeila Ghaffari size_t lev_dis = UINT_MAX; 758f7e22acaSJeremy L Thompson size_t lev_index = UINT_MAX, lev_priority = CEED_MAX_BACKEND_PRIORITY; 7599c9a0587SLeila Ghaffari for (size_t i = 0; i < num_backends; i++) { 7609c9a0587SLeila Ghaffari const char *prefix = backends[i].prefix; 7619c9a0587SLeila Ghaffari size_t prefix_length = strlen(backends[i].prefix); 7629c9a0587SLeila Ghaffari size_t min_len = (prefix_length < stem_length) ? prefix_length : stem_length; 763092904ddSLeila Ghaffari size_t column[min_len + 1]; 764092904ddSLeila Ghaffari for (size_t j = 0; j <= min_len; j++) column[j] = j; 7659c9a0587SLeila Ghaffari for (size_t j = 1; j <= min_len; j++) { 7669c9a0587SLeila Ghaffari column[0] = j; 7679c9a0587SLeila Ghaffari for (size_t k = 1, last_diag = j - 1; k <= min_len; k++) { 768092904ddSLeila Ghaffari size_t old_diag = column[k]; 7699c9a0587SLeila Ghaffari size_t min_1 = (column[k] < column[k - 1]) ? column[k] + 1 : column[k - 1] + 1; 7709c9a0587SLeila Ghaffari size_t min_2 = last_diag + (resource[k - 1] == prefix[j - 1] ? 0 : 1); 7719c9a0587SLeila Ghaffari column[k] = (min_1 < min_2) ? min_1 : min_2; 7729c9a0587SLeila Ghaffari last_diag = old_diag; 7739c9a0587SLeila Ghaffari } 7749c9a0587SLeila Ghaffari } 7759c9a0587SLeila Ghaffari size_t n = column[min_len]; 7769c9a0587SLeila Ghaffari priority = backends[i].priority; 7772b730f8bSJeremy L Thompson if (n < lev_dis || (n == lev_dis && lev_priority > priority)) { 7789c9a0587SLeila Ghaffari lev_dis = n; 7799c9a0587SLeila Ghaffari lev_priority = priority; 780f7e22acaSJeremy L Thompson lev_index = i; 7819c9a0587SLeila Ghaffari } 7829c9a0587SLeila Ghaffari } 783f7e22acaSJeremy L Thompson const char *prefix_lev = backends[lev_index].prefix; 7842b730f8bSJeremy L Thompson size_t lev_length = 0; 7852b730f8bSJeremy L Thompson while (prefix_lev[lev_length] && prefix_lev[lev_length] != '\0') lev_length++; 7869c9a0587SLeila Ghaffari size_t m = (lev_length < stem_length) ? lev_length : stem_length; 7879c9a0587SLeila Ghaffari if (lev_dis + 1 >= m) { 7882b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s", resource); 7899c9a0587SLeila Ghaffari } else { 7902b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_MAJOR, 7912b730f8bSJeremy L Thompson "No suitable backend: %s\n" 7922b730f8bSJeremy L Thompson "Closest match: %s", 7932b730f8bSJeremy L Thompson resource, backends[lev_index].prefix); 7942bbc7fe8Sjeremylt } 795203015caSLeila Ghaffari // LCOV_EXCL_STOP 7969c9a0587SLeila Ghaffari } 797fe2413ffSjeremylt 798fe2413ffSjeremylt // Setup Ceed 7992b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, ceed)); 8002b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &(*ceed)->jit_source_roots)); 801bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 8022b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 8032b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "exit")) (*ceed)->Error = CeedErrorExit; 8042b730f8bSJeremy L Thompson else if (!strcmp(ceed_error_handler, "store")) (*ceed)->Error = CeedErrorStore; 8052b730f8bSJeremy L Thompson else (*ceed)->Error = CeedErrorAbort; 806d1d35e2fSjeremylt memcpy((*ceed)->err_msg, "No error message stored", 24); 807d1d35e2fSjeremylt (*ceed)->ref_count = 1; 808d7b241e6Sjeremylt (*ceed)->data = NULL; 809fe2413ffSjeremylt 810fe2413ffSjeremylt // Set lookup table 811d1d35e2fSjeremylt FOffset f_offsets[] = { 8126e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 8136e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 8146e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 815f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 8166e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 817fc0567d9Srezgarshakeri CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateOriented), 8186e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 8196e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 8206e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 82150c301a5SRezgar Shakeri CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv), 822c4e3f59bSSebastian Grimberg CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl), 8236e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 8246e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 825777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate), 8266e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 8276e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 8289c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasValidArray), 8299c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType), 8306e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 8316a6c615bSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, TakeArray), 8326e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 833f48ed27dSnbeams CEED_FTABLE_ENTRY(CeedVector, SyncArray), 8346e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 8356e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 8369c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite), 8376e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 8386e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 839547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 840e0dd3b27Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Scale), 8410f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, AXPY), 8425fb68f37SKaren (Ren) Stengel CEED_FTABLE_ENTRY(CeedVector, AXPBY), 8430f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, PointwiseMult), 844d99fa3c5SJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, Reciprocal), 8456e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 8466e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 8476e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 848bd33150aSjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets), 8496e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 8506e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 8516e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 8526e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 8536e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 8546e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 8558c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction), 8568c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction), 8576e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 8589c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData), 8599c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType), 860777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData), 861891038deSjeremylt CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData), 862777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData), 86328bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead), 864777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData), 86528bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead), 8662e64a2b9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy), 867777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy), 86880ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction), 86970a7ffb3SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate), 87080ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal), 8719e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal), 87280ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal), 8739e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal), 874e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic), 875e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble), 876cefa2673SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle), 877713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 8786e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 879250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 880cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 881250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 8826e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 8836e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 8846e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 8851dfeef1dSjeremylt }; 886fe2413ffSjeremylt 8872b730f8bSJeremy L Thompson CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets)); 888d1d35e2fSjeremylt memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets)); 889fe2413ffSjeremylt 8905107b09fSJeremy L Thompson // Set fallback for advanced CeedOperator functions 891e2f04181SAndrew T. Barker const char fallbackresource[] = ""; 8922b730f8bSJeremy L Thompson CeedCall(CeedSetOperatorFallbackResource(*ceed, fallbackresource)); 8935107b09fSJeremy L Thompson 89460f9e2d6SJeremy L Thompson // Record env variables CEED_DEBUG or DBG 8952b730f8bSJeremy L Thompson (*ceed)->is_debug = !!getenv("CEED_DEBUG") || !!getenv("DEBUG") || !!getenv("DBG"); 89660f9e2d6SJeremy L Thompson 89722e44211Sjeremylt // Copy resource prefix, if backend setup successful 8982b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource)); 899ee5a26f2SJeremy L Thompson 900ee5a26f2SJeremy L Thompson // Set default JiT source root 901ea61e9acSJeremy L Thompson // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent 9022b730f8bSJeremy L Thompson CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault)); 903ee5a26f2SJeremy L Thompson 904d04bbc78SJeremy L Thompson // Backend specific setup 9052b730f8bSJeremy L Thompson CeedCall(backends[match_index].init(&resource[match_help], *ceed)); 906d04bbc78SJeremy L Thompson 907e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 908d7b241e6Sjeremylt } 909d7b241e6Sjeremylt 910d7b241e6Sjeremylt /** 911ea61e9acSJeremy L Thompson @brief Copy the pointer to a Ceed context. 912*4385fb7fSSebastian Grimberg 913512bb800SJeremy L Thompson Both pointers should be destroyed with `CeedDestroy()`. 914512bb800SJeremy L Thompson 915512bb800SJeremy 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. 916512bb800SJeremy L Thompson This Ceed context will be destroyed if `ceed_copy` is the only reference to this Ceed context. 9179560d06aSjeremylt 918ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to copy reference to 919ea61e9acSJeremy L Thompson @param[in,out] ceed_copy Variable to store copied reference 9209560d06aSjeremylt 9219560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 9229560d06aSjeremylt 9239560d06aSjeremylt @ref User 9249560d06aSjeremylt **/ 9259560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) { 9262b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 9272b730f8bSJeremy L Thompson CeedCall(CeedDestroy(ceed_copy)); 9289560d06aSjeremylt *ceed_copy = ceed; 9299560d06aSjeremylt return CEED_ERROR_SUCCESS; 9309560d06aSjeremylt } 9319560d06aSjeremylt 9329560d06aSjeremylt /** 9337a982d89SJeremy L. Thompson @brief Get the full resource name for a Ceed context 9342f86a920SJeremy L Thompson 935ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get resource name of 9367a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 9372f86a920SJeremy L Thompson 9382f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9392f86a920SJeremy L Thompson 9407a982d89SJeremy L. Thompson @ref User 9415107b09fSJeremy L Thompson **/ 9427a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 9437a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 944e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9455107b09fSJeremy L Thompson } 9465107b09fSJeremy L Thompson 9475107b09fSJeremy L Thompson /** 948d79b80ecSjeremylt @brief Return Ceed context preferred memory type 949c907536fSjeremylt 950ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get preferred memory type of 951d1d35e2fSjeremylt @param[out] mem_type Address to save preferred memory type to 952c907536fSjeremylt 953c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 954c907536fSjeremylt 9557a982d89SJeremy L. Thompson @ref User 956c907536fSjeremylt **/ 957d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) { 958c907536fSjeremylt if (ceed->GetPreferredMemType) { 9592b730f8bSJeremy L Thompson CeedCall(ceed->GetPreferredMemType(mem_type)); 960c907536fSjeremylt } else { 961c263cd57Sjeremylt Ceed delegate; 9622b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, &delegate)); 963c263cd57Sjeremylt 964c263cd57Sjeremylt if (delegate) { 9652b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(delegate, mem_type)); 966c263cd57Sjeremylt } else { 967d1d35e2fSjeremylt *mem_type = CEED_MEM_HOST; 968c907536fSjeremylt } 969c263cd57Sjeremylt } 970e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 971c907536fSjeremylt } 972c907536fSjeremylt 973c907536fSjeremylt /** 9749525855cSJeremy L Thompson @brief Get deterministic status of Ceed 9759525855cSJeremy L Thompson 9769525855cSJeremy L Thompson @param[in] ceed Ceed 977d1d35e2fSjeremylt @param[out] is_deterministic Variable to store deterministic status 9789525855cSJeremy L Thompson 9799525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9809525855cSJeremy L Thompson 9819525855cSJeremy L Thompson @ref User 9829525855cSJeremy L Thompson **/ 983d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) { 984d1d35e2fSjeremylt *is_deterministic = ceed->is_deterministic; 985e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9869525855cSJeremy L Thompson } 9879525855cSJeremy L Thompson 9889525855cSJeremy L Thompson /** 989ee5a26f2SJeremy L Thompson @brief Set additional JiT source root for Ceed 990ee5a26f2SJeremy L Thompson 991ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed 992ee5a26f2SJeremy L Thompson @param[in] jit_source_root Absolute path to additional JiT source directory 993ee5a26f2SJeremy L Thompson 994ee5a26f2SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 995ee5a26f2SJeremy L Thompson 996ee5a26f2SJeremy L Thompson @ref User 997ee5a26f2SJeremy L Thompson **/ 998ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) { 9996155f12fSJeremy L Thompson Ceed ceed_parent; 1000ee5a26f2SJeremy L Thompson 10012b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 10026155f12fSJeremy L Thompson 10036155f12fSJeremy L Thompson CeedInt index = ceed_parent->num_jit_source_roots; 1004ee5a26f2SJeremy L Thompson size_t path_length = strlen(jit_source_root); 10052b730f8bSJeremy L Thompson CeedCall(CeedRealloc(index + 1, &ceed_parent->jit_source_roots)); 10062b730f8bSJeremy L Thompson CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index])); 1007d602d780SJeremy L Thompson memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length); 10086155f12fSJeremy L Thompson ceed_parent->num_jit_source_roots++; 1009ee5a26f2SJeremy L Thompson 1010ee5a26f2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1011ee5a26f2SJeremy L Thompson } 1012ee5a26f2SJeremy L Thompson 1013ee5a26f2SJeremy L Thompson /** 10140a0da059Sjeremylt @brief View a Ceed 10150a0da059Sjeremylt 10160a0da059Sjeremylt @param[in] ceed Ceed to view 10170a0da059Sjeremylt @param[in] stream Filestream to write to 10180a0da059Sjeremylt 10190a0da059Sjeremylt @return An error code: 0 - success, otherwise - failure 10200a0da059Sjeremylt 10210a0da059Sjeremylt @ref User 10220a0da059Sjeremylt **/ 10230a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) { 1024d1d35e2fSjeremylt CeedMemType mem_type; 10250a0da059Sjeremylt 10262b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 10270a0da059Sjeremylt 10282b730f8bSJeremy L Thompson fprintf(stream, 10292b730f8bSJeremy L Thompson "Ceed\n" 10300a0da059Sjeremylt " Ceed Resource: %s\n" 10310a0da059Sjeremylt " Preferred MemType: %s\n", 1032d1d35e2fSjeremylt ceed->resource, CeedMemTypes[mem_type]); 1033e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 10340a0da059Sjeremylt } 10350a0da059Sjeremylt 10360a0da059Sjeremylt /** 1037b11c1e72Sjeremylt @brief Destroy a Ceed context 1038d7b241e6Sjeremylt 1039ea61e9acSJeremy L Thompson @param[in,out] ceed Address of Ceed context to destroy 1040b11c1e72Sjeremylt 1041b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1042dfdf5a53Sjeremylt 10437a982d89SJeremy L. Thompson @ref User 1044b11c1e72Sjeremylt **/ 1045d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 1046ad6481ceSJeremy L Thompson if (!*ceed || --(*ceed)->ref_count > 0) { 1047ad6481ceSJeremy L Thompson *ceed = NULL; 1048ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1049ad6481ceSJeremy L Thompson } 10502b730f8bSJeremy L Thompson if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate)); 10510ace9bf2Sjeremylt 1052d1d35e2fSjeremylt if ((*ceed)->obj_delegate_count > 0) { 105392ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) { 10542b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate))); 10552b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name)); 1056aefd8378Sjeremylt } 10572b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates)); 1058aefd8378Sjeremylt } 10590ace9bf2Sjeremylt 10602b730f8bSJeremy L Thompson if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed)); 10610ace9bf2Sjeremylt 106292ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) { 10632b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots[i])); 1064032e71eaSJeremy L Thompson } 10652b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots)); 1066032e71eaSJeremy L Thompson 10672b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->f_offsets)); 10682b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->resource)); 10692b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed)); 10702b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->op_fallback_resource)); 10712b730f8bSJeremy L Thompson CeedCall(CeedFree(ceed)); 1072e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1073d7b241e6Sjeremylt } 1074d7b241e6Sjeremylt 1075f9982c62SWill Pazner // LCOV_EXCL_START 1076f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) { 10772b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args); 10782b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorFormat(ceed->op_fallback_parent, format, args); 107978464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 108078464608Sjeremylt vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args); // NOLINT 1081d1d35e2fSjeremylt return ceed->err_msg; 1082f9982c62SWill Pazner } 1083f9982c62SWill Pazner // LCOV_EXCL_STOP 1084f9982c62SWill Pazner 10857a982d89SJeremy L. Thompson /** 10867a982d89SJeremy L. Thompson @brief Error handling implementation; use \ref CeedError instead. 10877a982d89SJeremy L. Thompson 10887a982d89SJeremy L. Thompson @ref Developer 10897a982d89SJeremy L. Thompson **/ 10902b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) { 10917a982d89SJeremy L. Thompson va_list args; 1092d1d35e2fSjeremylt int ret_val; 10937a982d89SJeremy L. Thompson va_start(args, format); 10947a982d89SJeremy L. Thompson if (ceed) { 1095d1d35e2fSjeremylt ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args); 10967a982d89SJeremy L. Thompson } else { 1097b0d62198Sjeremylt // LCOV_EXCL_START 1098477729cfSJeremy L Thompson const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 10992b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 11002b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "return")) ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args); 1101477729cfSJeremy L Thompson else 1102477729cfSJeremy L Thompson // This function will not return 1103d1d35e2fSjeremylt ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args); 11047a982d89SJeremy L. Thompson } 11057a982d89SJeremy L. Thompson va_end(args); 1106d1d35e2fSjeremylt return ret_val; 1107b0d62198Sjeremylt // LCOV_EXCL_STOP 11087a982d89SJeremy L. Thompson } 11097a982d89SJeremy L. Thompson 1110477729cfSJeremy L Thompson /** 1111477729cfSJeremy L Thompson @brief Error handler that returns without printing anything. 1112477729cfSJeremy L Thompson 1113477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1114477729cfSJeremy L Thompson 1115477729cfSJeremy L Thompson @ref Developer 1116477729cfSJeremy L Thompson **/ 1117477729cfSJeremy L Thompson // LCOV_EXCL_START 11182b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1119d1d35e2fSjeremylt return err_code; 1120477729cfSJeremy L Thompson } 1121477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1122477729cfSJeremy L Thompson 1123477729cfSJeremy L Thompson /** 1124ea61e9acSJeremy L Thompson @brief Error handler that stores the error message for future use and returns the error. 1125477729cfSJeremy L Thompson 1126477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1127477729cfSJeremy L Thompson 1128477729cfSJeremy L Thompson @ref Developer 1129477729cfSJeremy L Thompson **/ 1130477729cfSJeremy L Thompson // LCOV_EXCL_START 11312b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 11322b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args); 11332b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorStore(ceed->op_fallback_parent, filename, line_no, func, err_code, format, args); 1134477729cfSJeremy L Thompson 1135477729cfSJeremy L Thompson // Build message 1136990fdeb6SJeremy L Thompson int len; 11372b730f8bSJeremy L Thompson len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%s:%d in %s(): ", filename, line_no, func); 113878464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 113978464608Sjeremylt vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args); // NOLINT 1140d1d35e2fSjeremylt return err_code; 1141477729cfSJeremy L Thompson } 1142477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1143477729cfSJeremy L Thompson 1144477729cfSJeremy L Thompson /** 1145477729cfSJeremy L Thompson @brief Error handler that prints to stderr and aborts 1146477729cfSJeremy L Thompson 1147477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1148477729cfSJeremy L Thompson 1149477729cfSJeremy L Thompson @ref Developer 1150477729cfSJeremy L Thompson **/ 1151477729cfSJeremy L Thompson // LCOV_EXCL_START 11522b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1153d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 1154f9982c62SWill Pazner vfprintf(stderr, format, *args); 1155477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1156477729cfSJeremy L Thompson abort(); 1157d1d35e2fSjeremylt return err_code; 1158477729cfSJeremy L Thompson } 1159477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1160477729cfSJeremy L Thompson 1161477729cfSJeremy L Thompson /** 1162477729cfSJeremy L Thompson @brief Error handler that prints to stderr and exits 1163477729cfSJeremy L Thompson 1164477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1165477729cfSJeremy L Thompson 1166ea61e9acSJeremy L Thompson In contrast to CeedErrorAbort(), this exits without a signal, so atexit() handlers (e.g., as used by gcov) are run. 1167477729cfSJeremy L Thompson 1168477729cfSJeremy L Thompson @ref Developer 1169477729cfSJeremy L Thompson **/ 11702b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1171d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 117278464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 117378464608Sjeremylt vfprintf(stderr, format, *args); // NOLINT 1174477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1175d1d35e2fSjeremylt exit(err_code); 1176d1d35e2fSjeremylt return err_code; 1177477729cfSJeremy L Thompson } 1178477729cfSJeremy L Thompson 1179477729cfSJeremy L Thompson /** 1180477729cfSJeremy L Thompson @brief Set error handler 1181477729cfSJeremy L Thompson 1182ea61e9acSJeremy L Thompson A default error handler is set in CeedInit(). 1183ea61e9acSJeremy L Thompson Use this function to change the error handler to CeedErrorReturn(), CeedErrorAbort(), or a user-defined error handler. 1184477729cfSJeremy L Thompson 1185477729cfSJeremy L Thompson @ref Developer 1186477729cfSJeremy L Thompson **/ 1187d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) { 1188d1d35e2fSjeremylt ceed->Error = handler; 1189d1d35e2fSjeremylt if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler); 11902b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler); 1191e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1192477729cfSJeremy L Thompson } 1193477729cfSJeremy L Thompson 1194477729cfSJeremy L Thompson /** 1195477729cfSJeremy L Thompson @brief Get error message 1196477729cfSJeremy L Thompson 1197ea61e9acSJeremy L Thompson The error message is only stored when using the error handler CeedErrorStore() 1198477729cfSJeremy L Thompson 1199ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve error message 1200d1d35e2fSjeremylt @param[out] err_msg Char pointer to hold error message 1201477729cfSJeremy L Thompson 1202477729cfSJeremy L Thompson @ref Developer 1203477729cfSJeremy L Thompson **/ 1204d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) { 12052b730f8bSJeremy L Thompson if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg); 12062b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedGetErrorMessage(ceed->op_fallback_parent, err_msg); 1207d1d35e2fSjeremylt *err_msg = ceed->err_msg; 1208e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1209477729cfSJeremy L Thompson } 1210477729cfSJeremy L Thompson 1211477729cfSJeremy L Thompson /** 1212477729cfSJeremy L Thompson @brief Restore error message 1213477729cfSJeremy L Thompson 1214ea61e9acSJeremy L Thompson The error message is only stored when using the error handler CeedErrorStore() 1215477729cfSJeremy L Thompson 1216ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to restore error message 1217d1d35e2fSjeremylt @param[out] err_msg Char pointer that holds error message 1218477729cfSJeremy L Thompson 1219477729cfSJeremy L Thompson @ref Developer 1220477729cfSJeremy L Thompson **/ 1221d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) { 12222b730f8bSJeremy L Thompson if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg); 12232b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedResetErrorMessage(ceed->op_fallback_parent, err_msg); 1224d1d35e2fSjeremylt *err_msg = NULL; 1225d1d35e2fSjeremylt memcpy(ceed->err_msg, "No error message stored", 24); 1226e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1227477729cfSJeremy L Thompson } 1228477729cfSJeremy L Thompson 12291070991dSJed Brown /** 12301070991dSJed Brown @brief Get libCEED library version info 12311070991dSJed Brown 1232ea61e9acSJeremy L Thompson libCEED version numbers have the form major.minor.patch. 1233ea61e9acSJeremy L Thompson Non-release versions may contain unstable interfaces. 12341070991dSJed Brown 12351070991dSJed Brown @param[out] major Major version of the library 12361070991dSJed Brown @param[out] minor Minor version of the library 12371070991dSJed Brown @param[out] patch Patch (subminor) version of the library 12381070991dSJed Brown @param[out] release True for releases; false for development branches. 12391070991dSJed Brown 12401070991dSJed Brown The caller may pass NULL for any arguments that are not needed. 12411070991dSJed Brown 12421070991dSJed Brown @sa CEED_VERSION_GE() 12431070991dSJed Brown 12441070991dSJed Brown @ref Developer 12451070991dSJed Brown */ 12461070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) { 12471070991dSJed Brown if (major) *major = CEED_VERSION_MAJOR; 12481070991dSJed Brown if (minor) *minor = CEED_VERSION_MINOR; 12491070991dSJed Brown if (patch) *patch = CEED_VERSION_PATCH; 12501070991dSJed Brown if (release) *release = CEED_VERSION_RELEASE; 12511070991dSJed Brown return 0; 12521070991dSJed Brown } 12531070991dSJed Brown 125480a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) { 125580a9ef05SNatalie Beams *scalar_type = CEED_SCALAR_TYPE; 125680a9ef05SNatalie Beams return 0; 125780a9ef05SNatalie Beams } 125880a9ef05SNatalie Beams 1259d7b241e6Sjeremylt /// @} 1260