19ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, 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"); 168b0f67a9cSJeremy L Thompson // Note: increase ref_count to prevent Ceed destructor from triggering again 169b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)ceed)); 170b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)ceed)); 17173501bfeSJeremy L Thompson CeedCall(CeedVectorDestroy(&ceed->work_vectors->vecs[i])); 172b0f67a9cSJeremy L Thompson // Note: restore ref_count 173b0f67a9cSJeremy L Thompson CeedObjectDereference((CeedObject)ceed); 17473501bfeSJeremy L Thompson } 17573501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors->is_in_use)); 17673501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors->vecs)); 17773501bfeSJeremy L Thompson CeedCall(CeedFree(&ceed->work_vectors)); 17873501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 17973501bfeSJeremy L Thompson } 18073501bfeSJeremy L Thompson 181b0f67a9cSJeremy L Thompson /** 182b0f67a9cSJeremy L Thompson @brief View a `Ceed` passed as a `CeedObject` 183b0f67a9cSJeremy L Thompson 184b0f67a9cSJeremy L Thompson @param[in] ceed `Ceed` to view 185b0f67a9cSJeremy L Thompson @param[in] stream Filestream to write to 186b0f67a9cSJeremy L Thompson 187b0f67a9cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 188b0f67a9cSJeremy L Thompson 189b0f67a9cSJeremy L Thompson @ref Developer 190b0f67a9cSJeremy L Thompson **/ 191b0f67a9cSJeremy L Thompson static int CeedView_Object(CeedObject ceed, FILE *stream) { 192b0f67a9cSJeremy L Thompson CeedCall(CeedView((Ceed)ceed, stream)); 193b0f67a9cSJeremy L Thompson return CEED_ERROR_SUCCESS; 194b0f67a9cSJeremy L Thompson } 195b0f67a9cSJeremy L Thompson 196*6c328a79SJeremy L Thompson /** 197*6c328a79SJeremy L Thompson @brief Destroy a `Ceed` passed as a `CeedObject` 198*6c328a79SJeremy L Thompson 199*6c328a79SJeremy L Thompson @param[in,out] ceed Address of `Ceed` context to destroy 200*6c328a79SJeremy L Thompson 201*6c328a79SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 202*6c328a79SJeremy L Thompson 203*6c328a79SJeremy L Thompson @ref Developer 204*6c328a79SJeremy L Thompson **/ 205*6c328a79SJeremy L Thompson static int CeedDestroy_Object(CeedObject *ceed) { 206*6c328a79SJeremy L Thompson CeedCall(CeedDestroy((Ceed *)ceed)); 207*6c328a79SJeremy L Thompson return CEED_ERROR_SUCCESS; 208*6c328a79SJeremy L Thompson } 209*6c328a79SJeremy L Thompson 2107a982d89SJeremy L. Thompson /// @} 211d7b241e6Sjeremylt 2127a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 2137a982d89SJeremy L. Thompson /// Ceed Backend API 2147a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 2157a982d89SJeremy L. Thompson /// @addtogroup CeedBackend 2167a982d89SJeremy L. Thompson /// @{ 217d7b241e6Sjeremylt 218b11c1e72Sjeremylt /** 219ca94c3ddSJeremy L Thompson @brief Return value of `CEED_DEBUG` environment variable 22060f9e2d6SJeremy L Thompson 221ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 22260f9e2d6SJeremy L Thompson 223ca94c3ddSJeremy L Thompson @return Boolean value: true - debugging mode enabled 2243f21f6b1SJeremy L Thompson false - debugging mode disabled 22560f9e2d6SJeremy L Thompson 22660f9e2d6SJeremy L Thompson @ref Backend 22760f9e2d6SJeremy L Thompson **/ 228fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 2292b730f8bSJeremy L Thompson bool CeedDebugFlag(const Ceed ceed) { return ceed->is_debug; } 230fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 23160f9e2d6SJeremy L Thompson 23260f9e2d6SJeremy L Thompson /** 233ca94c3ddSJeremy L Thompson @brief Return value of `CEED_DEBUG` environment variable 23460f9e2d6SJeremy L Thompson 235ca94c3ddSJeremy L Thompson @return Boolean value: true - debugging mode enabled 2363f21f6b1SJeremy L Thompson false - debugging mode disabled 2373f21f6b1SJeremy L Thompson 2383f21f6b1SJeremy L Thompson @ref Backend 2393f21f6b1SJeremy L Thompson **/ 2403f21f6b1SJeremy L Thompson // LCOV_EXCL_START 2411c66c397SJeremy L Thompson bool CeedDebugFlagEnv(void) { return getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); } 2423f21f6b1SJeremy L Thompson // LCOV_EXCL_STOP 2433f21f6b1SJeremy L Thompson 2443f21f6b1SJeremy L Thompson /** 2453f21f6b1SJeremy L Thompson @brief Print debugging information in color 2463f21f6b1SJeremy L Thompson 247ca94c3ddSJeremy L Thompson @param[in] color Color to print 248ca94c3ddSJeremy L Thompson @param[in] format Printing format 24960f9e2d6SJeremy L Thompson 25060f9e2d6SJeremy L Thompson @ref Backend 25160f9e2d6SJeremy L Thompson **/ 252fc6bbcedSJeremy L Thompson // LCOV_EXCL_START 2533f21f6b1SJeremy L Thompson void CeedDebugImpl256(const unsigned char color, const char *format, ...) { 25460f9e2d6SJeremy L Thompson va_list args; 25560f9e2d6SJeremy L Thompson va_start(args, format); 25660f9e2d6SJeremy L Thompson fflush(stdout); 2572b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[38;5;%dm", color); 25860f9e2d6SJeremy L Thompson vfprintf(stdout, format, args); 2592b730f8bSJeremy L Thompson if (color != CEED_DEBUG_COLOR_NONE) fprintf(stdout, "\033[m"); 26060f9e2d6SJeremy L Thompson fprintf(stdout, "\n"); 26160f9e2d6SJeremy L Thompson fflush(stdout); 26260f9e2d6SJeremy L Thompson va_end(args); 26360f9e2d6SJeremy L Thompson } 264fc6bbcedSJeremy L Thompson // LCOV_EXCL_STOP 26560f9e2d6SJeremy L Thompson 26660f9e2d6SJeremy L Thompson /** 267ca94c3ddSJeremy L Thompson @brief Allocate an array on the host; use @ref CeedMalloc(). 268b11c1e72Sjeremylt 269ea61e9acSJeremy L Thompson Memory usage can be tracked by the library. 270ea61e9acSJeremy L Thompson This ensures sufficient alignment for vectorization and should be used for large allocations. 271b11c1e72Sjeremylt 272ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 273ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 274ca94c3ddSJeremy L Thompson @param[out] p Address of pointer to hold the result 275b11c1e72Sjeremylt 276b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 277b11c1e72Sjeremylt 2787a982d89SJeremy L. Thompson @ref Backend 279ca94c3ddSJeremy L Thompson 280ca94c3ddSJeremy L Thompson @sa CeedFree() 281b11c1e72Sjeremylt **/ 282d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 283d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n * unit); 2846574a04fSJeremy L Thompson CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "posix_memalign failed to allocate %zd members of size %zd\n", n, unit); 285e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 286d7b241e6Sjeremylt } 287d7b241e6Sjeremylt 288b11c1e72Sjeremylt /** 289ca94c3ddSJeremy L Thompson @brief Allocate a cleared (zeroed) array on the host; use @ref CeedCalloc(). 290b11c1e72Sjeremylt 291b11c1e72Sjeremylt Memory usage can be tracked by the library. 292b11c1e72Sjeremylt 293ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 294ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 295ca94c3ddSJeremy L Thompson @param[out] p Address of pointer to hold the result 296b11c1e72Sjeremylt 297b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 298b11c1e72Sjeremylt 2997a982d89SJeremy L. Thompson @ref Backend 300ca94c3ddSJeremy L Thompson 301ca94c3ddSJeremy L Thompson @sa CeedFree() 302b11c1e72Sjeremylt **/ 303d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 304d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 3056574a04fSJeremy L Thompson CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "calloc failed to allocate %zd members of size %zd\n", n, unit); 306e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 307d7b241e6Sjeremylt } 308d7b241e6Sjeremylt 309b11c1e72Sjeremylt /** 310ca94c3ddSJeremy L Thompson @brief Reallocate an array on the host; use @ref CeedRealloc(). 311b11c1e72Sjeremylt 312b11c1e72Sjeremylt Memory usage can be tracked by the library. 313b11c1e72Sjeremylt 314ea61e9acSJeremy L Thompson @param[in] n Number of units to allocate 315ea61e9acSJeremy L Thompson @param[in] unit Size of each unit 316ca94c3ddSJeremy L Thompson @param[out] p Address of pointer to hold the result 317b11c1e72Sjeremylt 318b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 319b11c1e72Sjeremylt 3207a982d89SJeremy L. Thompson @ref Backend 321ca94c3ddSJeremy L Thompson 322ca94c3ddSJeremy L Thompson @sa CeedFree() 323b11c1e72Sjeremylt **/ 324d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 325d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n * unit); 3266574a04fSJeremy L Thompson CeedCheck(!n || !unit || *(void **)p, NULL, CEED_ERROR_MAJOR, "realloc failed to allocate %zd members of size %zd\n", n, unit); 327e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 328d7b241e6Sjeremylt } 329d7b241e6Sjeremylt 330f7e22acaSJeremy L Thompson /** 331ca94c3ddSJeremy L Thompson @brief Allocate a cleared string buffer on the host. 332f7e22acaSJeremy L Thompson 333f7e22acaSJeremy L Thompson Memory usage can be tracked by the library. 334f7e22acaSJeremy L Thompson 335ea61e9acSJeremy L Thompson @param[in] source Pointer to string to be copied 336ea61e9acSJeremy L Thompson @param[out] copy Pointer to variable to hold newly allocated string copy 337f7e22acaSJeremy L Thompson 338f7e22acaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 339f7e22acaSJeremy L Thompson 340f7e22acaSJeremy L Thompson @ref Backend 341ca94c3ddSJeremy L Thompson 342ca94c3ddSJeremy L Thompson @sa CeedFree() 343f7e22acaSJeremy L Thompson **/ 344f7e22acaSJeremy L Thompson int CeedStringAllocCopy(const char *source, char **copy) { 345f7e22acaSJeremy L Thompson size_t len = strlen(source); 3462b730f8bSJeremy L Thompson CeedCall(CeedCalloc(len + 1, copy)); 347d602d780SJeremy L Thompson memcpy(*copy, source, len); 348f7e22acaSJeremy L Thompson return CEED_ERROR_SUCCESS; 349f7e22acaSJeremy L Thompson } 350f7e22acaSJeremy L Thompson 351ca94c3ddSJeremy L Thompson /** Free memory allocated using @ref CeedMalloc() or @ref CeedCalloc() 35234138859Sjeremylt 353ca94c3ddSJeremy L Thompson @param[in,out] p Address of pointer to memory. 354ca94c3ddSJeremy 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. 355ca94c3ddSJeremy L Thompson 356ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 357ca94c3ddSJeremy L Thompson 358ca94c3ddSJeremy L Thompson @ref Backend 35934138859Sjeremylt **/ 360d7b241e6Sjeremylt int CeedFree(void *p) { 361d7b241e6Sjeremylt free(*(void **)p); 362d7b241e6Sjeremylt *(void **)p = NULL; 363e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 364d7b241e6Sjeremylt } 365d7b241e6Sjeremylt 366f5d1e504SJeremy L Thompson /** Internal helper to manage handoff of user `source_array` to backend with proper @ref CeedCopyMode behavior. 367f5d1e504SJeremy L Thompson 368f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 369f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 370f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 37117afdf5cSJames Wright @param[in] size_unit Size of array element in bytes 372f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 373f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 374f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 375f5d1e504SJeremy L Thompson 376f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 377f5d1e504SJeremy L Thompson 378f5d1e504SJeremy L Thompson @ref Backend 379f5d1e504SJeremy L Thompson **/ 380f5d1e504SJeremy L Thompson static inline int CeedSetHostGenericArray(const void *source_array, CeedCopyMode copy_mode, size_t size_unit, CeedSize num_values, 381f5d1e504SJeremy L Thompson void *target_array_owned, void *target_array_borrowed, void *target_array) { 382f5d1e504SJeremy L Thompson switch (copy_mode) { 383f5d1e504SJeremy L Thompson case CEED_COPY_VALUES: 384cc3bdf8cSJeremy L Thompson if (!*(void **)target_array) { 385cc3bdf8cSJeremy L Thompson if (*(void **)target_array_borrowed) { 386cc3bdf8cSJeremy L Thompson *(void **)target_array = *(void **)target_array_borrowed; 387cc3bdf8cSJeremy L Thompson } else { 388f5d1e504SJeremy L Thompson if (!*(void **)target_array_owned) CeedCall(CeedCallocArray(num_values, size_unit, target_array_owned)); 389f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_owned; 390cc3bdf8cSJeremy L Thompson } 391cc3bdf8cSJeremy L Thompson } 392cc3bdf8cSJeremy L Thompson if (source_array) memcpy(*(void **)target_array, source_array, size_unit * num_values); 393f5d1e504SJeremy L Thompson break; 394f5d1e504SJeremy L Thompson case CEED_OWN_POINTER: 395f5d1e504SJeremy L Thompson CeedCall(CeedFree(target_array_owned)); 396f5d1e504SJeremy L Thompson *(void **)target_array_owned = (void *)source_array; 397f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = NULL; 398f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_owned; 399f5d1e504SJeremy L Thompson break; 400f5d1e504SJeremy L Thompson case CEED_USE_POINTER: 401f5d1e504SJeremy L Thompson CeedCall(CeedFree(target_array_owned)); 402f5d1e504SJeremy L Thompson *(void **)target_array_owned = NULL; 403f5d1e504SJeremy L Thompson *(void **)target_array_borrowed = (void *)source_array; 404f5d1e504SJeremy L Thompson *(void **)target_array = *(void **)target_array_borrowed; 405f5d1e504SJeremy L Thompson } 406f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 407f5d1e504SJeremy L Thompson } 408f5d1e504SJeremy L Thompson 409f5d1e504SJeremy L Thompson /** Manage handoff of user `bool` `source_array` to backend with proper @ref CeedCopyMode behavior. 410f5d1e504SJeremy L Thompson 411f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 412f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 413f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 414f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 415f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 416f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 417f5d1e504SJeremy L Thompson 418f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 419f5d1e504SJeremy L Thompson 420f5d1e504SJeremy L Thompson @ref Backend 421f5d1e504SJeremy L Thompson **/ 422f5d1e504SJeremy L Thompson int CeedSetHostBoolArray(const bool *source_array, CeedCopyMode copy_mode, CeedSize num_values, const bool **target_array_owned, 423f5d1e504SJeremy L Thompson const bool **target_array_borrowed, const bool **target_array) { 424f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(bool), num_values, target_array_owned, target_array_borrowed, target_array)); 425f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 426f5d1e504SJeremy L Thompson } 427f5d1e504SJeremy L Thompson 428f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedInt8` `source_array` to backend with proper @ref CeedCopyMode behavior. 429f5d1e504SJeremy L Thompson 430f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 431f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 432f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 433f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 434f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 435f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 436f5d1e504SJeremy L Thompson 437f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 438f5d1e504SJeremy L Thompson 439f5d1e504SJeremy L Thompson @ref Backend 440f5d1e504SJeremy L Thompson **/ 441f5d1e504SJeremy L Thompson int CeedSetHostCeedInt8Array(const CeedInt8 *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedInt8 **target_array_owned, 442f5d1e504SJeremy L Thompson const CeedInt8 **target_array_borrowed, const CeedInt8 **target_array) { 443f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedInt8), num_values, target_array_owned, target_array_borrowed, target_array)); 444f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 445f5d1e504SJeremy L Thompson } 446f5d1e504SJeremy L Thompson 447f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedInt` `source_array` to backend with proper @ref CeedCopyMode behavior. 448f5d1e504SJeremy L Thompson 449f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 450f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 451f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 452f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 453f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 454f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 455f5d1e504SJeremy L Thompson 456f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 457f5d1e504SJeremy L Thompson 458f5d1e504SJeremy L Thompson @ref Backend 459f5d1e504SJeremy L Thompson **/ 460f5d1e504SJeremy L Thompson int CeedSetHostCeedIntArray(const CeedInt *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedInt **target_array_owned, 461f5d1e504SJeremy L Thompson const CeedInt **target_array_borrowed, const CeedInt **target_array) { 462f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedInt), num_values, target_array_owned, target_array_borrowed, target_array)); 463f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 464f5d1e504SJeremy L Thompson } 465f5d1e504SJeremy L Thompson 466f5d1e504SJeremy L Thompson /** Manage handoff of user `CeedScalar` `source_array` to backend with proper @ref CeedCopyMode behavior. 467f5d1e504SJeremy L Thompson 468f5d1e504SJeremy L Thompson @param[in] source_array Source data provided by user 469f5d1e504SJeremy L Thompson @param[in] copy_mode Copy mode for the data 470f5d1e504SJeremy L Thompson @param[in] num_values Number of values to handle 471f5d1e504SJeremy L Thompson @param[in,out] target_array_owned Pointer to location to allocated or hold owned data, may be freed if already allocated 472f5d1e504SJeremy L Thompson @param[out] target_array_borrowed Pointer to location to hold borrowed data 473f5d1e504SJeremy L Thompson @param[out] target_array Pointer to location for data 474f5d1e504SJeremy L Thompson 475f5d1e504SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 476f5d1e504SJeremy L Thompson 477f5d1e504SJeremy L Thompson @ref Backend 478f5d1e504SJeremy L Thompson **/ 479f5d1e504SJeremy L Thompson int CeedSetHostCeedScalarArray(const CeedScalar *source_array, CeedCopyMode copy_mode, CeedSize num_values, const CeedScalar **target_array_owned, 480f5d1e504SJeremy L Thompson const CeedScalar **target_array_borrowed, const CeedScalar **target_array) { 481f5d1e504SJeremy L Thompson CeedCall(CeedSetHostGenericArray(source_array, copy_mode, sizeof(CeedScalar), num_values, target_array_owned, target_array_borrowed, target_array)); 482f5d1e504SJeremy L Thompson return CEED_ERROR_SUCCESS; 483f5d1e504SJeremy L Thompson } 484f5d1e504SJeremy L Thompson 485d7b241e6Sjeremylt /** 486ca94c3ddSJeremy L Thompson @brief Register a `Ceed` backend 487d7b241e6Sjeremylt 488ea61e9acSJeremy L Thompson @param[in] prefix Prefix of resources for this backend to respond to. 489ea61e9acSJeremy L Thompson For example, the reference backend responds to "/cpu/self". 490ca94c3ddSJeremy L Thompson @param[in] init Initialization function called by @ref CeedInit() when the backend is selected to drive the requested resource 491ea61e9acSJeremy L Thompson @param[in] priority Integer priority. 492ca94c3ddSJeremy L Thompson Lower values are preferred in case the resource requested by @ref CeedInit() has non-unique best prefix match. 493b11c1e72Sjeremylt 494b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 495dfdf5a53Sjeremylt 4967a982d89SJeremy L. Thompson @ref Backend 497b11c1e72Sjeremylt **/ 4982b730f8bSJeremy L Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), unsigned int priority) { 49910243053SJeremy L Thompson CeedDebugEnv("Backend Register: %s", prefix); 5006a406739SJeremy L Thompson CeedRegisterImpl(prefix, init, priority); 501e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 502d7b241e6Sjeremylt } 503d7b241e6Sjeremylt 504b11c1e72Sjeremylt /** 50560f9e2d6SJeremy L Thompson @brief Return debugging status flag 50660f9e2d6SJeremy L Thompson 507ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get debugging flag 508ea61e9acSJeremy L Thompson @param[out] is_debug Variable to store debugging flag 50960f9e2d6SJeremy L Thompson 51060f9e2d6SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 51160f9e2d6SJeremy L Thompson 512d1d35e2fSjeremylt @ref Backend 51360f9e2d6SJeremy L Thompson **/ 514d1d35e2fSjeremylt int CeedIsDebug(Ceed ceed, bool *is_debug) { 5153f21f6b1SJeremy L Thompson *is_debug = ceed->is_debug; 516e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 51760f9e2d6SJeremy L Thompson } 51860f9e2d6SJeremy L Thompson 51960f9e2d6SJeremy L Thompson /** 520bf84744cSJeremy L Thompson @brief Get the root of the requested resource. 521bf84744cSJeremy L Thompson 522bf84744cSJeremy L Thompson Note: Caller is responsible for calling @ref CeedFree() on the `resource_root`. 523bc246734SJeremy L Thompson 524ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get resource name of 525ca94c3ddSJeremy L Thompson @param[in] resource Full user specified resource 526ca94c3ddSJeremy L Thompson @param[in] delineator Delineator to break `resource_root` and `resource_spec` 527bc246734SJeremy L Thompson @param[out] resource_root Variable to store resource root 528bc246734SJeremy L Thompson 529bc246734SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 530bc246734SJeremy L Thompson 531bc246734SJeremy L Thompson @ref Backend 532bc246734SJeremy L Thompson **/ 533bc246734SJeremy L Thompson int CeedGetResourceRoot(Ceed ceed, const char *resource, const char *delineator, char **resource_root) { 534bc246734SJeremy L Thompson char *device_spec = strstr(resource, delineator); 535bc246734SJeremy L Thompson size_t resource_root_len = device_spec ? (size_t)(device_spec - resource) + 1 : strlen(resource) + 1; 5361c66c397SJeremy L Thompson 537bc246734SJeremy L Thompson CeedCall(CeedCalloc(resource_root_len, resource_root)); 538bc246734SJeremy L Thompson memcpy(*resource_root, resource, resource_root_len - 1); 539bc246734SJeremy L Thompson return CEED_ERROR_SUCCESS; 540bc246734SJeremy L Thompson } 541bc246734SJeremy L Thompson 542bc246734SJeremy L Thompson /** 543ca94c3ddSJeremy L Thompson @brief Retrieve a parent `Ceed` context 5447a982d89SJeremy L. Thompson 545ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve parent of 5467a982d89SJeremy L. Thompson @param[out] parent Address to save the parent to 5477a982d89SJeremy L. Thompson 5487a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5497a982d89SJeremy L. Thompson 5507a982d89SJeremy L. Thompson @ref Backend 5517a982d89SJeremy L. Thompson **/ 5527a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 5537a982d89SJeremy L. Thompson if (ceed->parent) { 5542b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed->parent, parent)); 555e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5567a982d89SJeremy L. Thompson } 5579bc66399SJeremy L Thompson *parent = NULL; 5589bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, parent)); 559e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5607a982d89SJeremy L. Thompson } 5617a982d89SJeremy L. Thompson 5627a982d89SJeremy L. Thompson /** 563ca94c3ddSJeremy L Thompson @brief Retrieve a delegate `Ceed` context 5647a982d89SJeremy L. Thompson 565ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve delegate of 5667a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 5677a982d89SJeremy L. Thompson 5687a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5697a982d89SJeremy L. Thompson 5707a982d89SJeremy L. Thompson @ref Backend 5717a982d89SJeremy L. Thompson **/ 5727a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 5739bc66399SJeremy L Thompson *delegate = NULL; 5749bc66399SJeremy L Thompson if (ceed->delegate) CeedCall(CeedReferenceCopy(ceed->delegate, delegate)); 575e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5767a982d89SJeremy L. Thompson } 5777a982d89SJeremy L. Thompson 5787a982d89SJeremy L. Thompson /** 579ca94c3ddSJeremy L Thompson @brief Set a delegate `Ceed` context 5807a982d89SJeremy L. Thompson 581ca94c3ddSJeremy L Thompson This function allows a `Ceed` context to set a delegate `Ceed` context. 582ca94c3ddSJeremy L Thompson All backend implementations default to the delegate `Ceed` context, unless overridden. 5837a982d89SJeremy L. Thompson 584ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to set delegate of 5857a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 5867a982d89SJeremy L. Thompson 5877a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5887a982d89SJeremy L. Thompson 5897a982d89SJeremy L. Thompson @ref Backend 5907a982d89SJeremy L. Thompson **/ 5917a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) { 5929bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(delegate, &ceed->delegate)); 5937a982d89SJeremy L. Thompson delegate->parent = ceed; 594e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5957a982d89SJeremy L. Thompson } 5967a982d89SJeremy L. Thompson 5977a982d89SJeremy L. Thompson /** 598ca94c3ddSJeremy L Thompson @brief Retrieve a delegate `Ceed` context for a specific object type 5997a982d89SJeremy L. Thompson 600ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve delegate of 6017a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 602d1d35e2fSjeremylt @param[in] obj_name Name of the object type to retrieve delegate for 6037a982d89SJeremy L. Thompson 6047a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6057a982d89SJeremy L. Thompson 6067a982d89SJeremy L. Thompson @ref Backend 6077a982d89SJeremy L. Thompson **/ 608d1d35e2fSjeremylt int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *obj_name) { 6097a982d89SJeremy L. Thompson // Check for object delegate 6102b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) { 611d1d35e2fSjeremylt if (!strcmp(obj_name, ceed->obj_delegates->obj_name)) { 6129bc66399SJeremy L Thompson *delegate = NULL; 6139bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed->obj_delegates->delegate, delegate)); 614e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6157a982d89SJeremy L. Thompson } 6162b730f8bSJeremy L Thompson } 6177a982d89SJeremy L. Thompson 6187a982d89SJeremy L. Thompson // Use default delegate if no object delegate 6192b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, delegate)); 620e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6217a982d89SJeremy L. Thompson } 6227a982d89SJeremy L. Thompson 6237a982d89SJeremy L. Thompson /** 624ca94c3ddSJeremy L Thompson @brief Set a delegate `Ceed` context for a specific object type 6257a982d89SJeremy L. Thompson 626ca94c3ddSJeremy L Thompson This function allows a `Ceed` context to set a delegate `Ceed` context for a given type of `Ceed` object. 627ca94c3ddSJeremy L Thompson All backend implementations default to the delegate `Ceed` context for this object. 628ca94c3ddSJeremy L Thompson For example, `CeedSetObjectDelegate(ceed, delegate, "Basis")` uses delegate implementations for all `CeedBasis` backend functions. 6297a982d89SJeremy L. Thompson 630ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set delegate of 631ca94c3ddSJeremy L Thompson @param[in] delegate `Ceed` context to use for delegation 632d1d35e2fSjeremylt @param[in] obj_name Name of the object type to set delegate for 6337a982d89SJeremy L. Thompson 6347a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6357a982d89SJeremy L. Thompson 6367a982d89SJeremy L. Thompson @ref Backend 6377a982d89SJeremy L. Thompson **/ 638d1d35e2fSjeremylt int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *obj_name) { 639d1d35e2fSjeremylt CeedInt count = ceed->obj_delegate_count; 6407a982d89SJeremy L. Thompson 6417a982d89SJeremy L. Thompson // Malloc or Realloc 6427a982d89SJeremy L. Thompson if (count) { 6432b730f8bSJeremy L Thompson CeedCall(CeedRealloc(count + 1, &ceed->obj_delegates)); 6447a982d89SJeremy L. Thompson } else { 6452b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &ceed->obj_delegates)); 6467a982d89SJeremy L. Thompson } 647d1d35e2fSjeremylt ceed->obj_delegate_count++; 6487a982d89SJeremy L. Thompson 6497a982d89SJeremy L. Thompson // Set object delegate 6509bc66399SJeremy L Thompson CeedCall(CeedReferenceCopy(delegate, &ceed->obj_delegates[count].delegate)); 6512b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(obj_name, &ceed->obj_delegates[count].obj_name)); 6527a982d89SJeremy L. Thompson 6537a982d89SJeremy L. Thompson // Set delegate parent 6547a982d89SJeremy L. Thompson delegate->parent = ceed; 655e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6567a982d89SJeremy L. Thompson } 6577a982d89SJeremy L. Thompson 6587a982d89SJeremy L. Thompson /** 659ca94c3ddSJeremy L Thompson @brief Get the fallback `Ceed` for `CeedOperator` 6608687e1d4SJeremy L Thompson 661ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 662ca94c3ddSJeremy L Thompson @param[out] fallback_ceed Variable to store fallback `Ceed` 6638687e1d4SJeremy L Thompson 6648687e1d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 6658687e1d4SJeremy L Thompson 6668687e1d4SJeremy L Thompson @ref Backend 6678687e1d4SJeremy L Thompson **/ 6688687e1d4SJeremy L Thompson int CeedGetOperatorFallbackCeed(Ceed ceed, Ceed *fallback_ceed) { 66946b50f9eSZach Atkins if (ceed->op_fallback_ceed) { 670ca38d01dSJeremy L Thompson CeedDebug256(ceed, CEED_DEBUG_COLOR_SUCCESS, "---------- Ceed Fallback ----------\n"); 67146b50f9eSZach Atkins CeedDebug(ceed, "Falling back from Ceed with backend %s at address %p to Ceed with backend %s at address %p", ceed->resource, ceed, 67246b50f9eSZach Atkins ceed->op_fallback_ceed->resource, ceed->op_fallback_ceed); 673d04bbc78SJeremy L Thompson } 6748687e1d4SJeremy L Thompson 6759bc66399SJeremy L Thompson *fallback_ceed = NULL; 6769bc66399SJeremy L Thompson if (ceed->op_fallback_ceed) CeedCall(CeedReferenceCopy(ceed->op_fallback_ceed, fallback_ceed)); 6778687e1d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 6788687e1d4SJeremy L Thompson } 6798687e1d4SJeremy L Thompson 6808687e1d4SJeremy L Thompson /** 681ca94c3ddSJeremy L Thompson @brief Set the fallback resource for `CeedOperator`. 6824385fb7fSSebastian Grimberg 68346b50f9eSZach Atkins The current fallback, if any, is freed by calling this function. 6847a982d89SJeremy L. Thompson 685ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context 68646b50f9eSZach Atkins @param[in] fallback_ceed `Ceed` context to create fallback operators 6877a982d89SJeremy L. Thompson 6887a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6897a982d89SJeremy L. Thompson 6907a982d89SJeremy L. Thompson @ref Backend 6917a982d89SJeremy L. Thompson **/ 69246b50f9eSZach Atkins int CeedSetOperatorFallbackCeed(Ceed ceed, Ceed fallback_ceed) { 69346b50f9eSZach Atkins CeedCall(CeedReferenceCopy(fallback_ceed, &ceed->op_fallback_ceed)); 69446b50f9eSZach Atkins fallback_ceed->parent = ceed; 695e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6967a982d89SJeremy L. Thompson } 6977a982d89SJeremy L. Thompson 6987a982d89SJeremy L. Thompson /** 699ca94c3ddSJeremy L Thompson @brief Flag `Ceed` context as deterministic 7009525855cSJeremy L Thompson 701ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` to flag as deterministic 70296b902e2Sjeremylt @param[out] is_deterministic Deterministic status to set 7039525855cSJeremy L Thompson 7049525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 7059525855cSJeremy L Thompson 7069525855cSJeremy L Thompson @ref Backend 7079525855cSJeremy L Thompson **/ 708d1d35e2fSjeremylt int CeedSetDeterministic(Ceed ceed, bool is_deterministic) { 709d1d35e2fSjeremylt ceed->is_deterministic = is_deterministic; 710e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7119525855cSJeremy L Thompson } 7129525855cSJeremy L Thompson 7139525855cSJeremy L Thompson /** 714ca94c3ddSJeremy L Thompson @brief Set a backend function. 7157a982d89SJeremy L. Thompson 716ea61e9acSJeremy L Thompson This function is used for a backend to set the function associated with the Ceed objects. 717ca94c3ddSJeremy 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(). 7189fd66db6SSebastian Grimberg Note, the prefix 'Ceed' is not required for the object type ("Basis" vs "CeedBasis"). 7197a982d89SJeremy L. Thompson 720ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context for error handling 721ea61e9acSJeremy L Thompson @param[in] type Type of Ceed object to set function for 7227a982d89SJeremy L. Thompson @param[out] object Ceed object to set function for 723ea61e9acSJeremy L Thompson @param[in] func_name Name of function to set 724ea61e9acSJeremy L Thompson @param[in] f Function to set 7257a982d89SJeremy L. Thompson 7267a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7277a982d89SJeremy L. Thompson 7287a982d89SJeremy L. Thompson @ref Backend 7297a982d89SJeremy L. Thompson **/ 730897d4737SSebastian Grimberg int CeedSetBackendFunctionImpl(Ceed ceed, const char *type, void *object, const char *func_name, void (*f)(void)) { 731d1d35e2fSjeremylt char lookup_name[CEED_MAX_RESOURCE_LEN + 1] = ""; 7327a982d89SJeremy L. Thompson 7337a982d89SJeremy L. Thompson // Build lookup name 7342b730f8bSJeremy L Thompson if (strcmp(type, "Ceed")) strncat(lookup_name, "Ceed", CEED_MAX_RESOURCE_LEN); 735d1d35e2fSjeremylt strncat(lookup_name, type, CEED_MAX_RESOURCE_LEN); 736d1d35e2fSjeremylt strncat(lookup_name, func_name, CEED_MAX_RESOURCE_LEN); 7377a982d89SJeremy L. Thompson 7387a982d89SJeremy L. Thompson // Find and use offset 7392b730f8bSJeremy L Thompson for (CeedInt i = 0; ceed->f_offsets[i].func_name; i++) { 740d1d35e2fSjeremylt if (!strcmp(ceed->f_offsets[i].func_name, lookup_name)) { 741d1d35e2fSjeremylt size_t offset = ceed->f_offsets[i].offset; 7427a982d89SJeremy L. Thompson int (**fpointer)(void) = (int (**)(void))((char *)object + offset); // *NOPAD* 7431c66c397SJeremy L Thompson 744897d4737SSebastian Grimberg *fpointer = (int (*)(void))f; 745e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7467a982d89SJeremy L. Thompson } 7472b730f8bSJeremy L Thompson } 7487a982d89SJeremy L. Thompson 7497a982d89SJeremy L. Thompson // LCOV_EXCL_START 7502b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Requested function '%s' was not found for CEED object '%s'", func_name, type); 7517a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7527a982d89SJeremy L. Thompson } 7537a982d89SJeremy L. Thompson 7547a982d89SJeremy L. Thompson /** 755ca94c3ddSJeremy L Thompson @brief Retrieve backend data for a `Ceed` context 7567a982d89SJeremy L. Thompson 757ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve data of 7587a982d89SJeremy L. Thompson @param[out] data Address to save data to 7597a982d89SJeremy L. Thompson 7607a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7617a982d89SJeremy L. Thompson 7627a982d89SJeremy L. Thompson @ref Backend 7637a982d89SJeremy L. Thompson **/ 764777ff853SJeremy L Thompson int CeedGetData(Ceed ceed, void *data) { 765777ff853SJeremy L Thompson *(void **)data = ceed->data; 766e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7677a982d89SJeremy L. Thompson } 7687a982d89SJeremy L. Thompson 7697a982d89SJeremy L. Thompson /** 770ca94c3ddSJeremy L Thompson @brief Set backend data for a `Ceed` context 7717a982d89SJeremy L. Thompson 772ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set data of 773ea61e9acSJeremy L Thompson @param[in] data Address of data to set 7747a982d89SJeremy L. Thompson 7757a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7767a982d89SJeremy L. Thompson 7777a982d89SJeremy L. Thompson @ref Backend 7787a982d89SJeremy L. Thompson **/ 779777ff853SJeremy L Thompson int CeedSetData(Ceed ceed, void *data) { 780777ff853SJeremy L Thompson ceed->data = data; 781e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7827a982d89SJeremy L. Thompson } 7837a982d89SJeremy L. Thompson 78434359f16Sjeremylt /** 785ca94c3ddSJeremy L Thompson @brief Increment the reference counter for a `Ceed` context 78634359f16Sjeremylt 787ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to increment the reference counter 78834359f16Sjeremylt 78934359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 79034359f16Sjeremylt 79134359f16Sjeremylt @ref Backend 79234359f16Sjeremylt **/ 7939560d06aSjeremylt int CeedReference(Ceed ceed) { 794b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)ceed)); 79534359f16Sjeremylt return CEED_ERROR_SUCCESS; 79634359f16Sjeremylt } 79734359f16Sjeremylt 79873501bfeSJeremy L Thompson /** 7990b37c066SZach Atkins @brief Computes the current memory usage of the work vectors in a `Ceed` context and prints to debug.abort 8000b37c066SZach Atkins 8010b37c066SZach Atkins @param[in] ceed `Ceed` context 802ec4241e6SJeremy L Thompson @param[out] usage_mb Address of the variable where the MB of work vector usage will be stored 8030b37c066SZach Atkins 8040b37c066SZach Atkins @return An error code: 0 - success, otherwise - failure 8050b37c066SZach Atkins 8060b37c066SZach Atkins @ref Developer 8070b37c066SZach Atkins **/ 80855326fe7SZach Atkins int CeedGetWorkVectorMemoryUsage(Ceed ceed, CeedScalar *usage_mb) { 809fd326ce8SZach Atkins if (!ceed->VectorCreate) { 810fd326ce8SZach Atkins Ceed delegate; 811fd326ce8SZach Atkins 812fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 813fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 814fd326ce8SZach Atkins CeedCall(CeedGetWorkVectorMemoryUsage(delegate, usage_mb)); 815fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 816fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 817fd326ce8SZach Atkins } 81855326fe7SZach Atkins *usage_mb = 0.0; 8190b37c066SZach Atkins if (ceed->work_vectors) { 8200b37c066SZach Atkins for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 8210b37c066SZach Atkins CeedSize vec_len; 8220b37c066SZach Atkins CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &vec_len)); 82355326fe7SZach Atkins *usage_mb += vec_len; 8240b37c066SZach Atkins } 82555326fe7SZach Atkins *usage_mb *= sizeof(CeedScalar) * 1e-6; 82655326fe7SZach Atkins CeedDebug(ceed, "Resource {%s}: Work vectors memory usage: %" CeedInt_FMT " vectors, %g MB\n", ceed->resource, ceed->work_vectors->num_vecs, 82755326fe7SZach Atkins *usage_mb); 8280b37c066SZach Atkins } 8290b37c066SZach Atkins return CEED_ERROR_SUCCESS; 8300b37c066SZach Atkins } 8310b37c066SZach Atkins 8320b37c066SZach Atkins /** 8330b37c066SZach Atkins @brief Clear inactive work vectors in a `Ceed` context below a minimum length. 8340b37c066SZach Atkins 8350b37c066SZach Atkins @param[in,out] ceed `Ceed` context 8360b37c066SZach Atkins @param[in] min_len Minimum length of work vector to keep 8370b37c066SZach Atkins 8380b37c066SZach Atkins @return An error code: 0 - success, otherwise - failure 8390b37c066SZach Atkins 8400b37c066SZach Atkins @ref Backend 8410b37c066SZach Atkins **/ 8420b37c066SZach Atkins int CeedClearWorkVectors(Ceed ceed, CeedSize min_len) { 843fd326ce8SZach Atkins if (!ceed->VectorCreate) { 844fd326ce8SZach Atkins Ceed delegate; 845fd326ce8SZach Atkins 846fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 847fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 848fd326ce8SZach Atkins CeedCall(CeedClearWorkVectors(delegate, min_len)); 849fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 850fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 851fd326ce8SZach Atkins } 8520b37c066SZach Atkins if (!ceed->work_vectors) return CEED_ERROR_SUCCESS; 8530b37c066SZach Atkins for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 8540b37c066SZach Atkins if (ceed->work_vectors->is_in_use[i]) continue; 8550b37c066SZach Atkins CeedSize vec_len; 8560b37c066SZach Atkins CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &vec_len)); 8570b37c066SZach Atkins if (vec_len < min_len) { 858b0f67a9cSJeremy L Thompson // Note: increase ref_count to prevent Ceed destructor from triggering 859b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)ceed)); 860b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)ceed)); 8610b37c066SZach Atkins CeedCall(CeedVectorDestroy(&ceed->work_vectors->vecs[i])); 862b0f67a9cSJeremy L Thompson // Note: restore ref_count 863b0f67a9cSJeremy L Thompson CeedObjectDereference((CeedObject)ceed); 8640b37c066SZach Atkins ceed->work_vectors->num_vecs--; 8650b37c066SZach Atkins if (ceed->work_vectors->num_vecs > 0) { 8660b37c066SZach Atkins ceed->work_vectors->vecs[i] = ceed->work_vectors->vecs[ceed->work_vectors->num_vecs]; 8670b37c066SZach Atkins ceed->work_vectors->is_in_use[i] = ceed->work_vectors->is_in_use[ceed->work_vectors->num_vecs]; 8680b37c066SZach Atkins ceed->work_vectors->is_in_use[ceed->work_vectors->num_vecs] = false; 8690b37c066SZach Atkins i--; 8700b37c066SZach Atkins } 8710b37c066SZach Atkins } 8720b37c066SZach Atkins } 8730b37c066SZach Atkins return CEED_ERROR_SUCCESS; 8740b37c066SZach Atkins } 8750b37c066SZach Atkins 8760b37c066SZach Atkins /** 87773501bfeSJeremy L Thompson @brief Get a `CeedVector` for scratch work from a `Ceed` context. 87873501bfeSJeremy L Thompson 87973501bfeSJeremy L Thompson Note: This vector must be restored with @ref CeedRestoreWorkVector(). 88073501bfeSJeremy L Thompson 88173501bfeSJeremy L Thompson @param[in] ceed `Ceed` context 88273501bfeSJeremy L Thompson @param[in] len Minimum length of work vector 88373501bfeSJeremy L Thompson @param[out] vec Address of the variable where `CeedVector` will be stored 88473501bfeSJeremy L Thompson 88573501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 88673501bfeSJeremy L Thompson 88773501bfeSJeremy L Thompson @ref Backend 88873501bfeSJeremy L Thompson **/ 88973501bfeSJeremy L Thompson int CeedGetWorkVector(Ceed ceed, CeedSize len, CeedVector *vec) { 89073501bfeSJeremy L Thompson CeedInt i = 0; 89155326fe7SZach Atkins CeedScalar usage_mb; 89273501bfeSJeremy L Thompson 893fd326ce8SZach Atkins if (!ceed->VectorCreate) { 894fd326ce8SZach Atkins Ceed delegate; 895fd326ce8SZach Atkins 896fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 897fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 898fd326ce8SZach Atkins CeedCall(CeedGetWorkVector(delegate, len, vec)); 899fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 900fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 901fd326ce8SZach Atkins } 902fd326ce8SZach Atkins 90373501bfeSJeremy L Thompson if (!ceed->work_vectors) CeedCall(CeedWorkVectorsCreate(ceed)); 90473501bfeSJeremy L Thompson 90573501bfeSJeremy L Thompson // Search for big enough work vector 90673501bfeSJeremy L Thompson for (i = 0; i < ceed->work_vectors->num_vecs; i++) { 90773501bfeSJeremy L Thompson if (!ceed->work_vectors->is_in_use[i]) { 90873501bfeSJeremy L Thompson CeedSize work_len; 90973501bfeSJeremy L Thompson 91073501bfeSJeremy L Thompson CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &work_len)); 91173501bfeSJeremy L Thompson if (work_len >= len) break; 91273501bfeSJeremy L Thompson } 91373501bfeSJeremy L Thompson } 91473501bfeSJeremy L Thompson // Long enough vector was not found 91573501bfeSJeremy L Thompson if (i == ceed->work_vectors->num_vecs) { 91673501bfeSJeremy L Thompson if (ceed->work_vectors->max_vecs == 0) { 91773501bfeSJeremy L Thompson ceed->work_vectors->max_vecs = 1; 91873501bfeSJeremy L Thompson CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs)); 91973501bfeSJeremy L Thompson CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use)); 92073501bfeSJeremy L Thompson } else if (ceed->work_vectors->max_vecs == i) { 92173501bfeSJeremy L Thompson ceed->work_vectors->max_vecs *= 2; 92273501bfeSJeremy L Thompson CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs)); 92373501bfeSJeremy L Thompson CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use)); 92473501bfeSJeremy L Thompson } 92573501bfeSJeremy L Thompson ceed->work_vectors->num_vecs++; 92673501bfeSJeremy L Thompson CeedCallBackend(CeedVectorCreate(ceed, len, &ceed->work_vectors->vecs[i])); 927b0f67a9cSJeremy L Thompson // Note: ref_count manipulation to prevent a ref-loop 928b0f67a9cSJeremy L Thompson CeedObjectDereference((CeedObject)ceed); 92955326fe7SZach Atkins if (ceed->is_debug) CeedGetWorkVectorMemoryUsage(ceed, &usage_mb); 93073501bfeSJeremy L Thompson } 93173501bfeSJeremy L Thompson // Return pointer to work vector 93273501bfeSJeremy L Thompson ceed->work_vectors->is_in_use[i] = true; 93373501bfeSJeremy L Thompson *vec = NULL; 93473501bfeSJeremy L Thompson CeedCall(CeedVectorReferenceCopy(ceed->work_vectors->vecs[i], vec)); 935b0f67a9cSJeremy L Thompson // Note: bump ref_count to account for external access 936b0f67a9cSJeremy L Thompson CeedCall(CeedObjectReference((CeedObject)ceed)); 93773501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 93873501bfeSJeremy L Thompson } 93973501bfeSJeremy L Thompson 94073501bfeSJeremy L Thompson /** 94173501bfeSJeremy L Thompson @brief Restore a `CeedVector` for scratch work from a `Ceed` context from @ref CeedGetWorkVector() 94273501bfeSJeremy L Thompson 94373501bfeSJeremy L Thompson @param[in] ceed `Ceed` context 94473501bfeSJeremy L Thompson @param[out] vec `CeedVector` to restore 94573501bfeSJeremy L Thompson 94673501bfeSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 94773501bfeSJeremy L Thompson 94873501bfeSJeremy L Thompson @ref Backend 94973501bfeSJeremy L Thompson **/ 95073501bfeSJeremy L Thompson int CeedRestoreWorkVector(Ceed ceed, CeedVector *vec) { 951fd326ce8SZach Atkins if (!ceed->VectorCreate) { 952fd326ce8SZach Atkins Ceed delegate; 953fd326ce8SZach Atkins 954fd326ce8SZach Atkins CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Vector")); 955fd326ce8SZach Atkins CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement VectorCreate"); 956fd326ce8SZach Atkins CeedCall(CeedRestoreWorkVector(delegate, vec)); 957fd326ce8SZach Atkins CeedCall(CeedDestroy(&delegate)); 958fd326ce8SZach Atkins return CEED_ERROR_SUCCESS; 959fd326ce8SZach Atkins } 960fd326ce8SZach Atkins 96173501bfeSJeremy L Thompson for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) { 96273501bfeSJeremy L Thompson if (*vec == ceed->work_vectors->vecs[i]) { 96373501bfeSJeremy 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"); 96473501bfeSJeremy L Thompson CeedCall(CeedVectorDestroy(vec)); 96573501bfeSJeremy L Thompson ceed->work_vectors->is_in_use[i] = false; 966b0f67a9cSJeremy L Thompson // Note: reduce ref_count again to prevent a ref-loop 967b0f67a9cSJeremy L Thompson CeedObjectDereference((CeedObject)ceed); 96873501bfeSJeremy L Thompson return CEED_ERROR_SUCCESS; 96973501bfeSJeremy L Thompson } 97073501bfeSJeremy L Thompson } 97173501bfeSJeremy L Thompson // LCOV_EXCL_START 97273501bfeSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MAJOR, "vec was not checked out via CeedGetWorkVector()"); 97373501bfeSJeremy L Thompson // LCOV_EXCL_STOP 97473501bfeSJeremy L Thompson } 97573501bfeSJeremy L Thompson 976b13efd58SJeremy L Thompson /** 977b13efd58SJeremy L Thompson @brief Retrieve list of additional JiT source roots from `Ceed` context. 978b13efd58SJeremy L Thompson 979b13efd58SJeremy L Thompson Note: The caller is responsible for restoring `jit_source_roots` with @ref CeedRestoreJitSourceRoots(). 980b13efd58SJeremy L Thompson 981b13efd58SJeremy L Thompson @param[in] ceed `Ceed` context 982b13efd58SJeremy L Thompson @param[out] num_source_roots Number of JiT source directories 983b13efd58SJeremy L Thompson @param[out] jit_source_roots Absolute paths to additional JiT source directories 984b13efd58SJeremy L Thompson 985b13efd58SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 986b13efd58SJeremy L Thompson 987b13efd58SJeremy L Thompson @ref Backend 988b13efd58SJeremy L Thompson **/ 989b13efd58SJeremy L Thompson int CeedGetJitSourceRoots(Ceed ceed, CeedInt *num_source_roots, const char ***jit_source_roots) { 990b13efd58SJeremy L Thompson Ceed ceed_parent; 991b13efd58SJeremy L Thompson 992b13efd58SJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 993b13efd58SJeremy L Thompson *num_source_roots = ceed_parent->num_jit_source_roots; 994b13efd58SJeremy L Thompson *jit_source_roots = (const char **)ceed_parent->jit_source_roots; 995aeb3a72dSJeremy L Thompson ceed_parent->num_jit_source_roots_readers++; 9969bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 997b13efd58SJeremy L Thompson return CEED_ERROR_SUCCESS; 998b13efd58SJeremy L Thompson } 999b13efd58SJeremy L Thompson 1000b13efd58SJeremy L Thompson /** 10012027fb9dSSirAlienTheGreat @brief Retrieve list of additional Rust source roots from `Ceed` context. 10022027fb9dSSirAlienTheGreat 10032027fb9dSSirAlienTheGreat Note: The caller is responsible for restoring `rust_source_roots` with @ref CeedRestoreRustSourceRoots(). 10042027fb9dSSirAlienTheGreat 10052027fb9dSSirAlienTheGreat @param[in] ceed `Ceed` context 10062027fb9dSSirAlienTheGreat @param[out] num_source_roots Number of JiT source directories 10072027fb9dSSirAlienTheGreat @param[out] rust_source_roots Absolute paths to additional Rust source directories 10082027fb9dSSirAlienTheGreat 10092027fb9dSSirAlienTheGreat @return An error code: 0 - success, otherwise - failure 10102027fb9dSSirAlienTheGreat 10112027fb9dSSirAlienTheGreat @ref Backend 10122027fb9dSSirAlienTheGreat **/ 10132027fb9dSSirAlienTheGreat int CeedGetRustSourceRoots(Ceed ceed, CeedInt *num_source_roots, const char ***rust_source_roots) { 10142027fb9dSSirAlienTheGreat Ceed ceed_parent; 10152027fb9dSSirAlienTheGreat 10162027fb9dSSirAlienTheGreat CeedCall(CeedGetParent(ceed, &ceed_parent)); 10172027fb9dSSirAlienTheGreat *num_source_roots = ceed_parent->num_rust_source_roots; 10182027fb9dSSirAlienTheGreat *rust_source_roots = (const char **)ceed_parent->rust_source_roots; 10192027fb9dSSirAlienTheGreat ceed_parent->num_rust_source_roots_readers++; 10202027fb9dSSirAlienTheGreat CeedCall(CeedDestroy(&ceed_parent)); 10212027fb9dSSirAlienTheGreat return CEED_ERROR_SUCCESS; 10222027fb9dSSirAlienTheGreat } 10232027fb9dSSirAlienTheGreat 10242027fb9dSSirAlienTheGreat /** 1025b13efd58SJeremy L Thompson @brief Restore list of additional JiT source roots from with @ref CeedGetJitSourceRoots() 1026b13efd58SJeremy L Thompson 1027b13efd58SJeremy L Thompson @param[in] ceed `Ceed` context 1028b13efd58SJeremy L Thompson @param[out] jit_source_roots Absolute paths to additional JiT source directories 1029b13efd58SJeremy L Thompson 1030b13efd58SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1031b13efd58SJeremy L Thompson 1032b13efd58SJeremy L Thompson @ref Backend 1033b13efd58SJeremy L Thompson **/ 1034b13efd58SJeremy L Thompson int CeedRestoreJitSourceRoots(Ceed ceed, const char ***jit_source_roots) { 1035aeb3a72dSJeremy L Thompson Ceed ceed_parent; 1036aeb3a72dSJeremy L Thompson 1037aeb3a72dSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 1038b13efd58SJeremy L Thompson *jit_source_roots = NULL; 1039aeb3a72dSJeremy L Thompson ceed_parent->num_jit_source_roots_readers--; 10409bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 1041b13efd58SJeremy L Thompson return CEED_ERROR_SUCCESS; 1042b13efd58SJeremy L Thompson } 1043b13efd58SJeremy L Thompson 10444753b775SJeremy L Thompson /** 10452027fb9dSSirAlienTheGreat @brief Restore list of additional Rust source roots from with @ref CeedGetJitSourceRoots() 10462027fb9dSSirAlienTheGreat 10472027fb9dSSirAlienTheGreat @param[in] ceed `Ceed` context 10482027fb9dSSirAlienTheGreat @param[out] rust_source_roots Absolute paths to additional Rust source directories 10492027fb9dSSirAlienTheGreat 10502027fb9dSSirAlienTheGreat @return An error code: 0 - success, otherwise - failure 10512027fb9dSSirAlienTheGreat 10522027fb9dSSirAlienTheGreat @ref Backend 10532027fb9dSSirAlienTheGreat **/ 10542027fb9dSSirAlienTheGreat int CeedRestoreRustSourceRoots(Ceed ceed, const char ***rust_source_roots) { 10552027fb9dSSirAlienTheGreat Ceed ceed_parent; 10562027fb9dSSirAlienTheGreat 10572027fb9dSSirAlienTheGreat CeedCall(CeedGetParent(ceed, &ceed_parent)); 10582027fb9dSSirAlienTheGreat *rust_source_roots = NULL; 10592027fb9dSSirAlienTheGreat ceed_parent->num_rust_source_roots_readers--; 10602027fb9dSSirAlienTheGreat CeedCall(CeedDestroy(&ceed_parent)); 10612027fb9dSSirAlienTheGreat return CEED_ERROR_SUCCESS; 10622027fb9dSSirAlienTheGreat } 10632027fb9dSSirAlienTheGreat 10642027fb9dSSirAlienTheGreat /** 10654753b775SJeremy L Thompson @brief Retrieve list of additional JiT defines from `Ceed` context. 10664753b775SJeremy L Thompson 10674753b775SJeremy L Thompson Note: The caller is responsible for restoring `jit_defines` with @ref CeedRestoreJitDefines(). 10684753b775SJeremy L Thompson 10694753b775SJeremy L Thompson @param[in] ceed `Ceed` context 10704753b775SJeremy L Thompson @param[out] num_jit_defines Number of JiT defines 10714753b775SJeremy L Thompson @param[out] jit_defines Strings such as `foo=bar`, used as `-Dfoo=bar` in JiT 10724753b775SJeremy L Thompson 10734753b775SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10744753b775SJeremy L Thompson 10754753b775SJeremy L Thompson @ref Backend 10764753b775SJeremy L Thompson **/ 10772686ebe6SJed Brown int CeedGetJitDefines(Ceed ceed, CeedInt *num_jit_defines, const char ***jit_defines) { 10784753b775SJeremy L Thompson Ceed ceed_parent; 10794753b775SJeremy L Thompson 10804753b775SJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 10812686ebe6SJed Brown *num_jit_defines = ceed_parent->num_jit_defines; 10824753b775SJeremy L Thompson *jit_defines = (const char **)ceed_parent->jit_defines; 1083aeb3a72dSJeremy L Thompson ceed_parent->num_jit_defines_readers++; 10849bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 10854753b775SJeremy L Thompson return CEED_ERROR_SUCCESS; 10864753b775SJeremy L Thompson } 10874753b775SJeremy L Thompson 10884753b775SJeremy L Thompson /** 10894753b775SJeremy L Thompson @brief Restore list of additional JiT defines from with @ref CeedGetJitDefines() 10904753b775SJeremy L Thompson 10914753b775SJeremy L Thompson @param[in] ceed `Ceed` context 10924753b775SJeremy L Thompson @param[out] jit_defines String such as `foo=bar`, used as `-Dfoo=bar` in JiT 10934753b775SJeremy L Thompson 10944753b775SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10954753b775SJeremy L Thompson 10964753b775SJeremy L Thompson @ref Backend 10974753b775SJeremy L Thompson **/ 10984753b775SJeremy L Thompson int CeedRestoreJitDefines(Ceed ceed, const char ***jit_defines) { 1099aeb3a72dSJeremy L Thompson Ceed ceed_parent; 1100aeb3a72dSJeremy L Thompson 1101aeb3a72dSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 11024753b775SJeremy L Thompson *jit_defines = NULL; 1103aeb3a72dSJeremy L Thompson ceed_parent->num_jit_defines_readers--; 11049bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 11054753b775SJeremy L Thompson return CEED_ERROR_SUCCESS; 11064753b775SJeremy L Thompson } 11074753b775SJeremy L Thompson 11087a982d89SJeremy L. Thompson /// @} 11097a982d89SJeremy L. Thompson 11107a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 11117a982d89SJeremy L. Thompson /// Ceed Public API 11127a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 11137a982d89SJeremy L. Thompson /// @addtogroup CeedUser 11147a982d89SJeremy L. Thompson /// @{ 11157a982d89SJeremy L. Thompson 11167a982d89SJeremy L. Thompson /** 1117ca94c3ddSJeremy L Thompson @brief Get the list of available resource names for `Ceed` contexts 11184385fb7fSSebastian Grimberg 1119ca94c3ddSJeremy 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. 112022e44211Sjeremylt 112192ee7d1cSjeremylt @param[out] n Number of available resources 112292ee7d1cSjeremylt @param[out] resources List of available resource names 112322e44211Sjeremylt @param[out] priorities Resource name prioritization values, lower is better 112422e44211Sjeremylt 112522e44211Sjeremylt @return An error code: 0 - success, otherwise - failure 112622e44211Sjeremylt 112722e44211Sjeremylt @ref User 112822e44211Sjeremylt **/ 112922e44211Sjeremylt // LCOV_EXCL_START 11302b730f8bSJeremy L Thompson int CeedRegistryGetList(size_t *n, char ***const resources, CeedInt **priorities) { 1131d0c91ce9Sjeremylt *n = 0; 11329ff86846Sjeremylt *resources = malloc(num_backends * sizeof(**resources)); 11336574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 11349ff86846Sjeremylt if (priorities) { 11359ff86846Sjeremylt *priorities = malloc(num_backends * sizeof(**priorities)); 11366574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "malloc() failure"); 11379ff86846Sjeremylt } 113822e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 1139d0c91ce9Sjeremylt // Only report compiled backends 1140d0c91ce9Sjeremylt if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) { 114122e44211Sjeremylt *resources[i] = backends[i].prefix; 11429ff86846Sjeremylt if (priorities) *priorities[i] = backends[i].priority; 1143d0c91ce9Sjeremylt *n += 1; 1144d0c91ce9Sjeremylt } 1145d0c91ce9Sjeremylt } 11466574a04fSJeremy L Thompson CeedCheck(*n, NULL, CEED_ERROR_MAJOR, "No backends installed"); 1147d0c91ce9Sjeremylt *resources = realloc(*resources, *n * sizeof(**resources)); 11486574a04fSJeremy L Thompson CeedCheck(resources, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 1149d0c91ce9Sjeremylt if (priorities) { 1150d0c91ce9Sjeremylt *priorities = realloc(*priorities, *n * sizeof(**priorities)); 11516574a04fSJeremy L Thompson CeedCheck(priorities, NULL, CEED_ERROR_MAJOR, "realloc() failure"); 115222e44211Sjeremylt } 115322e44211Sjeremylt return CEED_ERROR_SUCCESS; 115445f1e315Sjeremylt } 115522e44211Sjeremylt // LCOV_EXCL_STOP 115622e44211Sjeremylt 115722e44211Sjeremylt /** 1158ca94c3ddSJeremy L Thompson @brief Initialize a `Ceed` context to use the specified resource. 11594385fb7fSSebastian Grimberg 1160ca94c3ddSJeremy 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`. 1161b11c1e72Sjeremylt 1162ea61e9acSJeremy L Thompson @param[in] resource Resource to use, e.g., "/cpu/self" 1163ea61e9acSJeremy L Thompson @param[out] ceed The library context 1164b11c1e72Sjeremylt 1165b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1166dfdf5a53Sjeremylt 11677a982d89SJeremy L. Thompson @ref User 1168ca94c3ddSJeremy L Thompson 1169ca94c3ddSJeremy L Thompson @sa CeedRegister() CeedDestroy() 1170b11c1e72Sjeremylt **/ 1171d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 11722b730f8bSJeremy L Thompson size_t match_len = 0, match_index = UINT_MAX, match_priority = CEED_MAX_BACKEND_PRIORITY, priority; 1173d7b241e6Sjeremylt 1174fe2413ffSjeremylt // Find matching backend 11756574a04fSJeremy L Thompson CeedCheck(resource, NULL, CEED_ERROR_MAJOR, "No resource provided"); 11762b730f8bSJeremy L Thompson CeedCall(CeedRegisterAll()); 117713873f79Sjeremylt 117822e44211Sjeremylt // Check for help request 117922e44211Sjeremylt const char *help_prefix = "help"; 11802b730f8bSJeremy L Thompson size_t match_help = 0; 11812b730f8bSJeremy L Thompson while (match_help < 4 && resource[match_help] == help_prefix[match_help]) match_help++; 118222e44211Sjeremylt if (match_help == 4) { 11832b730f8bSJeremy L Thompson fprintf(stderr, "libCEED version: %d.%d%d%s\n", CEED_VERSION_MAJOR, CEED_VERSION_MINOR, CEED_VERSION_PATCH, 118422e44211Sjeremylt CEED_VERSION_RELEASE ? "" : "+development"); 118592ee7d1cSjeremylt fprintf(stderr, "Available backend resources:\n"); 118622e44211Sjeremylt for (size_t i = 0; i < num_backends; i++) { 1187d0c91ce9Sjeremylt // Only report compiled backends 11882b730f8bSJeremy L Thompson if (backends[i].priority < CEED_MAX_BACKEND_PRIORITY) fprintf(stderr, " %s\n", backends[i].prefix); 118922e44211Sjeremylt } 119022e44211Sjeremylt fflush(stderr); 119122e44211Sjeremylt match_help = 5; // Delineating character expected 119222e44211Sjeremylt } else { 119322e44211Sjeremylt match_help = 0; 119422e44211Sjeremylt } 119522e44211Sjeremylt 1196ea61e9acSJeremy L Thompson // Find best match, computed as number of matching characters from requested resource stem 11972b730f8bSJeremy L Thompson size_t stem_length = 0; 11982b730f8bSJeremy L Thompson while (resource[stem_length + match_help] && resource[stem_length + match_help] != ':') stem_length++; 1199d7b241e6Sjeremylt for (size_t i = 0; i < num_backends; i++) { 12002b730f8bSJeremy L Thompson size_t n = 0; 1201d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 12022b730f8bSJeremy L Thompson while (prefix[n] && prefix[n] == resource[n + match_help]) n++; 1203d7b241e6Sjeremylt priority = backends[i].priority; 1204d1d35e2fSjeremylt if (n > match_len || (n == match_len && match_priority > priority)) { 1205d1d35e2fSjeremylt match_len = n; 1206d1d35e2fSjeremylt match_priority = priority; 1207f7e22acaSJeremy L Thompson match_index = i; 1208d7b241e6Sjeremylt } 1209d7b241e6Sjeremylt } 12109c9a0587SLeila Ghaffari // Using Levenshtein distance to find closest match 12119c9a0587SLeila Ghaffari if (match_len <= 1 || match_len != stem_length) { 1212203015caSLeila Ghaffari // LCOV_EXCL_START 12139c9a0587SLeila Ghaffari size_t lev_dis = UINT_MAX; 1214f7e22acaSJeremy L Thompson size_t lev_index = UINT_MAX, lev_priority = CEED_MAX_BACKEND_PRIORITY; 12159c9a0587SLeila Ghaffari for (size_t i = 0; i < num_backends; i++) { 12169c9a0587SLeila Ghaffari const char *prefix = backends[i].prefix; 12179c9a0587SLeila Ghaffari size_t prefix_length = strlen(backends[i].prefix); 12189c9a0587SLeila Ghaffari size_t min_len = (prefix_length < stem_length) ? prefix_length : stem_length; 1219092904ddSLeila Ghaffari size_t column[min_len + 1]; 1220092904ddSLeila Ghaffari for (size_t j = 0; j <= min_len; j++) column[j] = j; 12219c9a0587SLeila Ghaffari for (size_t j = 1; j <= min_len; j++) { 12229c9a0587SLeila Ghaffari column[0] = j; 12239c9a0587SLeila Ghaffari for (size_t k = 1, last_diag = j - 1; k <= min_len; k++) { 1224092904ddSLeila Ghaffari size_t old_diag = column[k]; 12259c9a0587SLeila Ghaffari size_t min_1 = (column[k] < column[k - 1]) ? column[k] + 1 : column[k - 1] + 1; 12269c9a0587SLeila Ghaffari size_t min_2 = last_diag + (resource[k - 1] == prefix[j - 1] ? 0 : 1); 12279c9a0587SLeila Ghaffari column[k] = (min_1 < min_2) ? min_1 : min_2; 12289c9a0587SLeila Ghaffari last_diag = old_diag; 12299c9a0587SLeila Ghaffari } 12309c9a0587SLeila Ghaffari } 12319c9a0587SLeila Ghaffari size_t n = column[min_len]; 12329c9a0587SLeila Ghaffari priority = backends[i].priority; 12332b730f8bSJeremy L Thompson if (n < lev_dis || (n == lev_dis && lev_priority > priority)) { 12349c9a0587SLeila Ghaffari lev_dis = n; 12359c9a0587SLeila Ghaffari lev_priority = priority; 1236f7e22acaSJeremy L Thompson lev_index = i; 12379c9a0587SLeila Ghaffari } 12389c9a0587SLeila Ghaffari } 1239f7e22acaSJeremy L Thompson const char *prefix_lev = backends[lev_index].prefix; 12402b730f8bSJeremy L Thompson size_t lev_length = 0; 12412b730f8bSJeremy L Thompson while (prefix_lev[lev_length] && prefix_lev[lev_length] != '\0') lev_length++; 12429c9a0587SLeila Ghaffari size_t m = (lev_length < stem_length) ? lev_length : stem_length; 12436574a04fSJeremy L Thompson if (lev_dis + 1 >= m) return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s", resource); 12446574a04fSJeremy L Thompson else return CeedError(NULL, CEED_ERROR_MAJOR, "No suitable backend: %s\nClosest match: %s", resource, backends[lev_index].prefix); 1245203015caSLeila Ghaffari // LCOV_EXCL_STOP 12469c9a0587SLeila Ghaffari } 1247fe2413ffSjeremylt 1248fe2413ffSjeremylt // Setup Ceed 12492b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, ceed)); 1250*6c328a79SJeremy L Thompson CeedCall(CeedObjectCreate(NULL, CeedView_Object, CeedDestroy_Object, &(*ceed)->obj)); 12512b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, &(*ceed)->jit_source_roots)); 12522027fb9dSSirAlienTheGreat CeedCall(CeedCalloc(1, &(*ceed)->rust_source_roots)); 1253bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 12542b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 12552b730f8bSJeremy L Thompson if (!strcmp(ceed_error_handler, "exit")) (*ceed)->Error = CeedErrorExit; 12562b730f8bSJeremy L Thompson else if (!strcmp(ceed_error_handler, "store")) (*ceed)->Error = CeedErrorStore; 12572b730f8bSJeremy L Thompson else (*ceed)->Error = CeedErrorAbort; 1258d1d35e2fSjeremylt memcpy((*ceed)->err_msg, "No error message stored", 24); 1259d7b241e6Sjeremylt (*ceed)->data = NULL; 1260fe2413ffSjeremylt 1261fe2413ffSjeremylt // Set lookup table 1262d1d35e2fSjeremylt FOffset f_offsets[] = { 12636e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 12645ae360d4SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, SetStream), 12656e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 12666e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 1267f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 12686e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 12693ac8f562SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateAtPoints), 12706e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 12716e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 12726e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 127350c301a5SRezgar Shakeri CEED_FTABLE_ENTRY(Ceed, BasisCreateHdiv), 1274c4e3f59bSSebastian Grimberg CEED_FTABLE_ENTRY(Ceed, BasisCreateHcurl), 12756e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 12766e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 1277777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, QFunctionContextCreate), 12786e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 127948acf710SJeremy L Thompson CEED_FTABLE_ENTRY(Ceed, OperatorCreateAtPoints), 12806e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 12819c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasValidArray), 12829c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, HasBorrowedArrayOfType), 12830b8f3c4eSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, CopyStrided), 12846e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 12856a6c615bSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, TakeArray), 12866e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 12870b8f3c4eSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, SetValueStrided), 1288f48ed27dSnbeams CEED_FTABLE_ENTRY(CeedVector, SyncArray), 12896e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 12906e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 12919c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, GetArrayWrite), 12926e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 12936e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 1294547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 1295e0dd3b27Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Scale), 12960f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, AXPY), 12975fb68f37SKaren (Ren) Stengel CEED_FTABLE_ENTRY(CeedVector, AXPBY), 12980f7fd0f8Sjeremylt CEED_FTABLE_ENTRY(CeedVector, PointwiseMult), 1299d99fa3c5SJeremy L Thompson CEED_FTABLE_ENTRY(CeedVector, Reciprocal), 13006e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 13016e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 1302f30b1135SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnsigned), 13037c1dbaffSSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyUnoriented), 130405fa913cSJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyAtPointsInElement), 13056e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 1306bd33150aSjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, GetOffsets), 130777d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetOrientations), 130877d1c127SSebastian Grimberg CEED_FTABLE_ENTRY(CeedElemRestriction, GetCurlOrientations), 130919605835SJeremy L Thompson CEED_FTABLE_ENTRY(CeedElemRestriction, GetAtPointsElementOffset), 13106e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 13116e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 1312db2becc9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAdd), 1313c8c3fa7dSJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAtPoints), 1314db2becc9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedBasis, ApplyAddAtPoints), 13156e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 13166e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 13176e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 13186e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 13198c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetCUDAUserFunction), 13208c84ac63Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, SetHIPUserFunction), 13216e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 13229c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasValidData), 13239c774eddSJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, HasBorrowedDataOfType), 1324777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, SetData), 1325891038deSjeremylt CEED_FTABLE_ENTRY(CeedQFunctionContext, TakeData), 1326777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetData), 132728bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, GetDataRead), 1328777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreData), 132928bfd0b7SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, RestoreDataRead), 13302e64a2b9SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, DataDestroy), 1331777ff853SJeremy L Thompson CEED_FTABLE_ENTRY(CeedQFunctionContext, Destroy), 133280ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunction), 133370a7ffb3SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleQFunctionUpdate), 133480ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleDiagonal), 13359e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddDiagonal), 133680ac2e43SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssemblePointBlockDiagonal), 13379e9210b8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleAddPointBlockDiagonal), 1338e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSymbolic), 1339e2f04181SAndrew T. Barker CEED_FTABLE_ENTRY(CeedOperator, LinearAssemble), 1340cefa2673SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, LinearAssembleSingle), 1341713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 13426e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 1343250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 1344cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 1345250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 13466e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 13476e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 13486e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 13491dfeef1dSjeremylt }; 1350fe2413ffSjeremylt 13512b730f8bSJeremy L Thompson CeedCall(CeedCalloc(sizeof(f_offsets), &(*ceed)->f_offsets)); 1352d1d35e2fSjeremylt memcpy((*ceed)->f_offsets, f_offsets, sizeof(f_offsets)); 1353fe2413ffSjeremylt 135460f9e2d6SJeremy L Thompson // Record env variables CEED_DEBUG or DBG 13551c66c397SJeremy L Thompson (*ceed)->is_debug = getenv("CEED_DEBUG") || getenv("DEBUG") || getenv("DBG"); 135660f9e2d6SJeremy L Thompson 135722e44211Sjeremylt // Copy resource prefix, if backend setup successful 13582b730f8bSJeremy L Thompson CeedCall(CeedStringAllocCopy(backends[match_index].prefix, (char **)&(*ceed)->resource)); 1359ee5a26f2SJeremy L Thompson 1360ee5a26f2SJeremy L Thompson // Set default JiT source root 1361ea61e9acSJeremy L Thompson // Note: there will always be the default root for every Ceed but all additional paths are added to the top-most parent 13622b730f8bSJeremy L Thompson CeedCall(CeedAddJitSourceRoot(*ceed, (char *)CeedJitSourceRootDefault)); 1363ee5a26f2SJeremy L Thompson 13642027fb9dSSirAlienTheGreat // By default, make cuda compile without clang, use nvrtc instead 13652027fb9dSSirAlienTheGreat // Note that this is overridden if a rust file is included (rust requires clang) 13662027fb9dSSirAlienTheGreat const char *env = getenv("GPU_CLANG"); 13672027fb9dSSirAlienTheGreat 13682027fb9dSSirAlienTheGreat if (env && strcmp(env, "1") == 0) { 13692027fb9dSSirAlienTheGreat (*ceed)->cuda_compile_with_clang = true; 13702027fb9dSSirAlienTheGreat } else { 13712027fb9dSSirAlienTheGreat (*ceed)->cuda_compile_with_clang = false; 13722027fb9dSSirAlienTheGreat } 13732027fb9dSSirAlienTheGreat 1374d04bbc78SJeremy L Thompson // Backend specific setup 13752b730f8bSJeremy L Thompson CeedCall(backends[match_index].init(&resource[match_help], *ceed)); 1376e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1377d7b241e6Sjeremylt } 1378d7b241e6Sjeremylt 1379d7b241e6Sjeremylt /** 1380ca94c3ddSJeremy L Thompson @brief Set the GPU stream for a `Ceed` context 13815ae360d4SJeremy L Thompson 1382ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context to set the stream 13835ae360d4SJeremy L Thompson @param[in] handle Handle to GPU stream 13845ae360d4SJeremy L Thompson 13855ae360d4SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13865ae360d4SJeremy L Thompson 13875ae360d4SJeremy L Thompson @ref User 13885ae360d4SJeremy L Thompson **/ 13895ae360d4SJeremy L Thompson int CeedSetStream(Ceed ceed, void *handle) { 1390ca94c3ddSJeremy L Thompson CeedCheck(handle, ceed, CEED_ERROR_INCOMPATIBLE, "Stream handle must be non-NULL"); 13919ffb25e0SJames Wright if (ceed->SetStream) { 13925ae360d4SJeremy L Thompson CeedCall(ceed->SetStream(ceed, handle)); 13939ffb25e0SJames Wright } else { 13949ffb25e0SJames Wright Ceed delegate; 13959ffb25e0SJames Wright CeedCall(CeedGetDelegate(ceed, &delegate)); 13965ae360d4SJeremy L Thompson 139728ce3d2aSJeremy L Thompson if (delegate) CeedCall(CeedSetStream(delegate, handle)); 139828ce3d2aSJeremy L Thompson else return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support setting stream"); 13999bc66399SJeremy L Thompson CeedCall(CeedDestroy(&delegate)); 14009ffb25e0SJames Wright } 14015ae360d4SJeremy L Thompson return CEED_ERROR_SUCCESS; 14025ae360d4SJeremy L Thompson } 14035ae360d4SJeremy L Thompson 14045ae360d4SJeremy L Thompson /** 1405ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `Ceed` context. 14064385fb7fSSebastian Grimberg 1407ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedDestroy(). 1408512bb800SJeremy L Thompson 1409ca94c3ddSJeremy 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. 1410ca94c3ddSJeremy L Thompson This `Ceed` context will be destroyed if `*ceed_copy` is the only reference to this `Ceed` context. 14119560d06aSjeremylt 1412ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to copy reference to 1413ea61e9acSJeremy L Thompson @param[in,out] ceed_copy Variable to store copied reference 14149560d06aSjeremylt 14159560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 14169560d06aSjeremylt 14179560d06aSjeremylt @ref User 14189560d06aSjeremylt **/ 14199560d06aSjeremylt int CeedReferenceCopy(Ceed ceed, Ceed *ceed_copy) { 14202b730f8bSJeremy L Thompson CeedCall(CeedReference(ceed)); 14212b730f8bSJeremy L Thompson CeedCall(CeedDestroy(ceed_copy)); 14229560d06aSjeremylt *ceed_copy = ceed; 14239560d06aSjeremylt return CEED_ERROR_SUCCESS; 14249560d06aSjeremylt } 14259560d06aSjeremylt 14269560d06aSjeremylt /** 1427ca94c3ddSJeremy L Thompson @brief Get the full resource name for a `Ceed` context 14282f86a920SJeremy L Thompson 1429ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get resource name of 14307a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 14312f86a920SJeremy L Thompson 14322f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 14332f86a920SJeremy L Thompson 14347a982d89SJeremy L. Thompson @ref User 14355107b09fSJeremy L Thompson **/ 14367a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 14377a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 1438e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 14395107b09fSJeremy L Thompson } 14405107b09fSJeremy L Thompson 14415107b09fSJeremy L Thompson /** 1442ca94c3ddSJeremy L Thompson @brief Return `Ceed` context preferred memory type 1443c907536fSjeremylt 1444ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to get preferred memory type of 1445d1d35e2fSjeremylt @param[out] mem_type Address to save preferred memory type to 1446c907536fSjeremylt 1447c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 1448c907536fSjeremylt 14497a982d89SJeremy L. Thompson @ref User 1450c907536fSjeremylt **/ 1451d1d35e2fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *mem_type) { 1452c907536fSjeremylt if (ceed->GetPreferredMemType) { 14532b730f8bSJeremy L Thompson CeedCall(ceed->GetPreferredMemType(mem_type)); 1454c907536fSjeremylt } else { 1455c263cd57Sjeremylt Ceed delegate; 14562b730f8bSJeremy L Thompson CeedCall(CeedGetDelegate(ceed, &delegate)); 1457c263cd57Sjeremylt 1458c263cd57Sjeremylt if (delegate) { 14592b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(delegate, mem_type)); 1460c263cd57Sjeremylt } else { 1461d1d35e2fSjeremylt *mem_type = CEED_MEM_HOST; 1462c907536fSjeremylt } 14639bc66399SJeremy L Thompson CeedCall(CeedDestroy(&delegate)); 1464c263cd57Sjeremylt } 1465e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1466c907536fSjeremylt } 1467c907536fSjeremylt 1468c907536fSjeremylt /** 1469ca94c3ddSJeremy L Thompson @brief Get deterministic status of `Ceed` context 14709525855cSJeremy L Thompson 1471ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context 1472d1d35e2fSjeremylt @param[out] is_deterministic Variable to store deterministic status 14739525855cSJeremy L Thompson 14749525855cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 14759525855cSJeremy L Thompson 14769525855cSJeremy L Thompson @ref User 14779525855cSJeremy L Thompson **/ 1478d1d35e2fSjeremylt int CeedIsDeterministic(Ceed ceed, bool *is_deterministic) { 1479d1d35e2fSjeremylt *is_deterministic = ceed->is_deterministic; 1480e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 14819525855cSJeremy L Thompson } 14829525855cSJeremy L Thompson 14839525855cSJeremy L Thompson /** 1484ca94c3ddSJeremy L Thompson @brief Set additional JiT source root for `Ceed` context 1485ee5a26f2SJeremy L Thompson 1486ca94c3ddSJeremy L Thompson @param[in,out] ceed `Ceed` context 1487ee5a26f2SJeremy L Thompson @param[in] jit_source_root Absolute path to additional JiT source directory 1488ee5a26f2SJeremy L Thompson 1489ee5a26f2SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1490ee5a26f2SJeremy L Thompson 1491ee5a26f2SJeremy L Thompson @ref User 1492ee5a26f2SJeremy L Thompson **/ 1493ee5a26f2SJeremy L Thompson int CeedAddJitSourceRoot(Ceed ceed, const char *jit_source_root) { 14946155f12fSJeremy L Thompson Ceed ceed_parent; 1495ee5a26f2SJeremy L Thompson 14962b730f8bSJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 1497830fc37bSJeremy 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"); 14986155f12fSJeremy L Thompson 14996155f12fSJeremy L Thompson CeedInt index = ceed_parent->num_jit_source_roots; 1500ee5a26f2SJeremy L Thompson size_t path_length = strlen(jit_source_root); 15011c66c397SJeremy L Thompson 15024753b775SJeremy L Thompson if (ceed_parent->num_jit_source_roots == ceed_parent->max_jit_source_roots) { 15034753b775SJeremy L Thompson if (ceed_parent->max_jit_source_roots == 0) ceed_parent->max_jit_source_roots = 1; 15044753b775SJeremy L Thompson ceed_parent->max_jit_source_roots *= 2; 15054753b775SJeremy L Thompson CeedCall(CeedRealloc(ceed_parent->max_jit_source_roots, &ceed_parent->jit_source_roots)); 15064753b775SJeremy L Thompson } 15072b730f8bSJeremy L Thompson CeedCall(CeedCalloc(path_length + 1, &ceed_parent->jit_source_roots[index])); 1508d602d780SJeremy L Thompson memcpy(ceed_parent->jit_source_roots[index], jit_source_root, path_length); 15096155f12fSJeremy L Thompson ceed_parent->num_jit_source_roots++; 15109bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 1511ee5a26f2SJeremy L Thompson return CEED_ERROR_SUCCESS; 1512ee5a26f2SJeremy L Thompson } 1513ee5a26f2SJeremy L Thompson 1514ee5a26f2SJeremy L Thompson /** 15152027fb9dSSirAlienTheGreat @brief Set additional Rust source root for `Ceed` context for use in QFunction 15162027fb9dSSirAlienTheGreat 15172027fb9dSSirAlienTheGreat @param[in,out] ceed `Ceed` context 15182027fb9dSSirAlienTheGreat @param[in] rust_source_root Absolute path to additional Rust source directory 15192027fb9dSSirAlienTheGreat 15202027fb9dSSirAlienTheGreat @return An error code: 0 - success, otherwise - failure 15212027fb9dSSirAlienTheGreat 15222027fb9dSSirAlienTheGreat @ref User 15232027fb9dSSirAlienTheGreat **/ 15242027fb9dSSirAlienTheGreat int CeedAddRustSourceRoot(Ceed ceed, const char *rust_source_root) { 15252027fb9dSSirAlienTheGreat Ceed ceed_parent; 15262027fb9dSSirAlienTheGreat 15272027fb9dSSirAlienTheGreat CeedCall(CeedGetParent(ceed, &ceed_parent)); 15282027fb9dSSirAlienTheGreat CeedCheck(!ceed_parent->num_rust_source_roots_readers, ceed, CEED_ERROR_ACCESS, "Cannot add Rust source root, read access has not been restored"); 15292027fb9dSSirAlienTheGreat 15302027fb9dSSirAlienTheGreat CeedInt index = ceed_parent->num_rust_source_roots; 15312027fb9dSSirAlienTheGreat size_t path_length = strlen(rust_source_root); 15322027fb9dSSirAlienTheGreat 15332027fb9dSSirAlienTheGreat if (ceed_parent->num_rust_source_roots == ceed_parent->max_rust_source_roots) { 15342027fb9dSSirAlienTheGreat if (ceed_parent->max_rust_source_roots == 0) ceed_parent->max_rust_source_roots = 1; 15352027fb9dSSirAlienTheGreat ceed_parent->max_rust_source_roots *= 2; 15362027fb9dSSirAlienTheGreat CeedCall(CeedRealloc(ceed_parent->max_rust_source_roots, &ceed_parent->rust_source_roots)); 15372027fb9dSSirAlienTheGreat } 15382027fb9dSSirAlienTheGreat CeedCall(CeedCalloc(path_length + 1, &ceed_parent->rust_source_roots[index])); 15392027fb9dSSirAlienTheGreat memcpy(ceed_parent->rust_source_roots[index], rust_source_root, path_length); 15402027fb9dSSirAlienTheGreat ceed_parent->num_rust_source_roots++; 15412027fb9dSSirAlienTheGreat ceed_parent->cuda_compile_with_clang = true; 15422027fb9dSSirAlienTheGreat ceed->cuda_compile_with_clang = true; 15432027fb9dSSirAlienTheGreat CeedCall(CeedDestroy(&ceed_parent)); 15442027fb9dSSirAlienTheGreat return CEED_ERROR_SUCCESS; 15452027fb9dSSirAlienTheGreat } 15462027fb9dSSirAlienTheGreat 15472027fb9dSSirAlienTheGreat /** 15484753b775SJeremy L Thompson @brief Set additional JiT compiler define for `Ceed` context 15494753b775SJeremy L Thompson 15504753b775SJeremy L Thompson @param[in,out] ceed `Ceed` context 15514753b775SJeremy L Thompson @param[in] jit_define String such as `foo=bar`, used as `-Dfoo=bar` in JiT 15524753b775SJeremy L Thompson 15534753b775SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 15544753b775SJeremy L Thompson 15554753b775SJeremy L Thompson @ref User 15564753b775SJeremy L Thompson **/ 15574753b775SJeremy L Thompson int CeedAddJitDefine(Ceed ceed, const char *jit_define) { 15584753b775SJeremy L Thompson Ceed ceed_parent; 15594753b775SJeremy L Thompson 15604753b775SJeremy L Thompson CeedCall(CeedGetParent(ceed, &ceed_parent)); 1561830fc37bSJeremy L Thompson CeedCheck(!ceed_parent->num_jit_defines_readers, ceed, CEED_ERROR_ACCESS, "Cannot add JiT define, read access has not been restored"); 15624753b775SJeremy L Thompson 15634753b775SJeremy L Thompson CeedInt index = ceed_parent->num_jit_defines; 15644753b775SJeremy L Thompson size_t define_length = strlen(jit_define); 15654753b775SJeremy L Thompson 15664753b775SJeremy L Thompson if (ceed_parent->num_jit_defines == ceed_parent->max_jit_defines) { 15674753b775SJeremy L Thompson if (ceed_parent->max_jit_defines == 0) ceed_parent->max_jit_defines = 1; 15684753b775SJeremy L Thompson ceed_parent->max_jit_defines *= 2; 15694753b775SJeremy L Thompson CeedCall(CeedRealloc(ceed_parent->max_jit_defines, &ceed_parent->jit_defines)); 15704753b775SJeremy L Thompson } 15714753b775SJeremy L Thompson CeedCall(CeedCalloc(define_length + 1, &ceed_parent->jit_defines[index])); 15724753b775SJeremy L Thompson memcpy(ceed_parent->jit_defines[index], jit_define, define_length); 15734753b775SJeremy L Thompson ceed_parent->num_jit_defines++; 15749bc66399SJeremy L Thompson CeedCall(CeedDestroy(&ceed_parent)); 15754753b775SJeremy L Thompson return CEED_ERROR_SUCCESS; 15764753b775SJeremy L Thompson } 15774753b775SJeremy L Thompson 15784753b775SJeremy L Thompson /** 15794c789ea2SJeremy L Thompson @brief Set the number of tabs to indent for @ref CeedView() output 15804c789ea2SJeremy L Thompson 15814c789ea2SJeremy L Thompson @param[in] ceed `Ceed` to set the number of view tabs 15824c789ea2SJeremy L Thompson @param[in] num_tabs Number of view tabs to set 15834c789ea2SJeremy L Thompson 15844c789ea2SJeremy L Thompson @return Error code: 0 - success, otherwise - failure 15854c789ea2SJeremy L Thompson 15864c789ea2SJeremy L Thompson @ref User 15874c789ea2SJeremy L Thompson **/ 15884c789ea2SJeremy L Thompson int CeedSetNumViewTabs(Ceed ceed, CeedInt num_tabs) { 1589a299a25bSJeremy L Thompson CeedCall(CeedObjectSetNumViewTabs((CeedObject)ceed, num_tabs)); 15904c789ea2SJeremy L Thompson return CEED_ERROR_SUCCESS; 15914c789ea2SJeremy L Thompson } 15924c789ea2SJeremy L Thompson 15934c789ea2SJeremy L Thompson /** 1594690992b2SZach Atkins @brief Get the number of tabs to indent for @ref CeedView() output 1595690992b2SZach Atkins 1596690992b2SZach Atkins @param[in] ceed `Ceed` to get the number of view tabs 1597690992b2SZach Atkins @param[out] num_tabs Number of view tabs 1598690992b2SZach Atkins 1599690992b2SZach Atkins @return Error code: 0 - success, otherwise - failure 1600690992b2SZach Atkins 1601690992b2SZach Atkins @ref User 1602690992b2SZach Atkins **/ 1603690992b2SZach Atkins int CeedGetNumViewTabs(Ceed ceed, CeedInt *num_tabs) { 1604a299a25bSJeremy L Thompson CeedCall(CeedObjectGetNumViewTabs((CeedObject)ceed, num_tabs)); 1605690992b2SZach Atkins return CEED_ERROR_SUCCESS; 1606690992b2SZach Atkins } 1607690992b2SZach Atkins 1608690992b2SZach Atkins /** 1609ca94c3ddSJeremy L Thompson @brief View a `Ceed` 16100a0da059Sjeremylt 1611ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` to view 16120a0da059Sjeremylt @param[in] stream Filestream to write to 16130a0da059Sjeremylt 16140a0da059Sjeremylt @return An error code: 0 - success, otherwise - failure 16150a0da059Sjeremylt 16160a0da059Sjeremylt @ref User 16170a0da059Sjeremylt **/ 16180a0da059Sjeremylt int CeedView(Ceed ceed, FILE *stream) { 16194c789ea2SJeremy L Thompson char *tabs = NULL; 1620d1d35e2fSjeremylt CeedMemType mem_type; 16210a0da059Sjeremylt 16224c789ea2SJeremy L Thompson { 16234c789ea2SJeremy L Thompson CeedInt num_tabs = 0; 16244c789ea2SJeremy L Thompson 16254c789ea2SJeremy L Thompson CeedCall(CeedGetNumViewTabs(ceed, &num_tabs)); 16264c789ea2SJeremy L Thompson CeedCall(CeedCalloc(CEED_TAB_WIDTH * num_tabs + 1, &tabs)); 16274c789ea2SJeremy L Thompson for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' '; 16284c789ea2SJeremy L Thompson } 16294c789ea2SJeremy L Thompson 16302b730f8bSJeremy L Thompson CeedCall(CeedGetPreferredMemType(ceed, &mem_type)); 16310a0da059Sjeremylt 16322b730f8bSJeremy L Thompson fprintf(stream, 16334c789ea2SJeremy L Thompson "%sCeed\n" 16344c789ea2SJeremy L Thompson "%s Ceed Resource: %s\n" 16354c789ea2SJeremy L Thompson "%s Preferred MemType: %s\n", 16364c789ea2SJeremy L Thompson tabs, tabs, ceed->resource, tabs, CeedMemTypes[mem_type]); 16374c789ea2SJeremy L Thompson CeedCall(CeedFree(&tabs)); 1638e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 16390a0da059Sjeremylt } 16400a0da059Sjeremylt 16410a0da059Sjeremylt /** 1642ca94c3ddSJeremy L Thompson @brief Destroy a `Ceed` 1643d7b241e6Sjeremylt 1644ca94c3ddSJeremy L Thompson @param[in,out] ceed Address of `Ceed` context to destroy 1645b11c1e72Sjeremylt 1646b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1647dfdf5a53Sjeremylt 16487a982d89SJeremy L. Thompson @ref User 1649b11c1e72Sjeremylt **/ 1650d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 1651b0f67a9cSJeremy L Thompson if (!*ceed || CeedObjectDereference((CeedObject)*ceed) > 0) { 1652ad6481ceSJeremy L Thompson *ceed = NULL; 1653ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1654ad6481ceSJeremy L Thompson } 1655aeb3a72dSJeremy L Thompson 1656aeb3a72dSJeremy L Thompson CeedCheck(!(*ceed)->num_jit_source_roots_readers, *ceed, CEED_ERROR_ACCESS, 1657aeb3a72dSJeremy L Thompson "Cannot destroy ceed context, read access for JiT source roots has been granted"); 1658aeb3a72dSJeremy 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"); 1659aeb3a72dSJeremy L Thompson 16602b730f8bSJeremy L Thompson if ((*ceed)->delegate) CeedCall(CeedDestroy(&(*ceed)->delegate)); 16610ace9bf2Sjeremylt 1662d1d35e2fSjeremylt if ((*ceed)->obj_delegate_count > 0) { 166392ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->obj_delegate_count; i++) { 16642b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&((*ceed)->obj_delegates[i].delegate))); 16652b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates[i].obj_name)); 1666aefd8378Sjeremylt } 16672b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->obj_delegates)); 1668aefd8378Sjeremylt } 16690ace9bf2Sjeremylt 16702b730f8bSJeremy L Thompson if ((*ceed)->Destroy) CeedCall((*ceed)->Destroy(*ceed)); 16710ace9bf2Sjeremylt 167292ae7e47SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_source_roots; i++) { 16732b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots[i])); 1674032e71eaSJeremy L Thompson } 16752b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_source_roots)); 1676032e71eaSJeremy L Thompson 16774753b775SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_jit_defines; i++) { 16784753b775SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_defines[i])); 16794753b775SJeremy L Thompson } 16804753b775SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->jit_defines)); 16814753b775SJeremy L Thompson 1682898eb931SJeremy L Thompson for (CeedInt i = 0; i < (*ceed)->num_rust_source_roots; i++) { 1683898eb931SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->rust_source_roots[i])); 1684898eb931SJeremy L Thompson } 1685898eb931SJeremy L Thompson CeedCall(CeedFree(&(*ceed)->rust_source_roots)); 1686898eb931SJeremy L Thompson 16872b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->f_offsets)); 16882b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*ceed)->resource)); 16892b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed)); 169073501bfeSJeremy L Thompson CeedCall(CeedWorkVectorsDestroy(*ceed)); 1691*6c328a79SJeremy L Thompson CeedCall(CeedObjectDestroy_Private(&(*ceed)->obj)); 16922b730f8bSJeremy L Thompson CeedCall(CeedFree(ceed)); 1693e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1694d7b241e6Sjeremylt } 1695d7b241e6Sjeremylt 1696f9982c62SWill Pazner // LCOV_EXCL_START 1697f9982c62SWill Pazner const char *CeedErrorFormat(Ceed ceed, const char *format, va_list *args) { 16982b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorFormat(ceed->parent, format, args); 169978464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 170078464608Sjeremylt vsnprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, format, *args); // NOLINT 1701d1d35e2fSjeremylt return ceed->err_msg; 1702f9982c62SWill Pazner } 1703f9982c62SWill Pazner // LCOV_EXCL_STOP 1704f9982c62SWill Pazner 17057a982d89SJeremy L. Thompson /** 1706ca94c3ddSJeremy L Thompson @brief Error handling implementation; use @ref CeedError() instead. 1707ca94c3ddSJeremy L Thompson 1708ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 17097a982d89SJeremy L. Thompson 17107a982d89SJeremy L. Thompson @ref Developer 17117a982d89SJeremy L. Thompson **/ 17122b730f8bSJeremy L Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, int ecode, const char *format, ...) { 17137a982d89SJeremy L. Thompson va_list args; 1714d1d35e2fSjeremylt int ret_val; 17151c66c397SJeremy L Thompson 17167a982d89SJeremy L. Thompson va_start(args, format); 17177a982d89SJeremy L. Thompson if (ceed) { 1718d1d35e2fSjeremylt ret_val = ceed->Error(ceed, filename, lineno, func, ecode, format, &args); 17197a982d89SJeremy L. Thompson } else { 1720b0d62198Sjeremylt // LCOV_EXCL_START 1721477729cfSJeremy L Thompson const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 17222b730f8bSJeremy L Thompson if (!ceed_error_handler) ceed_error_handler = "abort"; 1723bcbe1c99SJeremy L Thompson if (!strcmp(ceed_error_handler, "return")) { 1724bcbe1c99SJeremy L Thompson ret_val = CeedErrorReturn(ceed, filename, lineno, func, ecode, format, &args); 1725bcbe1c99SJeremy L Thompson } else { 1726477729cfSJeremy L Thompson // This function will not return 1727d1d35e2fSjeremylt ret_val = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, &args); 17287a982d89SJeremy L. Thompson } 1729bcbe1c99SJeremy L Thompson } 17307a982d89SJeremy L. Thompson va_end(args); 1731d1d35e2fSjeremylt return ret_val; 1732b0d62198Sjeremylt // LCOV_EXCL_STOP 17337a982d89SJeremy L. Thompson } 17347a982d89SJeremy L. Thompson 1735477729cfSJeremy L Thompson /** 1736477729cfSJeremy L Thompson @brief Error handler that returns without printing anything. 1737477729cfSJeremy L Thompson 1738ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1739ca94c3ddSJeremy L Thompson 1740ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1741477729cfSJeremy L Thompson 1742477729cfSJeremy L Thompson @ref Developer 1743477729cfSJeremy L Thompson **/ 1744477729cfSJeremy L Thompson // LCOV_EXCL_START 17452b730f8bSJeremy L Thompson int CeedErrorReturn(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1746d1d35e2fSjeremylt return err_code; 1747477729cfSJeremy L Thompson } 1748477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1749477729cfSJeremy L Thompson 1750477729cfSJeremy L Thompson /** 1751ea61e9acSJeremy L Thompson @brief Error handler that stores the error message for future use and returns the error. 1752477729cfSJeremy L Thompson 1753ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1754ca94c3ddSJeremy L Thompson 1755ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1756477729cfSJeremy L Thompson 1757477729cfSJeremy L Thompson @ref Developer 1758477729cfSJeremy L Thompson **/ 1759477729cfSJeremy L Thompson // LCOV_EXCL_START 17602b730f8bSJeremy L Thompson int CeedErrorStore(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 17612b730f8bSJeremy L Thompson if (ceed->parent) return CeedErrorStore(ceed->parent, filename, line_no, func, err_code, format, args); 1762477729cfSJeremy L Thompson 1763477729cfSJeremy L Thompson // Build message 17641c66c397SJeremy L Thompson int len = snprintf(ceed->err_msg, CEED_MAX_RESOURCE_LEN, "%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 vsnprintf(ceed->err_msg + len, CEED_MAX_RESOURCE_LEN - len, format, *args); // NOLINT 1767d1d35e2fSjeremylt return err_code; 1768477729cfSJeremy L Thompson } 1769477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1770477729cfSJeremy L Thompson 1771477729cfSJeremy L Thompson /** 1772ca94c3ddSJeremy L Thompson @brief Error handler that prints to `stderr` and aborts 1773477729cfSJeremy L Thompson 1774ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1775ca94c3ddSJeremy L Thompson 1776ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1777477729cfSJeremy L Thompson 1778477729cfSJeremy L Thompson @ref Developer 1779477729cfSJeremy L Thompson **/ 1780477729cfSJeremy L Thompson // LCOV_EXCL_START 17812b730f8bSJeremy L Thompson int CeedErrorAbort(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1782d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 1783f9982c62SWill Pazner vfprintf(stderr, format, *args); 1784477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1785477729cfSJeremy L Thompson abort(); 1786d1d35e2fSjeremylt return err_code; 1787477729cfSJeremy L Thompson } 1788477729cfSJeremy L Thompson // LCOV_EXCL_STOP 1789477729cfSJeremy L Thompson 1790477729cfSJeremy L Thompson /** 1791ca94c3ddSJeremy L Thompson @brief Error handler that prints to `stderr` and exits. 1792477729cfSJeremy L Thompson 1793ca94c3ddSJeremy L Thompson Pass this to @ref CeedSetErrorHandler() to obtain this error handling behavior. 1794477729cfSJeremy L Thompson 1795ca94c3ddSJeremy L Thompson In contrast to @ref CeedErrorAbort(), this exits without a signal, so `atexit()` handlers (e.g., as used by gcov) are run. 1796ca94c3ddSJeremy L Thompson 1797ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1798477729cfSJeremy L Thompson 1799477729cfSJeremy L Thompson @ref Developer 1800477729cfSJeremy L Thompson **/ 18012b730f8bSJeremy L Thompson int CeedErrorExit(Ceed ceed, const char *filename, int line_no, const char *func, int err_code, const char *format, va_list *args) { 1802d1d35e2fSjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, line_no, func); 180378464608Sjeremylt // Using pointer to va_list for better FFI, but clang-tidy can't verify va_list is initalized 180478464608Sjeremylt vfprintf(stderr, format, *args); // NOLINT 1805477729cfSJeremy L Thompson fprintf(stderr, "\n"); 1806d1d35e2fSjeremylt exit(err_code); 1807d1d35e2fSjeremylt return err_code; 1808477729cfSJeremy L Thompson } 1809477729cfSJeremy L Thompson 1810477729cfSJeremy L Thompson /** 1811477729cfSJeremy L Thompson @brief Set error handler 1812477729cfSJeremy L Thompson 1813ca94c3ddSJeremy L Thompson A default error handler is set in @ref CeedInit(). 1814ca94c3ddSJeremy L Thompson Use this function to change the error handler to @ref CeedErrorReturn(), @ref CeedErrorAbort(), or a user-defined error handler. 1815ca94c3ddSJeremy L Thompson 1816ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1817477729cfSJeremy L Thompson 1818477729cfSJeremy L Thompson @ref Developer 1819477729cfSJeremy L Thompson **/ 1820d1d35e2fSjeremylt int CeedSetErrorHandler(Ceed ceed, CeedErrorHandler handler) { 1821d1d35e2fSjeremylt ceed->Error = handler; 1822d1d35e2fSjeremylt if (ceed->delegate) CeedSetErrorHandler(ceed->delegate, handler); 18232b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ceed->obj_delegate_count; i++) CeedSetErrorHandler(ceed->obj_delegates[i].delegate, handler); 1824e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1825477729cfSJeremy L Thompson } 1826477729cfSJeremy L Thompson 1827477729cfSJeremy L Thompson /** 1828477729cfSJeremy L Thompson @brief Get error message 1829477729cfSJeremy L Thompson 1830ca94c3ddSJeremy L Thompson The error message is only stored when using the error handler @ref CeedErrorStore() 1831477729cfSJeremy L Thompson 1832ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to retrieve error message 1833d1d35e2fSjeremylt @param[out] err_msg Char pointer to hold error message 1834477729cfSJeremy L Thompson 1835ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1836ca94c3ddSJeremy L Thompson 1837477729cfSJeremy L Thompson @ref Developer 1838477729cfSJeremy L Thompson **/ 1839d1d35e2fSjeremylt int CeedGetErrorMessage(Ceed ceed, const char **err_msg) { 18402b730f8bSJeremy L Thompson if (ceed->parent) return CeedGetErrorMessage(ceed->parent, err_msg); 1841d1d35e2fSjeremylt *err_msg = ceed->err_msg; 1842e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1843477729cfSJeremy L Thompson } 1844477729cfSJeremy L Thompson 1845477729cfSJeremy L Thompson /** 1846ca94c3ddSJeremy L Thompson @brief Restore error message. 1847477729cfSJeremy L Thompson 1848ca94c3ddSJeremy L Thompson The error message is only stored when using the error handler @ref CeedErrorStore(). 1849477729cfSJeremy L Thompson 1850ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context to restore error message 1851d1d35e2fSjeremylt @param[out] err_msg Char pointer that holds error message 1852477729cfSJeremy L Thompson 1853ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1854ca94c3ddSJeremy L Thompson 1855477729cfSJeremy L Thompson @ref Developer 1856477729cfSJeremy L Thompson **/ 1857d1d35e2fSjeremylt int CeedResetErrorMessage(Ceed ceed, const char **err_msg) { 18582b730f8bSJeremy L Thompson if (ceed->parent) return CeedResetErrorMessage(ceed->parent, err_msg); 1859d1d35e2fSjeremylt *err_msg = NULL; 1860d1d35e2fSjeremylt memcpy(ceed->err_msg, "No error message stored", 24); 1861e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1862477729cfSJeremy L Thompson } 1863477729cfSJeremy L Thompson 18641070991dSJed Brown /** 1865ca94c3ddSJeremy L Thompson @brief Get libCEED library version information. 18661070991dSJed Brown 1867ea61e9acSJeremy L Thompson libCEED version numbers have the form major.minor.patch. 1868ea61e9acSJeremy L Thompson Non-release versions may contain unstable interfaces. 18691070991dSJed Brown 18701070991dSJed Brown @param[out] major Major version of the library 18711070991dSJed Brown @param[out] minor Minor version of the library 18721070991dSJed Brown @param[out] patch Patch (subminor) version of the library 187353cbfc38SJeremy L Thompson @param[out] release True for releases; false for development branches 18741070991dSJed Brown 1875ca94c3ddSJeremy L Thompson The caller may pass `NULL` for any arguments that are not needed. 18761070991dSJed Brown 1877ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 18781070991dSJed Brown 18791070991dSJed Brown @ref Developer 1880ca94c3ddSJeremy L Thompson 18814f69910bSJed Brown @sa CEED_VERSION_GE() CeedGetGitVersion() CeedGetBuildConfiguration() 18821070991dSJed Brown */ 18831070991dSJed Brown int CeedGetVersion(int *major, int *minor, int *patch, bool *release) { 18841070991dSJed Brown if (major) *major = CEED_VERSION_MAJOR; 18851070991dSJed Brown if (minor) *minor = CEED_VERSION_MINOR; 18861070991dSJed Brown if (patch) *patch = CEED_VERSION_PATCH; 18871070991dSJed Brown if (release) *release = CEED_VERSION_RELEASE; 1888ca94c3ddSJeremy L Thompson return CEED_ERROR_SUCCESS; 18891070991dSJed Brown } 18901070991dSJed Brown 189153cbfc38SJeremy L Thompson /** 189253cbfc38SJeremy L Thompson @brief Get libCEED scalar type, such as F64 or F32 189353cbfc38SJeremy L Thompson 189453cbfc38SJeremy L Thompson @param[out] scalar_type Type of libCEED scalars 189553cbfc38SJeremy L Thompson 1896ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1897ca94c3ddSJeremy L Thompson 189853cbfc38SJeremy L Thompson @ref Developer 189953cbfc38SJeremy L Thompson */ 190080a9ef05SNatalie Beams int CeedGetScalarType(CeedScalarType *scalar_type) { 190180a9ef05SNatalie Beams *scalar_type = CEED_SCALAR_TYPE; 1902ca94c3ddSJeremy L Thompson return CEED_ERROR_SUCCESS; 190380a9ef05SNatalie Beams } 190480a9ef05SNatalie Beams 1905d7b241e6Sjeremylt /// @} 1906