15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, 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 31eaae1aeaSJames Wright #define CEED_FTABLE_ENTRY(class, method) {#class #method, offsetof(struct class##_private, method)} 32d7b241e6Sjeremylt /// @endcond 33d7b241e6Sjeremylt 34d7b241e6Sjeremylt /// @file 35d7b241e6Sjeremylt /// Implementation of core components of Ceed library 367a982d89SJeremy L. Thompson 377a982d89SJeremy L. Thompson /// @addtogroup CeedUser 38d7b241e6Sjeremylt /// @{ 39d7b241e6Sjeremylt 40dfdf5a53Sjeremylt /** 41dfdf5a53Sjeremylt @brief Request immediate completion 42dfdf5a53Sjeremylt 43ca94c3ddSJeremy 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. 44ca94c3ddSJeremy L Thompson The code 45dfdf5a53Sjeremylt 46dfdf5a53Sjeremylt @code 47dfdf5a53Sjeremylt CeedOperatorApply(op, ..., CEED_REQUEST_IMMEDIATE); 48dfdf5a53Sjeremylt @endcode 49dfdf5a53Sjeremylt 50dfdf5a53Sjeremylt is semantically equivalent to 51dfdf5a53Sjeremylt 52dfdf5a53Sjeremylt @code 53dfdf5a53Sjeremylt CeedRequest request; 54dfdf5a53Sjeremylt CeedOperatorApply(op, ..., &request); 55dfdf5a53Sjeremylt CeedRequestWait(&request); 56dfdf5a53Sjeremylt @endcode 57dfdf5a53Sjeremylt 58dfdf5a53Sjeremylt @sa CEED_REQUEST_ORDERED 59dfdf5a53Sjeremylt **/ 60d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_IMMEDIATE = &ceed_request_immediate; 61d7b241e6Sjeremylt 62d7b241e6Sjeremylt /** 63b11c1e72Sjeremylt @brief Request ordered completion 64d7b241e6Sjeremylt 65ca94c3ddSJeremy 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. 66ca94c3ddSJeremy L Thompson It is typically used in a construct such as: 67d7b241e6Sjeremylt 68d7b241e6Sjeremylt @code 69d7b241e6Sjeremylt CeedRequest request; 70d7b241e6Sjeremylt CeedOperatorApply(op1, ..., CEED_REQUEST_ORDERED); 71d7b241e6Sjeremylt CeedOperatorApply(op2, ..., &request); 72d7b241e6Sjeremylt // other optional work 738b2d6f4aSMatthew Knepley CeedRequestWait(&request); 74d7b241e6Sjeremylt @endcode 75d7b241e6Sjeremylt 76ea61e9acSJeremy L Thompson which allows the sequence to complete asynchronously but does not start `op2` until `op1` has completed. 77d7b241e6Sjeremylt 78ea61e9acSJeremy L Thompson @todo The current implementation is overly strict, offering equivalent semantics to @ref CEED_REQUEST_IMMEDIATE. 79d7b241e6Sjeremylt 80d7b241e6Sjeremylt @sa CEED_REQUEST_IMMEDIATE 81d7b241e6Sjeremylt */ 82d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_ORDERED = &ceed_request_ordered; 83d7b241e6Sjeremylt 84b11c1e72Sjeremylt /** 85ca94c3ddSJeremy L Thompson @brief Wait for a @ref CeedRequest to complete. 86dfdf5a53Sjeremylt 87ca94c3ddSJeremy L Thompson Calling @ref CeedRequestWait() on a `NULL` request is a no-op. 887a982d89SJeremy L. Thompson 89ca94c3ddSJeremy L Thompson @param[in,out] req Address of @ref CeedRequest to wait for; zeroed on completion. 907a982d89SJeremy L. Thompson 917a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 927a982d89SJeremy L. Thompson 937a982d89SJeremy L. Thompson @ref User 94b11c1e72Sjeremylt **/ 957a982d89SJeremy L. Thompson int CeedRequestWait(CeedRequest *req) { 962b730f8bSJeremy L Thompson if (!*req) return CEED_ERROR_SUCCESS; 972b730f8bSJeremy L Thompson return CeedError(NULL, CEED_ERROR_UNSUPPORTED, "CeedRequestWait not implemented"); 98683faae0SJed Brown } 997a982d89SJeremy L. Thompson 1007a982d89SJeremy L. Thompson /// @} 1017a982d89SJeremy L. Thompson 1027a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1037a982d89SJeremy L. Thompson /// Ceed Library Internal Functions 1047a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1057a982d89SJeremy L. Thompson /// @addtogroup CeedDeveloper 1067a982d89SJeremy L. Thompson /// @{ 107d7b241e6Sjeremylt 1086a406739SJeremy L Thompson /** 1096a406739SJeremy L Thompson @brief Register a Ceed backend internally. 1104385fb7fSSebastian Grimberg 111ca94c3ddSJeremy L Thompson Note: Backends should call @ref CeedRegister() instead. 1126a406739SJeremy L Thompson 113ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 114ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 115ca94c3ddSJeremy L Thompson @param[in] init Initialization function called by @ref CeedInit() when the backend is selected to drive the requested resource 116ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 117ca94c3ddSJeremy L Thompson Lower values are preferred in case the resource requested by @ref CeedInit() has non-unique best prefix match. 1186a406739SJeremy L Thompson 1196a406739SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1206a406739SJeremy L Thompson 1216a406739SJeremy L Thompson @ref Developer 1226a406739SJeremy L Thompson **/ 1232b730f8bSJeremy L Thompson int CeedRegisterImpl(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 12458c07c4fSSebastian Grimberg int ierr = 0; 1256a406739SJeremy L Thompson 12658c07c4fSSebastian Grimberg CeedPragmaCritical(CeedRegisterImpl) { 12758c07c4fSSebastian Grimberg if (num_backends < sizeof(backends) / sizeof(backends[0])) { 1286a406739SJeremy L Thompson strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN); 1296a406739SJeremy L Thompson backends[num_backends].prefix[CEED_MAX_RESOURCE_LEN - 1] = 0; 1306a406739SJeremy L Thompson backends[num_backends].init = init; 1316a406739SJeremy L Thompson backends[num_backends].priority = priority; 1326a406739SJeremy L Thompson num_backends++; 13358c07c4fSSebastian Grimberg } else { 13458c07c4fSSebastian Grimberg ierr = 1; 13558c07c4fSSebastian Grimberg } 13658c07c4fSSebastian Grimberg } 13758c07c4fSSebastian Grimberg CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "Too many backends"); 1386a406739SJeremy L Thompson return CEED_ERROR_SUCCESS; 1396a406739SJeremy L Thompson } 1406a406739SJeremy L Thompson 141*73501bfeSJeremy L Thompson /** 142*73501bfeSJeremy L Thompson @brief Create a work vector space for a `ceed` 143*73501bfeSJeremy L Thompson 144*73501bfeSJeremy L Thompson @param[in,out] ceed `Ceed` to create work vector space for 145*73501bfeSJeremy L Thompson 146*73501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 147*73501bfeSJeremy L Thompson 148*73501bfeSJeremy L Thompson @ref Developer 149*73501bfeSJeremy L Thompson **/ 150*73501bfeSJeremy L Thompson static int CeedWorkVectorsCreate(Ceed ceed) { 151*73501bfeSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->work_vectors)); 152*73501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 153*73501bfeSJeremy L Thompson } 154*73501bfeSJeremy L Thompson 155*73501bfeSJeremy L Thompson /** 156*73501bfeSJeremy L Thompson @brief Destroy a work vector space for a `ceed` 157*73501bfeSJeremy L Thompson 158*73501bfeSJeremy L Thompson @param[in,out] ceed `Ceed` to destroy work vector space for 159*73501bfeSJeremy L Thompson 160*73501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 161*73501bfeSJeremy L Thompson 162*73501bfeSJeremy L Thompson @ref Developer 163*73501bfeSJeremy L Thompson **/ 164*73501bfeSJeremy L Thompson static int CeedWorkVectorsDestroy(Ceed ceed) { 165*73501bfeSJeremy L Thompson if (!ceed->work_vectors) return CEED_ERROR_SUCCESS; 166*73501bfeSJeremy L Thompson for (CeedSize i = 0; i < ceed->work_vectors->num_vecs; i++) { 167*73501bfeSJeremy L Thompson CeedCheck(!ceed->work_vectors->is_in_use[i], ceed, CEED_ERROR_ACCESS, "Work vector %" CeedSize_FMT " checked out but not returned"); 168*73501bfeSJeremy L Thompson ceed->ref_count += 2; // Note: increase ref_count to prevent Ceed destructor from triggering again 169*73501bfeSJeremy L Thompson CeedCall(CeedVectorDestroy(&ceed->work_vectors->vecs[i])); 170*73501bfeSJeremy L Thompson ceed->ref_count -= 1; // Note: restore ref_count 171*73501bfeSJeremy L Thompson } 172*73501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors->is_in_use)); 173*73501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors->vecs)); 174*73501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors)); 175*73501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 176*73501bfeSJeremy L Thompson } 177*73501bfeSJeremy L Thompson 1787a982d89SJeremy L. Thompson /// @} 179d7b241e6Sjeremylt 1807a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1817a982d89SJeremy L. Thompson /// Ceed Backend API 1827a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 1837a982d89SJeremy L. Thompson /// @addtogroup CeedBackend 1847a982d89SJeremy L. Thompson /// @{ 185d7b241e6Sjeremylt 186b11c1e72Sjeremylt /** 187ca94c3ddSJeremy L Thompson @brief Return value of `CEED_DEBUG` environment variable 18860f9e2d6SJeremy L Thompson 189ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 19060f9e2d6SJeremy L Thompson 191ca94c3ddSJeremy L Thompson @return Boolean value: true - debugging mode enabled 1923f21f6b1SJeremy L Thompson false - debugging mode disabled 19360f9e2d6SJeremy L Thompson 19460f9e2d6SJeremy L Thompson @ref Backend 19560f9e2d6SJeremy L Thompson **/ 196fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 1972b730f8bSJeremy L Thompson bool CeedDebugFlag(const Ceed ceed) { return ceed->is_debug; } 198fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 19960f9e2d6SJeremy L Thompson 20060f9e2d6SJeremy L Thompson /** 201ca94c3ddSJeremy L Thompson @brief Return value of `CEED_DEBUG` environment variable 20260f9e2d6SJeremy L Thompson 203ca94c3ddSJeremy L Thompson @return Boolean value: true - debugging mode enabled 2043f21f6b1SJeremy L Thompson false - debugging mode disabled 2053f21f6b1SJeremy L Thompson 2063f21f6b1SJeremy L Thompson @ref Backend 2073f21f6b1SJeremy L Thompson **/ 2083f21f6b1SJeremy L Thompson // LCOV_EXCL_START 2091c66c397SJeremy L Thompson bool CeedDebugFlagEnv(void) { return getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); } 2103f21f6b1SJeremy L Thompson // LCOV_EXCL_STOP 2113f21f6b1SJeremy L Thompson 2123f21f6b1SJeremy L Thompson /** 2133f21f6b1SJeremy L Thompson @brief Print debugging information in color 2143f21f6b1SJeremy L Thompson 215ca94c3ddSJeremy L Thompson @param[in] color Color to print 216ca94c3ddSJeremy L Thompson @param[in] format Printing format 21760f9e2d6SJeremy L Thompson 21860f9e2d6SJeremy L Thompson @ref Backend 21960f9e2d6SJeremy L Thompson **/ 220fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 2213f21f6b1SJeremy L Thompson void CeedDebugImpl256(const unsigned char color, const char *format, ...) { 22260f9e2d6SJeremy L Thompson va_list args; 22360f9e2d6SJeremy L Thompson va_start(args, format); 22460f9e2d6SJeremy L Thompson fflush(stdout); 2252b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[38;5;%dm", color); 22660f9e2d6SJeremy L Thompson vfprintf(stdout, format, args); 2272b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[m"); 22860f9e2d6SJeremy L Thompson fprintf(stdout, "\n"); 22960f9e2d6SJeremy L Thompson fflush(stdout); 23060f9e2d6SJeremy L Thompson va_end(args); 23160f9e2d6SJeremy L Thompson } 232fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 23360f9e2d6SJeremy L Thompson 23460f9e2d6SJeremy L Thompson /** 235ca94c3ddSJeremy L Thompson @brief Allocate an array on the host; use @ref CeedMalloc(). 236b11c1e72Sjeremylt 237ea61e9acSJeremy L Thompson Memory usage can be tracked by the library. 238ea61e9acSJeremy L Thompson This ensures sufficient alignment for vectorization and should be used for large allocations. 239b11c1e72Sjeremylt 240ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 241ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 242ca94c3ddSJeremy L Thompson @param[out] p Address of pointer to hold the result 243b11c1e72Sjeremylt 244b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 245b11c1e72Sjeremylt 2467a982d89SJeremy L. Thompson @ref Backend 247ca94c3ddSJeremy L Thompson 248ca94c3ddSJeremy L Thompson @sa CeedFree() 249b11c1e72Sjeremylt **/ 250d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 251d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n * unit); 2526574a04fSJeremy L Thompson CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "posix_memalign failed to allocate %zd members of size %zd\n", n, unit); 253e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 254d7b241e6Sjeremylt } 255d7b241e6Sjeremylt 256b11c1e72Sjeremylt /** 257ca94c3ddSJeremy L Thompson @brief Allocate a cleared (zeroed) array on the host; use @ref CeedCalloc(). 258b11c1e72Sjeremylt 259b11c1e72Sjeremylt Memory usage can be tracked by the library. 260b11c1e72Sjeremylt 261ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 262ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 263ca94c3ddSJeremy L Thompson @param[out] p Address of pointer to hold the result 264b11c1e72Sjeremylt 265b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 266b11c1e72Sjeremylt 2677a982d89SJeremy L. Thompson @ref Backend 268ca94c3ddSJeremy L Thompson 269ca94c3ddSJeremy L Thompson @sa CeedFree() 270b11c1e72Sjeremylt **/ 271d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 272d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 2736574a04fSJeremy L Thompson CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "calloc failed to allocate %zd members of size %zd\n", n, unit); 274e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 275d7b241e6Sjeremylt } 276d7b241e6Sjeremylt 277b11c1e72Sjeremylt /** 278ca94c3ddSJeremy L Thompson @brief Reallocate an array on the host; use @ref CeedRealloc(). 279b11c1e72Sjeremylt 280b11c1e72Sjeremylt Memory usage can be tracked by the library. 281b11c1e72Sjeremylt 282ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 283ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 284ca94c3ddSJeremy L Thompson @param[out] p Address of pointer to hold the result 285b11c1e72Sjeremylt 286b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 287b11c1e72Sjeremylt 2887a982d89SJeremy L. Thompson @ref Backend 289ca94c3ddSJeremy L Thompson 290ca94c3ddSJeremy L Thompson @sa CeedFree() 291b11c1e72Sjeremylt **/ 292d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 293d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n * unit); 2946574a04fSJeremy L Thompson CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "realloc failed to allocate %zd members of size %zd\n", n, unit); 295e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 296d7b241e6Sjeremylt } 297d7b241e6Sjeremylt 298f7e22acaSJeremy L Thompson /** 299ca94c3ddSJeremy L Thompson @brief Allocate a cleared string buffer on the host. 300f7e22acaSJeremy L Thompson 301f7e22acaSJeremy L Thompson Memory usage can be tracked by the library. 302f7e22acaSJeremy L Thompson 303ea61e9acSJeremy L Thompson @param[in] source Pointer to string to be copied 304ea61e9acSJeremy L Thompson @param[out] copy Pointer to variable to hold newly allocated string copy 305f7e22acaSJeremy L Thompson 306f7e22acaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 307f7e22acaSJeremy L Thompson 308f7e22acaSJeremy L Thompson @ref Backend 309ca94c3ddSJeremy L Thompson 310ca94c3ddSJeremy L Thompson @sa CeedFree() 311f7e22acaSJeremy L Thompson **/ 312f7e22acaSJeremy L Thompson int CeedStringAllocCopy(const char *source, char **copy) { 313f7e22acaSJeremy L Thompson size_t len = strlen(source); 3142b730f8bSJeremy L Thompson CeedCall(CeedCalloc(len + 1, copy)); 315d602d780SJeremy L Thompson memcpy(*copy, source, len); 316f7e22acaSJeremy L Thompson return CEED_ERROR_SUCCESS; 317f7e22acaSJeremy L Thompson } 318f7e22acaSJeremy L Thompson 319ca94c3ddSJeremy L Thompson /** Free memory allocated using @ref CeedMalloc() or @ref CeedCalloc() 32034138859Sjeremylt 321ca94c3ddSJeremy L Thompson @param[in,out] p Address of pointer to memory. 322ca94c3ddSJeremy 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. 323ca94c3ddSJeremy L Thompson 324ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 325ca94c3ddSJeremy L Thompson 326ca94c3ddSJeremy L Thompson @ref Backend 32734138859Sjeremylt **/ 328d7b241e6Sjeremylt int CeedFree(void *p) { 329d7b241e6Sjeremylt free(*(void **)p); 330d7b241e6Sjeremylt *(void **)p = NULL; 331e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 332d7b241e6Sjeremylt } 333d7b241e6Sjeremylt 334f5d1e504SJeremy L Thompson /** Internal helper to manage handoff of user `source_array` to backend with proper @ref CeedCopyMode behavior. 335f5d1e504SJeremy L Thompson 336f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 337f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 338f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 33917afdf5cSJames Wright @param[in] size_unit Size of array element in bytes 340f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 341f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 342f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 343f5d1e504SJeremy L Thompson 344f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 345f5d1e504SJeremy L Thompson 346f5d1e504SJeremy L Thompson @ref Backend 347f5d1e504SJeremy L Thompson **/ 348f5d1e504SJeremy L Thompson static inline int CeedSetHostGenericArray(const void *source_array, CeedCopyMode copy_mode, size_t size_unit, CeedSize num_values, 349f5d1e504SJeremy L Thompson void *target_array_owned, void *target_array_borrowed, void *target_array) { 350f5d1e504SJeremy L Thompson switch (copy_mode) { 351f5d1e504SJeremy L Thompson case CEED_COPY_VALUES: 352f5d1e504SJeremy L Thompson if (!*(void **)target_array_owned) CeedCall(CeedCallocArray(num_values, size_unit, target_array_owned)); 353f5d1e504SJeremy L Thompson if (source_array) memcpy(*(void **)target_array_owned, source_array, size_unit * num_values); 354f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = NULL; 355f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_owned; 356f5d1e504SJeremy L Thompson break; 357f5d1e504SJeremy L Thompson case CEED_OWN_POINTER: 358f5d1e504SJeremy L Thompson CeedCall(CeedFree(target_array_owned)); 359f5d1e504SJeremy L Thompson *(void **)target_array_owned = (void *)source_array; 360f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = NULL; 361f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_owned; 362f5d1e504SJeremy L Thompson break; 363f5d1e504SJeremy L Thompson case CEED_USE_POINTER: 364f5d1e504SJeremy L Thompson CeedCall(CeedFree(target_array_owned)); 365f5d1e504SJeremy L Thompson *(void **)target_array_owned = NULL; 366f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = (void *)source_array; 367f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_borrowed; 368f5d1e504SJeremy L Thompson } 369f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 370f5d1e504SJeremy L Thompson } 371f5d1e504SJeremy L Thompson 372f5d1e504SJeremy L Thompson /** Manage handoff of user `bool` `source_array` to backend with proper @ref CeedCopyMode behavior. 373f5d1e504SJeremy L Thompson 374f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 375f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 376f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 377f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 378f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 379f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 380f5d1e504SJeremy L Thompson 381f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 382f5d1e504SJeremy L Thompson 383f5d1e504SJeremy L Thompson @ref Backend 384f5d1e504SJeremy L Thompson **/ 385f5d1e504SJeremy L Thompson int CeedSetHostBoolArray(const bool *source_array, CeedCopyMode copy_mode, CeedSize num_values, const bool **target_array_owned, 386f5d1e504SJeremy L Thompson const bool **target_array_borrowed, const bool **target_array) { 387f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(bool), num_values, target_array_owned, target_array_borrowed, target_array)); 388f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 389f5d1e504SJeremy L Thompson } 390f5d1e504SJeremy L Thompson 391f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedInt8` `source_array` to backend with proper @ref CeedCopyMode behavior. 392f5d1e504SJeremy L Thompson 393f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 394f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 395f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 396f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 397f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 398f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 399f5d1e504SJeremy L Thompson 400f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 401f5d1e504SJeremy L Thompson 402f5d1e504SJeremy L Thompson @ref Backend 403f5d1e504SJeremy L Thompson **/ 404f5d1e504SJeremy L Thompson int CeedSetHostCeedInt8Array(const CeedInt8 *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedInt8 **target_array_owned, 405f5d1e504SJeremy L Thompson const CeedInt8 **target_array_borrowed, const CeedInt8 **target_array) { 406f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedInt8), num_values, target_array_owned, target_array_borrowed, target_array)); 407f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 408f5d1e504SJeremy L Thompson } 409f5d1e504SJeremy L Thompson 410f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedInt` `source_array` to backend with proper @ref CeedCopyMode behavior. 411f5d1e504SJeremy L Thompson 412f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 413f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 414f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 415f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 416f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 417f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 418f5d1e504SJeremy L Thompson 419f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 420f5d1e504SJeremy L Thompson 421f5d1e504SJeremy L Thompson @ref Backend 422f5d1e504SJeremy L Thompson **/ 423f5d1e504SJeremy L Thompson int CeedSetHostCeedIntArray(const CeedInt *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedInt **target_array_owned, 424f5d1e504SJeremy L Thompson const CeedInt **target_array_borrowed, const CeedInt **target_array) { 425f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedInt), num_values, target_array_owned, target_array_borrowed, target_array)); 426f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 427f5d1e504SJeremy L Thompson } 428f5d1e504SJeremy L Thompson 429f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedScalar` `source_array` to backend with proper @ref CeedCopyMode behavior. 430f5d1e504SJeremy L Thompson 431f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 432f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 433f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 434f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 435f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 436f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 437f5d1e504SJeremy L Thompson 438f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 439f5d1e504SJeremy L Thompson 440f5d1e504SJeremy L Thompson @ref Backend 441f5d1e504SJeremy L Thompson **/ 442f5d1e504SJeremy L Thompson int CeedSetHostCeedScalarArray(const CeedScalar *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedScalar **target_array_owned, 443f5d1e504SJeremy L Thompson const CeedScalar **target_array_borrowed, const CeedScalar **target_array) { 444f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedScalar), num_values, target_array_owned, target_array_borrowed, target_array)); 445f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 446f5d1e504SJeremy L Thompson } 447f5d1e504SJeremy L Thompson 448d7b241e6Sjeremylt /** 449ca94c3ddSJeremy L Thompson @brief Register a `Ceed` backend 450d7b241e6Sjeremylt 451ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 452ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 453ca94c3ddSJeremy L Thompson @param[in] init Initialization function called by @ref CeedInit() when the backend is selected to drive the requested resource 454ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 455ca94c3ddSJeremy L Thompson Lower values are preferred in case the resource requested by @ref CeedInit() has non-unique best prefix match. 456b11c1e72Sjeremylt 457b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 458dfdf5a53Sjeremylt 4597a982d89SJeremy L. Thompson @ref Backend 460b11c1e72Sjeremylt **/ 4612b730f8bSJeremy L Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 46210243053SJeremy L Thompson CeedDebugEnv("Backend Register: %s", prefix); 4636a406739SJeremy L Thompson CeedRegisterImpl(prefix, init, priority); 464e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 465d7b241e6Sjeremylt } 466d7b241e6Sjeremylt 467b11c1e72Sjeremylt /** 46860f9e2d6SJeremy L Thompson @brief Return debugging status flag 46960f9e2d6SJeremy L Thompson 470ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get debugging flag 471ea61e9acSJeremy L Thompson @param[out] is_debug Variable to store debugging flag 47260f9e2d6SJeremy L Thompson 47360f9e2d6SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 47460f9e2d6SJeremy L Thompson 475d1d35e2fSjeremylt @ref Backend 47660f9e2d6SJeremy L Thompson **/ 477d1d35e2fSjeremylt int CeedIsDebug(Ceed ceed, bool *is_debug) { 4783f21f6b1SJeremy L Thompson *is_debug = ceed->is_debug; 479e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 48060f9e2d6SJeremy L Thompson } 48160f9e2d6SJeremy L Thompson 48260f9e2d6SJeremy L Thompson /** 483bf84744cSJeremy L Thompson @brief Get the root of the requested resource. 484bf84744cSJeremy L Thompson 485bf84744cSJeremy L Thompson Note: Caller is responsible for calling @ref CeedFree() on the `resource_root`. 486bc246734SJeremy L Thompson 487ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get resource name of 488ca94c3ddSJeremy L Thompson @param[in] resource Full user specified resource 489ca94c3ddSJeremy L Thompson @param[in] delineator Delineator to break `resource_root` and `resource_spec` 490bc246734SJeremy L Thompson @param[out] resource_root Variable to store resource root 491bc246734SJeremy L Thompson 492bc246734SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 493bc246734SJeremy L Thompson 494bc246734SJeremy L Thompson @ref Backend 495bc246734SJeremy L Thompson **/ 496bc246734SJeremy L Thompson int CeedGetResourceRoot(Ceed ceed, const char *resource, const char *delineator, char **resource_root) { 497bc246734SJeremy L Thompson char *device_spec = strstr(resource, delineator); 498bc246734SJeremy L Thompson size_t resource_root_len = device_spec ? (size_t)(device_spec - resource) + 1 : strlen(resource) + 1; 4991c66c397SJeremy L Thompson 500bc246734SJeremy L Thompson CeedCall(CeedCalloc(resource_root_len, resource_root)); 501bc246734SJeremy L Thompson memcpy(*resource_root, resource, resource_root_len - 1); 502bc246734SJeremy L Thompson return CEED_ERROR_SUCCESS; 503bc246734SJeremy L Thompson } 504bc246734SJeremy L Thompson 505bc246734SJeremy L Thompson /** 506ca94c3ddSJeremy L Thompson @brief Retrieve a parent `Ceed` context 5077a982d89SJeremy L. Thompson 508ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve parent of 5097a982d89SJeremy L. Thompson @param[out] parent Address to save the parent to 5107a982d89SJeremy L. Thompson 5117a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5127a982d89SJeremy L. Thompson 5137a982d89SJeremy L. Thompson @ref Backend 5147a982d89SJeremy L. Thompson **/ 5157a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 5167a982d89SJeremy L. Thompson if (ceed->parent) { 5172b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed->parent, parent)); 518e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5197a982d89SJeremy L. Thompson } 5207a982d89SJeremy L. Thompson *parent = ceed; 521e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5227a982d89SJeremy L. Thompson } 5237a982d89SJeremy L. Thompson 5247a982d89SJeremy L. Thompson /** 525ca94c3ddSJeremy L Thompson @brief Retrieve a delegate `Ceed` context 5267a982d89SJeremy L. Thompson 527ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve delegate of 5287a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 5297a982d89SJeremy L. Thompson 5307a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5317a982d89SJeremy L. Thompson 5327a982d89SJeremy L. Thompson @ref Backend 5337a982d89SJeremy L. Thompson **/ 5347a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 5357a982d89SJeremy L. Thompson *delegate = ceed->delegate; 536e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5377a982d89SJeremy L. Thompson } 5387a982d89SJeremy L. Thompson 5397a982d89SJeremy L. Thompson /** 540ca94c3ddSJeremy L Thompson @brief Set a delegate `Ceed` context 5417a982d89SJeremy L. Thompson 542ca94c3ddSJeremy L Thompson This function allows a `Ceed` context to set a delegate `Ceed` context. 543ca94c3ddSJeremy L Thompson All backend implementations default to the delegate `Ceed` context, unless overridden. 5447a982d89SJeremy L. Thompson 545ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to set delegate of 5467a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 5477a982d89SJeremy L. Thompson 5487a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5497a982d89SJeremy L. Thompson 5507a982d89SJeremy L. Thompson @ref Backend 5517a982d89SJeremy L. Thompson **/ 5527a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) { 5537a982d89SJeremy L. Thompson ceed->delegate = delegate; 5547a982d89SJeremy L. Thompson delegate->parent = ceed; 555e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5567a982d89SJeremy L. Thompson } 5577a982d89SJeremy L. Thompson 5587a982d89SJeremy L. Thompson /** 559ca94c3ddSJeremy L Thompson @brief Retrieve a delegate `Ceed` context for a specific object type 5607a982d89SJeremy L. Thompson 561ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve delegate of 5627a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 563d1d35e2fSjeremylt @param[in] obj_name Name of the object type to retrieve delegate for 5647a982d89SJeremy L. Thompson 5657a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5667a982d89SJeremy L. Thompson 5677a982d89SJeremy L. Thompson @ref Backend 5687a982d89SJeremy L. Thompson **/ 569d1d35e2fSjeremylt int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *obj_name) { 5707a982d89SJeremy L. Thompson // Check for object delegate 5712b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) { 572d1d35e2fSjeremylt if (!strcmp(obj_name, ceed->obj_delegates->obj_name)) { 573d1d35e2fSjeremylt *delegate = ceed->obj_delegates->delegate; 574e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5757a982d89SJeremy L. Thompson } 5762b730f8bSJeremy L Thompson } 5777a982d89SJeremy L. Thompson 5787a982d89SJeremy L. Thompson // Use default delegate if no object delegate 5792b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, delegate)); 580e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5817a982d89SJeremy L. Thompson } 5827a982d89SJeremy L. Thompson 5837a982d89SJeremy L. Thompson /** 584ca94c3ddSJeremy L Thompson @brief Set a delegate `Ceed` context for a specific object type 5857a982d89SJeremy L. Thompson 586ca94c3ddSJeremy L Thompson This function allows a `Ceed` context to set a delegate `Ceed` context for a given type of `Ceed` object. 587ca94c3ddSJeremy L Thompson All backend implementations default to the delegate `Ceed` context for this object. 588ca94c3ddSJeremy L Thompson For example, `CeedSetObjectDelegate(ceed, delegate, "Basis")` uses delegate implementations for all `CeedBasis` backend functions. 5897a982d89SJeremy L. Thompson 590ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set delegate of 591ca94c3ddSJeremy L Thompson @param[in] delegate `Ceed` context to use for delegation 592d1d35e2fSjeremylt @param[in] obj_name Name of the object type to set delegate for 5937a982d89SJeremy L. Thompson 5947a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5957a982d89SJeremy L. Thompson 5967a982d89SJeremy L. Thompson @ref Backend 5977a982d89SJeremy L. Thompson **/ 598d1d35e2fSjeremylt int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *obj_name) { 599d1d35e2fSjeremylt CeedInt count = ceed->obj_delegate_count; 6007a982d89SJeremy L. Thompson 6017a982d89SJeremy L. Thompson // Malloc or Realloc 6027a982d89SJeremy L. Thompson if (count) { 6032b730f8bSJeremy L Thompson CeedCall(CeedRealloc(count + 1, &ceed->obj_delegates)); 6047a982d89SJeremy L. Thompson } else { 6052b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->obj_delegates)); 6067a982d89SJeremy L. Thompson } 607d1d35e2fSjeremylt ceed->obj_delegate_count++; 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson // Set object delegate 610d1d35e2fSjeremylt ceed->obj_delegates[count].delegate = delegate; 6112b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(obj_name, &ceed->obj_delegates[count].obj_name)); 6127a982d89SJeremy L. Thompson 6137a982d89SJeremy L. Thompson // Set delegate parent 6147a982d89SJeremy L. Thompson delegate->parent = ceed; 615e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6167a982d89SJeremy L. Thompson } 6177a982d89SJeremy L. Thompson 6187a982d89SJeremy L. Thompson /** 619ca94c3ddSJeremy L Thompson @brief Get the fallback resource for `CeedOperator` 6207a982d89SJeremy L. Thompson 621ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 6227a982d89SJeremy L. Thompson @param[out] resource Variable to store fallback resource 6237a982d89SJeremy L. Thompson 6247a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6257a982d89SJeremy L. Thompson 6267a982d89SJeremy L. Thompson @ref Backend 6277a982d89SJeremy L. Thompson **/ 628363aefefSSebastian Grimberg int CeedGetOperatorFallbackResource(Ceed ceed, const char **resource) { 629d1d35e2fSjeremylt *resource = (const char *)ceed->op_fallback_resource; 630e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6317a982d89SJeremy L. Thompson } 6327a982d89SJeremy L. Thompson 6337a982d89SJeremy L. Thompson /** 634ca94c3ddSJeremy L Thompson @brief Get the fallback `Ceed` for `CeedOperator` 6358687e1d4SJeremy L Thompson 636ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 637ca94c3ddSJeremy L Thompson @param[out] fallback_ceed Variable to store fallback `Ceed` 6388687e1d4SJeremy L Thompson 6398687e1d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 6408687e1d4SJeremy L Thompson 6418687e1d4SJeremy L Thompson @ref Backend 6428687e1d4SJeremy L Thompson **/ 6438687e1d4SJeremy L Thompson int CeedGetOperatorFallbackCeed(Ceed ceed, Ceed *fallback_ceed) { 644d04bbc78SJeremy L Thompson if (ceed->has_valid_op_fallback_resource) { 64523d4529eSJeremy L Thompson CeedDebug256(ceed, CEED_DEBUG_COLOR_SUCCESS, "---------- CeedOperator Fallback ----------\n"); 6462b730f8bSJeremy L Thompson CeedDebug(ceed, "Getting fallback from %s to %s\n", ceed->resource, ceed->op_fallback_resource); 647d04bbc78SJeremy L Thompson } 6488687e1d4SJeremy L Thompson 649d04bbc78SJeremy L Thompson // Create fallback Ceed if uninitalized 650d04bbc78SJeremy L Thompson if (!ceed->op_fallback_ceed && ceed->has_valid_op_fallback_resource) { 65113f886e9SJeremy L Thompson CeedDebug(ceed, "Creating fallback Ceed"); 652d04bbc78SJeremy L Thompson 6538687e1d4SJeremy L Thompson Ceed fallback_ceed; 654d04bbc78SJeremy L Thompson const char *fallback_resource; 655d04bbc78SJeremy L Thompson 656363aefefSSebastian Grimberg CeedCall(CeedGetOperatorFallbackResource(ceed, &fallback_resource)); 6572b730f8bSJeremy L Thompson CeedCall(CeedInit(fallback_resource, &fallback_ceed)); 6588687e1d4SJeremy L Thompson fallback_ceed->op_fallback_parent = ceed; 6598687e1d4SJeremy L Thompson fallback_ceed->Error = ceed->Error; 6608687e1d4SJeremy L Thompson ceed->op_fallback_ceed = fallback_ceed; 6618687e1d4SJeremy L Thompson } 6628687e1d4SJeremy L Thompson *fallback_ceed = ceed->op_fallback_ceed; 6638687e1d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 6648687e1d4SJeremy L Thompson } 6658687e1d4SJeremy L Thompson 6668687e1d4SJeremy L Thompson /** 667ca94c3ddSJeremy L Thompson @brief Set the fallback resource for `CeedOperator`. 6684385fb7fSSebastian Grimberg 669ea61e9acSJeremy L Thompson The current resource, if any, is freed by calling this function. 670ca94c3ddSJeremy L Thompson This string is freed upon the destruction of the `Ceed` context. 6717a982d89SJeremy L. Thompson 672ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context 673ea61e9acSJeremy L Thompson @param[in] resource Fallback resource to set 6747a982d89SJeremy L. Thompson 6757a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6767a982d89SJeremy L. Thompson 6777a982d89SJeremy L. Thompson @ref Backend 6787a982d89SJeremy L. Thompson **/ 6797a982d89SJeremy L. Thompson int CeedSetOperatorFallbackResource(Ceed ceed, const char *resource) { 6807a982d89SJeremy L. Thompson // Free old 6812b730f8bSJeremy L Thompson CeedCall(CeedFree(&ceed->op_fallback_resource)); 6827a982d89SJeremy L. Thompson 6837a982d89SJeremy L. Thompson // Set new 6842b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(resource, (char **)&ceed->op_fallback_resource)); 685d04bbc78SJeremy L Thompson 686d04bbc78SJeremy L Thompson // Check validity 6872b730f8bSJeremy L Thompson ceed->has_valid_op_fallback_resource = ceed->op_fallback_resource && ceed->resource && strcmp(ceed->op_fallback_resource, ceed->resource); 688e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6897a982d89SJeremy L. Thompson } 6907a982d89SJeremy L. Thompson 6917a982d89SJeremy L. Thompson /** 692ca94c3ddSJeremy L Thompson @brief Flag `Ceed` context as deterministic 6939525855cSJeremy L Thompson 694ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` to flag as deterministic 69596b902e2Sjeremylt @param[out] is_deterministic Deterministic status to set 6969525855cSJeremy L Thompson 6979525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 6989525855cSJeremy L Thompson 6999525855cSJeremy L Thompson @ref Backend 7009525855cSJeremy L Thompson **/ 701d1d35e2fSjeremylt int CeedSetDeterministic(Ceed ceed, bool is_deterministic) { 702d1d35e2fSjeremylt ceed->is_deterministic = is_deterministic; 703e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7049525855cSJeremy L Thompson } 7059525855cSJeremy L Thompson 7069525855cSJeremy L Thompson /** 707ca94c3ddSJeremy L Thompson @brief Set a backend function. 7087a982d89SJeremy L. Thompson 709ea61e9acSJeremy L Thompson This function is used for a backend to set the function associated with the Ceed objects. 710ca94c3ddSJeremy 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(). 7119fd66db6SSebastian Grimberg Note, the prefix 'Ceed' is not required for the object type ("Basis" vs "CeedBasis"). 7127a982d89SJeremy L. Thompson 713ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context for error handling 714ea61e9acSJeremy L Thompson @param[in] type Type of Ceed object to set function for 7157a982d89SJeremy L. Thompson @param[out] object Ceed object to set function for 716ea61e9acSJeremy L Thompson @param[in] func_name Name of function to set 717ea61e9acSJeremy L Thompson @param[in] f Function to set 7187a982d89SJeremy L. Thompson 7197a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7207a982d89SJeremy L. Thompson 7217a982d89SJeremy L. Thompson @ref Backend 7227a982d89SJeremy L. Thompson **/ 723897d4737SSebastian Grimberg int CeedSetBackendFunctionImpl(Ceed ceed, const char *type, void *object, const char *func_name, void (*f)(void)) { 724d1d35e2fSjeremylt char lookup_name[CEED_MAX_RESOURCE_LEN + 1] = ""; 7257a982d89SJeremy L. Thompson 7267a982d89SJeremy L. Thompson // Build lookup name 7272b730f8bSJeremy L Thompson if (strcmp(type, "Ceed")) strncat(lookup_name, "Ceed", CEED_MAX_RESOURCE_LEN); 728d1d35e2fSjeremylt strncat(lookup_name, type, CEED_MAX_RESOURCE_LEN); 729d1d35e2fSjeremylt strncat(lookup_name, func_name, CEED_MAX_RESOURCE_LEN); 7307a982d89SJeremy L. Thompson 7317a982d89SJeremy L. Thompson // Find and use offset 7322b730f8bSJeremy L Thompson for (CeedInt i = 0; ceed->f_offsets[i].func_name; i++) { 733d1d35e2fSjeremylt if (!strcmp(ceed->f_offsets[i].func_name, lookup_name)) { 734d1d35e2fSjeremylt size_t offset = ceed->f_offsets[i].offset; 7357a982d89SJeremy L. Thompson int (**fpointer)(void) = (int (**)(void))((char *)object + offset); // *NOPAD* 7361c66c397SJeremy L Thompson 737897d4737SSebastian Grimberg *fpointer = (int (*)(void))f; 738e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7397a982d89SJeremy L. Thompson } 7402b730f8bSJeremy L Thompson } 7417a982d89SJeremy L. Thompson 7427a982d89SJeremy L. Thompson // LCOV_EXCL_START 7432b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Requested function '%s' was not found for CEED object '%s'", func_name, type); 7447a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7457a982d89SJeremy L. Thompson } 7467a982d89SJeremy L. Thompson 7477a982d89SJeremy L. Thompson /** 748ca94c3ddSJeremy L Thompson @brief Retrieve backend data for a `Ceed` context 7497a982d89SJeremy L. Thompson 750ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve data of 7517a982d89SJeremy L. Thompson @param[out] data Address to save data to 7527a982d89SJeremy L. Thompson 7537a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7547a982d89SJeremy L. Thompson 7557a982d89SJeremy L. Thompson @ref Backend 7567a982d89SJeremy L. Thompson **/ 757777ff853SJeremy L Thompson int CeedGetData(Ceed ceed, void *data) { 758777ff853SJeremy L Thompson *(void **)data = ceed->data; 759e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7607a982d89SJeremy L. Thompson } 7617a982d89SJeremy L. Thompson 7627a982d89SJeremy L. Thompson /** 763ca94c3ddSJeremy L Thompson @brief Set backend data for a `Ceed` context 7647a982d89SJeremy L. Thompson 765ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set data of 766ea61e9acSJeremy L Thompson @param[in] data Address of data to set 7677a982d89SJeremy L. Thompson 7687a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7697a982d89SJeremy L. Thompson 7707a982d89SJeremy L. Thompson @ref Backend 7717a982d89SJeremy L. Thompson **/ 772777ff853SJeremy L Thompson int CeedSetData(Ceed ceed, void *data) { 773777ff853SJeremy L Thompson ceed->data = data; 774e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7757a982d89SJeremy L. Thompson } 7767a982d89SJeremy L. Thompson 77734359f16Sjeremylt /** 778ca94c3ddSJeremy L Thompson @brief Increment the reference counter for a `Ceed` context 77934359f16Sjeremylt 780ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to increment the reference counter 78134359f16Sjeremylt 78234359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 78334359f16Sjeremylt 78434359f16Sjeremylt @ref Backend 78534359f16Sjeremylt **/ 7869560d06aSjeremylt int CeedReference(Ceed ceed) { 78734359f16Sjeremylt ceed->ref_count++; 78834359f16Sjeremylt return CEED_ERROR_SUCCESS; 78934359f16Sjeremylt } 79034359f16Sjeremylt 791*73501bfeSJeremy L Thompson /** 792*73501bfeSJeremy L Thompson @brief Get a `CeedVector` for scratch work from a `Ceed` context. 793*73501bfeSJeremy L Thompson 794*73501bfeSJeremy L Thompson Note: This vector must be restored with @ref CeedRestoreWorkVector(). 795*73501bfeSJeremy L Thompson 796*73501bfeSJeremy L Thompson @param[in] ceed `Ceed` context 797*73501bfeSJeremy L Thompson @param[in] len Minimum length of work vector 798*73501bfeSJeremy L Thompson @param[out] vec Address of the variable where `CeedVector` will be stored 799*73501bfeSJeremy L Thompson 800*73501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 801*73501bfeSJeremy L Thompson 802*73501bfeSJeremy L Thompson @ref Backend 803*73501bfeSJeremy L Thompson **/ 804*73501bfeSJeremy L Thompson int CeedGetWorkVector(Ceed ceed, CeedSize len, CeedVector *vec) { 805*73501bfeSJeremy L Thompson CeedInt i = 0; 806*73501bfeSJeremy L Thompson 807*73501bfeSJeremy L Thompson if (!ceed->work_vectors) CeedCall(CeedWorkVectorsCreate(ceed)); 808*73501bfeSJeremy L Thompson 809*73501bfeSJeremy L Thompson // Search for big enough work vector 810*73501bfeSJeremy L Thompson for (i = 0; i < ceed->work_vectors->num_vecs; i++) { 811*73501bfeSJeremy L Thompson if (!ceed->work_vectors->is_in_use[i]) { 812*73501bfeSJeremy L Thompson CeedSize work_len; 813*73501bfeSJeremy L Thompson 814*73501bfeSJeremy L Thompson CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &work_len)); 815*73501bfeSJeremy L Thompson if (work_len >= len) break; 816*73501bfeSJeremy L Thompson } 817*73501bfeSJeremy L Thompson } 818*73501bfeSJeremy L Thompson // Long enough vector was not found 819*73501bfeSJeremy L Thompson if (i == ceed->work_vectors->num_vecs) { 820*73501bfeSJeremy L Thompson if (ceed->work_vectors->max_vecs == 0) { 821*73501bfeSJeremy L Thompson ceed->work_vectors->max_vecs = 1; 822*73501bfeSJeremy L Thompson CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs)); 823*73501bfeSJeremy L Thompson CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use)); 824*73501bfeSJeremy L Thompson } else if (ceed->work_vectors->max_vecs == i) { 825*73501bfeSJeremy L Thompson ceed->work_vectors->max_vecs *= 2; 826*73501bfeSJeremy L Thompson CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs)); 827*73501bfeSJeremy L Thompson CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use)); 828*73501bfeSJeremy L Thompson } 829*73501bfeSJeremy L Thompson ceed->work_vectors->num_vecs++; 830*73501bfeSJeremy L Thompson CeedCallBackend(CeedVectorCreate(ceed, len, &ceed->work_vectors->vecs[i])); 831*73501bfeSJeremy L Thompson ceed->ref_count--; // Note: ref_count manipulation to prevent a ref-loop 832*73501bfeSJeremy L Thompson } 833*73501bfeSJeremy L Thompson // Return pointer to work vector 834*73501bfeSJeremy L Thompson ceed->work_vectors->is_in_use[i] = true; 835*73501bfeSJeremy L Thompson *vec = NULL; 836*73501bfeSJeremy L Thompson CeedCall(CeedVectorReferenceCopy(ceed->work_vectors->vecs[i], vec)); 837*73501bfeSJeremy L Thompson ceed->ref_count++; // Note: bump ref_count to account for external access 838*73501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 839*73501bfeSJeremy L Thompson } 840*73501bfeSJeremy L Thompson 841*73501bfeSJeremy L Thompson /** 842*73501bfeSJeremy L Thompson @brief Restore a `CeedVector` for scratch work from a `Ceed` context from @ref CeedGetWorkVector() 843*73501bfeSJeremy L Thompson 844*73501bfeSJeremy L Thompson @param[in] ceed `Ceed` context 845*73501bfeSJeremy L Thompson @param[out] vec `CeedVector` to restore 846*73501bfeSJeremy L Thompson 847*73501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 848*73501bfeSJeremy L Thompson 849*73501bfeSJeremy L Thompson @ref Backend 850*73501bfeSJeremy L Thompson **/ 851*73501bfeSJeremy L Thompson int CeedRestoreWorkVector(Ceed ceed, CeedVector *vec) { 852*73501bfeSJeremy L Thompson for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 853*73501bfeSJeremy L Thompson if (*vec == ceed->work_vectors->vecs[i]) { 854*73501bfeSJeremy L Thompson CeedCheck(ceed->work_vectors->is_in_use[i], ceed, CEED_ERROR_ACCESS, "Work vector %" CeedSize_FMT " was not checked out but is being returned"); 855*73501bfeSJeremy L Thompson CeedCall(CeedVectorDestroy(vec)); 856*73501bfeSJeremy L Thompson ceed->work_vectors->is_in_use[i] = false; 857*73501bfeSJeremy L Thompson ceed->ref_count--; // Note: reduce ref_count again to prevent a ref-loop 858*73501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 859*73501bfeSJeremy L Thompson } 860*73501bfeSJeremy L Thompson } 861*73501bfeSJeremy L Thompson // LCOV_EXCL_START 862*73501bfeSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MAJOR, "vec was not checked out via CeedGetWorkVector()"); 863*73501bfeSJeremy L Thompson // LCOV_EXCL_STOP 864*73501bfeSJeremy L Thompson } 865*73501bfeSJeremy L Thompson 8667a982d89SJeremy L. Thompson /// @} 8677a982d89SJeremy L. Thompson 8687a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8697a982d89SJeremy L. Thompson /// Ceed Public API 8707a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8717a982d89SJeremy L. Thompson /// @addtogroup CeedUser 8727a982d89SJeremy L. Thompson /// @{ 8737a982d89SJeremy L. Thompson 8747a982d89SJeremy L. Thompson /** 875ca94c3ddSJeremy L Thompson @brief Get the list of available resource names for `Ceed` contexts 8764385fb7fSSebastian Grimberg 877ca94c3ddSJeremy 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. 87822e44211Sjeremylt 87992ee7d1cSjeremylt @param[out] n Number of available resources 88092ee7d1cSjeremylt @param[out] resources List of available resource names 88122e44211Sjeremylt @param[out] priorities Resource name prioritization values, lower is better 88222e44211Sjeremylt 88322e44211Sjeremylt @return An error code: 0 - success, otherwise - failure 88422e44211Sjeremylt 88522e44211Sjeremylt @ref User 88622e44211Sjeremylt **/ 88722e44211Sjeremylt // LCOV_EXCL_START 8882b730f8bSJeremy L Thompson int CeedRegistryGetList(size_t *n, char ***const resources, CeedInt **priorities) { 889d0c91ce9Sjeremylt *n = 0; 8909ff86846Sjeremylt *resources = malloc(num_backends * sizeof(**resources)); 8916574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 8929ff86846Sjeremylt if (priorities) { 8939ff86846Sjeremylt *priorities = malloc(num_backends * sizeof(**priorities)); 8946574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 8959ff86846Sjeremylt } 89622e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 897d0c91ce9Sjeremylt // Only report compiled backends 898d0c91ce9Sjeremylt if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) { 89922e44211Sjeremylt *resources[i] = backends[i].prefix; 9009ff86846Sjeremylt if (priorities) *priorities[i] = backends[i].priority; 901d0c91ce9Sjeremylt *n += 1; 902d0c91ce9Sjeremylt } 903d0c91ce9Sjeremylt } 9046574a04fSJeremy L Thompson CeedCheck(*n, NULL, CEED_ERROR_MAJOR, "No backends installed"); 905d0c91ce9Sjeremylt *resources = realloc(*resources, *n * sizeof(**resources)); 9066574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 907d0c91ce9Sjeremylt if (priorities) { 908d0c91ce9Sjeremylt *priorities = realloc(*priorities, *n * sizeof(**priorities)); 9096574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 91022e44211Sjeremylt } 91122e44211Sjeremylt return CEED_ERROR_SUCCESS; 91245f1e315Sjeremylt } 91322e44211Sjeremylt // LCOV_EXCL_STOP 91422e44211Sjeremylt 91522e44211Sjeremylt /** 916ca94c3ddSJeremy L Thompson @brief Initialize a `Ceed` context to use the specified resource. 9174385fb7fSSebastian Grimberg 918ca94c3ddSJeremy 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`. 919b11c1e72Sjeremylt 920ea61e9acSJeremy L Thompson @param[in] resource Resource to use, e.g., "/cpu/self" 921ea61e9acSJeremy L Thompson @param[out] ceed The library context 922b11c1e72Sjeremylt 923b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 924dfdf5a53Sjeremylt 9257a982d89SJeremy L. Thompson @ref User 926ca94c3ddSJeremy L Thompson 927ca94c3ddSJeremy L Thompson @sa CeedRegister() CeedDestroy() 928b11c1e72Sjeremylt **/ 929d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 9302b730f8bSJeremy L Thompson size_t match_len = 0, match_index = UINT_MAX, match_priority = CEED_MAX_BACKEND_PRIORITY, priority; 931d7b241e6Sjeremylt 932fe2413ffSjeremylt // Find matching backend 9336574a04fSJeremy L Thompson CeedCheck(resource, NULL, CEED_ERROR_MAJOR, "No resource provided"); 9342b730f8bSJeremy L Thompson CeedCall(CeedRegisterAll()); 93513873f79Sjeremylt 93622e44211Sjeremylt // Check for help request 93722e44211Sjeremylt const char *help_prefix = "help"; 9382b730f8bSJeremy L Thompson size_t match_help = 0; 9392b730f8bSJeremy L Thompson while (match_help < 4 && resource[match_help] == help_prefix[match_help]) match_help++; 94022e44211Sjeremylt if (match_help == 4) { 9412b730f8bSJeremy L Thompson fprintf(stderr, "libCEED version: %d.%d%d%s\n", CEED_VERSION_MAJOR, CEED_VERSION_MINOR, CEED_VERSION_PATCH, 94222e44211Sjeremylt CEED_VERSION_RELEASE ? "" : "+development"); 94392ee7d1cSjeremylt fprintf(stderr, "Available backend resources:\n"); 94422e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 945d0c91ce9Sjeremylt // Only report compiled backends 9462b730f8bSJeremy L Thompson if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) fprintf(stderr, " %s\n", backends[i].prefix); 94722e44211Sjeremylt } 94822e44211Sjeremylt fflush(stderr); 94922e44211Sjeremylt match_help = 5; // Delineating character expected 95022e44211Sjeremylt } else { 95122e44211Sjeremylt match_help = 0; 95222e44211Sjeremylt } 95322e44211Sjeremylt 954ea61e9acSJeremy L Thompson // Find best match, computed as number of matching characters from requested resource stem 9552b730f8bSJeremy L Thompson size_t stem_length = 0; 9562b730f8bSJeremy L Thompson while (resource[stem_length + match_help] && resource[stem_length + match_help] != ':') stem_length++; 957d7b241e6Sjeremylt for (size_t i = 0; i < num_backends; i++) { 9582b730f8bSJeremy L Thompson size_t n = 0; 959d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 9602b730f8bSJeremy L Thompson while (prefix[n] && prefix[n] == resource[n + match_help]) n++; 961d7b241e6Sjeremylt priority = backends[i].priority; 962d1d35e2fSjeremylt if (n > match_len || (n == match_len && match_priority > priority)) { 963d1d35e2fSjeremylt match_len = n; 964d1d35e2fSjeremylt match_priority = priority; 965f7e22acaSJeremy L Thompson match_index = i; 966d7b241e6Sjeremylt } 967d7b241e6Sjeremylt } 9689c9a0587SLeila Ghaffari // Using Levenshtein distance to find closest match 9699c9a0587SLeila Ghaffari if (match_len <= 1 || match_len != stem_length) { 970203015caSLeila Ghaffari // LCOV_EXCL_START 9719c9a0587SLeila Ghaffari size_t lev_dis = UINT_MAX; 972f7e22acaSJeremy L Thompson size_t lev_index = UINT_MAX, lev_priority = CEED_MAX_BACKEND_PRIORITY; 9739c9a0587SLeila Ghaffari for (size_t i = 0; i < num_backends; i++) { 9749c9a0587SLeila Ghaffari const char *prefix = backends[i].prefix; 9759c9a0587SLeila Ghaffari size_t prefix_length = strlen(backends[i].prefix); 9769c9a0587SLeila Ghaffari size_t min_len = (prefix_length < stem_length) ? prefix_length : stem_length; 977092904ddSLeila Ghaffari size_t column[min_len + 1]; 978092904ddSLeila Ghaffari for (size_t j = 0; j <= min_len; j++) column[j] = j; 9799c9a0587SLeila Ghaffari for (size_t j = 1; j <= min_len; j++) { 9809c9a0587SLeila Ghaffari column[0] = j; 9819c9a0587SLeila Ghaffari for (size_t k = 1, last_diag = j - 1; k <= min_len; k++) { 982092904ddSLeila Ghaffari size_t old_diag = column[k]; 9839c9a0587SLeila Ghaffari size_t min_1 = (column[k] < column[k - 1]) ? column[k] + 1 : column[k - 1] + 1; 9849c9a0587SLeila Ghaffari size_t min_2 = last_diag + (resource[k - 1] == prefix[j - 1] ? 0 : 1); 9859c9a0587SLeila Ghaffari column[k] = (min_1 < min_2) ? min_1 : min_2; 9869c9a0587SLeila Ghaffari last_diag = old_diag; 9879c9a0587SLeila Ghaffari } 9889c9a0587SLeila Ghaffari } 9899c9a0587SLeila Ghaffari size_t n = column[min_len]; 9909c9a0587SLeila Ghaffari priority = backends[i].priority; 9912b730f8bSJeremy L Thompson if (n < lev_dis || (n == lev_dis && lev_priority > priority)) { 9929c9a0587SLeila Ghaffari lev_dis = n; 9939c9a0587SLeila Ghaffari lev_priority = priority; 994f7e22acaSJeremy L Thompson lev_index = i; 9959c9a0587SLeila Ghaffari } 9969c9a0587SLeila Ghaffari } 997f7e22acaSJeremy L Thompson const char *prefix_lev = backends[lev_index].prefix; 9982b730f8bSJeremy L Thompson size_t lev_length = 0; 9992b730f8bSJeremy L Thompson while (prefix_lev[lev_length] && prefix_lev[lev_length] != '\0') lev_length++; 10009c9a0587SLeila Ghaffari size_t m = (lev_length < stem_length) ? lev_length : stem_length; 10016574a04fSJeremy L Thompson if (lev_dis + 1 >= m) return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s", resource); 10026574a04fSJeremy L Thompson else return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s\nClosest match: %s", resource, backends[lev_index].prefix); 1003203015caSLeila Ghaffari // LCOV_EXCL_STOP 10049c9a0587SLeila Ghaffari } 1005fe2413ffSjeremylt 1006fe2413ffSjeremylt // Setup Ceed 10072b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, ceed)); 10082b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &(*ceed)->jit_source_roots)); 1009bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 10102b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 10112b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "exit")) (*ceed)->Error = CeedErrorExit; 10122b730f8bSJeremy L Thompson else if (!strcmp(ceed_error_handler, "store")) (*ceed)->Error = CeedErrorStore; 10132b730f8bSJeremy L Thompson else (*ceed)->Error = CeedErrorAbort; 1014d1d35e2fSjeremylt memcpy((*ceed)->err_msg, "No error message stored", 24); 1015d1d35e2fSjeremylt (*ceed)->ref_count = 1; 1016d7b241e6Sjeremylt (*ceed)->data = NULL; 1017fe2413ffSjeremylt 1018fe2413ffSjeremylt // Set lookup table 1019d1d35e2fSjeremylt FOffset f_offsets[] = { 10206e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 10215ae360d4SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, SetStream), 10226e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 10236e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 1024f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 10256e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 10263ac8f562SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateAtPoints), 10276e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 10286e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 10296e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 103050c301a5SRezgar Shakeri CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv), 1031c4e3f59bSSebastian Grimberg CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl), 10326e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 10336e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 1034777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate), 10356e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 103648acf710SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, OperatorCreateAtPoints), 10376e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 10389c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasValidArray), 10399c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType), 10400b8f3c4eSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, CopyStrided), 10416e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 10426a6c615bSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, TakeArray), 10436e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 10440b8f3c4eSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, SetValueStrided), 1045f48ed27dSnbeams CEED_FTABLE_ENTRY(CeedVector, SyncArray), 10466e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 10476e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 10489c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite), 10496e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 10506e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 1051547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 1052e0dd3b27Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Scale), 10530f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, AXPY), 10545fb68f37SKaren (Ren) Stengel CEED_FTABLE_ENTRY(CeedVector, AXPBY), 10550f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, PointwiseMult), 1056d99fa3c5SJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, Reciprocal), 10576e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 10586e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 1059f30b1135SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnsigned), 10607c1dbaffSSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnoriented), 106105fa913cSJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyAtPointsInElement), 10626e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 1063bd33150aSjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets), 106477d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetOrientations), 106577d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetCurlOrientations), 106619605835SJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, GetAtPointsElementOffset), 10676e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 10686e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 1069db2becc9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAdd), 1070c8c3fa7dSJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAtPoints), 1071db2becc9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAddAtPoints), 10726e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 10736e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 10746e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 10756e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 10768c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction), 10778c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction), 10786e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 10799c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData), 10809c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType), 1081777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData), 1082891038deSjeremylt CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData), 1083777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData), 108428bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead), 1085777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData), 108628bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead), 10872e64a2b9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy), 1088777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy), 108980ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction), 109070a7ffb3SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate), 109180ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal), 10929e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal), 109380ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal), 10949e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal), 1095e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic), 1096e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble), 1097cefa2673SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle), 1098713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 10996e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 1100250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 1101cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 1102250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 11036e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 11046e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 11056e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 11061dfeef1dSjeremylt }; 1107fe2413ffSjeremylt 11082b730f8bSJeremy L Thompson CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets)); 1109d1d35e2fSjeremylt memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets)); 1110fe2413ffSjeremylt 11115107b09fSJeremy L Thompson // Set fallback for advanced CeedOperator functions 1112ca735530SJeremy L Thompson const char fallback_resource[] = ""; 1113ca735530SJeremy L Thompson CeedCall(CeedSetOperatorFallbackResource(*ceed, fallback_resource)); 11145107b09fSJeremy L Thompson 111560f9e2d6SJeremy L Thompson // Record env variables CEED_DEBUG or DBG 11161c66c397SJeremy L Thompson (*ceed)->is_debug = getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); 111760f9e2d6SJeremy L Thompson 111822e44211Sjeremylt // Copy resource prefix, if backend setup successful 11192b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource)); 1120ee5a26f2SJeremy L Thompson 1121ee5a26f2SJeremy L Thompson // Set default JiT source root 1122ea61e9acSJeremy L Thompson // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent 11232b730f8bSJeremy L Thompson CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault)); 1124ee5a26f2SJeremy L Thompson 1125d04bbc78SJeremy L Thompson // Backend specific setup 11262b730f8bSJeremy L Thompson CeedCall(backends[match_index].init(&resource[match_help], *ceed)); 1127e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1128d7b241e6Sjeremylt } 1129d7b241e6Sjeremylt 1130d7b241e6Sjeremylt /** 1131ca94c3ddSJeremy L Thompson @brief Set the GPU stream for a `Ceed` context 11325ae360d4SJeremy L Thompson 1133ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set the stream 11345ae360d4SJeremy L Thompson @param[in] handle Handle to GPU stream 11355ae360d4SJeremy L Thompson 11365ae360d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11375ae360d4SJeremy L Thompson 11385ae360d4SJeremy L Thompson @ref User 11395ae360d4SJeremy L Thompson **/ 11405ae360d4SJeremy L Thompson int CeedSetStream(Ceed ceed, void *handle) { 1141ca94c3ddSJeremy L Thompson CeedCheck(handle, ceed, CEED_ERROR_INCOMPATIBLE, "Stream handle must be non-NULL"); 11429ffb25e0SJames Wright if (ceed->SetStream) { 11435ae360d4SJeremy L Thompson CeedCall(ceed->SetStream(ceed, handle)); 11449ffb25e0SJames Wright } else { 11459ffb25e0SJames Wright Ceed delegate; 11469ffb25e0SJames Wright CeedCall(CeedGetDelegate(ceed, &delegate)); 11475ae360d4SJeremy L Thompson 114828ce3d2aSJeremy L Thompson if (delegate) CeedCall(CeedSetStream(delegate, handle)); 114928ce3d2aSJeremy L Thompson else return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support setting stream"); 11509ffb25e0SJames Wright } 11515ae360d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 11525ae360d4SJeremy L Thompson } 11535ae360d4SJeremy L Thompson 11545ae360d4SJeremy L Thompson /** 1155ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `Ceed` context. 11564385fb7fSSebastian Grimberg 1157ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedDestroy(). 1158512bb800SJeremy L Thompson 1159ca94c3ddSJeremy 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. 1160ca94c3ddSJeremy L Thompson This `Ceed` context will be destroyed if `*ceed_copy` is the only reference to this `Ceed` context. 11619560d06aSjeremylt 1162ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to copy reference to 1163ea61e9acSJeremy L Thompson @param[in,out] ceed_copy Variable to store copied reference 11649560d06aSjeremylt 11659560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 11669560d06aSjeremylt 11679560d06aSjeremylt @ref User 11689560d06aSjeremylt **/ 11699560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) { 11702b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 11712b730f8bSJeremy L Thompson CeedCall(CeedDestroy(ceed_copy)); 11729560d06aSjeremylt *ceed_copy = ceed; 11739560d06aSjeremylt return CEED_ERROR_SUCCESS; 11749560d06aSjeremylt } 11759560d06aSjeremylt 11769560d06aSjeremylt /** 1177ca94c3ddSJeremy L Thompson @brief Get the full resource name for a `Ceed` context 11782f86a920SJeremy L Thompson 1179ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get resource name of 11807a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 11812f86a920SJeremy L Thompson 11822f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11832f86a920SJeremy L Thompson 11847a982d89SJeremy L. Thompson @ref User 11855107b09fSJeremy L Thompson **/ 11867a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 11877a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 1188e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11895107b09fSJeremy L Thompson } 11905107b09fSJeremy L Thompson 11915107b09fSJeremy L Thompson /** 1192ca94c3ddSJeremy L Thompson @brief Return `Ceed` context preferred memory type 1193c907536fSjeremylt 1194ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get preferred memory type of 1195d1d35e2fSjeremylt @param[out] mem_type Address to save preferred memory type to 1196c907536fSjeremylt 1197c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 1198c907536fSjeremylt 11997a982d89SJeremy L. Thompson @ref User 1200c907536fSjeremylt **/ 1201d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) { 1202c907536fSjeremylt if (ceed->GetPreferredMemType) { 12032b730f8bSJeremy L Thompson CeedCall(ceed->GetPreferredMemType(mem_type)); 1204c907536fSjeremylt } else { 1205c263cd57Sjeremylt Ceed delegate; 12062b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, &delegate)); 1207c263cd57Sjeremylt 1208c263cd57Sjeremylt if (delegate) { 12092b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(delegate, mem_type)); 1210c263cd57Sjeremylt } else { 1211d1d35e2fSjeremylt *mem_type = CEED_MEM_HOST; 1212c907536fSjeremylt } 1213c263cd57Sjeremylt } 1214e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1215c907536fSjeremylt } 1216c907536fSjeremylt 1217c907536fSjeremylt /** 1218ca94c3ddSJeremy L Thompson @brief Get deterministic status of `Ceed` context 12199525855cSJeremy L Thompson 1220ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 1221d1d35e2fSjeremylt @param[out] is_deterministic Variable to store deterministic status 12229525855cSJeremy L Thompson 12239525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12249525855cSJeremy L Thompson 12259525855cSJeremy L Thompson @ref User 12269525855cSJeremy L Thompson **/ 1227d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) { 1228d1d35e2fSjeremylt *is_deterministic = ceed->is_deterministic; 1229e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 12309525855cSJeremy L Thompson } 12319525855cSJeremy L Thompson 12329525855cSJeremy L Thompson /** 1233ca94c3ddSJeremy L Thompson @brief Set additional JiT source root for `Ceed` context 1234ee5a26f2SJeremy L Thompson 1235ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context 1236ee5a26f2SJeremy L Thompson @param[in] jit_source_root Absolute path to additional JiT source directory 1237ee5a26f2SJeremy L Thompson 1238ee5a26f2SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1239ee5a26f2SJeremy L Thompson 1240ee5a26f2SJeremy L Thompson @ref User 1241ee5a26f2SJeremy L Thompson **/ 1242ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) { 12436155f12fSJeremy L Thompson Ceed ceed_parent; 1244ee5a26f2SJeremy L Thompson 12452b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 12466155f12fSJeremy L Thompson 12476155f12fSJeremy L Thompson CeedInt index = ceed_parent->num_jit_source_roots; 1248ee5a26f2SJeremy L Thompson size_t path_length = strlen(jit_source_root); 12491c66c397SJeremy L Thompson 12502b730f8bSJeremy L Thompson CeedCall(CeedRealloc(index + 1, &ceed_parent->jit_source_roots)); 12512b730f8bSJeremy L Thompson CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index])); 1252d602d780SJeremy L Thompson memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length); 12536155f12fSJeremy L Thompson ceed_parent->num_jit_source_roots++; 1254ee5a26f2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1255ee5a26f2SJeremy L Thompson } 1256ee5a26f2SJeremy L Thompson 1257ee5a26f2SJeremy L Thompson /** 1258ca94c3ddSJeremy L Thompson @brief View a `Ceed` 12590a0da059Sjeremylt 1260ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` to view 12610a0da059Sjeremylt @param[in] stream Filestream to write to 12620a0da059Sjeremylt 12630a0da059Sjeremylt @return An error code: 0 - success, otherwise - failure 12640a0da059Sjeremylt 12650a0da059Sjeremylt @ref User 12660a0da059Sjeremylt **/ 12670a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) { 1268d1d35e2fSjeremylt CeedMemType mem_type; 12690a0da059Sjeremylt 12702b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 12710a0da059Sjeremylt 12722b730f8bSJeremy L Thompson fprintf(stream, 12732b730f8bSJeremy L Thompson "Ceed\n" 12740a0da059Sjeremylt " Ceed Resource: %s\n" 12750a0da059Sjeremylt " Preferred MemType: %s\n", 1276d1d35e2fSjeremylt ceed->resource, CeedMemTypes[mem_type]); 1277e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 12780a0da059Sjeremylt } 12790a0da059Sjeremylt 12800a0da059Sjeremylt /** 1281ca94c3ddSJeremy L Thompson @brief Destroy a `Ceed` 1282d7b241e6Sjeremylt 1283ca94c3ddSJeremy L Thompson @param[in,out] ceed Address of `Ceed` context to destroy 1284b11c1e72Sjeremylt 1285b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1286dfdf5a53Sjeremylt 12877a982d89SJeremy L. Thompson @ref User 1288b11c1e72Sjeremylt **/ 1289d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 1290ad6481ceSJeremy L Thompson if (!*ceed || --(*ceed)->ref_count > 0) { 1291ad6481ceSJeremy L Thompson *ceed = NULL; 1292ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1293ad6481ceSJeremy L Thompson } 12942b730f8bSJeremy L Thompson if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate)); 12950ace9bf2Sjeremylt 1296d1d35e2fSjeremylt if ((*ceed)->obj_delegate_count > 0) { 129792ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) { 12982b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate))); 12992b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name)); 1300aefd8378Sjeremylt } 13012b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates)); 1302aefd8378Sjeremylt } 13030ace9bf2Sjeremylt 13042b730f8bSJeremy L Thompson if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed)); 13050ace9bf2Sjeremylt 130692ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) { 13072b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots[i])); 1308032e71eaSJeremy L Thompson } 13092b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots)); 1310032e71eaSJeremy L Thompson 13112b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->f_offsets)); 13122b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->resource)); 13132b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed)); 13142b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->op_fallback_resource)); 1315*73501bfeSJeremy L Thompson CeedCall(CeedWorkVectorsDestroy(*ceed)); 13162b730f8bSJeremy L Thompson CeedCall(CeedFree(ceed)); 1317e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1318d7b241e6Sjeremylt } 1319d7b241e6Sjeremylt 1320f9982c62SWill Pazner // LCOV_EXCL_START 1321f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) { 13222b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args); 13232b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorFormat(ceed->op_fallback_parent, format, args); 132478464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 132578464608Sjeremylt vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args); // NOLINT 1326d1d35e2fSjeremylt return ceed->err_msg; 1327f9982c62SWill Pazner } 1328f9982c62SWill Pazner // LCOV_EXCL_STOP 1329f9982c62SWill Pazner 13307a982d89SJeremy L. Thompson /** 1331ca94c3ddSJeremy L Thompson @brief Error handling implementation; use @ref CeedError() instead. 1332ca94c3ddSJeremy L Thompson 1333ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13347a982d89SJeremy L. Thompson 13357a982d89SJeremy L. Thompson @ref Developer 13367a982d89SJeremy L. Thompson **/ 13372b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) { 13387a982d89SJeremy L. Thompson va_list args; 1339d1d35e2fSjeremylt int ret_val; 13401c66c397SJeremy L Thompson 13417a982d89SJeremy L. Thompson va_start(args, format); 13427a982d89SJeremy L. Thompson if (ceed) { 1343d1d35e2fSjeremylt ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args); 13447a982d89SJeremy L. Thompson } else { 1345b0d62198Sjeremylt // LCOV_EXCL_START 1346477729cfSJeremy L Thompson const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 13472b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 1348bcbe1c99SJeremy L Thompson if (!strcmp(ceed_error_handler, "return")) { 1349bcbe1c99SJeremy L Thompson ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args); 1350bcbe1c99SJeremy L Thompson } else { 1351477729cfSJeremy L Thompson // This function will not return 1352d1d35e2fSjeremylt ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args); 13537a982d89SJeremy L. Thompson } 1354bcbe1c99SJeremy L Thompson } 13557a982d89SJeremy L. Thompson va_end(args); 1356d1d35e2fSjeremylt return ret_val; 1357b0d62198Sjeremylt // LCOV_EXCL_STOP 13587a982d89SJeremy L. Thompson } 13597a982d89SJeremy L. Thompson 1360477729cfSJeremy L Thompson /** 1361477729cfSJeremy L Thompson @brief Error handler that returns without printing anything. 1362477729cfSJeremy L Thompson 1363ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1364ca94c3ddSJeremy L Thompson 1365ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1366477729cfSJeremy L Thompson 1367477729cfSJeremy L Thompson @ref Developer 1368477729cfSJeremy L Thompson **/ 1369477729cfSJeremy L Thompson // LCOV_EXCL_START 13702b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1371d1d35e2fSjeremylt return err_code; 1372477729cfSJeremy L Thompson } 1373477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1374477729cfSJeremy L Thompson 1375477729cfSJeremy L Thompson /** 1376ea61e9acSJeremy L Thompson @brief Error handler that stores the error message for future use and returns the error. 1377477729cfSJeremy L Thompson 1378ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1379ca94c3ddSJeremy L Thompson 1380ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1381477729cfSJeremy L Thompson 1382477729cfSJeremy L Thompson @ref Developer 1383477729cfSJeremy L Thompson **/ 1384477729cfSJeremy L Thompson // LCOV_EXCL_START 13852b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 13862b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args); 13872b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedErrorStore(ceed->op_fallback_parent, filename, line_no, func, err_code, format, args); 1388477729cfSJeremy L Thompson 1389477729cfSJeremy L Thompson // Build message 13901c66c397SJeremy L Thompson int len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%s:%d in %s(): ", filename, line_no, func); 139178464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 139278464608Sjeremylt vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args); // NOLINT 1393d1d35e2fSjeremylt return err_code; 1394477729cfSJeremy L Thompson } 1395477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1396477729cfSJeremy L Thompson 1397477729cfSJeremy L Thompson /** 1398ca94c3ddSJeremy L Thompson @brief Error handler that prints to `stderr` and aborts 1399477729cfSJeremy L Thompson 1400ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1401ca94c3ddSJeremy L Thompson 1402ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1403477729cfSJeremy L Thompson 1404477729cfSJeremy L Thompson @ref Developer 1405477729cfSJeremy L Thompson **/ 1406477729cfSJeremy L Thompson // LCOV_EXCL_START 14072b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1408d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 1409f9982c62SWill Pazner vfprintf(stderr, format, *args); 1410477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1411477729cfSJeremy L Thompson abort(); 1412d1d35e2fSjeremylt return err_code; 1413477729cfSJeremy L Thompson } 1414477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1415477729cfSJeremy L Thompson 1416477729cfSJeremy L Thompson /** 1417ca94c3ddSJeremy L Thompson @brief Error handler that prints to `stderr` and exits. 1418477729cfSJeremy L Thompson 1419ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1420477729cfSJeremy L Thompson 1421ca94c3ddSJeremy L Thompson In contrast to @ref CeedErrorAbort(), this exits without a signal, so `atexit()` handlers (e.g., as used by gcov) are run. 1422ca94c3ddSJeremy L Thompson 1423ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1424477729cfSJeremy L Thompson 1425477729cfSJeremy L Thompson @ref Developer 1426477729cfSJeremy L Thompson **/ 14272b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1428d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 142978464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 143078464608Sjeremylt vfprintf(stderr, format, *args); // NOLINT 1431477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1432d1d35e2fSjeremylt exit(err_code); 1433d1d35e2fSjeremylt return err_code; 1434477729cfSJeremy L Thompson } 1435477729cfSJeremy L Thompson 1436477729cfSJeremy L Thompson /** 1437477729cfSJeremy L Thompson @brief Set error handler 1438477729cfSJeremy L Thompson 1439ca94c3ddSJeremy L Thompson A default error handler is set in @ref CeedInit(). 1440ca94c3ddSJeremy L Thompson Use this function to change the error handler to @ref CeedErrorReturn(), @ref CeedErrorAbort(), or a user-defined error handler. 1441ca94c3ddSJeremy L Thompson 1442ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1443477729cfSJeremy L Thompson 1444477729cfSJeremy L Thompson @ref Developer 1445477729cfSJeremy L Thompson **/ 1446d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) { 1447d1d35e2fSjeremylt ceed->Error = handler; 1448d1d35e2fSjeremylt if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler); 14492b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler); 1450e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1451477729cfSJeremy L Thompson } 1452477729cfSJeremy L Thompson 1453477729cfSJeremy L Thompson /** 1454477729cfSJeremy L Thompson @brief Get error message 1455477729cfSJeremy L Thompson 1456ca94c3ddSJeremy L Thompson The error message is only stored when using the error handler @ref CeedErrorStore() 1457477729cfSJeremy L Thompson 1458ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve error message 1459d1d35e2fSjeremylt @param[out] err_msg Char pointer to hold error message 1460477729cfSJeremy L Thompson 1461ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1462ca94c3ddSJeremy L Thompson 1463477729cfSJeremy L Thompson @ref Developer 1464477729cfSJeremy L Thompson **/ 1465d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) { 14662b730f8bSJeremy L Thompson if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg); 14672b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedGetErrorMessage(ceed->op_fallback_parent, err_msg); 1468d1d35e2fSjeremylt *err_msg = ceed->err_msg; 1469e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1470477729cfSJeremy L Thompson } 1471477729cfSJeremy L Thompson 1472477729cfSJeremy L Thompson /** 1473ca94c3ddSJeremy L Thompson @brief Restore error message. 1474477729cfSJeremy L Thompson 1475ca94c3ddSJeremy L Thompson The error message is only stored when using the error handler @ref CeedErrorStore(). 1476477729cfSJeremy L Thompson 1477ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to restore error message 1478d1d35e2fSjeremylt @param[out] err_msg Char pointer that holds error message 1479477729cfSJeremy L Thompson 1480ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1481ca94c3ddSJeremy L Thompson 1482477729cfSJeremy L Thompson @ref Developer 1483477729cfSJeremy L Thompson **/ 1484d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) { 14852b730f8bSJeremy L Thompson if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg); 14862b730f8bSJeremy L Thompson if (ceed->op_fallback_parent) return CeedResetErrorMessage(ceed->op_fallback_parent, err_msg); 1487d1d35e2fSjeremylt *err_msg = NULL; 1488d1d35e2fSjeremylt memcpy(ceed->err_msg, "No error message stored", 24); 1489e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1490477729cfSJeremy L Thompson } 1491477729cfSJeremy L Thompson 14921070991dSJed Brown /** 1493ca94c3ddSJeremy L Thompson @brief Get libCEED library version information. 14941070991dSJed Brown 1495ea61e9acSJeremy L Thompson libCEED version numbers have the form major.minor.patch. 1496ea61e9acSJeremy L Thompson Non-release versions may contain unstable interfaces. 14971070991dSJed Brown 14981070991dSJed Brown @param[out] major Major version of the library 14991070991dSJed Brown @param[out] minor Minor version of the library 15001070991dSJed Brown @param[out] patch Patch (subminor) version of the library 150153cbfc38SJeremy L Thompson @param[out] release True for releases; false for development branches 15021070991dSJed Brown 1503ca94c3ddSJeremy L Thompson The caller may pass `NULL` for any arguments that are not needed. 15041070991dSJed Brown 1505ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 15061070991dSJed Brown 15071070991dSJed Brown @ref Developer 1508ca94c3ddSJeremy L Thompson 1509ca94c3ddSJeremy L Thompson @sa CEED_VERSION_GE() 15101070991dSJed Brown */ 15111070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) { 15121070991dSJed Brown if (major) *major = CEED_VERSION_MAJOR; 15131070991dSJed Brown if (minor) *minor = CEED_VERSION_MINOR; 15141070991dSJed Brown if (patch) *patch = CEED_VERSION_PATCH; 15151070991dSJed Brown if (release) *release = CEED_VERSION_RELEASE; 1516ca94c3ddSJeremy L Thompson return CEED_ERROR_SUCCESS; 15171070991dSJed Brown } 15181070991dSJed Brown 151953cbfc38SJeremy L Thompson /** 152053cbfc38SJeremy L Thompson @brief Get libCEED scalar type, such as F64 or F32 152153cbfc38SJeremy L Thompson 152253cbfc38SJeremy L Thompson @param[out] scalar_type Type of libCEED scalars 152353cbfc38SJeremy L Thompson 1524ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1525ca94c3ddSJeremy L Thompson 152653cbfc38SJeremy L Thompson @ref Developer 152753cbfc38SJeremy L Thompson */ 152880a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) { 152980a9ef05SNatalie Beams *scalar_type = CEED_SCALAR_TYPE; 1530ca94c3ddSJeremy L Thompson return CEED_ERROR_SUCCESS; 153180a9ef05SNatalie Beams } 153280a9ef05SNatalie Beams 1533d7b241e6Sjeremylt /// @} 1534