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 **/ 466*ca735530SJeremy L Thompson int CeedGetOperatorfallback_resource(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 494*ca735530SJeremy L Thompson CeedCall(CeedGetOperatorfallback_resource(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), 7916e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 7926e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 7936e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 79450c301a5SRezgar Shakeri CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv), 795c4e3f59bSSebastian Grimberg CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl), 7966e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 7976e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 798777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate), 7996e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 8006e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 8019c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasValidArray), 8029c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType), 8036e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 8046a6c615bSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, TakeArray), 8056e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 806f48ed27dSnbeams CEED_FTABLE_ENTRY(CeedVector, SyncArray), 8076e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 8086e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 8099c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite), 8106e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 8116e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 812547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 813e0dd3b27Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Scale), 8140f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, AXPY), 8155fb68f37SKaren (Ren) Stengel CEED_FTABLE_ENTRY(CeedVector, AXPBY), 8160f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, PointwiseMult), 817d99fa3c5SJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, Reciprocal), 8186e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 8196e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 820f30b1135SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnsigned), 8217c1dbaffSSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnoriented), 8226e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 823bd33150aSjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets), 82477d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetOrientations), 82577d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetCurlOrientations), 8266e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 8276e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 828c8c3fa7dSJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAtPoints), 8296e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 8306e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 8316e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 8326e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 8338c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction), 8348c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction), 8356e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 8369c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData), 8379c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType), 838777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData), 839891038deSjeremylt CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData), 840777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData), 84128bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead), 842777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData), 84328bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead), 8442e64a2b9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy), 845777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy), 84680ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction), 84770a7ffb3SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate), 84880ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal), 8499e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal), 85080ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal), 8519e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal), 852e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic), 853e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble), 854cefa2673SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle), 855713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 8566e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 857250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 858cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 859250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 8606e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 8616e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 8626e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 8631dfeef1dSjeremylt }; 864fe2413ffSjeremylt 8652b730f8bSJeremy L Thompson CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets)); 866d1d35e2fSjeremylt memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets)); 867fe2413ffSjeremylt 8685107b09fSJeremy L Thompson // Set fallback for advanced CeedOperator functions 869*ca735530SJeremy L Thompson const char fallback_resource[] = ""; 870*ca735530SJeremy L Thompson CeedCall(CeedSetOperatorFallbackResource(*ceed, fallback_resource)); 8715107b09fSJeremy L Thompson 87260f9e2d6SJeremy L Thompson // Record env variables CEED_DEBUG or DBG 8731c66c397SJeremy L Thompson (*ceed)->is_debug = getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); 87460f9e2d6SJeremy L Thompson 87522e44211Sjeremylt // Copy resource prefix, if backend setup successful 8762b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource)); 877ee5a26f2SJeremy L Thompson 878ee5a26f2SJeremy L Thompson // Set default JiT source root 879ea61e9acSJeremy L Thompson // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent 8802b730f8bSJeremy L Thompson CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault)); 881ee5a26f2SJeremy L Thompson 882d04bbc78SJeremy L Thompson // Backend specific setup 8832b730f8bSJeremy L Thompson CeedCall(backends[match_index].init(&resource[match_help], *ceed)); 884d04bbc78SJeremy L Thompson 885e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 886d7b241e6Sjeremylt } 887d7b241e6Sjeremylt 888d7b241e6Sjeremylt /** 8895ae360d4SJeremy L Thompson @brief Set the GPU stream for a Ceed context 8905ae360d4SJeremy L Thompson 8915ae360d4SJeremy L Thompson @param[in,out] ceed Ceed context to set the stream 8925ae360d4SJeremy L Thompson @param[in] handle Handle to GPU stream 8935ae360d4SJeremy L Thompson 8945ae360d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 8955ae360d4SJeremy L Thompson 8965ae360d4SJeremy L Thompson @ref User 8975ae360d4SJeremy L Thompson **/ 8985ae360d4SJeremy L Thompson int CeedSetStream(Ceed ceed, void *handle) { 8995ae360d4SJeremy L Thompson CeedCheck(handle, ceed, CEED_ERROR_INCOMPATIBLE, "Stream handle must be non-null"); 9009ffb25e0SJames Wright if (ceed->SetStream) { 9015ae360d4SJeremy L Thompson CeedCall(ceed->SetStream(ceed, handle)); 9029ffb25e0SJames Wright } else { 9039ffb25e0SJames Wright Ceed delegate; 9049ffb25e0SJames Wright CeedCall(CeedGetDelegate(ceed, &delegate)); 9055ae360d4SJeremy L Thompson 90628ce3d2aSJeremy L Thompson if (delegate) CeedCall(CeedSetStream(delegate, handle)); 90728ce3d2aSJeremy L Thompson else return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support setting stream"); 9089ffb25e0SJames Wright } 9095ae360d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 9105ae360d4SJeremy L Thompson } 9115ae360d4SJeremy L Thompson 9125ae360d4SJeremy L Thompson /** 913ea61e9acSJeremy L Thompson @brief Copy the pointer to a Ceed context. 9144385fb7fSSebastian Grimberg 915512bb800SJeremy L Thompson Both pointers should be destroyed with `CeedDestroy()`. 916512bb800SJeremy L Thompson 917512bb800SJeremy 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. 918512bb800SJeremy L Thompson This Ceed context will be destroyed if `ceed_copy` is the only reference to this Ceed context. 9199560d06aSjeremylt 920ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to copy reference to 921ea61e9acSJeremy L Thompson @param[in,out] ceed_copy Variable to store copied reference 9229560d06aSjeremylt 9239560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 9249560d06aSjeremylt 9259560d06aSjeremylt @ref User 9269560d06aSjeremylt **/ 9279560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) { 9282b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 9292b730f8bSJeremy L Thompson CeedCall(CeedDestroy(ceed_copy)); 9309560d06aSjeremylt *ceed_copy = ceed; 9319560d06aSjeremylt return CEED_ERROR_SUCCESS; 9329560d06aSjeremylt } 9339560d06aSjeremylt 9349560d06aSjeremylt /** 9357a982d89SJeremy L. Thompson @brief Get the full resource name for a Ceed context 9362f86a920SJeremy L Thompson 937ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get resource name of 9387a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 9392f86a920SJeremy L Thompson 9402f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9412f86a920SJeremy L Thompson 9427a982d89SJeremy L. Thompson @ref User 9435107b09fSJeremy L Thompson **/ 9447a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 9457a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 946e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9475107b09fSJeremy L Thompson } 9485107b09fSJeremy L Thompson 9495107b09fSJeremy L Thompson /** 950d79b80ecSjeremylt @brief Return Ceed context preferred memory type 951c907536fSjeremylt 952ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to get preferred memory type of 953d1d35e2fSjeremylt @param[out] mem_type Address to save preferred memory type to 954c907536fSjeremylt 955c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 956c907536fSjeremylt 9577a982d89SJeremy L. Thompson @ref User 958c907536fSjeremylt **/ 959d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) { 960c907536fSjeremylt if (ceed->GetPreferredMemType) { 9612b730f8bSJeremy L Thompson CeedCall(ceed->GetPreferredMemType(mem_type)); 962c907536fSjeremylt } else { 963c263cd57Sjeremylt Ceed delegate; 9642b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, &delegate)); 965c263cd57Sjeremylt 966c263cd57Sjeremylt if (delegate) { 9672b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(delegate, mem_type)); 968c263cd57Sjeremylt } else { 969d1d35e2fSjeremylt *mem_type = CEED_MEM_HOST; 970c907536fSjeremylt } 971c263cd57Sjeremylt } 972e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 973c907536fSjeremylt } 974c907536fSjeremylt 975c907536fSjeremylt /** 9769525855cSJeremy L Thompson @brief Get deterministic status of Ceed 9779525855cSJeremy L Thompson 9789525855cSJeremy L Thompson @param[in] ceed Ceed 979d1d35e2fSjeremylt @param[out] is_deterministic Variable to store deterministic status 9809525855cSJeremy L Thompson 9819525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9829525855cSJeremy L Thompson 9839525855cSJeremy L Thompson @ref User 9849525855cSJeremy L Thompson **/ 985d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) { 986d1d35e2fSjeremylt *is_deterministic = ceed->is_deterministic; 987e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9889525855cSJeremy L Thompson } 9899525855cSJeremy L Thompson 9909525855cSJeremy L Thompson /** 991ee5a26f2SJeremy L Thompson @brief Set additional JiT source root for Ceed 992ee5a26f2SJeremy L Thompson 993ea61e9acSJeremy L Thompson @param[in,out] ceed Ceed 994ee5a26f2SJeremy L Thompson @param[in] jit_source_root Absolute path to additional JiT source directory 995ee5a26f2SJeremy L Thompson 996ee5a26f2SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 997ee5a26f2SJeremy L Thompson 998ee5a26f2SJeremy L Thompson @ref User 999ee5a26f2SJeremy L Thompson **/ 1000ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) { 10016155f12fSJeremy L Thompson Ceed ceed_parent; 1002ee5a26f2SJeremy L Thompson 10032b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 10046155f12fSJeremy L Thompson 10056155f12fSJeremy L Thompson CeedInt index = ceed_parent->num_jit_source_roots; 1006ee5a26f2SJeremy L Thompson size_t path_length = strlen(jit_source_root); 10071c66c397SJeremy L Thompson 10082b730f8bSJeremy L Thompson CeedCall(CeedRealloc(index + 1, &ceed_parent->jit_source_roots)); 10092b730f8bSJeremy L Thompson CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index])); 1010d602d780SJeremy L Thompson memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length); 10116155f12fSJeremy L Thompson ceed_parent->num_jit_source_roots++; 1012ee5a26f2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1013ee5a26f2SJeremy L Thompson } 1014ee5a26f2SJeremy L Thompson 1015ee5a26f2SJeremy L Thompson /** 10160a0da059Sjeremylt @brief View a Ceed 10170a0da059Sjeremylt 10180a0da059Sjeremylt @param[in] ceed Ceed to view 10190a0da059Sjeremylt @param[in] stream Filestream to write to 10200a0da059Sjeremylt 10210a0da059Sjeremylt @return An error code: 0 - success, otherwise - failure 10220a0da059Sjeremylt 10230a0da059Sjeremylt @ref User 10240a0da059Sjeremylt **/ 10250a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) { 1026d1d35e2fSjeremylt CeedMemType mem_type; 10270a0da059Sjeremylt 10282b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 10290a0da059Sjeremylt 10302b730f8bSJeremy L Thompson fprintf(stream, 10312b730f8bSJeremy L Thompson "Ceed\n" 10320a0da059Sjeremylt " Ceed Resource: %s\n" 10330a0da059Sjeremylt " Preferred MemType: %s\n", 1034d1d35e2fSjeremylt ceed->resource, CeedMemTypes[mem_type]); 1035e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 10360a0da059Sjeremylt } 10370a0da059Sjeremylt 10380a0da059Sjeremylt /** 1039b11c1e72Sjeremylt @brief Destroy a Ceed context 1040d7b241e6Sjeremylt 1041ea61e9acSJeremy L Thompson @param[in,out] ceed Address of Ceed context to destroy 1042b11c1e72Sjeremylt 1043b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1044dfdf5a53Sjeremylt 10457a982d89SJeremy L. Thompson @ref User 1046b11c1e72Sjeremylt **/ 1047d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 1048ad6481ceSJeremy L Thompson if (!*ceed || --(*ceed)->ref_count > 0) { 1049ad6481ceSJeremy L Thompson *ceed = NULL; 1050ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1051ad6481ceSJeremy L Thompson } 10522b730f8bSJeremy L Thompson if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate)); 10530ace9bf2Sjeremylt 1054d1d35e2fSjeremylt if ((*ceed)->obj_delegate_count > 0) { 105592ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) { 10562b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate))); 10572b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name)); 1058aefd8378Sjeremylt } 10592b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates)); 1060aefd8378Sjeremylt } 10610ace9bf2Sjeremylt 10622b730f8bSJeremy L Thompson if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed)); 10630ace9bf2Sjeremylt 106492ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) { 10652b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots[i])); 1066032e71eaSJeremy L Thompson } 10672b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots)); 1068032e71eaSJeremy L Thompson 10692b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->f_offsets)); 10702b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->resource)); 10712b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed)); 10722b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->op_fallback_resource)); 10732b730f8bSJeremy L Thompson CeedCall(CeedFree(ceed)); 1074e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1075d7b241e6Sjeremylt } 1076d7b241e6Sjeremylt 1077f9982c62SWill Pazner // LCOV_EXCL_START 1078f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) { 10792b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args); 10802b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorFormat(ceed->op_fallback_parent, format, args); 108178464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 108278464608Sjeremylt vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args); // NOLINT 1083d1d35e2fSjeremylt return ceed->err_msg; 1084f9982c62SWill Pazner } 1085f9982c62SWill Pazner // LCOV_EXCL_STOP 1086f9982c62SWill Pazner 10877a982d89SJeremy L. Thompson /** 10887a982d89SJeremy L. Thompson @brief Error handling implementation; use \ref CeedError instead. 10897a982d89SJeremy L. Thompson 10907a982d89SJeremy L. Thompson @ref Developer 10917a982d89SJeremy L. Thompson **/ 10922b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) { 10937a982d89SJeremy L. Thompson va_list args; 1094d1d35e2fSjeremylt int ret_val; 10951c66c397SJeremy L Thompson 10967a982d89SJeremy L. Thompson va_start(args, format); 10977a982d89SJeremy L. Thompson if (ceed) { 1098d1d35e2fSjeremylt ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args); 10997a982d89SJeremy L. Thompson } else { 1100b0d62198Sjeremylt // LCOV_EXCL_START 1101477729cfSJeremy L Thompson const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 11022b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 11032b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "return")) ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args); 1104477729cfSJeremy L Thompson else 1105477729cfSJeremy L Thompson // This function will not return 1106d1d35e2fSjeremylt ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args); 11077a982d89SJeremy L. Thompson } 11087a982d89SJeremy L. Thompson va_end(args); 1109d1d35e2fSjeremylt return ret_val; 1110b0d62198Sjeremylt // LCOV_EXCL_STOP 11117a982d89SJeremy L. Thompson } 11127a982d89SJeremy L. Thompson 1113477729cfSJeremy L Thompson /** 1114477729cfSJeremy L Thompson @brief Error handler that returns without printing anything. 1115477729cfSJeremy L Thompson 1116477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1117477729cfSJeremy L Thompson 1118477729cfSJeremy L Thompson @ref Developer 1119477729cfSJeremy L Thompson **/ 1120477729cfSJeremy L Thompson // LCOV_EXCL_START 11212b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1122d1d35e2fSjeremylt return err_code; 1123477729cfSJeremy L Thompson } 1124477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1125477729cfSJeremy L Thompson 1126477729cfSJeremy L Thompson /** 1127ea61e9acSJeremy L Thompson @brief Error handler that stores the error message for future use and returns the error. 1128477729cfSJeremy L Thompson 1129477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1130477729cfSJeremy L Thompson 1131477729cfSJeremy L Thompson @ref Developer 1132477729cfSJeremy L Thompson **/ 1133477729cfSJeremy L Thompson // LCOV_EXCL_START 11342b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 11352b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args); 11362b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorStore(ceed->op_fallback_parent, filename, line_no, func, err_code, format, args); 1137477729cfSJeremy L Thompson 1138477729cfSJeremy L Thompson // Build message 11391c66c397SJeremy L Thompson int len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%s:%d in %s(): ", filename, line_no, func); 114078464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 114178464608Sjeremylt vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args); // NOLINT 1142d1d35e2fSjeremylt return err_code; 1143477729cfSJeremy L Thompson } 1144477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1145477729cfSJeremy L Thompson 1146477729cfSJeremy L Thompson /** 1147477729cfSJeremy L Thompson @brief Error handler that prints to stderr and aborts 1148477729cfSJeremy L Thompson 1149477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1150477729cfSJeremy L Thompson 1151477729cfSJeremy L Thompson @ref Developer 1152477729cfSJeremy L Thompson **/ 1153477729cfSJeremy L Thompson // LCOV_EXCL_START 11542b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1155d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 1156f9982c62SWill Pazner vfprintf(stderr, format, *args); 1157477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1158477729cfSJeremy L Thompson abort(); 1159d1d35e2fSjeremylt return err_code; 1160477729cfSJeremy L Thompson } 1161477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1162477729cfSJeremy L Thompson 1163477729cfSJeremy L Thompson /** 1164477729cfSJeremy L Thompson @brief Error handler that prints to stderr and exits 1165477729cfSJeremy L Thompson 1166477729cfSJeremy L Thompson Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 1167477729cfSJeremy L Thompson 1168ea61e9acSJeremy L Thompson In contrast to CeedErrorAbort(), this exits without a signal, so atexit() handlers (e.g., as used by gcov) are run. 1169477729cfSJeremy L Thompson 1170477729cfSJeremy L Thompson @ref Developer 1171477729cfSJeremy L Thompson **/ 11722b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1173d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 117478464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 117578464608Sjeremylt vfprintf(stderr, format, *args); // NOLINT 1176477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1177d1d35e2fSjeremylt exit(err_code); 1178d1d35e2fSjeremylt return err_code; 1179477729cfSJeremy L Thompson } 1180477729cfSJeremy L Thompson 1181477729cfSJeremy L Thompson /** 1182477729cfSJeremy L Thompson @brief Set error handler 1183477729cfSJeremy L Thompson 1184ea61e9acSJeremy L Thompson A default error handler is set in CeedInit(). 1185ea61e9acSJeremy L Thompson Use this function to change the error handler to CeedErrorReturn(), CeedErrorAbort(), or a user-defined error handler. 1186477729cfSJeremy L Thompson 1187477729cfSJeremy L Thompson @ref Developer 1188477729cfSJeremy L Thompson **/ 1189d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) { 1190d1d35e2fSjeremylt ceed->Error = handler; 1191d1d35e2fSjeremylt if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler); 11922b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler); 1193e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1194477729cfSJeremy L Thompson } 1195477729cfSJeremy L Thompson 1196477729cfSJeremy L Thompson /** 1197477729cfSJeremy L Thompson @brief Get error message 1198477729cfSJeremy L Thompson 1199ea61e9acSJeremy L Thompson The error message is only stored when using the error handler CeedErrorStore() 1200477729cfSJeremy L Thompson 1201ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to retrieve error message 1202d1d35e2fSjeremylt @param[out] err_msg Char pointer to hold error message 1203477729cfSJeremy L Thompson 1204477729cfSJeremy L Thompson @ref Developer 1205477729cfSJeremy L Thompson **/ 1206d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) { 12072b730f8bSJeremy L Thompson if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg); 12082b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedGetErrorMessage(ceed->op_fallback_parent, err_msg); 1209d1d35e2fSjeremylt *err_msg = ceed->err_msg; 1210e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1211477729cfSJeremy L Thompson } 1212477729cfSJeremy L Thompson 1213477729cfSJeremy L Thompson /** 1214477729cfSJeremy L Thompson @brief Restore error message 1215477729cfSJeremy L Thompson 1216ea61e9acSJeremy L Thompson The error message is only stored when using the error handler CeedErrorStore() 1217477729cfSJeremy L Thompson 1218ea61e9acSJeremy L Thompson @param[in] ceed Ceed context to restore error message 1219d1d35e2fSjeremylt @param[out] err_msg Char pointer that holds error message 1220477729cfSJeremy L Thompson 1221477729cfSJeremy L Thompson @ref Developer 1222477729cfSJeremy L Thompson **/ 1223d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) { 12242b730f8bSJeremy L Thompson if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg); 12252b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedResetErrorMessage(ceed->op_fallback_parent, err_msg); 1226d1d35e2fSjeremylt *err_msg = NULL; 1227d1d35e2fSjeremylt memcpy(ceed->err_msg, "No error message stored", 24); 1228e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1229477729cfSJeremy L Thompson } 1230477729cfSJeremy L Thompson 12311070991dSJed Brown /** 12321070991dSJed Brown @brief Get libCEED library version info 12331070991dSJed Brown 1234ea61e9acSJeremy L Thompson libCEED version numbers have the form major.minor.patch. 1235ea61e9acSJeremy L Thompson Non-release versions may contain unstable interfaces. 12361070991dSJed Brown 12371070991dSJed Brown @param[out] major Major version of the library 12381070991dSJed Brown @param[out] minor Minor version of the library 12391070991dSJed Brown @param[out] patch Patch (subminor) version of the library 12401070991dSJed Brown @param[out] release True for releases; false for development branches. 12411070991dSJed Brown 12421070991dSJed Brown The caller may pass NULL for any arguments that are not needed. 12431070991dSJed Brown 12441070991dSJed Brown @sa CEED_VERSION_GE() 12451070991dSJed Brown 12461070991dSJed Brown @ref Developer 12471070991dSJed Brown */ 12481070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) { 12491070991dSJed Brown if (major) *major = CEED_VERSION_MAJOR; 12501070991dSJed Brown if (minor) *minor = CEED_VERSION_MINOR; 12511070991dSJed Brown if (patch) *patch = CEED_VERSION_PATCH; 12521070991dSJed Brown if (release) *release = CEED_VERSION_RELEASE; 12531070991dSJed Brown return 0; 12541070991dSJed Brown } 12551070991dSJed Brown 125680a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) { 125780a9ef05SNatalie Beams *scalar_type = CEED_SCALAR_TYPE; 125880a9ef05SNatalie Beams return 0; 125980a9ef05SNatalie Beams } 126080a9ef05SNatalie Beams 1261d7b241e6Sjeremylt /// @} 1262