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