1d275d636SJeremy L Thompson // Copyright (c) 2017-2025, 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 14173501bfeSJeremy L Thompson /** 14273501bfeSJeremy L Thompson @brief Create a work vector space for a `ceed` 14373501bfeSJeremy L Thompson 14473501bfeSJeremy L Thompson @param[in,out] ceed `Ceed` to create work vector space for 14573501bfeSJeremy L Thompson 14673501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 14773501bfeSJeremy L Thompson 14873501bfeSJeremy L Thompson @ref Developer 14973501bfeSJeremy L Thompson **/ 15073501bfeSJeremy L Thompson static int CeedWorkVectorsCreate(Ceed ceed) { 15173501bfeSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->work_vectors)); 15273501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 15373501bfeSJeremy L Thompson } 15473501bfeSJeremy L Thompson 15573501bfeSJeremy L Thompson /** 15673501bfeSJeremy L Thompson @brief Destroy a work vector space for a `ceed` 15773501bfeSJeremy L Thompson 15873501bfeSJeremy L Thompson @param[in,out] ceed `Ceed` to destroy work vector space for 15973501bfeSJeremy L Thompson 16073501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 16173501bfeSJeremy L Thompson 16273501bfeSJeremy L Thompson @ref Developer 16373501bfeSJeremy L Thompson **/ 16473501bfeSJeremy L Thompson static int CeedWorkVectorsDestroy(Ceed ceed) { 16573501bfeSJeremy L Thompson if (!ceed->work_vectors) return CEED_ERROR_SUCCESS; 16673501bfeSJeremy L Thompson for (CeedSize i = 0; i < ceed->work_vectors->num_vecs; i++) { 16773501bfeSJeremy L Thompson CeedCheck(!ceed->work_vectors->is_in_use[i], ceed, CEED_ERROR_ACCESS, "Work vector %" CeedSize_FMT " checked out but not returned"); 16873501bfeSJeremy L Thompson ceed->ref_count += 2; // Note: increase ref_count to prevent Ceed destructor from triggering again 16973501bfeSJeremy L Thompson CeedCall(CeedVectorDestroy(&ceed->work_vectors->vecs[i])); 17073501bfeSJeremy L Thompson ceed->ref_count -= 1; // Note: restore ref_count 17173501bfeSJeremy L Thompson } 17273501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors->is_in_use)); 17373501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors->vecs)); 17473501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors)); 17573501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 17673501bfeSJeremy L Thompson } 17773501bfeSJeremy 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: 352cc3bdf8cSJeremy L Thompson if (!*(void **)target_array) { 353cc3bdf8cSJeremy L Thompson if (*(void **)target_array_borrowed) { 354cc3bdf8cSJeremy L Thompson *(void **)target_array = *(void **)target_array_borrowed; 355cc3bdf8cSJeremy L Thompson } else { 356f5d1e504SJeremy L Thompson if (!*(void **)target_array_owned) CeedCall(CeedCallocArray(num_values, size_unit, target_array_owned)); 357f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_owned; 358cc3bdf8cSJeremy L Thompson } 359cc3bdf8cSJeremy L Thompson } 360cc3bdf8cSJeremy L Thompson if (source_array) memcpy(*(void **)target_array, source_array, size_unit * num_values); 361f5d1e504SJeremy L Thompson break; 362f5d1e504SJeremy L Thompson case CEED_OWN_POINTER: 363f5d1e504SJeremy L Thompson CeedCall(CeedFree(target_array_owned)); 364f5d1e504SJeremy L Thompson *(void **)target_array_owned = (void *)source_array; 365f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = NULL; 366f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_owned; 367f5d1e504SJeremy L Thompson break; 368f5d1e504SJeremy L Thompson case CEED_USE_POINTER: 369f5d1e504SJeremy L Thompson CeedCall(CeedFree(target_array_owned)); 370f5d1e504SJeremy L Thompson *(void **)target_array_owned = NULL; 371f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = (void *)source_array; 372f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_borrowed; 373f5d1e504SJeremy L Thompson } 374f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 375f5d1e504SJeremy L Thompson } 376f5d1e504SJeremy L Thompson 377f5d1e504SJeremy L Thompson /** Manage handoff of user `bool` `source_array` to backend with proper @ref CeedCopyMode behavior. 378f5d1e504SJeremy L Thompson 379f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 380f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 381f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 382f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 383f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 384f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 385f5d1e504SJeremy L Thompson 386f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 387f5d1e504SJeremy L Thompson 388f5d1e504SJeremy L Thompson @ref Backend 389f5d1e504SJeremy L Thompson **/ 390f5d1e504SJeremy L Thompson int CeedSetHostBoolArray(const bool *source_array, CeedCopyMode copy_mode, CeedSize num_values, const bool **target_array_owned, 391f5d1e504SJeremy L Thompson const bool **target_array_borrowed, const bool **target_array) { 392f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(bool), num_values, target_array_owned, target_array_borrowed, target_array)); 393f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 394f5d1e504SJeremy L Thompson } 395f5d1e504SJeremy L Thompson 396f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedInt8` `source_array` to backend with proper @ref CeedCopyMode behavior. 397f5d1e504SJeremy L Thompson 398f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 399f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 400f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 401f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 402f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 403f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 404f5d1e504SJeremy L Thompson 405f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 406f5d1e504SJeremy L Thompson 407f5d1e504SJeremy L Thompson @ref Backend 408f5d1e504SJeremy L Thompson **/ 409f5d1e504SJeremy L Thompson int CeedSetHostCeedInt8Array(const CeedInt8 *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedInt8 **target_array_owned, 410f5d1e504SJeremy L Thompson const CeedInt8 **target_array_borrowed, const CeedInt8 **target_array) { 411f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedInt8), num_values, target_array_owned, target_array_borrowed, target_array)); 412f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 413f5d1e504SJeremy L Thompson } 414f5d1e504SJeremy L Thompson 415f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedInt` `source_array` to backend with proper @ref CeedCopyMode behavior. 416f5d1e504SJeremy L Thompson 417f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 418f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 419f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 420f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 421f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 422f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 423f5d1e504SJeremy L Thompson 424f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 425f5d1e504SJeremy L Thompson 426f5d1e504SJeremy L Thompson @ref Backend 427f5d1e504SJeremy L Thompson **/ 428f5d1e504SJeremy L Thompson int CeedSetHostCeedIntArray(const CeedInt *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedInt **target_array_owned, 429f5d1e504SJeremy L Thompson const CeedInt **target_array_borrowed, const CeedInt **target_array) { 430f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedInt), num_values, target_array_owned, target_array_borrowed, target_array)); 431f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 432f5d1e504SJeremy L Thompson } 433f5d1e504SJeremy L Thompson 434f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedScalar` `source_array` to backend with proper @ref CeedCopyMode behavior. 435f5d1e504SJeremy L Thompson 436f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 437f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 438f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 439f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 440f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 441f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 442f5d1e504SJeremy L Thompson 443f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 444f5d1e504SJeremy L Thompson 445f5d1e504SJeremy L Thompson @ref Backend 446f5d1e504SJeremy L Thompson **/ 447f5d1e504SJeremy L Thompson int CeedSetHostCeedScalarArray(const CeedScalar *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedScalar **target_array_owned, 448f5d1e504SJeremy L Thompson const CeedScalar **target_array_borrowed, const CeedScalar **target_array) { 449f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedScalar), num_values, target_array_owned, target_array_borrowed, target_array)); 450f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 451f5d1e504SJeremy L Thompson } 452f5d1e504SJeremy L Thompson 453d7b241e6Sjeremylt /** 454ca94c3ddSJeremy L Thompson @brief Register a `Ceed` backend 455d7b241e6Sjeremylt 456ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 457ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 458ca94c3ddSJeremy L Thompson @param[in] init Initialization function called by @ref CeedInit() when the backend is selected to drive the requested resource 459ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 460ca94c3ddSJeremy L Thompson Lower values are preferred in case the resource requested by @ref CeedInit() has non-unique best prefix match. 461b11c1e72Sjeremylt 462b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 463dfdf5a53Sjeremylt 4647a982d89SJeremy L. Thompson @ref Backend 465b11c1e72Sjeremylt **/ 4662b730f8bSJeremy L Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 46710243053SJeremy L Thompson CeedDebugEnv("Backend Register: %s", prefix); 4686a406739SJeremy L Thompson CeedRegisterImpl(prefix, init, priority); 469e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 470d7b241e6Sjeremylt } 471d7b241e6Sjeremylt 472b11c1e72Sjeremylt /** 47360f9e2d6SJeremy L Thompson @brief Return debugging status flag 47460f9e2d6SJeremy L Thompson 475ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get debugging flag 476ea61e9acSJeremy L Thompson @param[out] is_debug Variable to store debugging flag 47760f9e2d6SJeremy L Thompson 47860f9e2d6SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 47960f9e2d6SJeremy L Thompson 480d1d35e2fSjeremylt @ref Backend 48160f9e2d6SJeremy L Thompson **/ 482d1d35e2fSjeremylt int CeedIsDebug(Ceed ceed, bool *is_debug) { 4833f21f6b1SJeremy L Thompson *is_debug = ceed->is_debug; 484e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 48560f9e2d6SJeremy L Thompson } 48660f9e2d6SJeremy L Thompson 48760f9e2d6SJeremy L Thompson /** 488bf84744cSJeremy L Thompson @brief Get the root of the requested resource. 489bf84744cSJeremy L Thompson 490bf84744cSJeremy L Thompson Note: Caller is responsible for calling @ref CeedFree() on the `resource_root`. 491bc246734SJeremy L Thompson 492ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get resource name of 493ca94c3ddSJeremy L Thompson @param[in] resource Full user specified resource 494ca94c3ddSJeremy L Thompson @param[in] delineator Delineator to break `resource_root` and `resource_spec` 495bc246734SJeremy L Thompson @param[out] resource_root Variable to store resource root 496bc246734SJeremy L Thompson 497bc246734SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 498bc246734SJeremy L Thompson 499bc246734SJeremy L Thompson @ref Backend 500bc246734SJeremy L Thompson **/ 501bc246734SJeremy L Thompson int CeedGetResourceRoot(Ceed ceed, const char *resource, const char *delineator, char **resource_root) { 502bc246734SJeremy L Thompson char *device_spec = strstr(resource, delineator); 503bc246734SJeremy L Thompson size_t resource_root_len = device_spec ? (size_t)(device_spec - resource) + 1 : strlen(resource) + 1; 5041c66c397SJeremy L Thompson 505bc246734SJeremy L Thompson CeedCall(CeedCalloc(resource_root_len, resource_root)); 506bc246734SJeremy L Thompson memcpy(*resource_root, resource, resource_root_len - 1); 507bc246734SJeremy L Thompson return CEED_ERROR_SUCCESS; 508bc246734SJeremy L Thompson } 509bc246734SJeremy L Thompson 510bc246734SJeremy L Thompson /** 511ca94c3ddSJeremy L Thompson @brief Retrieve a parent `Ceed` context 5127a982d89SJeremy L. Thompson 513ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve parent of 5147a982d89SJeremy L. Thompson @param[out] parent Address to save the parent to 5157a982d89SJeremy L. Thompson 5167a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5177a982d89SJeremy L. Thompson 5187a982d89SJeremy L. Thompson @ref Backend 5197a982d89SJeremy L. Thompson **/ 5207a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 5217a982d89SJeremy L. Thompson if (ceed->parent) { 5222b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed->parent, parent)); 523e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5247a982d89SJeremy L. Thompson } 5259bc66399SJeremy L Thompson *parent = NULL; 5269bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, parent)); 527e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5287a982d89SJeremy L. Thompson } 5297a982d89SJeremy L. Thompson 5307a982d89SJeremy L. Thompson /** 531ca94c3ddSJeremy L Thompson @brief Retrieve a delegate `Ceed` context 5327a982d89SJeremy L. Thompson 533ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve delegate of 5347a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 5357a982d89SJeremy L. Thompson 5367a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5377a982d89SJeremy L. Thompson 5387a982d89SJeremy L. Thompson @ref Backend 5397a982d89SJeremy L. Thompson **/ 5407a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 5419bc66399SJeremy L Thompson *delegate = NULL; 5429bc66399SJeremy L Thompson if (ceed->delegate) CeedCall(CeedReferenceCopy(ceed->delegate, delegate)); 543e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5447a982d89SJeremy L. Thompson } 5457a982d89SJeremy L. Thompson 5467a982d89SJeremy L. Thompson /** 547ca94c3ddSJeremy L Thompson @brief Set a delegate `Ceed` context 5487a982d89SJeremy L. Thompson 549ca94c3ddSJeremy L Thompson This function allows a `Ceed` context to set a delegate `Ceed` context. 550ca94c3ddSJeremy L Thompson All backend implementations default to the delegate `Ceed` context, unless overridden. 5517a982d89SJeremy L. Thompson 552ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to set delegate of 5537a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 5547a982d89SJeremy L. Thompson 5557a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5567a982d89SJeremy L. Thompson 5577a982d89SJeremy L. Thompson @ref Backend 5587a982d89SJeremy L. Thompson **/ 5597a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) { 5609bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(delegate, &ceed->delegate)); 5617a982d89SJeremy L. Thompson delegate->parent = ceed; 562e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5637a982d89SJeremy L. Thompson } 5647a982d89SJeremy L. Thompson 5657a982d89SJeremy L. Thompson /** 566ca94c3ddSJeremy L Thompson @brief Retrieve a delegate `Ceed` context for a specific object type 5677a982d89SJeremy L. Thompson 568ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve delegate of 5697a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 570d1d35e2fSjeremylt @param[in] obj_name Name of the object type to retrieve delegate for 5717a982d89SJeremy L. Thompson 5727a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5737a982d89SJeremy L. Thompson 5747a982d89SJeremy L. Thompson @ref Backend 5757a982d89SJeremy L. Thompson **/ 576d1d35e2fSjeremylt int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *obj_name) { 5777a982d89SJeremy L. Thompson // Check for object delegate 5782b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) { 579d1d35e2fSjeremylt if (!strcmp(obj_name, ceed->obj_delegates->obj_name)) { 5809bc66399SJeremy L Thompson *delegate = NULL; 5819bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed->obj_delegates->delegate, delegate)); 582e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5837a982d89SJeremy L. Thompson } 5842b730f8bSJeremy L Thompson } 5857a982d89SJeremy L. Thompson 5867a982d89SJeremy L. Thompson // Use default delegate if no object delegate 5872b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, delegate)); 588e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5897a982d89SJeremy L. Thompson } 5907a982d89SJeremy L. Thompson 5917a982d89SJeremy L. Thompson /** 592ca94c3ddSJeremy L Thompson @brief Set a delegate `Ceed` context for a specific object type 5937a982d89SJeremy L. Thompson 594ca94c3ddSJeremy L Thompson This function allows a `Ceed` context to set a delegate `Ceed` context for a given type of `Ceed` object. 595ca94c3ddSJeremy L Thompson All backend implementations default to the delegate `Ceed` context for this object. 596ca94c3ddSJeremy L Thompson For example, `CeedSetObjectDelegate(ceed, delegate, "Basis")` uses delegate implementations for all `CeedBasis` backend functions. 5977a982d89SJeremy L. Thompson 598ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set delegate of 599ca94c3ddSJeremy L Thompson @param[in] delegate `Ceed` context to use for delegation 600d1d35e2fSjeremylt @param[in] obj_name Name of the object type to set delegate for 6017a982d89SJeremy L. Thompson 6027a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6037a982d89SJeremy L. Thompson 6047a982d89SJeremy L. Thompson @ref Backend 6057a982d89SJeremy L. Thompson **/ 606d1d35e2fSjeremylt int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *obj_name) { 607d1d35e2fSjeremylt CeedInt count = ceed->obj_delegate_count; 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson // Malloc or Realloc 6107a982d89SJeremy L. Thompson if (count) { 6112b730f8bSJeremy L Thompson CeedCall(CeedRealloc(count + 1, &ceed->obj_delegates)); 6127a982d89SJeremy L. Thompson } else { 6132b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->obj_delegates)); 6147a982d89SJeremy L. Thompson } 615d1d35e2fSjeremylt ceed->obj_delegate_count++; 6167a982d89SJeremy L. Thompson 6177a982d89SJeremy L. Thompson // Set object delegate 6189bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(delegate, &ceed->obj_delegates[count].delegate)); 6192b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(obj_name, &ceed->obj_delegates[count].obj_name)); 6207a982d89SJeremy L. Thompson 6217a982d89SJeremy L. Thompson // Set delegate parent 6227a982d89SJeremy L. Thompson delegate->parent = ceed; 623e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6247a982d89SJeremy L. Thompson } 6257a982d89SJeremy L. Thompson 6267a982d89SJeremy L. Thompson /** 627ca94c3ddSJeremy L Thompson @brief Get the fallback `Ceed` for `CeedOperator` 6288687e1d4SJeremy L Thompson 629ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 630ca94c3ddSJeremy L Thompson @param[out] fallback_ceed Variable to store fallback `Ceed` 6318687e1d4SJeremy L Thompson 6328687e1d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 6338687e1d4SJeremy L Thompson 6348687e1d4SJeremy L Thompson @ref Backend 6358687e1d4SJeremy L Thompson **/ 6368687e1d4SJeremy L Thompson int CeedGetOperatorFallbackCeed(Ceed ceed, Ceed *fallback_ceed) { 63746b50f9eSZach Atkins if (ceed->op_fallback_ceed) { 638ca38d01dSJeremy L Thompson CeedDebug256(ceed, CEED_DEBUG_COLOR_SUCCESS, "---------- Ceed Fallback ----------\n"); 63946b50f9eSZach Atkins CeedDebug(ceed, "Falling back from Ceed with backend %s at address %p to Ceed with backend %s at address %p", ceed->resource, ceed, 64046b50f9eSZach Atkins ceed->op_fallback_ceed->resource, ceed->op_fallback_ceed); 641d04bbc78SJeremy L Thompson } 6428687e1d4SJeremy L Thompson 6439bc66399SJeremy L Thompson *fallback_ceed = NULL; 6449bc66399SJeremy L Thompson if (ceed->op_fallback_ceed) CeedCall(CeedReferenceCopy(ceed->op_fallback_ceed, fallback_ceed)); 6458687e1d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 6468687e1d4SJeremy L Thompson } 6478687e1d4SJeremy L Thompson 6488687e1d4SJeremy L Thompson /** 649ca94c3ddSJeremy L Thompson @brief Set the fallback resource for `CeedOperator`. 6504385fb7fSSebastian Grimberg 65146b50f9eSZach Atkins The current fallback, if any, is freed by calling this function. 6527a982d89SJeremy L. Thompson 653ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context 65446b50f9eSZach Atkins @param[in] fallback_ceed `Ceed` context to create fallback operators 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6577a982d89SJeremy L. Thompson 6587a982d89SJeremy L. Thompson @ref Backend 6597a982d89SJeremy L. Thompson **/ 66046b50f9eSZach Atkins int CeedSetOperatorFallbackCeed(Ceed ceed, Ceed fallback_ceed) { 66146b50f9eSZach Atkins CeedCall(CeedReferenceCopy(fallback_ceed, &ceed->op_fallback_ceed)); 66246b50f9eSZach Atkins fallback_ceed->parent = ceed; 663e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6647a982d89SJeremy L. Thompson } 6657a982d89SJeremy L. Thompson 6667a982d89SJeremy L. Thompson /** 667*4c789ea2SJeremy L Thompson @brief Get the number of tabs to indent for @ref CeedView() output 668*4c789ea2SJeremy L Thompson 669*4c789ea2SJeremy L Thompson @param[in] ceed `Ceed` to get the number of view tabs 670*4c789ea2SJeremy L Thompson @param[out] num_tabs Number of view tabs 671*4c789ea2SJeremy L Thompson 672*4c789ea2SJeremy L Thompson @return Error code: 0 - success, otherwise - failure 673*4c789ea2SJeremy L Thompson 674*4c789ea2SJeremy L Thompson @ref Backend 675*4c789ea2SJeremy L Thompson **/ 676*4c789ea2SJeremy L Thompson int CeedGetNumViewTabs(Ceed ceed, CeedInt *num_tabs) { 677*4c789ea2SJeremy L Thompson *num_tabs = ceed->num_tabs; 678*4c789ea2SJeremy L Thompson return CEED_ERROR_SUCCESS; 679*4c789ea2SJeremy L Thompson } 680*4c789ea2SJeremy L Thompson 681*4c789ea2SJeremy L Thompson /** 682ca94c3ddSJeremy L Thompson @brief Flag `Ceed` context as deterministic 6839525855cSJeremy L Thompson 684ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` to flag as deterministic 68596b902e2Sjeremylt @param[out] is_deterministic Deterministic status to set 6869525855cSJeremy L Thompson 6879525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 6889525855cSJeremy L Thompson 6899525855cSJeremy L Thompson @ref Backend 6909525855cSJeremy L Thompson **/ 691d1d35e2fSjeremylt int CeedSetDeterministic(Ceed ceed, bool is_deterministic) { 692d1d35e2fSjeremylt ceed->is_deterministic = is_deterministic; 693e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6949525855cSJeremy L Thompson } 6959525855cSJeremy L Thompson 6969525855cSJeremy L Thompson /** 697ca94c3ddSJeremy L Thompson @brief Set a backend function. 6987a982d89SJeremy L. Thompson 699ea61e9acSJeremy L Thompson This function is used for a backend to set the function associated with the Ceed objects. 700ca94c3ddSJeremy 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(). 7019fd66db6SSebastian Grimberg Note, the prefix 'Ceed' is not required for the object type ("Basis" vs "CeedBasis"). 7027a982d89SJeremy L. Thompson 703ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context for error handling 704ea61e9acSJeremy L Thompson @param[in] type Type of Ceed object to set function for 7057a982d89SJeremy L. Thompson @param[out] object Ceed object to set function for 706ea61e9acSJeremy L Thompson @param[in] func_name Name of function to set 707ea61e9acSJeremy L Thompson @param[in] f Function to set 7087a982d89SJeremy L. Thompson 7097a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7107a982d89SJeremy L. Thompson 7117a982d89SJeremy L. Thompson @ref Backend 7127a982d89SJeremy L. Thompson **/ 713897d4737SSebastian Grimberg int CeedSetBackendFunctionImpl(Ceed ceed, const char *type, void *object, const char *func_name, void (*f)(void)) { 714d1d35e2fSjeremylt char lookup_name[CEED_MAX_RESOURCE_LEN + 1] = ""; 7157a982d89SJeremy L. Thompson 7167a982d89SJeremy L. Thompson // Build lookup name 7172b730f8bSJeremy L Thompson if (strcmp(type, "Ceed")) strncat(lookup_name, "Ceed", CEED_MAX_RESOURCE_LEN); 718d1d35e2fSjeremylt strncat(lookup_name, type, CEED_MAX_RESOURCE_LEN); 719d1d35e2fSjeremylt strncat(lookup_name, func_name, CEED_MAX_RESOURCE_LEN); 7207a982d89SJeremy L. Thompson 7217a982d89SJeremy L. Thompson // Find and use offset 7222b730f8bSJeremy L Thompson for (CeedInt i = 0; ceed->f_offsets[i].func_name; i++) { 723d1d35e2fSjeremylt if (!strcmp(ceed->f_offsets[i].func_name, lookup_name)) { 724d1d35e2fSjeremylt size_t offset = ceed->f_offsets[i].offset; 7257a982d89SJeremy L. Thompson int (**fpointer)(void) = (int (**)(void))((char *)object + offset); // *NOPAD* 7261c66c397SJeremy L Thompson 727897d4737SSebastian Grimberg *fpointer = (int (*)(void))f; 728e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7297a982d89SJeremy L. Thompson } 7302b730f8bSJeremy L Thompson } 7317a982d89SJeremy L. Thompson 7327a982d89SJeremy L. Thompson // LCOV_EXCL_START 7332b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Requested function '%s' was not found for CEED object '%s'", func_name, type); 7347a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7357a982d89SJeremy L. Thompson } 7367a982d89SJeremy L. Thompson 7377a982d89SJeremy L. Thompson /** 738ca94c3ddSJeremy L Thompson @brief Retrieve backend data for a `Ceed` context 7397a982d89SJeremy L. Thompson 740ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve data of 7417a982d89SJeremy L. Thompson @param[out] data Address to save data to 7427a982d89SJeremy L. Thompson 7437a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7447a982d89SJeremy L. Thompson 7457a982d89SJeremy L. Thompson @ref Backend 7467a982d89SJeremy L. Thompson **/ 747777ff853SJeremy L Thompson int CeedGetData(Ceed ceed, void *data) { 748777ff853SJeremy L Thompson *(void **)data = ceed->data; 749e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7507a982d89SJeremy L. Thompson } 7517a982d89SJeremy L. Thompson 7527a982d89SJeremy L. Thompson /** 753ca94c3ddSJeremy L Thompson @brief Set backend data for a `Ceed` context 7547a982d89SJeremy L. Thompson 755ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set data of 756ea61e9acSJeremy L Thompson @param[in] data Address of data to set 7577a982d89SJeremy L. Thompson 7587a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7597a982d89SJeremy L. Thompson 7607a982d89SJeremy L. Thompson @ref Backend 7617a982d89SJeremy L. Thompson **/ 762777ff853SJeremy L Thompson int CeedSetData(Ceed ceed, void *data) { 763777ff853SJeremy L Thompson ceed->data = data; 764e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7657a982d89SJeremy L. Thompson } 7667a982d89SJeremy L. Thompson 76734359f16Sjeremylt /** 768ca94c3ddSJeremy L Thompson @brief Increment the reference counter for a `Ceed` context 76934359f16Sjeremylt 770ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to increment the reference counter 77134359f16Sjeremylt 77234359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 77334359f16Sjeremylt 77434359f16Sjeremylt @ref Backend 77534359f16Sjeremylt **/ 7769560d06aSjeremylt int CeedReference(Ceed ceed) { 77734359f16Sjeremylt ceed->ref_count++; 77834359f16Sjeremylt return CEED_ERROR_SUCCESS; 77934359f16Sjeremylt } 78034359f16Sjeremylt 78173501bfeSJeremy L Thompson /** 7820b37c066SZach Atkins @brief Computes the current memory usage of the work vectors in a `Ceed` context and prints to debug.abort 7830b37c066SZach Atkins 7840b37c066SZach Atkins @param[in] ceed `Ceed` context 785ec4241e6SJeremy L Thompson @param[out] usage_mb Address of the variable where the MB of work vector usage will be stored 7860b37c066SZach Atkins 7870b37c066SZach Atkins @return An error code: 0 - success, otherwise - failure 7880b37c066SZach Atkins 7890b37c066SZach Atkins @ref Developer 7900b37c066SZach Atkins **/ 79155326fe7SZach Atkins int CeedGetWorkVectorMemoryUsage(Ceed ceed, CeedScalar *usage_mb) { 792fd326ce8SZach Atkins if (!ceed->VectorCreate) { 793fd326ce8SZach Atkins Ceed delegate; 794fd326ce8SZach Atkins 795fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 796fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 797fd326ce8SZach Atkins CeedCall(CeedGetWorkVectorMemoryUsage(delegate, usage_mb)); 798fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 799fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 800fd326ce8SZach Atkins } 80155326fe7SZach Atkins *usage_mb = 0.0; 8020b37c066SZach Atkins if (ceed->work_vectors) { 8030b37c066SZach Atkins for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 8040b37c066SZach Atkins CeedSize vec_len; 8050b37c066SZach Atkins CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &vec_len)); 80655326fe7SZach Atkins *usage_mb += vec_len; 8070b37c066SZach Atkins } 80855326fe7SZach Atkins *usage_mb *= sizeof(CeedScalar) * 1e-6; 80955326fe7SZach Atkins CeedDebug(ceed, "Resource {%s}: Work vectors memory usage: %" CeedInt_FMT " vectors, %g MB\n", ceed->resource, ceed->work_vectors->num_vecs, 81055326fe7SZach Atkins *usage_mb); 8110b37c066SZach Atkins } 8120b37c066SZach Atkins return CEED_ERROR_SUCCESS; 8130b37c066SZach Atkins } 8140b37c066SZach Atkins 8150b37c066SZach Atkins /** 8160b37c066SZach Atkins @brief Clear inactive work vectors in a `Ceed` context below a minimum length. 8170b37c066SZach Atkins 8180b37c066SZach Atkins @param[in,out] ceed `Ceed` context 8190b37c066SZach Atkins @param[in] min_len Minimum length of work vector to keep 8200b37c066SZach Atkins 8210b37c066SZach Atkins @return An error code: 0 - success, otherwise - failure 8220b37c066SZach Atkins 8230b37c066SZach Atkins @ref Backend 8240b37c066SZach Atkins **/ 8250b37c066SZach Atkins int CeedClearWorkVectors(Ceed ceed, CeedSize min_len) { 826fd326ce8SZach Atkins if (!ceed->VectorCreate) { 827fd326ce8SZach Atkins Ceed delegate; 828fd326ce8SZach Atkins 829fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 830fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 831fd326ce8SZach Atkins CeedCall(CeedClearWorkVectors(delegate, min_len)); 832fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 833fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 834fd326ce8SZach Atkins } 8350b37c066SZach Atkins if (!ceed->work_vectors) return CEED_ERROR_SUCCESS; 8360b37c066SZach Atkins for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 8370b37c066SZach Atkins if (ceed->work_vectors->is_in_use[i]) continue; 8380b37c066SZach Atkins CeedSize vec_len; 8390b37c066SZach Atkins CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &vec_len)); 8400b37c066SZach Atkins if (vec_len < min_len) { 84156a26733SZach Atkins ceed->ref_count += 2; // Note: increase ref_count to prevent Ceed destructor from triggering 8420b37c066SZach Atkins CeedCall(CeedVectorDestroy(&ceed->work_vectors->vecs[i])); 8430b37c066SZach Atkins ceed->ref_count -= 1; // Note: restore ref_count 8440b37c066SZach Atkins ceed->work_vectors->num_vecs--; 8450b37c066SZach Atkins if (ceed->work_vectors->num_vecs > 0) { 8460b37c066SZach Atkins ceed->work_vectors->vecs[i] = ceed->work_vectors->vecs[ceed->work_vectors->num_vecs]; 8470b37c066SZach Atkins ceed->work_vectors->is_in_use[i] = ceed->work_vectors->is_in_use[ceed->work_vectors->num_vecs]; 8480b37c066SZach Atkins ceed->work_vectors->is_in_use[ceed->work_vectors->num_vecs] = false; 8490b37c066SZach Atkins i--; 8500b37c066SZach Atkins } 8510b37c066SZach Atkins } 8520b37c066SZach Atkins } 8530b37c066SZach Atkins return CEED_ERROR_SUCCESS; 8540b37c066SZach Atkins } 8550b37c066SZach Atkins 8560b37c066SZach Atkins /** 85773501bfeSJeremy L Thompson @brief Get a `CeedVector` for scratch work from a `Ceed` context. 85873501bfeSJeremy L Thompson 85973501bfeSJeremy L Thompson Note: This vector must be restored with @ref CeedRestoreWorkVector(). 86073501bfeSJeremy L Thompson 86173501bfeSJeremy L Thompson @param[in] ceed `Ceed` context 86273501bfeSJeremy L Thompson @param[in] len Minimum length of work vector 86373501bfeSJeremy L Thompson @param[out] vec Address of the variable where `CeedVector` will be stored 86473501bfeSJeremy L Thompson 86573501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 86673501bfeSJeremy L Thompson 86773501bfeSJeremy L Thompson @ref Backend 86873501bfeSJeremy L Thompson **/ 86973501bfeSJeremy L Thompson int CeedGetWorkVector(Ceed ceed, CeedSize len, CeedVector *vec) { 87073501bfeSJeremy L Thompson CeedInt i = 0; 87155326fe7SZach Atkins CeedScalar usage_mb; 87273501bfeSJeremy L Thompson 873fd326ce8SZach Atkins if (!ceed->VectorCreate) { 874fd326ce8SZach Atkins Ceed delegate; 875fd326ce8SZach Atkins 876fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 877fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 878fd326ce8SZach Atkins CeedCall(CeedGetWorkVector(delegate, len, vec)); 879fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 880fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 881fd326ce8SZach Atkins } 882fd326ce8SZach Atkins 88373501bfeSJeremy L Thompson if (!ceed->work_vectors) CeedCall(CeedWorkVectorsCreate(ceed)); 88473501bfeSJeremy L Thompson 88573501bfeSJeremy L Thompson // Search for big enough work vector 88673501bfeSJeremy L Thompson for (i = 0; i < ceed->work_vectors->num_vecs; i++) { 88773501bfeSJeremy L Thompson if (!ceed->work_vectors->is_in_use[i]) { 88873501bfeSJeremy L Thompson CeedSize work_len; 88973501bfeSJeremy L Thompson 89073501bfeSJeremy L Thompson CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &work_len)); 89173501bfeSJeremy L Thompson if (work_len >= len) break; 89273501bfeSJeremy L Thompson } 89373501bfeSJeremy L Thompson } 89473501bfeSJeremy L Thompson // Long enough vector was not found 89573501bfeSJeremy L Thompson if (i == ceed->work_vectors->num_vecs) { 89673501bfeSJeremy L Thompson if (ceed->work_vectors->max_vecs == 0) { 89773501bfeSJeremy L Thompson ceed->work_vectors->max_vecs = 1; 89873501bfeSJeremy L Thompson CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs)); 89973501bfeSJeremy L Thompson CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use)); 90073501bfeSJeremy L Thompson } else if (ceed->work_vectors->max_vecs == i) { 90173501bfeSJeremy L Thompson ceed->work_vectors->max_vecs *= 2; 90273501bfeSJeremy L Thompson CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs)); 90373501bfeSJeremy L Thompson CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use)); 90473501bfeSJeremy L Thompson } 90573501bfeSJeremy L Thompson ceed->work_vectors->num_vecs++; 90673501bfeSJeremy L Thompson CeedCallBackend(CeedVectorCreate(ceed, len, &ceed->work_vectors->vecs[i])); 90773501bfeSJeremy L Thompson ceed->ref_count--; // Note: ref_count manipulation to prevent a ref-loop 90855326fe7SZach Atkins if (ceed->is_debug) CeedGetWorkVectorMemoryUsage(ceed, &usage_mb); 90973501bfeSJeremy L Thompson } 91073501bfeSJeremy L Thompson // Return pointer to work vector 91173501bfeSJeremy L Thompson ceed->work_vectors->is_in_use[i] = true; 91273501bfeSJeremy L Thompson *vec = NULL; 91373501bfeSJeremy L Thompson CeedCall(CeedVectorReferenceCopy(ceed->work_vectors->vecs[i], vec)); 91473501bfeSJeremy L Thompson ceed->ref_count++; // Note: bump ref_count to account for external access 91573501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 91673501bfeSJeremy L Thompson } 91773501bfeSJeremy L Thompson 91873501bfeSJeremy L Thompson /** 91973501bfeSJeremy L Thompson @brief Restore a `CeedVector` for scratch work from a `Ceed` context from @ref CeedGetWorkVector() 92073501bfeSJeremy L Thompson 92173501bfeSJeremy L Thompson @param[in] ceed `Ceed` context 92273501bfeSJeremy L Thompson @param[out] vec `CeedVector` to restore 92373501bfeSJeremy L Thompson 92473501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 92573501bfeSJeremy L Thompson 92673501bfeSJeremy L Thompson @ref Backend 92773501bfeSJeremy L Thompson **/ 92873501bfeSJeremy L Thompson int CeedRestoreWorkVector(Ceed ceed, CeedVector *vec) { 929fd326ce8SZach Atkins if (!ceed->VectorCreate) { 930fd326ce8SZach Atkins Ceed delegate; 931fd326ce8SZach Atkins 932fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 933fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 934fd326ce8SZach Atkins CeedCall(CeedRestoreWorkVector(delegate, vec)); 935fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 936fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 937fd326ce8SZach Atkins } 938fd326ce8SZach Atkins 93973501bfeSJeremy L Thompson for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 94073501bfeSJeremy L Thompson if (*vec == ceed->work_vectors->vecs[i]) { 94173501bfeSJeremy 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"); 94273501bfeSJeremy L Thompson CeedCall(CeedVectorDestroy(vec)); 94373501bfeSJeremy L Thompson ceed->work_vectors->is_in_use[i] = false; 94473501bfeSJeremy L Thompson ceed->ref_count--; // Note: reduce ref_count again to prevent a ref-loop 94573501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 94673501bfeSJeremy L Thompson } 94773501bfeSJeremy L Thompson } 94873501bfeSJeremy L Thompson // LCOV_EXCL_START 94973501bfeSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MAJOR, "vec was not checked out via CeedGetWorkVector()"); 95073501bfeSJeremy L Thompson // LCOV_EXCL_STOP 95173501bfeSJeremy L Thompson } 95273501bfeSJeremy L Thompson 953b13efd58SJeremy L Thompson /** 954b13efd58SJeremy L Thompson @brief Retrieve list of additional JiT source roots from `Ceed` context. 955b13efd58SJeremy L Thompson 956b13efd58SJeremy L Thompson Note: The caller is responsible for restoring `jit_source_roots` with @ref CeedRestoreJitSourceRoots(). 957b13efd58SJeremy L Thompson 958b13efd58SJeremy L Thompson @param[in] ceed `Ceed` context 959b13efd58SJeremy L Thompson @param[out] num_source_roots Number of JiT source directories 960b13efd58SJeremy L Thompson @param[out] jit_source_roots Absolute paths to additional JiT source directories 961b13efd58SJeremy L Thompson 962b13efd58SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 963b13efd58SJeremy L Thompson 964b13efd58SJeremy L Thompson @ref Backend 965b13efd58SJeremy L Thompson **/ 966b13efd58SJeremy L Thompson int CeedGetJitSourceRoots(Ceed ceed, CeedInt *num_source_roots, const char ***jit_source_roots) { 967b13efd58SJeremy L Thompson Ceed ceed_parent; 968b13efd58SJeremy L Thompson 969b13efd58SJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 970b13efd58SJeremy L Thompson *num_source_roots = ceed_parent->num_jit_source_roots; 971b13efd58SJeremy L Thompson *jit_source_roots = (const char **)ceed_parent->jit_source_roots; 972aeb3a72dSJeremy L Thompson ceed_parent->num_jit_source_roots_readers++; 9739bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 974b13efd58SJeremy L Thompson return CEED_ERROR_SUCCESS; 975b13efd58SJeremy L Thompson } 976b13efd58SJeremy L Thompson 977b13efd58SJeremy L Thompson /** 9782027fb9dSSirAlienTheGreat @brief Retrieve list of additional Rust source roots from `Ceed` context. 9792027fb9dSSirAlienTheGreat 9802027fb9dSSirAlienTheGreat Note: The caller is responsible for restoring `rust_source_roots` with @ref CeedRestoreRustSourceRoots(). 9812027fb9dSSirAlienTheGreat 9822027fb9dSSirAlienTheGreat @param[in] ceed `Ceed` context 9832027fb9dSSirAlienTheGreat @param[out] num_source_roots Number of JiT source directories 9842027fb9dSSirAlienTheGreat @param[out] rust_source_roots Absolute paths to additional Rust source directories 9852027fb9dSSirAlienTheGreat 9862027fb9dSSirAlienTheGreat @return An error code: 0 - success, otherwise - failure 9872027fb9dSSirAlienTheGreat 9882027fb9dSSirAlienTheGreat @ref Backend 9892027fb9dSSirAlienTheGreat **/ 9902027fb9dSSirAlienTheGreat int CeedGetRustSourceRoots(Ceed ceed, CeedInt *num_source_roots, const char ***rust_source_roots) { 9912027fb9dSSirAlienTheGreat Ceed ceed_parent; 9922027fb9dSSirAlienTheGreat 9932027fb9dSSirAlienTheGreat CeedCall(CeedGetParent(ceed, &ceed_parent)); 9942027fb9dSSirAlienTheGreat *num_source_roots = ceed_parent->num_rust_source_roots; 9952027fb9dSSirAlienTheGreat *rust_source_roots = (const char **)ceed_parent->rust_source_roots; 9962027fb9dSSirAlienTheGreat ceed_parent->num_rust_source_roots_readers++; 9972027fb9dSSirAlienTheGreat CeedCall(CeedDestroy(&ceed_parent)); 9982027fb9dSSirAlienTheGreat return CEED_ERROR_SUCCESS; 9992027fb9dSSirAlienTheGreat } 10002027fb9dSSirAlienTheGreat 10012027fb9dSSirAlienTheGreat /** 1002b13efd58SJeremy L Thompson @brief Restore list of additional JiT source roots from with @ref CeedGetJitSourceRoots() 1003b13efd58SJeremy L Thompson 1004b13efd58SJeremy L Thompson @param[in] ceed `Ceed` context 1005b13efd58SJeremy L Thompson @param[out] jit_source_roots Absolute paths to additional JiT source directories 1006b13efd58SJeremy L Thompson 1007b13efd58SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1008b13efd58SJeremy L Thompson 1009b13efd58SJeremy L Thompson @ref Backend 1010b13efd58SJeremy L Thompson **/ 1011b13efd58SJeremy L Thompson int CeedRestoreJitSourceRoots(Ceed ceed, const char ***jit_source_roots) { 1012aeb3a72dSJeremy L Thompson Ceed ceed_parent; 1013aeb3a72dSJeremy L Thompson 1014aeb3a72dSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 1015b13efd58SJeremy L Thompson *jit_source_roots = NULL; 1016aeb3a72dSJeremy L Thompson ceed_parent->num_jit_source_roots_readers--; 10179bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 1018b13efd58SJeremy L Thompson return CEED_ERROR_SUCCESS; 1019b13efd58SJeremy L Thompson } 1020b13efd58SJeremy L Thompson 10214753b775SJeremy L Thompson /** 10222027fb9dSSirAlienTheGreat @brief Restore list of additional Rust source roots from with @ref CeedGetJitSourceRoots() 10232027fb9dSSirAlienTheGreat 10242027fb9dSSirAlienTheGreat @param[in] ceed `Ceed` context 10252027fb9dSSirAlienTheGreat @param[out] rust_source_roots Absolute paths to additional Rust source directories 10262027fb9dSSirAlienTheGreat 10272027fb9dSSirAlienTheGreat @return An error code: 0 - success, otherwise - failure 10282027fb9dSSirAlienTheGreat 10292027fb9dSSirAlienTheGreat @ref Backend 10302027fb9dSSirAlienTheGreat **/ 10312027fb9dSSirAlienTheGreat int CeedRestoreRustSourceRoots(Ceed ceed, const char ***rust_source_roots) { 10322027fb9dSSirAlienTheGreat Ceed ceed_parent; 10332027fb9dSSirAlienTheGreat 10342027fb9dSSirAlienTheGreat CeedCall(CeedGetParent(ceed, &ceed_parent)); 10352027fb9dSSirAlienTheGreat *rust_source_roots = NULL; 10362027fb9dSSirAlienTheGreat ceed_parent->num_rust_source_roots_readers--; 10372027fb9dSSirAlienTheGreat CeedCall(CeedDestroy(&ceed_parent)); 10382027fb9dSSirAlienTheGreat return CEED_ERROR_SUCCESS; 10392027fb9dSSirAlienTheGreat } 10402027fb9dSSirAlienTheGreat 10412027fb9dSSirAlienTheGreat /** 10424753b775SJeremy L Thompson @brief Retrieve list of additional JiT defines from `Ceed` context. 10434753b775SJeremy L Thompson 10444753b775SJeremy L Thompson Note: The caller is responsible for restoring `jit_defines` with @ref CeedRestoreJitDefines(). 10454753b775SJeremy L Thompson 10464753b775SJeremy L Thompson @param[in] ceed `Ceed` context 10474753b775SJeremy L Thompson @param[out] num_jit_defines Number of JiT defines 10484753b775SJeremy L Thompson @param[out] jit_defines Strings such as `foo=bar`, used as `-Dfoo=bar` in JiT 10494753b775SJeremy L Thompson 10504753b775SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10514753b775SJeremy L Thompson 10524753b775SJeremy L Thompson @ref Backend 10534753b775SJeremy L Thompson **/ 10542686ebe6SJed Brown int CeedGetJitDefines(Ceed ceed, CeedInt *num_jit_defines, const char ***jit_defines) { 10554753b775SJeremy L Thompson Ceed ceed_parent; 10564753b775SJeremy L Thompson 10574753b775SJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 10582686ebe6SJed Brown *num_jit_defines = ceed_parent->num_jit_defines; 10594753b775SJeremy L Thompson *jit_defines = (const char **)ceed_parent->jit_defines; 1060aeb3a72dSJeremy L Thompson ceed_parent->num_jit_defines_readers++; 10619bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 10624753b775SJeremy L Thompson return CEED_ERROR_SUCCESS; 10634753b775SJeremy L Thompson } 10644753b775SJeremy L Thompson 10654753b775SJeremy L Thompson /** 10664753b775SJeremy L Thompson @brief Restore list of additional JiT defines from with @ref CeedGetJitDefines() 10674753b775SJeremy L Thompson 10684753b775SJeremy L Thompson @param[in] ceed `Ceed` context 10694753b775SJeremy L Thompson @param[out] jit_defines String such as `foo=bar`, used as `-Dfoo=bar` in JiT 10704753b775SJeremy L Thompson 10714753b775SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10724753b775SJeremy L Thompson 10734753b775SJeremy L Thompson @ref Backend 10744753b775SJeremy L Thompson **/ 10754753b775SJeremy L Thompson int CeedRestoreJitDefines(Ceed ceed, const char ***jit_defines) { 1076aeb3a72dSJeremy L Thompson Ceed ceed_parent; 1077aeb3a72dSJeremy L Thompson 1078aeb3a72dSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 10794753b775SJeremy L Thompson *jit_defines = NULL; 1080aeb3a72dSJeremy L Thompson ceed_parent->num_jit_defines_readers--; 10819bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 10824753b775SJeremy L Thompson return CEED_ERROR_SUCCESS; 10834753b775SJeremy L Thompson } 10844753b775SJeremy L Thompson 10857a982d89SJeremy L. Thompson /// @} 10867a982d89SJeremy L. Thompson 10877a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 10887a982d89SJeremy L. Thompson /// Ceed Public API 10897a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 10907a982d89SJeremy L. Thompson /// @addtogroup CeedUser 10917a982d89SJeremy L. Thompson /// @{ 10927a982d89SJeremy L. Thompson 10937a982d89SJeremy L. Thompson /** 1094ca94c3ddSJeremy L Thompson @brief Get the list of available resource names for `Ceed` contexts 10954385fb7fSSebastian Grimberg 1096ca94c3ddSJeremy 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. 109722e44211Sjeremylt 109892ee7d1cSjeremylt @param[out] n Number of available resources 109992ee7d1cSjeremylt @param[out] resources List of available resource names 110022e44211Sjeremylt @param[out] priorities Resource name prioritization values, lower is better 110122e44211Sjeremylt 110222e44211Sjeremylt @return An error code: 0 - success, otherwise - failure 110322e44211Sjeremylt 110422e44211Sjeremylt @ref User 110522e44211Sjeremylt **/ 110622e44211Sjeremylt // LCOV_EXCL_START 11072b730f8bSJeremy L Thompson int CeedRegistryGetList(size_t *n, char ***const resources, CeedInt **priorities) { 1108d0c91ce9Sjeremylt *n = 0; 11099ff86846Sjeremylt *resources = malloc(num_backends * sizeof(**resources)); 11106574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 11119ff86846Sjeremylt if (priorities) { 11129ff86846Sjeremylt *priorities = malloc(num_backends * sizeof(**priorities)); 11136574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 11149ff86846Sjeremylt } 111522e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 1116d0c91ce9Sjeremylt // Only report compiled backends 1117d0c91ce9Sjeremylt if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) { 111822e44211Sjeremylt *resources[i] = backends[i].prefix; 11199ff86846Sjeremylt if (priorities) *priorities[i] = backends[i].priority; 1120d0c91ce9Sjeremylt *n += 1; 1121d0c91ce9Sjeremylt } 1122d0c91ce9Sjeremylt } 11236574a04fSJeremy L Thompson CeedCheck(*n, NULL, CEED_ERROR_MAJOR, "No backends installed"); 1124d0c91ce9Sjeremylt *resources = realloc(*resources, *n * sizeof(**resources)); 11256574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 1126d0c91ce9Sjeremylt if (priorities) { 1127d0c91ce9Sjeremylt *priorities = realloc(*priorities, *n * sizeof(**priorities)); 11286574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 112922e44211Sjeremylt } 113022e44211Sjeremylt return CEED_ERROR_SUCCESS; 113145f1e315Sjeremylt } 113222e44211Sjeremylt // LCOV_EXCL_STOP 113322e44211Sjeremylt 113422e44211Sjeremylt /** 1135ca94c3ddSJeremy L Thompson @brief Initialize a `Ceed` context to use the specified resource. 11364385fb7fSSebastian Grimberg 1137ca94c3ddSJeremy 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`. 1138b11c1e72Sjeremylt 1139ea61e9acSJeremy L Thompson @param[in] resource Resource to use, e.g., "/cpu/self" 1140ea61e9acSJeremy L Thompson @param[out] ceed The library context 1141b11c1e72Sjeremylt 1142b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1143dfdf5a53Sjeremylt 11447a982d89SJeremy L. Thompson @ref User 1145ca94c3ddSJeremy L Thompson 1146ca94c3ddSJeremy L Thompson @sa CeedRegister() CeedDestroy() 1147b11c1e72Sjeremylt **/ 1148d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 11492b730f8bSJeremy L Thompson size_t match_len = 0, match_index = UINT_MAX, match_priority = CEED_MAX_BACKEND_PRIORITY, priority; 1150d7b241e6Sjeremylt 1151fe2413ffSjeremylt // Find matching backend 11526574a04fSJeremy L Thompson CeedCheck(resource, NULL, CEED_ERROR_MAJOR, "No resource provided"); 11532b730f8bSJeremy L Thompson CeedCall(CeedRegisterAll()); 115413873f79Sjeremylt 115522e44211Sjeremylt // Check for help request 115622e44211Sjeremylt const char *help_prefix = "help"; 11572b730f8bSJeremy L Thompson size_t match_help = 0; 11582b730f8bSJeremy L Thompson while (match_help < 4 && resource[match_help] == help_prefix[match_help]) match_help++; 115922e44211Sjeremylt if (match_help == 4) { 11602b730f8bSJeremy L Thompson fprintf(stderr, "libCEED version: %d.%d%d%s\n", CEED_VERSION_MAJOR, CEED_VERSION_MINOR, CEED_VERSION_PATCH, 116122e44211Sjeremylt CEED_VERSION_RELEASE ? "" : "+development"); 116292ee7d1cSjeremylt fprintf(stderr, "Available backend resources:\n"); 116322e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 1164d0c91ce9Sjeremylt // Only report compiled backends 11652b730f8bSJeremy L Thompson if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) fprintf(stderr, " %s\n", backends[i].prefix); 116622e44211Sjeremylt } 116722e44211Sjeremylt fflush(stderr); 116822e44211Sjeremylt match_help = 5; // Delineating character expected 116922e44211Sjeremylt } else { 117022e44211Sjeremylt match_help = 0; 117122e44211Sjeremylt } 117222e44211Sjeremylt 1173ea61e9acSJeremy L Thompson // Find best match, computed as number of matching characters from requested resource stem 11742b730f8bSJeremy L Thompson size_t stem_length = 0; 11752b730f8bSJeremy L Thompson while (resource[stem_length + match_help] && resource[stem_length + match_help] != ':') stem_length++; 1176d7b241e6Sjeremylt for (size_t i = 0; i < num_backends; i++) { 11772b730f8bSJeremy L Thompson size_t n = 0; 1178d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 11792b730f8bSJeremy L Thompson while (prefix[n] && prefix[n] == resource[n + match_help]) n++; 1180d7b241e6Sjeremylt priority = backends[i].priority; 1181d1d35e2fSjeremylt if (n > match_len || (n == match_len && match_priority > priority)) { 1182d1d35e2fSjeremylt match_len = n; 1183d1d35e2fSjeremylt match_priority = priority; 1184f7e22acaSJeremy L Thompson match_index = i; 1185d7b241e6Sjeremylt } 1186d7b241e6Sjeremylt } 11879c9a0587SLeila Ghaffari // Using Levenshtein distance to find closest match 11889c9a0587SLeila Ghaffari if (match_len <= 1 || match_len != stem_length) { 1189203015caSLeila Ghaffari // LCOV_EXCL_START 11909c9a0587SLeila Ghaffari size_t lev_dis = UINT_MAX; 1191f7e22acaSJeremy L Thompson size_t lev_index = UINT_MAX, lev_priority = CEED_MAX_BACKEND_PRIORITY; 11929c9a0587SLeila Ghaffari for (size_t i = 0; i < num_backends; i++) { 11939c9a0587SLeila Ghaffari const char *prefix = backends[i].prefix; 11949c9a0587SLeila Ghaffari size_t prefix_length = strlen(backends[i].prefix); 11959c9a0587SLeila Ghaffari size_t min_len = (prefix_length < stem_length) ? prefix_length : stem_length; 1196092904ddSLeila Ghaffari size_t column[min_len + 1]; 1197092904ddSLeila Ghaffari for (size_t j = 0; j <= min_len; j++) column[j] = j; 11989c9a0587SLeila Ghaffari for (size_t j = 1; j <= min_len; j++) { 11999c9a0587SLeila Ghaffari column[0] = j; 12009c9a0587SLeila Ghaffari for (size_t k = 1, last_diag = j - 1; k <= min_len; k++) { 1201092904ddSLeila Ghaffari size_t old_diag = column[k]; 12029c9a0587SLeila Ghaffari size_t min_1 = (column[k] < column[k - 1]) ? column[k] + 1 : column[k - 1] + 1; 12039c9a0587SLeila Ghaffari size_t min_2 = last_diag + (resource[k - 1] == prefix[j - 1] ? 0 : 1); 12049c9a0587SLeila Ghaffari column[k] = (min_1 < min_2) ? min_1 : min_2; 12059c9a0587SLeila Ghaffari last_diag = old_diag; 12069c9a0587SLeila Ghaffari } 12079c9a0587SLeila Ghaffari } 12089c9a0587SLeila Ghaffari size_t n = column[min_len]; 12099c9a0587SLeila Ghaffari priority = backends[i].priority; 12102b730f8bSJeremy L Thompson if (n < lev_dis || (n == lev_dis && lev_priority > priority)) { 12119c9a0587SLeila Ghaffari lev_dis = n; 12129c9a0587SLeila Ghaffari lev_priority = priority; 1213f7e22acaSJeremy L Thompson lev_index = i; 12149c9a0587SLeila Ghaffari } 12159c9a0587SLeila Ghaffari } 1216f7e22acaSJeremy L Thompson const char *prefix_lev = backends[lev_index].prefix; 12172b730f8bSJeremy L Thompson size_t lev_length = 0; 12182b730f8bSJeremy L Thompson while (prefix_lev[lev_length] && prefix_lev[lev_length] != '\0') lev_length++; 12199c9a0587SLeila Ghaffari size_t m = (lev_length < stem_length) ? lev_length : stem_length; 12206574a04fSJeremy L Thompson if (lev_dis + 1 >= m) return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s", resource); 12216574a04fSJeremy L Thompson else return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s\nClosest match: %s", resource, backends[lev_index].prefix); 1222203015caSLeila Ghaffari // LCOV_EXCL_STOP 12239c9a0587SLeila Ghaffari } 1224fe2413ffSjeremylt 1225fe2413ffSjeremylt // Setup Ceed 12262b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, ceed)); 12272b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &(*ceed)->jit_source_roots)); 12282027fb9dSSirAlienTheGreat CeedCall(CeedCalloc(1, &(*ceed)->rust_source_roots)); 1229bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 12302b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 12312b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "exit")) (*ceed)->Error = CeedErrorExit; 12322b730f8bSJeremy L Thompson else if (!strcmp(ceed_error_handler, "store")) (*ceed)->Error = CeedErrorStore; 12332b730f8bSJeremy L Thompson else (*ceed)->Error = CeedErrorAbort; 1234d1d35e2fSjeremylt memcpy((*ceed)->err_msg, "No error message stored", 24); 1235d1d35e2fSjeremylt (*ceed)->ref_count = 1; 1236d7b241e6Sjeremylt (*ceed)->data = NULL; 1237fe2413ffSjeremylt 1238fe2413ffSjeremylt // Set lookup table 1239d1d35e2fSjeremylt FOffset f_offsets[] = { 12406e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 12415ae360d4SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, SetStream), 12426e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 12436e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 1244f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 12456e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 12463ac8f562SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateAtPoints), 12476e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 12486e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 12496e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 125050c301a5SRezgar Shakeri CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv), 1251c4e3f59bSSebastian Grimberg CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl), 12526e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 12536e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 1254777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate), 12556e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 125648acf710SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, OperatorCreateAtPoints), 12576e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 12589c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasValidArray), 12599c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType), 12600b8f3c4eSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, CopyStrided), 12616e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 12626a6c615bSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, TakeArray), 12636e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 12640b8f3c4eSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, SetValueStrided), 1265f48ed27dSnbeams CEED_FTABLE_ENTRY(CeedVector, SyncArray), 12666e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 12676e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 12689c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite), 12696e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 12706e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 1271547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 1272e0dd3b27Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Scale), 12730f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, AXPY), 12745fb68f37SKaren (Ren) Stengel CEED_FTABLE_ENTRY(CeedVector, AXPBY), 12750f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, PointwiseMult), 1276d99fa3c5SJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, Reciprocal), 12776e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 12786e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 1279f30b1135SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnsigned), 12807c1dbaffSSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnoriented), 128105fa913cSJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyAtPointsInElement), 12826e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 1283bd33150aSjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets), 128477d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetOrientations), 128577d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetCurlOrientations), 128619605835SJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, GetAtPointsElementOffset), 12876e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 12886e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 1289db2becc9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAdd), 1290c8c3fa7dSJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAtPoints), 1291db2becc9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAddAtPoints), 12926e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 12936e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 12946e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 12956e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 12968c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction), 12978c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction), 12986e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 12999c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData), 13009c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType), 1301777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData), 1302891038deSjeremylt CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData), 1303777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData), 130428bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead), 1305777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData), 130628bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead), 13072e64a2b9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy), 1308777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy), 130980ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction), 131070a7ffb3SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate), 131180ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal), 13129e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal), 131380ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal), 13149e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal), 1315e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic), 1316e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble), 1317cefa2673SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle), 1318713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 13196e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 1320250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 1321cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 1322250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 13236e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 13246e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 13256e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 13261dfeef1dSjeremylt }; 1327fe2413ffSjeremylt 13282b730f8bSJeremy L Thompson CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets)); 1329d1d35e2fSjeremylt memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets)); 1330fe2413ffSjeremylt 133160f9e2d6SJeremy L Thompson // Record env variables CEED_DEBUG or DBG 13321c66c397SJeremy L Thompson (*ceed)->is_debug = getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); 133360f9e2d6SJeremy L Thompson 133422e44211Sjeremylt // Copy resource prefix, if backend setup successful 13352b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource)); 1336ee5a26f2SJeremy L Thompson 1337ee5a26f2SJeremy L Thompson // Set default JiT source root 1338ea61e9acSJeremy L Thompson // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent 13392b730f8bSJeremy L Thompson CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault)); 1340ee5a26f2SJeremy L Thompson 13412027fb9dSSirAlienTheGreat // By default, make cuda compile without clang, use nvrtc instead 13422027fb9dSSirAlienTheGreat // Note that this is overridden if a rust file is included (rust requires clang) 13432027fb9dSSirAlienTheGreat const char *env = getenv("GPU_CLANG"); 13442027fb9dSSirAlienTheGreat 13452027fb9dSSirAlienTheGreat if (env && strcmp(env, "1") == 0) { 13462027fb9dSSirAlienTheGreat (*ceed)->cuda_compile_with_clang = true; 13472027fb9dSSirAlienTheGreat } else { 13482027fb9dSSirAlienTheGreat (*ceed)->cuda_compile_with_clang = false; 13492027fb9dSSirAlienTheGreat } 13502027fb9dSSirAlienTheGreat 1351d04bbc78SJeremy L Thompson // Backend specific setup 13522b730f8bSJeremy L Thompson CeedCall(backends[match_index].init(&resource[match_help], *ceed)); 1353e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1354d7b241e6Sjeremylt } 1355d7b241e6Sjeremylt 1356d7b241e6Sjeremylt /** 1357ca94c3ddSJeremy L Thompson @brief Set the GPU stream for a `Ceed` context 13585ae360d4SJeremy L Thompson 1359ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set the stream 13605ae360d4SJeremy L Thompson @param[in] handle Handle to GPU stream 13615ae360d4SJeremy L Thompson 13625ae360d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13635ae360d4SJeremy L Thompson 13645ae360d4SJeremy L Thompson @ref User 13655ae360d4SJeremy L Thompson **/ 13665ae360d4SJeremy L Thompson int CeedSetStream(Ceed ceed, void *handle) { 1367ca94c3ddSJeremy L Thompson CeedCheck(handle, ceed, CEED_ERROR_INCOMPATIBLE, "Stream handle must be non-NULL"); 13689ffb25e0SJames Wright if (ceed->SetStream) { 13695ae360d4SJeremy L Thompson CeedCall(ceed->SetStream(ceed, handle)); 13709ffb25e0SJames Wright } else { 13719ffb25e0SJames Wright Ceed delegate; 13729ffb25e0SJames Wright CeedCall(CeedGetDelegate(ceed, &delegate)); 13735ae360d4SJeremy L Thompson 137428ce3d2aSJeremy L Thompson if (delegate) CeedCall(CeedSetStream(delegate, handle)); 137528ce3d2aSJeremy L Thompson else return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support setting stream"); 13769bc66399SJeremy L Thompson CeedCall(CeedDestroy(&delegate)); 13779ffb25e0SJames Wright } 13785ae360d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 13795ae360d4SJeremy L Thompson } 13805ae360d4SJeremy L Thompson 13815ae360d4SJeremy L Thompson /** 1382ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `Ceed` context. 13834385fb7fSSebastian Grimberg 1384ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedDestroy(). 1385512bb800SJeremy L Thompson 1386ca94c3ddSJeremy 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. 1387ca94c3ddSJeremy L Thompson This `Ceed` context will be destroyed if `*ceed_copy` is the only reference to this `Ceed` context. 13889560d06aSjeremylt 1389ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to copy reference to 1390ea61e9acSJeremy L Thompson @param[in,out] ceed_copy Variable to store copied reference 13919560d06aSjeremylt 13929560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 13939560d06aSjeremylt 13949560d06aSjeremylt @ref User 13959560d06aSjeremylt **/ 13969560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) { 13972b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 13982b730f8bSJeremy L Thompson CeedCall(CeedDestroy(ceed_copy)); 13999560d06aSjeremylt *ceed_copy = ceed; 14009560d06aSjeremylt return CEED_ERROR_SUCCESS; 14019560d06aSjeremylt } 14029560d06aSjeremylt 14039560d06aSjeremylt /** 1404ca94c3ddSJeremy L Thompson @brief Get the full resource name for a `Ceed` context 14052f86a920SJeremy L Thompson 1406ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get resource name of 14077a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 14082f86a920SJeremy L Thompson 14092f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 14102f86a920SJeremy L Thompson 14117a982d89SJeremy L. Thompson @ref User 14125107b09fSJeremy L Thompson **/ 14137a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 14147a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 1415e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 14165107b09fSJeremy L Thompson } 14175107b09fSJeremy L Thompson 14185107b09fSJeremy L Thompson /** 1419ca94c3ddSJeremy L Thompson @brief Return `Ceed` context preferred memory type 1420c907536fSjeremylt 1421ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get preferred memory type of 1422d1d35e2fSjeremylt @param[out] mem_type Address to save preferred memory type to 1423c907536fSjeremylt 1424c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 1425c907536fSjeremylt 14267a982d89SJeremy L. Thompson @ref User 1427c907536fSjeremylt **/ 1428d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) { 1429c907536fSjeremylt if (ceed->GetPreferredMemType) { 14302b730f8bSJeremy L Thompson CeedCall(ceed->GetPreferredMemType(mem_type)); 1431c907536fSjeremylt } else { 1432c263cd57Sjeremylt Ceed delegate; 14332b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, &delegate)); 1434c263cd57Sjeremylt 1435c263cd57Sjeremylt if (delegate) { 14362b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(delegate, mem_type)); 1437c263cd57Sjeremylt } else { 1438d1d35e2fSjeremylt *mem_type = CEED_MEM_HOST; 1439c907536fSjeremylt } 14409bc66399SJeremy L Thompson CeedCall(CeedDestroy(&delegate)); 1441c263cd57Sjeremylt } 1442e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1443c907536fSjeremylt } 1444c907536fSjeremylt 1445c907536fSjeremylt /** 1446ca94c3ddSJeremy L Thompson @brief Get deterministic status of `Ceed` context 14479525855cSJeremy L Thompson 1448ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 1449d1d35e2fSjeremylt @param[out] is_deterministic Variable to store deterministic status 14509525855cSJeremy L Thompson 14519525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 14529525855cSJeremy L Thompson 14539525855cSJeremy L Thompson @ref User 14549525855cSJeremy L Thompson **/ 1455d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) { 1456d1d35e2fSjeremylt *is_deterministic = ceed->is_deterministic; 1457e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 14589525855cSJeremy L Thompson } 14599525855cSJeremy L Thompson 14609525855cSJeremy L Thompson /** 1461ca94c3ddSJeremy L Thompson @brief Set additional JiT source root for `Ceed` context 1462ee5a26f2SJeremy L Thompson 1463ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context 1464ee5a26f2SJeremy L Thompson @param[in] jit_source_root Absolute path to additional JiT source directory 1465ee5a26f2SJeremy L Thompson 1466ee5a26f2SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1467ee5a26f2SJeremy L Thompson 1468ee5a26f2SJeremy L Thompson @ref User 1469ee5a26f2SJeremy L Thompson **/ 1470ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) { 14716155f12fSJeremy L Thompson Ceed ceed_parent; 1472ee5a26f2SJeremy L Thompson 14732b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 1474830fc37bSJeremy L Thompson CeedCheck(!ceed_parent->num_jit_source_roots_readers, ceed, CEED_ERROR_ACCESS, "Cannot add JiT source root, read access has not been restored"); 14756155f12fSJeremy L Thompson 14766155f12fSJeremy L Thompson CeedInt index = ceed_parent->num_jit_source_roots; 1477ee5a26f2SJeremy L Thompson size_t path_length = strlen(jit_source_root); 14781c66c397SJeremy L Thompson 14794753b775SJeremy L Thompson if (ceed_parent->num_jit_source_roots == ceed_parent->max_jit_source_roots) { 14804753b775SJeremy L Thompson if (ceed_parent->max_jit_source_roots == 0) ceed_parent->max_jit_source_roots = 1; 14814753b775SJeremy L Thompson ceed_parent->max_jit_source_roots *= 2; 14824753b775SJeremy L Thompson CeedCall(CeedRealloc(ceed_parent->max_jit_source_roots, &ceed_parent->jit_source_roots)); 14834753b775SJeremy L Thompson } 14842b730f8bSJeremy L Thompson CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index])); 1485d602d780SJeremy L Thompson memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length); 14866155f12fSJeremy L Thompson ceed_parent->num_jit_source_roots++; 14879bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 1488ee5a26f2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1489ee5a26f2SJeremy L Thompson } 1490ee5a26f2SJeremy L Thompson 1491ee5a26f2SJeremy L Thompson /** 14922027fb9dSSirAlienTheGreat @brief Set additional Rust source root for `Ceed` context for use in QFunction 14932027fb9dSSirAlienTheGreat 14942027fb9dSSirAlienTheGreat @param[in,out] ceed `Ceed` context 14952027fb9dSSirAlienTheGreat @param[in] rust_source_root Absolute path to additional Rust source directory 14962027fb9dSSirAlienTheGreat 14972027fb9dSSirAlienTheGreat @return An error code: 0 - success, otherwise - failure 14982027fb9dSSirAlienTheGreat 14992027fb9dSSirAlienTheGreat @ref User 15002027fb9dSSirAlienTheGreat **/ 15012027fb9dSSirAlienTheGreat int CeedAddRustSourceRoot(Ceed ceed, const char *rust_source_root) { 15022027fb9dSSirAlienTheGreat Ceed ceed_parent; 15032027fb9dSSirAlienTheGreat 15042027fb9dSSirAlienTheGreat CeedCall(CeedGetParent(ceed, &ceed_parent)); 15052027fb9dSSirAlienTheGreat CeedCheck(!ceed_parent->num_rust_source_roots_readers, ceed, CEED_ERROR_ACCESS, "Cannot add Rust source root, read access has not been restored"); 15062027fb9dSSirAlienTheGreat 15072027fb9dSSirAlienTheGreat CeedInt index = ceed_parent->num_rust_source_roots; 15082027fb9dSSirAlienTheGreat size_t path_length = strlen(rust_source_root); 15092027fb9dSSirAlienTheGreat 15102027fb9dSSirAlienTheGreat if (ceed_parent->num_rust_source_roots == ceed_parent->max_rust_source_roots) { 15112027fb9dSSirAlienTheGreat if (ceed_parent->max_rust_source_roots == 0) ceed_parent->max_rust_source_roots = 1; 15122027fb9dSSirAlienTheGreat ceed_parent->max_rust_source_roots *= 2; 15132027fb9dSSirAlienTheGreat CeedCall(CeedRealloc(ceed_parent->max_rust_source_roots, &ceed_parent->rust_source_roots)); 15142027fb9dSSirAlienTheGreat } 15152027fb9dSSirAlienTheGreat CeedCall(CeedCalloc(path_length + 1, &ceed_parent->rust_source_roots[index])); 15162027fb9dSSirAlienTheGreat memcpy(ceed_parent->rust_source_roots[index], rust_source_root, path_length); 15172027fb9dSSirAlienTheGreat ceed_parent->num_rust_source_roots++; 15182027fb9dSSirAlienTheGreat ceed_parent->cuda_compile_with_clang = true; 15192027fb9dSSirAlienTheGreat ceed->cuda_compile_with_clang = true; 15202027fb9dSSirAlienTheGreat CeedCall(CeedDestroy(&ceed_parent)); 15212027fb9dSSirAlienTheGreat return CEED_ERROR_SUCCESS; 15222027fb9dSSirAlienTheGreat } 15232027fb9dSSirAlienTheGreat 15242027fb9dSSirAlienTheGreat /** 15254753b775SJeremy L Thompson @brief Set additional JiT compiler define for `Ceed` context 15264753b775SJeremy L Thompson 15274753b775SJeremy L Thompson @param[in,out] ceed `Ceed` context 15284753b775SJeremy L Thompson @param[in] jit_define String such as `foo=bar`, used as `-Dfoo=bar` in JiT 15294753b775SJeremy L Thompson 15304753b775SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 15314753b775SJeremy L Thompson 15324753b775SJeremy L Thompson @ref User 15334753b775SJeremy L Thompson **/ 15344753b775SJeremy L Thompson int CeedAddJitDefine(Ceed ceed, const char *jit_define) { 15354753b775SJeremy L Thompson Ceed ceed_parent; 15364753b775SJeremy L Thompson 15374753b775SJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 1538830fc37bSJeremy L Thompson CeedCheck(!ceed_parent->num_jit_defines_readers, ceed, CEED_ERROR_ACCESS, "Cannot add JiT define, read access has not been restored"); 15394753b775SJeremy L Thompson 15404753b775SJeremy L Thompson CeedInt index = ceed_parent->num_jit_defines; 15414753b775SJeremy L Thompson size_t define_length = strlen(jit_define); 15424753b775SJeremy L Thompson 15434753b775SJeremy L Thompson if (ceed_parent->num_jit_defines == ceed_parent->max_jit_defines) { 15444753b775SJeremy L Thompson if (ceed_parent->max_jit_defines == 0) ceed_parent->max_jit_defines = 1; 15454753b775SJeremy L Thompson ceed_parent->max_jit_defines *= 2; 15464753b775SJeremy L Thompson CeedCall(CeedRealloc(ceed_parent->max_jit_defines, &ceed_parent->jit_defines)); 15474753b775SJeremy L Thompson } 15484753b775SJeremy L Thompson CeedCall(CeedCalloc(define_length + 1, &ceed_parent->jit_defines[index])); 15494753b775SJeremy L Thompson memcpy(ceed_parent->jit_defines[index], jit_define, define_length); 15504753b775SJeremy L Thompson ceed_parent->num_jit_defines++; 15519bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 15524753b775SJeremy L Thompson return CEED_ERROR_SUCCESS; 15534753b775SJeremy L Thompson } 15544753b775SJeremy L Thompson 15554753b775SJeremy L Thompson /** 1556*4c789ea2SJeremy L Thompson @brief Set the number of tabs to indent for @ref CeedView() output 1557*4c789ea2SJeremy L Thompson 1558*4c789ea2SJeremy L Thompson @param[in] ceed `Ceed` to set the number of view tabs 1559*4c789ea2SJeremy L Thompson @param[in] num_tabs Number of view tabs to set 1560*4c789ea2SJeremy L Thompson 1561*4c789ea2SJeremy L Thompson @return Error code: 0 - success, otherwise - failure 1562*4c789ea2SJeremy L Thompson 1563*4c789ea2SJeremy L Thompson @ref User 1564*4c789ea2SJeremy L Thompson **/ 1565*4c789ea2SJeremy L Thompson int CeedSetNumViewTabs(Ceed ceed, CeedInt num_tabs) { 1566*4c789ea2SJeremy L Thompson CeedCheck(num_tabs >= 0, ceed, CEED_ERROR_MINOR, "Number of view tabs must be non-negative"); 1567*4c789ea2SJeremy L Thompson ceed->num_tabs = num_tabs; 1568*4c789ea2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1569*4c789ea2SJeremy L Thompson } 1570*4c789ea2SJeremy L Thompson 1571*4c789ea2SJeremy L Thompson /** 1572ca94c3ddSJeremy L Thompson @brief View a `Ceed` 15730a0da059Sjeremylt 1574ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` to view 15750a0da059Sjeremylt @param[in] stream Filestream to write to 15760a0da059Sjeremylt 15770a0da059Sjeremylt @return An error code: 0 - success, otherwise - failure 15780a0da059Sjeremylt 15790a0da059Sjeremylt @ref User 15800a0da059Sjeremylt **/ 15810a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) { 1582*4c789ea2SJeremy L Thompson char *tabs = NULL; 1583d1d35e2fSjeremylt CeedMemType mem_type; 15840a0da059Sjeremylt 1585*4c789ea2SJeremy L Thompson { 1586*4c789ea2SJeremy L Thompson CeedInt num_tabs = 0; 1587*4c789ea2SJeremy L Thompson 1588*4c789ea2SJeremy L Thompson CeedCall(CeedGetNumViewTabs(ceed, &num_tabs)); 1589*4c789ea2SJeremy L Thompson CeedCall(CeedCalloc(CEED_TAB_WIDTH * num_tabs + 1, &tabs)); 1590*4c789ea2SJeremy L Thompson for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' '; 1591*4c789ea2SJeremy L Thompson } 1592*4c789ea2SJeremy L Thompson 15932b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 15940a0da059Sjeremylt 15952b730f8bSJeremy L Thompson fprintf(stream, 1596*4c789ea2SJeremy L Thompson "%sCeed\n" 1597*4c789ea2SJeremy L Thompson "%s Ceed Resource: %s\n" 1598*4c789ea2SJeremy L Thompson "%s Preferred MemType: %s\n", 1599*4c789ea2SJeremy L Thompson tabs, tabs, ceed->resource, tabs, CeedMemTypes[mem_type]); 1600*4c789ea2SJeremy L Thompson CeedCall(CeedFree(&tabs)); 1601e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 16020a0da059Sjeremylt } 16030a0da059Sjeremylt 16040a0da059Sjeremylt /** 1605ca94c3ddSJeremy L Thompson @brief Destroy a `Ceed` 1606d7b241e6Sjeremylt 1607ca94c3ddSJeremy L Thompson @param[in,out] ceed Address of `Ceed` context to destroy 1608b11c1e72Sjeremylt 1609b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1610dfdf5a53Sjeremylt 16117a982d89SJeremy L. Thompson @ref User 1612b11c1e72Sjeremylt **/ 1613d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 1614ad6481ceSJeremy L Thompson if (!*ceed || --(*ceed)->ref_count > 0) { 1615ad6481ceSJeremy L Thompson *ceed = NULL; 1616ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1617ad6481ceSJeremy L Thompson } 1618aeb3a72dSJeremy L Thompson 1619aeb3a72dSJeremy L Thompson CeedCheck(!(*ceed)->num_jit_source_roots_readers, *ceed, CEED_ERROR_ACCESS, 1620aeb3a72dSJeremy L Thompson "Cannot destroy ceed context, read access for JiT source roots has been granted"); 1621aeb3a72dSJeremy L Thompson CeedCheck(!(*ceed)->num_jit_defines_readers, *ceed, CEED_ERROR_ACCESS, "Cannot add JiT source root, read access for JiT defines has been granted"); 1622aeb3a72dSJeremy L Thompson 16232b730f8bSJeremy L Thompson if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate)); 16240ace9bf2Sjeremylt 1625d1d35e2fSjeremylt if ((*ceed)->obj_delegate_count > 0) { 162692ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) { 16272b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate))); 16282b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name)); 1629aefd8378Sjeremylt } 16302b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates)); 1631aefd8378Sjeremylt } 16320ace9bf2Sjeremylt 16332b730f8bSJeremy L Thompson if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed)); 16340ace9bf2Sjeremylt 163592ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) { 16362b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots[i])); 1637032e71eaSJeremy L Thompson } 16382b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots)); 1639032e71eaSJeremy L Thompson 16404753b775SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_defines; i++) { 16414753b775SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_defines[i])); 16424753b775SJeremy L Thompson } 16434753b775SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_defines)); 16444753b775SJeremy L Thompson 1645898eb931SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_rust_source_roots; i++) { 1646898eb931SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->rust_source_roots[i])); 1647898eb931SJeremy L Thompson } 1648898eb931SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->rust_source_roots)); 1649898eb931SJeremy L Thompson 16502b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->f_offsets)); 16512b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->resource)); 16522b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed)); 165373501bfeSJeremy L Thompson CeedCall(CeedWorkVectorsDestroy(*ceed)); 16542b730f8bSJeremy L Thompson CeedCall(CeedFree(ceed)); 1655e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1656d7b241e6Sjeremylt } 1657d7b241e6Sjeremylt 1658f9982c62SWill Pazner // LCOV_EXCL_START 1659f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) { 16602b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args); 166178464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 166278464608Sjeremylt vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args); // NOLINT 1663d1d35e2fSjeremylt return ceed->err_msg; 1664f9982c62SWill Pazner } 1665f9982c62SWill Pazner // LCOV_EXCL_STOP 1666f9982c62SWill Pazner 16677a982d89SJeremy L. Thompson /** 1668ca94c3ddSJeremy L Thompson @brief Error handling implementation; use @ref CeedError() instead. 1669ca94c3ddSJeremy L Thompson 1670ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 16717a982d89SJeremy L. Thompson 16727a982d89SJeremy L. Thompson @ref Developer 16737a982d89SJeremy L. Thompson **/ 16742b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) { 16757a982d89SJeremy L. Thompson va_list args; 1676d1d35e2fSjeremylt int ret_val; 16771c66c397SJeremy L Thompson 16787a982d89SJeremy L. Thompson va_start(args, format); 16797a982d89SJeremy L. Thompson if (ceed) { 1680d1d35e2fSjeremylt ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args); 16817a982d89SJeremy L. Thompson } else { 1682b0d62198Sjeremylt // LCOV_EXCL_START 1683477729cfSJeremy L Thompson const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 16842b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 1685bcbe1c99SJeremy L Thompson if (!strcmp(ceed_error_handler, "return")) { 1686bcbe1c99SJeremy L Thompson ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args); 1687bcbe1c99SJeremy L Thompson } else { 1688477729cfSJeremy L Thompson // This function will not return 1689d1d35e2fSjeremylt ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args); 16907a982d89SJeremy L. Thompson } 1691bcbe1c99SJeremy L Thompson } 16927a982d89SJeremy L. Thompson va_end(args); 1693d1d35e2fSjeremylt return ret_val; 1694b0d62198Sjeremylt // LCOV_EXCL_STOP 16957a982d89SJeremy L. Thompson } 16967a982d89SJeremy L. Thompson 1697477729cfSJeremy L Thompson /** 1698477729cfSJeremy L Thompson @brief Error handler that returns without printing anything. 1699477729cfSJeremy L Thompson 1700ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1701ca94c3ddSJeremy L Thompson 1702ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1703477729cfSJeremy L Thompson 1704477729cfSJeremy L Thompson @ref Developer 1705477729cfSJeremy L Thompson **/ 1706477729cfSJeremy L Thompson // LCOV_EXCL_START 17072b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1708d1d35e2fSjeremylt return err_code; 1709477729cfSJeremy L Thompson } 1710477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1711477729cfSJeremy L Thompson 1712477729cfSJeremy L Thompson /** 1713ea61e9acSJeremy L Thompson @brief Error handler that stores the error message for future use and returns the error. 1714477729cfSJeremy L Thompson 1715ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1716ca94c3ddSJeremy L Thompson 1717ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1718477729cfSJeremy L Thompson 1719477729cfSJeremy L Thompson @ref Developer 1720477729cfSJeremy L Thompson **/ 1721477729cfSJeremy L Thompson // LCOV_EXCL_START 17222b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 17232b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args); 1724477729cfSJeremy L Thompson 1725477729cfSJeremy L Thompson // Build message 17261c66c397SJeremy L Thompson int len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%s:%d in %s(): ", filename, line_no, func); 172778464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 172878464608Sjeremylt vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args); // NOLINT 1729d1d35e2fSjeremylt return err_code; 1730477729cfSJeremy L Thompson } 1731477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1732477729cfSJeremy L Thompson 1733477729cfSJeremy L Thompson /** 1734ca94c3ddSJeremy L Thompson @brief Error handler that prints to `stderr` and aborts 1735477729cfSJeremy L Thompson 1736ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1737ca94c3ddSJeremy L Thompson 1738ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1739477729cfSJeremy L Thompson 1740477729cfSJeremy L Thompson @ref Developer 1741477729cfSJeremy L Thompson **/ 1742477729cfSJeremy L Thompson // LCOV_EXCL_START 17432b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1744d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 1745f9982c62SWill Pazner vfprintf(stderr, format, *args); 1746477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1747477729cfSJeremy L Thompson abort(); 1748d1d35e2fSjeremylt return err_code; 1749477729cfSJeremy L Thompson } 1750477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1751477729cfSJeremy L Thompson 1752477729cfSJeremy L Thompson /** 1753ca94c3ddSJeremy L Thompson @brief Error handler that prints to `stderr` and exits. 1754477729cfSJeremy L Thompson 1755ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1756477729cfSJeremy L Thompson 1757ca94c3ddSJeremy L Thompson In contrast to @ref CeedErrorAbort(), this exits without a signal, so `atexit()` handlers (e.g., as used by gcov) are run. 1758ca94c3ddSJeremy L Thompson 1759ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1760477729cfSJeremy L Thompson 1761477729cfSJeremy L Thompson @ref Developer 1762477729cfSJeremy L Thompson **/ 17632b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1764d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 176578464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 176678464608Sjeremylt vfprintf(stderr, format, *args); // NOLINT 1767477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1768d1d35e2fSjeremylt exit(err_code); 1769d1d35e2fSjeremylt return err_code; 1770477729cfSJeremy L Thompson } 1771477729cfSJeremy L Thompson 1772477729cfSJeremy L Thompson /** 1773477729cfSJeremy L Thompson @brief Set error handler 1774477729cfSJeremy L Thompson 1775ca94c3ddSJeremy L Thompson A default error handler is set in @ref CeedInit(). 1776ca94c3ddSJeremy L Thompson Use this function to change the error handler to @ref CeedErrorReturn(), @ref CeedErrorAbort(), or a user-defined error handler. 1777ca94c3ddSJeremy L Thompson 1778ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1779477729cfSJeremy L Thompson 1780477729cfSJeremy L Thompson @ref Developer 1781477729cfSJeremy L Thompson **/ 1782d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) { 1783d1d35e2fSjeremylt ceed->Error = handler; 1784d1d35e2fSjeremylt if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler); 17852b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler); 1786e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1787477729cfSJeremy L Thompson } 1788477729cfSJeremy L Thompson 1789477729cfSJeremy L Thompson /** 1790477729cfSJeremy L Thompson @brief Get error message 1791477729cfSJeremy L Thompson 1792ca94c3ddSJeremy L Thompson The error message is only stored when using the error handler @ref CeedErrorStore() 1793477729cfSJeremy L Thompson 1794ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve error message 1795d1d35e2fSjeremylt @param[out] err_msg Char pointer to hold error message 1796477729cfSJeremy L Thompson 1797ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1798ca94c3ddSJeremy L Thompson 1799477729cfSJeremy L Thompson @ref Developer 1800477729cfSJeremy L Thompson **/ 1801d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) { 18022b730f8bSJeremy L Thompson if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg); 1803d1d35e2fSjeremylt *err_msg = ceed->err_msg; 1804e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1805477729cfSJeremy L Thompson } 1806477729cfSJeremy L Thompson 1807477729cfSJeremy L Thompson /** 1808ca94c3ddSJeremy L Thompson @brief Restore error message. 1809477729cfSJeremy L Thompson 1810ca94c3ddSJeremy L Thompson The error message is only stored when using the error handler @ref CeedErrorStore(). 1811477729cfSJeremy L Thompson 1812ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to restore error message 1813d1d35e2fSjeremylt @param[out] err_msg Char pointer that holds error message 1814477729cfSJeremy L Thompson 1815ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1816ca94c3ddSJeremy L Thompson 1817477729cfSJeremy L Thompson @ref Developer 1818477729cfSJeremy L Thompson **/ 1819d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) { 18202b730f8bSJeremy L Thompson if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg); 1821d1d35e2fSjeremylt *err_msg = NULL; 1822d1d35e2fSjeremylt memcpy(ceed->err_msg, "No error message stored", 24); 1823e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1824477729cfSJeremy L Thompson } 1825477729cfSJeremy L Thompson 18261070991dSJed Brown /** 1827ca94c3ddSJeremy L Thompson @brief Get libCEED library version information. 18281070991dSJed Brown 1829ea61e9acSJeremy L Thompson libCEED version numbers have the form major.minor.patch. 1830ea61e9acSJeremy L Thompson Non-release versions may contain unstable interfaces. 18311070991dSJed Brown 18321070991dSJed Brown @param[out] major Major version of the library 18331070991dSJed Brown @param[out] minor Minor version of the library 18341070991dSJed Brown @param[out] patch Patch (subminor) version of the library 183553cbfc38SJeremy L Thompson @param[out] release True for releases; false for development branches 18361070991dSJed Brown 1837ca94c3ddSJeremy L Thompson The caller may pass `NULL` for any arguments that are not needed. 18381070991dSJed Brown 1839ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 18401070991dSJed Brown 18411070991dSJed Brown @ref Developer 1842ca94c3ddSJeremy L Thompson 18434f69910bSJed Brown @sa CEED_VERSION_GE() CeedGetGitVersion() CeedGetBuildConfiguration() 18441070991dSJed Brown */ 18451070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) { 18461070991dSJed Brown if (major) *major = CEED_VERSION_MAJOR; 18471070991dSJed Brown if (minor) *minor = CEED_VERSION_MINOR; 18481070991dSJed Brown if (patch) *patch = CEED_VERSION_PATCH; 18491070991dSJed Brown if (release) *release = CEED_VERSION_RELEASE; 1850ca94c3ddSJeremy L Thompson return CEED_ERROR_SUCCESS; 18511070991dSJed Brown } 18521070991dSJed Brown 185353cbfc38SJeremy L Thompson /** 185453cbfc38SJeremy L Thompson @brief Get libCEED scalar type, such as F64 or F32 185553cbfc38SJeremy L Thompson 185653cbfc38SJeremy L Thompson @param[out] scalar_type Type of libCEED scalars 185753cbfc38SJeremy L Thompson 1858ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1859ca94c3ddSJeremy L Thompson 186053cbfc38SJeremy L Thompson @ref Developer 186153cbfc38SJeremy L Thompson */ 186280a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) { 186380a9ef05SNatalie Beams *scalar_type = CEED_SCALAR_TYPE; 1864ca94c3ddSJeremy L Thompson return CEED_ERROR_SUCCESS; 186580a9ef05SNatalie Beams } 186680a9ef05SNatalie Beams 1867d7b241e6Sjeremylt /// @} 1868