1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 17d7b241e6Sjeremylt #define _POSIX_C_SOURCE 200112 18d7b241e6Sjeremylt #include <ceed-impl.h> 19d863ab9bSjeremylt #include <ceed-backend.h> 20aedaa0e5Sjeremylt #include <limits.h> 21d7b241e6Sjeremylt #include <stdarg.h> 226e79d475Sjeremylt #include <stddef.h> 23d7b241e6Sjeremylt #include <stdio.h> 24d7b241e6Sjeremylt #include <stdlib.h> 25d7b241e6Sjeremylt #include <string.h> 26d7b241e6Sjeremylt 27d7b241e6Sjeremylt /// @cond DOXYGEN_SKIP 28d7b241e6Sjeremylt static CeedRequest ceed_request_immediate; 29d7b241e6Sjeremylt static CeedRequest ceed_request_ordered; 30d7b241e6Sjeremylt 31d7b241e6Sjeremylt static struct { 32d7b241e6Sjeremylt char prefix[CEED_MAX_RESOURCE_LEN]; 33d7b241e6Sjeremylt int (*init)(const char *resource, Ceed f); 34d7b241e6Sjeremylt unsigned int priority; 35d7b241e6Sjeremylt } backends[32]; 36d7b241e6Sjeremylt static size_t num_backends; 37fe2413ffSjeremylt 386e79d475Sjeremylt #define CEED_FTABLE_ENTRY(class, method) \ 396e79d475Sjeremylt {#class #method, offsetof(struct class ##_private, method)} 40d7b241e6Sjeremylt /// @endcond 41d7b241e6Sjeremylt 42d7b241e6Sjeremylt /// @file 43d7b241e6Sjeremylt /// Implementation of core components of Ceed library 44*7a982d89SJeremy L. Thompson 45*7a982d89SJeremy L. Thompson /// @addtogroup CeedUser 46d7b241e6Sjeremylt /// @{ 47d7b241e6Sjeremylt 48dfdf5a53Sjeremylt /** 49dfdf5a53Sjeremylt @brief Request immediate completion 50dfdf5a53Sjeremylt 51dfdf5a53Sjeremylt This predefined constant is passed as the \ref CeedRequest argument to 52dfdf5a53Sjeremylt interfaces when the caller wishes for the operation to be performed 53dfdf5a53Sjeremylt immediately. The code 54dfdf5a53Sjeremylt 55dfdf5a53Sjeremylt @code 56dfdf5a53Sjeremylt CeedOperatorApply(op, ..., CEED_REQUEST_IMMEDIATE); 57dfdf5a53Sjeremylt @endcode 58dfdf5a53Sjeremylt 59dfdf5a53Sjeremylt is semantically equivalent to 60dfdf5a53Sjeremylt 61dfdf5a53Sjeremylt @code 62dfdf5a53Sjeremylt CeedRequest request; 63dfdf5a53Sjeremylt CeedOperatorApply(op, ..., &request); 64dfdf5a53Sjeremylt CeedRequestWait(&request); 65dfdf5a53Sjeremylt @endcode 66dfdf5a53Sjeremylt 67dfdf5a53Sjeremylt @sa CEED_REQUEST_ORDERED 68dfdf5a53Sjeremylt **/ 69d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_IMMEDIATE = &ceed_request_immediate; 70d7b241e6Sjeremylt 71d7b241e6Sjeremylt /** 72b11c1e72Sjeremylt @brief Request ordered completion 73d7b241e6Sjeremylt 74d7b241e6Sjeremylt This predefined constant is passed as the \ref CeedRequest argument to 75d7b241e6Sjeremylt interfaces when the caller wishes for the operation to be completed in the 76d7b241e6Sjeremylt order that it is submitted to the device. It is typically used in a construct 77d7b241e6Sjeremylt such as 78d7b241e6Sjeremylt 79d7b241e6Sjeremylt @code 80d7b241e6Sjeremylt CeedRequest request; 81d7b241e6Sjeremylt CeedOperatorApply(op1, ..., CEED_REQUEST_ORDERED); 82d7b241e6Sjeremylt CeedOperatorApply(op2, ..., &request); 83d7b241e6Sjeremylt // other optional work 84d7b241e6Sjeremylt CeedWait(&request); 85d7b241e6Sjeremylt @endcode 86d7b241e6Sjeremylt 87d7b241e6Sjeremylt which allows the sequence to complete asynchronously but does not start 88d7b241e6Sjeremylt `op2` until `op1` has completed. 89d7b241e6Sjeremylt 90288c0443SJeremy L Thompson @todo The current implementation is overly strict, offering equivalent 91d7b241e6Sjeremylt semantics to CEED_REQUEST_IMMEDIATE. 92d7b241e6Sjeremylt 93d7b241e6Sjeremylt @sa CEED_REQUEST_IMMEDIATE 94d7b241e6Sjeremylt */ 95d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_ORDERED = &ceed_request_ordered; 96d7b241e6Sjeremylt 97b11c1e72Sjeremylt /** 98*7a982d89SJeremy L. Thompson @brief Wait for a CeedRequest to complete. 99dfdf5a53Sjeremylt 100*7a982d89SJeremy L. Thompson Calling CeedRequestWait on a NULL request is a no-op. 101*7a982d89SJeremy L. Thompson 102*7a982d89SJeremy L. Thompson @param req Address of CeedRequest to wait for; zeroed on completion. 103*7a982d89SJeremy L. Thompson 104*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 105*7a982d89SJeremy L. Thompson 106*7a982d89SJeremy L. Thompson @ref User 107b11c1e72Sjeremylt **/ 108*7a982d89SJeremy L. Thompson int CeedRequestWait(CeedRequest *req) { 109*7a982d89SJeremy L. Thompson if (!*req) 110*7a982d89SJeremy L. Thompson return 0; 111*7a982d89SJeremy L. Thompson return CeedError(NULL, 2, "CeedRequestWait not implemented"); 112683faae0SJed Brown } 113*7a982d89SJeremy L. Thompson 114*7a982d89SJeremy L. Thompson /// @} 115*7a982d89SJeremy L. Thompson 116*7a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 117*7a982d89SJeremy L. Thompson /// Ceed Library Internal Functions 118*7a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 119*7a982d89SJeremy L. Thompson /// @addtogroup CeedDeveloper 120*7a982d89SJeremy L. Thompson /// @{ 121d7b241e6Sjeremylt 122b11c1e72Sjeremylt /** 123b11c1e72Sjeremylt @brief Error handler that returns without printing anything. 124b11c1e72Sjeremylt 125b11c1e72Sjeremylt Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 126dfdf5a53Sjeremylt 127dfdf5a53Sjeremylt @ref Developer 128b11c1e72Sjeremylt **/ 12913873f79Sjeremylt // LCOV_EXCL_START 130d7b241e6Sjeremylt int CeedErrorReturn(Ceed ceed, const char *filename, int lineno, 131d7b241e6Sjeremylt const char *func, int ecode, const char *format, 132d7b241e6Sjeremylt va_list args) { 133d7b241e6Sjeremylt return ecode; 134d7b241e6Sjeremylt } 13513873f79Sjeremylt // LCOV_EXCL_STOP 136d7b241e6Sjeremylt 137b11c1e72Sjeremylt /** 138b11c1e72Sjeremylt @brief Error handler that prints to stderr and aborts 139b11c1e72Sjeremylt 140b11c1e72Sjeremylt Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 141dfdf5a53Sjeremylt 142dfdf5a53Sjeremylt @ref Developer 143b11c1e72Sjeremylt **/ 14413873f79Sjeremylt // LCOV_EXCL_START 145d7b241e6Sjeremylt int CeedErrorAbort(Ceed ceed, const char *filename, int lineno, 1461d102b48SJeremy L Thompson const char *func, int ecode, const char *format, 1471d102b48SJeremy L Thompson va_list args) { 148d7b241e6Sjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, lineno, func); 149d7b241e6Sjeremylt vfprintf(stderr, format, args); 150d7b241e6Sjeremylt fprintf(stderr, "\n"); 151d7b241e6Sjeremylt abort(); 152d7b241e6Sjeremylt return ecode; 153d7b241e6Sjeremylt } 15413873f79Sjeremylt // LCOV_EXCL_STOP 155d7b241e6Sjeremylt 156b11c1e72Sjeremylt /** 15756e866f4SJed Brown @brief Error handler that prints to stderr and exits 15856e866f4SJed Brown 15956e866f4SJed Brown Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 16056e866f4SJed Brown 16156e866f4SJed Brown In contrast to CeedErrorAbort(), this exits without a signal, so atexit() 16256e866f4SJed Brown handlers (e.g., as used by gcov) are run. 16356e866f4SJed Brown 16456e866f4SJed Brown @ref Developer 16556e866f4SJed Brown **/ 166692c2638Sjeremylt int CeedErrorExit(Ceed ceed, const char *filename, int lineno, const char *func, 167692c2638Sjeremylt int ecode, const char *format, va_list args) { 16856e866f4SJed Brown fprintf(stderr, "%s:%d in %s(): ", filename, lineno, func); 16956e866f4SJed Brown vfprintf(stderr, format, args); 17056e866f4SJed Brown fprintf(stderr, "\n"); 17156e866f4SJed Brown exit(ecode); 17256e866f4SJed Brown return ecode; 17356e866f4SJed Brown } 17456e866f4SJed Brown 17556e866f4SJed Brown /** 176dfdf5a53Sjeremylt @brief Set error handler 177b11c1e72Sjeremylt 178b11c1e72Sjeremylt A default error handler is set in CeedInit(). Use this function to change 179b11c1e72Sjeremylt the error handler to CeedErrorReturn(), CeedErrorAbort(), or a user-defined 180b11c1e72Sjeremylt error handler. 181dfdf5a53Sjeremylt 182dfdf5a53Sjeremylt @ref Developer 183b11c1e72Sjeremylt **/ 184d7b241e6Sjeremylt int CeedSetErrorHandler(Ceed ceed, 185*7a982d89SJeremy L. Thompson int (*eh)(Ceed, const char *, int, const char *, 186d7b241e6Sjeremylt int, const char *, va_list)) { 187d7b241e6Sjeremylt ceed->Error = eh; 188d7b241e6Sjeremylt return 0; 189d7b241e6Sjeremylt } 190d7b241e6Sjeremylt 191*7a982d89SJeremy L. Thompson /// @} 192d7b241e6Sjeremylt 193*7a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 194*7a982d89SJeremy L. Thompson /// Ceed Backend API 195*7a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 196*7a982d89SJeremy L. Thompson /// @addtogroup CeedBackend 197*7a982d89SJeremy L. Thompson /// @{ 198d7b241e6Sjeremylt 199b11c1e72Sjeremylt /** 200b11c1e72Sjeremylt @brief Allocate an array on the host; use CeedMalloc() 201b11c1e72Sjeremylt 202b11c1e72Sjeremylt Memory usage can be tracked by the library. This ensures sufficient 203b11c1e72Sjeremylt alignment for vectorization and should be used for large allocations. 204b11c1e72Sjeremylt 205b11c1e72Sjeremylt @param n Number of units to allocate 206b11c1e72Sjeremylt @param unit Size of each unit 207b11c1e72Sjeremylt @param p Address of pointer to hold the result. 208b11c1e72Sjeremylt 209b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 210b11c1e72Sjeremylt 211b11c1e72Sjeremylt @sa CeedFree() 212dfdf5a53Sjeremylt 213*7a982d89SJeremy L. Thompson @ref Backend 214b11c1e72Sjeremylt **/ 215d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 216d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n*unit); 217d7b241e6Sjeremylt if (ierr) 218c042f62fSJeremy L Thompson // LCOV_EXCL_START 2191d102b48SJeremy L Thompson return CeedError(NULL, ierr, "posix_memalign failed to allocate %zd " 2201d102b48SJeremy L Thompson "members of size %zd\n", n, unit); 221c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 222c042f62fSJeremy L Thompson 223d7b241e6Sjeremylt return 0; 224d7b241e6Sjeremylt } 225d7b241e6Sjeremylt 226b11c1e72Sjeremylt /** 227b11c1e72Sjeremylt @brief Allocate a cleared (zeroed) array on the host; use CeedCalloc() 228b11c1e72Sjeremylt 229b11c1e72Sjeremylt Memory usage can be tracked by the library. 230b11c1e72Sjeremylt 231b11c1e72Sjeremylt @param n Number of units to allocate 232b11c1e72Sjeremylt @param unit Size of each unit 233b11c1e72Sjeremylt @param p Address of pointer to hold the result. 234b11c1e72Sjeremylt 235b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 236b11c1e72Sjeremylt 237b11c1e72Sjeremylt @sa CeedFree() 238dfdf5a53Sjeremylt 239*7a982d89SJeremy L. Thompson @ref Backend 240b11c1e72Sjeremylt **/ 241d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 242d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 243d7b241e6Sjeremylt if (n && unit && !*(void **)p) 244c042f62fSJeremy L Thompson // LCOV_EXCL_START 2451d102b48SJeremy L Thompson return CeedError(NULL, 1, "calloc failed to allocate %zd members of size " 2461d102b48SJeremy L Thompson "%zd\n", n, unit); 247c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 248c042f62fSJeremy L Thompson 249d7b241e6Sjeremylt return 0; 250d7b241e6Sjeremylt } 251d7b241e6Sjeremylt 252b11c1e72Sjeremylt /** 253b11c1e72Sjeremylt @brief Reallocate an array on the host; use CeedRealloc() 254b11c1e72Sjeremylt 255b11c1e72Sjeremylt Memory usage can be tracked by the library. 256b11c1e72Sjeremylt 257b11c1e72Sjeremylt @param n Number of units to allocate 258b11c1e72Sjeremylt @param unit Size of each unit 259b11c1e72Sjeremylt @param p Address of pointer to hold the result. 260b11c1e72Sjeremylt 261b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 262b11c1e72Sjeremylt 263b11c1e72Sjeremylt @sa CeedFree() 264dfdf5a53Sjeremylt 265*7a982d89SJeremy L. Thompson @ref Backend 266b11c1e72Sjeremylt **/ 267d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 268d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n*unit); 269d7b241e6Sjeremylt if (n && unit && !*(void **)p) 270c042f62fSJeremy L Thompson // LCOV_EXCL_START 2711d102b48SJeremy L Thompson return CeedError(NULL, 1, "realloc failed to allocate %zd members of size " 2721d102b48SJeremy L Thompson "%zd\n", n, unit); 273c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 274c042f62fSJeremy L Thompson 275d7b241e6Sjeremylt return 0; 276d7b241e6Sjeremylt } 277d7b241e6Sjeremylt 27834138859Sjeremylt /** Free memory allocated using CeedMalloc() or CeedCalloc() 27934138859Sjeremylt 28034138859Sjeremylt @param p address of pointer to memory. This argument is of type void* to 28134138859Sjeremylt avoid needing a cast, but is the address of the pointer (which is 28234138859Sjeremylt zeroed) rather than the pointer. 28334138859Sjeremylt **/ 284d7b241e6Sjeremylt int CeedFree(void *p) { 285d7b241e6Sjeremylt free(*(void **)p); 286d7b241e6Sjeremylt *(void **)p = NULL; 287d7b241e6Sjeremylt return 0; 288d7b241e6Sjeremylt } 289d7b241e6Sjeremylt 290d7b241e6Sjeremylt /** 291*7a982d89SJeremy L. Thompson @brief Register a Ceed backend 292d7b241e6Sjeremylt 293*7a982d89SJeremy L. Thompson @param prefix Prefix of resources for this backend to respond to. For 294*7a982d89SJeremy L. Thompson example, the reference backend responds to "/cpu/self". 295*7a982d89SJeremy L. Thompson @param init Initialization function called by CeedInit() when the backend 296*7a982d89SJeremy L. Thompson is selected to drive the requested resource. 297*7a982d89SJeremy L. Thompson @param priority Integer priority. Lower values are preferred in case the 298*7a982d89SJeremy L. Thompson resource requested by CeedInit() has non-unique best prefix 299*7a982d89SJeremy L. Thompson match. 300b11c1e72Sjeremylt 301b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 302dfdf5a53Sjeremylt 303*7a982d89SJeremy L. Thompson @ref Backend 304b11c1e72Sjeremylt **/ 305*7a982d89SJeremy L. Thompson int CeedRegister(const char *prefix, int (*init)(const char *, Ceed), 306*7a982d89SJeremy L. Thompson unsigned int priority) { 307*7a982d89SJeremy L. Thompson if (num_backends >= sizeof(backends) / sizeof(backends[0])) 308*7a982d89SJeremy L. Thompson // LCOV_EXCL_START 309*7a982d89SJeremy L. Thompson return CeedError(NULL, 1, "Too many backends"); 310*7a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 311*7a982d89SJeremy L. Thompson 312*7a982d89SJeremy L. Thompson strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN); 313*7a982d89SJeremy L. Thompson backends[num_backends].prefix[CEED_MAX_RESOURCE_LEN-1] = 0; 314*7a982d89SJeremy L. Thompson backends[num_backends].init = init; 315*7a982d89SJeremy L. Thompson backends[num_backends].priority = priority; 316*7a982d89SJeremy L. Thompson num_backends++; 3171d102b48SJeremy L Thompson return 0; 318d7b241e6Sjeremylt } 319d7b241e6Sjeremylt 320b11c1e72Sjeremylt /** 321*7a982d89SJeremy L. Thompson @brief Retrieve a parent Ceed context 322*7a982d89SJeremy L. Thompson 323*7a982d89SJeremy L. Thompson @param ceed Ceed context to retrieve parent of 324*7a982d89SJeremy L. Thompson @param[out] parent Address to save the parent to 325*7a982d89SJeremy L. Thompson 326*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 327*7a982d89SJeremy L. Thompson 328*7a982d89SJeremy L. Thompson @ref Backend 329*7a982d89SJeremy L. Thompson **/ 330*7a982d89SJeremy L. Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 331*7a982d89SJeremy L. Thompson int ierr; 332*7a982d89SJeremy L. Thompson if (ceed->parent) { 333*7a982d89SJeremy L. Thompson ierr = CeedGetParent(ceed->parent, parent); CeedChk(ierr); 334*7a982d89SJeremy L. Thompson return 0; 335*7a982d89SJeremy L. Thompson } 336*7a982d89SJeremy L. Thompson *parent = ceed; 337*7a982d89SJeremy L. Thompson return 0; 338*7a982d89SJeremy L. Thompson } 339*7a982d89SJeremy L. Thompson 340*7a982d89SJeremy L. Thompson /** 341*7a982d89SJeremy L. Thompson @brief Retrieve a delegate Ceed context 342*7a982d89SJeremy L. Thompson 343*7a982d89SJeremy L. Thompson @param ceed Ceed context to retrieve delegate of 344*7a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 345*7a982d89SJeremy L. Thompson 346*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 347*7a982d89SJeremy L. Thompson 348*7a982d89SJeremy L. Thompson @ref Backend 349*7a982d89SJeremy L. Thompson **/ 350*7a982d89SJeremy L. Thompson int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 351*7a982d89SJeremy L. Thompson *delegate = ceed->delegate; 352*7a982d89SJeremy L. Thompson return 0; 353*7a982d89SJeremy L. Thompson } 354*7a982d89SJeremy L. Thompson 355*7a982d89SJeremy L. Thompson /** 356*7a982d89SJeremy L. Thompson @brief Set a delegate Ceed context 357*7a982d89SJeremy L. Thompson 358*7a982d89SJeremy L. Thompson This function allows a Ceed context to set a delegate Ceed context. All 359*7a982d89SJeremy L. Thompson backend implementations default to the delegate Ceed context, unless 360*7a982d89SJeremy L. Thompson overridden. 361*7a982d89SJeremy L. Thompson 362*7a982d89SJeremy L. Thompson @param ceed Ceed context to set delegate of 363*7a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 364*7a982d89SJeremy L. Thompson 365*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 366*7a982d89SJeremy L. Thompson 367*7a982d89SJeremy L. Thompson @ref Backend 368*7a982d89SJeremy L. Thompson **/ 369*7a982d89SJeremy L. Thompson int CeedSetDelegate(Ceed ceed, Ceed delegate) { 370*7a982d89SJeremy L. Thompson ceed->delegate = delegate; 371*7a982d89SJeremy L. Thompson delegate->parent = ceed; 372*7a982d89SJeremy L. Thompson return 0; 373*7a982d89SJeremy L. Thompson } 374*7a982d89SJeremy L. Thompson 375*7a982d89SJeremy L. Thompson /** 376*7a982d89SJeremy L. Thompson @brief Retrieve a delegate Ceed context for a specific object type 377*7a982d89SJeremy L. Thompson 378*7a982d89SJeremy L. Thompson @param ceed Ceed context to retrieve delegate of 379*7a982d89SJeremy L. Thompson @param[out] delegate Address to save the delegate to 380*7a982d89SJeremy L. Thompson @param[in] objname Name of the object type to retrieve delegate for 381*7a982d89SJeremy L. Thompson 382*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 383*7a982d89SJeremy L. Thompson 384*7a982d89SJeremy L. Thompson @ref Backend 385*7a982d89SJeremy L. Thompson **/ 386*7a982d89SJeremy L. Thompson int CeedGetObjectDelegate(Ceed ceed, Ceed *delegate, const char *objname) { 387*7a982d89SJeremy L. Thompson CeedInt ierr; 388*7a982d89SJeremy L. Thompson 389*7a982d89SJeremy L. Thompson // Check for object delegate 390*7a982d89SJeremy L. Thompson for (CeedInt i=0; i<ceed->objdelegatecount; i++) 391*7a982d89SJeremy L. Thompson if (!strcmp(objname, ceed->objdelegates->objname)) { 392*7a982d89SJeremy L. Thompson *delegate = ceed->objdelegates->delegate; 393*7a982d89SJeremy L. Thompson return 0; 394*7a982d89SJeremy L. Thompson } 395*7a982d89SJeremy L. Thompson 396*7a982d89SJeremy L. Thompson // Use default delegate if no object delegate 397*7a982d89SJeremy L. Thompson ierr = CeedGetDelegate(ceed, delegate); CeedChk(ierr); 398*7a982d89SJeremy L. Thompson 399*7a982d89SJeremy L. Thompson return 0; 400*7a982d89SJeremy L. Thompson } 401*7a982d89SJeremy L. Thompson 402*7a982d89SJeremy L. Thompson /** 403*7a982d89SJeremy L. Thompson @brief Set a delegate Ceed context for a specific object type 404*7a982d89SJeremy L. Thompson 405*7a982d89SJeremy L. Thompson This function allows a Ceed context to set a delegate Ceed context for a 406*7a982d89SJeremy L. Thompson given type of Ceed object. All backend implementations default to the 407*7a982d89SJeremy L. Thompson delegate Ceed context for this object. For example, 408*7a982d89SJeremy L. Thompson CeedSetObjectDelegate(ceed, refceed, "Basis") 409*7a982d89SJeremy L. Thompson uses refceed implementations for all CeedBasis backend functions. 410*7a982d89SJeremy L. Thompson 411*7a982d89SJeremy L. Thompson @param ceed Ceed context to set delegate of 412*7a982d89SJeremy L. Thompson @param[out] delegate Address to set the delegate to 413*7a982d89SJeremy L. Thompson @param[in] objname Name of the object type to set delegate for 414*7a982d89SJeremy L. Thompson 415*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 416*7a982d89SJeremy L. Thompson 417*7a982d89SJeremy L. Thompson @ref Backend 418*7a982d89SJeremy L. Thompson **/ 419*7a982d89SJeremy L. Thompson int CeedSetObjectDelegate(Ceed ceed, Ceed delegate, const char *objname) { 420*7a982d89SJeremy L. Thompson CeedInt ierr; 421*7a982d89SJeremy L. Thompson CeedInt count = ceed->objdelegatecount; 422*7a982d89SJeremy L. Thompson 423*7a982d89SJeremy L. Thompson // Malloc or Realloc 424*7a982d89SJeremy L. Thompson if (count) { 425*7a982d89SJeremy L. Thompson ierr = CeedRealloc(count+1, &ceed->objdelegates); CeedChk(ierr); 426*7a982d89SJeremy L. Thompson } else { 427*7a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &ceed->objdelegates); CeedChk(ierr); 428*7a982d89SJeremy L. Thompson } 429*7a982d89SJeremy L. Thompson ceed->objdelegatecount++; 430*7a982d89SJeremy L. Thompson 431*7a982d89SJeremy L. Thompson // Set object delegate 432*7a982d89SJeremy L. Thompson ceed->objdelegates[count].delegate = delegate; 433*7a982d89SJeremy L. Thompson size_t slen = strlen(objname) + 1; 434*7a982d89SJeremy L. Thompson ierr = CeedMalloc(slen, &ceed->objdelegates[count].objname); CeedChk(ierr); 435*7a982d89SJeremy L. Thompson memcpy(ceed->objdelegates[count].objname, objname, slen); 436*7a982d89SJeremy L. Thompson 437*7a982d89SJeremy L. Thompson // Set delegate parent 438*7a982d89SJeremy L. Thompson delegate->parent = ceed; 439*7a982d89SJeremy L. Thompson 440*7a982d89SJeremy L. Thompson return 0; 441*7a982d89SJeremy L. Thompson } 442*7a982d89SJeremy L. Thompson 443*7a982d89SJeremy L. Thompson /** 444*7a982d89SJeremy L. Thompson @brief Get the fallback resource for CeedOperators 445*7a982d89SJeremy L. Thompson 446*7a982d89SJeremy L. Thompson @param ceed Ceed context 447*7a982d89SJeremy L. Thompson @param[out] resource Variable to store fallback resource 448*7a982d89SJeremy L. Thompson 449*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 450*7a982d89SJeremy L. Thompson 451*7a982d89SJeremy L. Thompson @ref Backend 452*7a982d89SJeremy L. Thompson **/ 453*7a982d89SJeremy L. Thompson 454*7a982d89SJeremy L. Thompson int CeedGetOperatorFallbackResource(Ceed ceed, const char **resource) { 455*7a982d89SJeremy L. Thompson *resource = (const char *)ceed->opfallbackresource; 456*7a982d89SJeremy L. Thompson return 0; 457*7a982d89SJeremy L. Thompson } 458*7a982d89SJeremy L. Thompson 459*7a982d89SJeremy L. Thompson /** 460*7a982d89SJeremy L. Thompson @brief Set the fallback resource for CeedOperators. The current resource, if 461*7a982d89SJeremy L. Thompson any, is freed by calling this function. This string is freed upon the 462*7a982d89SJeremy L. Thompson destruction of the Ceed context. 463*7a982d89SJeremy L. Thompson 464*7a982d89SJeremy L. Thompson @param[out] ceed Ceed context 465*7a982d89SJeremy L. Thompson @param resource Fallback resource to set 466*7a982d89SJeremy L. Thompson 467*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 468*7a982d89SJeremy L. Thompson 469*7a982d89SJeremy L. Thompson @ref Backend 470*7a982d89SJeremy L. Thompson **/ 471*7a982d89SJeremy L. Thompson 472*7a982d89SJeremy L. Thompson int CeedSetOperatorFallbackResource(Ceed ceed, const char *resource) { 473*7a982d89SJeremy L. Thompson int ierr; 474*7a982d89SJeremy L. Thompson 475*7a982d89SJeremy L. Thompson // Free old 476*7a982d89SJeremy L. Thompson ierr = CeedFree(&ceed->opfallbackresource); CeedChk(ierr); 477*7a982d89SJeremy L. Thompson 478*7a982d89SJeremy L. Thompson // Set new 479*7a982d89SJeremy L. Thompson size_t len = strlen(resource); 480*7a982d89SJeremy L. Thompson char *tmp; 481*7a982d89SJeremy L. Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 482*7a982d89SJeremy L. Thompson memcpy(tmp, resource, len+1); 483*7a982d89SJeremy L. Thompson ceed->opfallbackresource = tmp; 484*7a982d89SJeremy L. Thompson 485*7a982d89SJeremy L. Thompson return 0; 486*7a982d89SJeremy L. Thompson } 487*7a982d89SJeremy L. Thompson 488*7a982d89SJeremy L. Thompson /** 489*7a982d89SJeremy L. Thompson @brief Get the parent Ceed context associated with a fallback Ceed context 490*7a982d89SJeremy L. Thompson for a CeedOperator 491*7a982d89SJeremy L. Thompson 492*7a982d89SJeremy L. Thompson @param ceed Ceed context 493*7a982d89SJeremy L. Thompson @param[out] parent Variable to store parent Ceed context 494*7a982d89SJeremy L. Thompson 495*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 496*7a982d89SJeremy L. Thompson 497*7a982d89SJeremy L. Thompson @ref Backend 498*7a982d89SJeremy L. Thompson **/ 499*7a982d89SJeremy L. Thompson 500*7a982d89SJeremy L. Thompson int CeedGetOperatorFallbackParentCeed(Ceed ceed, Ceed *parent) { 501*7a982d89SJeremy L. Thompson *parent = ceed->opfallbackparent; 502*7a982d89SJeremy L. Thompson return 0; 503*7a982d89SJeremy L. Thompson } 504*7a982d89SJeremy L. Thompson 505*7a982d89SJeremy L. Thompson /** 506*7a982d89SJeremy L. Thompson @brief Set a backend function 507*7a982d89SJeremy L. Thompson 508*7a982d89SJeremy L. Thompson This function is used for a backend to set the function associated with 509*7a982d89SJeremy L. Thompson the Ceed objects. For example, 510*7a982d89SJeremy L. Thompson CeedSetBackendFunction(ceed, "Ceed", ceed, "VectorCreate", BackendVectorCreate) 511*7a982d89SJeremy L. Thompson sets the backend implementation of 'CeedVectorCreate' and 512*7a982d89SJeremy L. Thompson CeedSetBackendFunction(ceed, "Basis", basis, "Apply", BackendBasisApply) 513*7a982d89SJeremy L. Thompson sets the backend implementation of 'CeedBasisApply'. Note, the prefix 'Ceed' 514*7a982d89SJeremy L. Thompson is not required for the object type ("Basis" vs "CeedBasis"). 515*7a982d89SJeremy L. Thompson 516*7a982d89SJeremy L. Thompson @param ceed Ceed context for error handling 517*7a982d89SJeremy L. Thompson @param type Type of Ceed object to set function for 518*7a982d89SJeremy L. Thompson @param[out] object Ceed object to set function for 519*7a982d89SJeremy L. Thompson @param fname Name of function to set 520*7a982d89SJeremy L. Thompson @param f Function to set 521*7a982d89SJeremy L. Thompson 522*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 523*7a982d89SJeremy L. Thompson 524*7a982d89SJeremy L. Thompson @ref Backend 525*7a982d89SJeremy L. Thompson **/ 526*7a982d89SJeremy L. Thompson int CeedSetBackendFunction(Ceed ceed, const char *type, void *object, 527*7a982d89SJeremy L. Thompson const char *fname, int (*f)()) { 528*7a982d89SJeremy L. Thompson char lookupname[CEED_MAX_RESOURCE_LEN+1] = ""; 529*7a982d89SJeremy L. Thompson 530*7a982d89SJeremy L. Thompson // Build lookup name 531*7a982d89SJeremy L. Thompson if (strcmp(type, "Ceed")) 532*7a982d89SJeremy L. Thompson strncat (lookupname, "Ceed", CEED_MAX_RESOURCE_LEN); 533*7a982d89SJeremy L. Thompson strncat(lookupname, type, CEED_MAX_RESOURCE_LEN); 534*7a982d89SJeremy L. Thompson strncat(lookupname, fname, CEED_MAX_RESOURCE_LEN); 535*7a982d89SJeremy L. Thompson 536*7a982d89SJeremy L. Thompson // Find and use offset 537*7a982d89SJeremy L. Thompson for (CeedInt i = 0; ceed->foffsets[i].fname; i++) 538*7a982d89SJeremy L. Thompson if (!strcmp(ceed->foffsets[i].fname, lookupname)) { 539*7a982d89SJeremy L. Thompson size_t offset = ceed->foffsets[i].offset; 540*7a982d89SJeremy L. Thompson int (**fpointer)(void) = (int (**)(void))((char *)object + offset); // *NOPAD* 541*7a982d89SJeremy L. Thompson *fpointer = f; 542*7a982d89SJeremy L. Thompson return 0; 543*7a982d89SJeremy L. Thompson } 544*7a982d89SJeremy L. Thompson 545*7a982d89SJeremy L. Thompson // LCOV_EXCL_START 546*7a982d89SJeremy L. Thompson return CeedError(ceed, 1, "Requested function '%s' was not found for CEED " 547*7a982d89SJeremy L. Thompson "object '%s'", fname, type); 548*7a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 549*7a982d89SJeremy L. Thompson } 550*7a982d89SJeremy L. Thompson 551*7a982d89SJeremy L. Thompson /** 552*7a982d89SJeremy L. Thompson @brief Retrieve backend data for a Ceed context 553*7a982d89SJeremy L. Thompson 554*7a982d89SJeremy L. Thompson @param ceed Ceed context to retrieve data of 555*7a982d89SJeremy L. Thompson @param[out] data Address to save data to 556*7a982d89SJeremy L. Thompson 557*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 558*7a982d89SJeremy L. Thompson 559*7a982d89SJeremy L. Thompson @ref Backend 560*7a982d89SJeremy L. Thompson **/ 561*7a982d89SJeremy L. Thompson int CeedGetData(Ceed ceed, void **data) { 562*7a982d89SJeremy L. Thompson *data = ceed->data; 563*7a982d89SJeremy L. Thompson return 0; 564*7a982d89SJeremy L. Thompson } 565*7a982d89SJeremy L. Thompson 566*7a982d89SJeremy L. Thompson /** 567*7a982d89SJeremy L. Thompson @brief Set backend data for a Ceed context 568*7a982d89SJeremy L. Thompson 569*7a982d89SJeremy L. Thompson @param ceed Ceed context to set data of 570*7a982d89SJeremy L. Thompson @param data Address of data to set 571*7a982d89SJeremy L. Thompson 572*7a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 573*7a982d89SJeremy L. Thompson 574*7a982d89SJeremy L. Thompson @ref Backend 575*7a982d89SJeremy L. Thompson **/ 576*7a982d89SJeremy L. Thompson int CeedSetData(Ceed ceed, void **data) { 577*7a982d89SJeremy L. Thompson ceed->data = *data; 578*7a982d89SJeremy L. Thompson return 0; 579*7a982d89SJeremy L. Thompson } 580*7a982d89SJeremy L. Thompson 581*7a982d89SJeremy L. Thompson /// @} 582*7a982d89SJeremy L. Thompson 583*7a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 584*7a982d89SJeremy L. Thompson /// Ceed Public API 585*7a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 586*7a982d89SJeremy L. Thompson /// @addtogroup CeedUser 587*7a982d89SJeremy L. Thompson /// @{ 588*7a982d89SJeremy L. Thompson 589*7a982d89SJeremy L. Thompson /** 590d79b80ecSjeremylt @brief Initialize a \ref Ceed context to use the specified resource. 591b11c1e72Sjeremylt 592b11c1e72Sjeremylt @param resource Resource to use, e.g., "/cpu/self" 593b11c1e72Sjeremylt @param ceed The library context 594b11c1e72Sjeremylt @sa CeedRegister() CeedDestroy() 595b11c1e72Sjeremylt 596b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 597dfdf5a53Sjeremylt 598*7a982d89SJeremy L. Thompson @ref User 599b11c1e72Sjeremylt **/ 600d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 601d7b241e6Sjeremylt int ierr; 602aedaa0e5Sjeremylt size_t matchlen = 0, matchidx = UINT_MAX, matchpriority = UINT_MAX, priority; 603d7b241e6Sjeremylt 604fe2413ffSjeremylt // Find matching backend 6051d102b48SJeremy L Thompson if (!resource) 60613873f79Sjeremylt // LCOV_EXCL_START 6071d102b48SJeremy L Thompson return CeedError(NULL, 1, "No resource provided"); 60813873f79Sjeremylt // LCOV_EXCL_STOP 60913873f79Sjeremylt 610d7b241e6Sjeremylt for (size_t i=0; i<num_backends; i++) { 611d7b241e6Sjeremylt size_t n; 612d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 613d7b241e6Sjeremylt for (n = 0; prefix[n] && prefix[n] == resource[n]; n++) {} 614d7b241e6Sjeremylt priority = backends[i].priority; 615d7b241e6Sjeremylt if (n > matchlen || (n == matchlen && matchpriority > priority)) { 616d7b241e6Sjeremylt matchlen = n; 617d7b241e6Sjeremylt matchpriority = priority; 618d7b241e6Sjeremylt matchidx = i; 619d7b241e6Sjeremylt } 620d7b241e6Sjeremylt } 6211d102b48SJeremy L Thompson if (!matchlen) 62213873f79Sjeremylt // LCOV_EXCL_START 6231d102b48SJeremy L Thompson return CeedError(NULL, 1, "No suitable backend"); 62413873f79Sjeremylt // LCOV_EXCL_STOP 625fe2413ffSjeremylt 626fe2413ffSjeremylt // Setup Ceed 627d7b241e6Sjeremylt ierr = CeedCalloc(1, ceed); CeedChk(ierr); 628bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 6291d102b48SJeremy L Thompson if (!ceed_error_handler) 6301d102b48SJeremy L Thompson ceed_error_handler = "abort"; 631bc81ce41Sjeremylt if (!strcmp(ceed_error_handler, "exit")) 63256e866f4SJed Brown (*ceed)->Error = CeedErrorExit; 63356e866f4SJed Brown else 634d7b241e6Sjeremylt (*ceed)->Error = CeedErrorAbort; 635d7b241e6Sjeremylt (*ceed)->refcount = 1; 636d7b241e6Sjeremylt (*ceed)->data = NULL; 637fe2413ffSjeremylt 638fe2413ffSjeremylt // Set lookup table 6396e79d475Sjeremylt foffset foffsets[] = { 6406e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 6416e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 6426e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 643f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 6446e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 6456e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 6466e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 6476e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 6486e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 6496e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 6506e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 6516e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 6526e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 6536e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 6546e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 6556e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 6566e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 6576e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 658547d9b97Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Norm), 6596e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 6606e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 6616e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 6626e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 6636e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 6646e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 6656e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 6666e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 6676e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 6686e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 6691d102b48SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, AssembleLinearQFunction), 670b7ec98d8SJeremy L Thompson CEED_FTABLE_ENTRY(CeedOperator, AssembleLinearDiagonal), 671713f43c3Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, CreateFDMElementInverse), 6726e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 673250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyComposite), 674cae8b89aSjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAdd), 675250756a7Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyAddComposite), 6766e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 6776e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 6786e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 6791dfeef1dSjeremylt }; 680fe2413ffSjeremylt 6816e79d475Sjeremylt ierr = CeedCalloc(sizeof(foffsets), &(*ceed)->foffsets); CeedChk(ierr); 6826e79d475Sjeremylt memcpy((*ceed)->foffsets, foffsets, sizeof(foffsets)); 683fe2413ffSjeremylt 6845107b09fSJeremy L Thompson // Set fallback for advanced CeedOperator functions 6855107b09fSJeremy L Thompson const char fallbackresource[] = "/cpu/self/ref/serial"; 6865107b09fSJeremy L Thompson ierr = CeedSetOperatorFallbackResource(*ceed, fallbackresource); 6875107b09fSJeremy L Thompson CeedChk(ierr); 6885107b09fSJeremy L Thompson 689fe2413ffSjeremylt // Backend specific setup 690d7b241e6Sjeremylt ierr = backends[matchidx].init(resource, *ceed); CeedChk(ierr); 691fe2413ffSjeremylt 692e07206deSjeremylt // Copy resource prefix, if backend setup sucessful 693e07206deSjeremylt size_t len = strlen(backends[matchidx].prefix); 694e07206deSjeremylt char *tmp; 695e07206deSjeremylt ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 696e07206deSjeremylt memcpy(tmp, backends[matchidx].prefix, len+1); 697e07206deSjeremylt (*ceed)->resource = tmp; 698e07206deSjeremylt 699d7b241e6Sjeremylt return 0; 700d7b241e6Sjeremylt } 701d7b241e6Sjeremylt 702d7b241e6Sjeremylt /** 703*7a982d89SJeremy L. Thompson @brief Get the full resource name for a Ceed context 7042f86a920SJeremy L Thompson 705*7a982d89SJeremy L. Thompson @param ceed Ceed context to get resource name of 706*7a982d89SJeremy L. Thompson @param[out] resource Variable to store resource name 7072f86a920SJeremy L Thompson 7082f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 7092f86a920SJeremy L Thompson 710*7a982d89SJeremy L. Thompson @ref User 7115107b09fSJeremy L Thompson **/ 7125107b09fSJeremy L Thompson 713*7a982d89SJeremy L. Thompson int CeedGetResource(Ceed ceed, const char **resource) { 714*7a982d89SJeremy L. Thompson *resource = (const char *)ceed->resource; 7155107b09fSJeremy L Thompson return 0; 7165107b09fSJeremy L Thompson } 7175107b09fSJeremy L Thompson 7185107b09fSJeremy L Thompson /** 719d79b80ecSjeremylt @brief Return Ceed context preferred memory type 720c907536fSjeremylt 721d79b80ecSjeremylt @param ceed Ceed context to get preferred memory type of 722288c0443SJeremy L Thompson @param[out] type Address to save preferred memory type to 723c907536fSjeremylt 724c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 725c907536fSjeremylt 726*7a982d89SJeremy L. Thompson @ref User 727c907536fSjeremylt **/ 728c907536fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *type) { 729c907536fSjeremylt int ierr; 730c263cd57Sjeremylt 731c907536fSjeremylt if (ceed->GetPreferredMemType) { 732c907536fSjeremylt ierr = ceed->GetPreferredMemType(type); CeedChk(ierr); 733c907536fSjeremylt } else { 734c263cd57Sjeremylt Ceed delegate; 735c263cd57Sjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 736c263cd57Sjeremylt 737c263cd57Sjeremylt if (delegate) { 738c263cd57Sjeremylt ierr = CeedGetPreferredMemType(delegate, type); CeedChk(ierr); 739c263cd57Sjeremylt } else { 740c907536fSjeremylt *type = CEED_MEM_HOST; 741c907536fSjeremylt } 742c263cd57Sjeremylt } 743c907536fSjeremylt 744c907536fSjeremylt return 0; 745c907536fSjeremylt } 746c907536fSjeremylt 747c907536fSjeremylt /** 748b11c1e72Sjeremylt @brief Destroy a Ceed context 749d7b241e6Sjeremylt 750d7b241e6Sjeremylt @param ceed Address of Ceed context to destroy 751b11c1e72Sjeremylt 752b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 753dfdf5a53Sjeremylt 754*7a982d89SJeremy L. Thompson @ref User 755b11c1e72Sjeremylt **/ 756d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 757d7b241e6Sjeremylt int ierr; 7581d102b48SJeremy L Thompson if (!*ceed || --(*ceed)->refcount > 0) 7591d102b48SJeremy L Thompson return 0; 7600ace9bf2Sjeremylt 7615fe0d4faSjeremylt if ((*ceed)->delegate) { 7625fe0d4faSjeremylt ierr = CeedDestroy(&(*ceed)->delegate); CeedChk(ierr); 7635fe0d4faSjeremylt } 7640ace9bf2Sjeremylt 765aefd8378Sjeremylt if ((*ceed)->objdelegatecount > 0) { 766aefd8378Sjeremylt for (int i=0; i<(*ceed)->objdelegatecount; i++) { 767aefd8378Sjeremylt ierr = CeedDestroy(&((*ceed)->objdelegates[i].delegate)); CeedChk(ierr); 768aefd8378Sjeremylt ierr = CeedFree(&(*ceed)->objdelegates[i].objname); CeedChk(ierr); 769aefd8378Sjeremylt } 770aefd8378Sjeremylt ierr = CeedFree(&(*ceed)->objdelegates); CeedChk(ierr); 771aefd8378Sjeremylt } 7720ace9bf2Sjeremylt 773d7b241e6Sjeremylt if ((*ceed)->Destroy) { 774d7b241e6Sjeremylt ierr = (*ceed)->Destroy(*ceed); CeedChk(ierr); 775d7b241e6Sjeremylt } 7760ace9bf2Sjeremylt 7776e79d475Sjeremylt ierr = CeedFree(&(*ceed)->foffsets); CeedChk(ierr); 778e07206deSjeremylt ierr = CeedFree(&(*ceed)->resource); CeedChk(ierr); 7795107b09fSJeremy L Thompson ierr = CeedDestroy(&(*ceed)->opfallbackceed); CeedChk(ierr); 7805107b09fSJeremy L Thompson ierr = CeedFree(&(*ceed)->opfallbackresource); CeedChk(ierr); 781d7b241e6Sjeremylt ierr = CeedFree(ceed); CeedChk(ierr); 782d7b241e6Sjeremylt return 0; 783d7b241e6Sjeremylt } 784d7b241e6Sjeremylt 785*7a982d89SJeremy L. Thompson /** 786*7a982d89SJeremy L. Thompson @brief Error handling implementation; use \ref CeedError instead. 787*7a982d89SJeremy L. Thompson 788*7a982d89SJeremy L. Thompson @ref Developer 789*7a982d89SJeremy L. Thompson **/ 790*7a982d89SJeremy L. Thompson int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, 791*7a982d89SJeremy L. Thompson int ecode, const char *format, ...) { 792*7a982d89SJeremy L. Thompson va_list args; 793*7a982d89SJeremy L. Thompson int retval; 794*7a982d89SJeremy L. Thompson va_start(args, format); 795*7a982d89SJeremy L. Thompson if (ceed) { 796*7a982d89SJeremy L. Thompson retval = ceed->Error(ceed, filename, lineno, func, ecode, format, args); 797*7a982d89SJeremy L. Thompson } else { 798*7a982d89SJeremy L. Thompson // This function doesn't actually return 799*7a982d89SJeremy L. Thompson retval = CeedErrorAbort(ceed, filename, lineno, func, ecode, format, args); 800*7a982d89SJeremy L. Thompson } 801*7a982d89SJeremy L. Thompson va_end(args); 802*7a982d89SJeremy L. Thompson return retval; 803*7a982d89SJeremy L. Thompson } 804*7a982d89SJeremy L. Thompson 805d7b241e6Sjeremylt /// @} 806