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> 20d7b241e6Sjeremylt #include <stdarg.h> 21d7b241e6Sjeremylt #include <stdio.h> 22d7b241e6Sjeremylt #include <stdlib.h> 23d7b241e6Sjeremylt #include <string.h> 24d7b241e6Sjeremylt 25d7b241e6Sjeremylt /// @cond DOXYGEN_SKIP 26d7b241e6Sjeremylt static CeedRequest ceed_request_immediate; 27d7b241e6Sjeremylt static CeedRequest ceed_request_ordered; 28d7b241e6Sjeremylt 29d7b241e6Sjeremylt static struct { 30d7b241e6Sjeremylt char prefix[CEED_MAX_RESOURCE_LEN]; 31d7b241e6Sjeremylt int (*init)(const char *resource, Ceed f); 32d7b241e6Sjeremylt unsigned int priority; 33d7b241e6Sjeremylt } backends[32]; 34d7b241e6Sjeremylt static size_t num_backends; 35*fe2413ffSjeremylt 36*fe2413ffSjeremylt #define ceedoffsetof(st, m) \ 37*fe2413ffSjeremylt ((size_t) ( (char *)&((st)(0))->m - (char *)0 )) 38d7b241e6Sjeremylt /// @endcond 39d7b241e6Sjeremylt 40d7b241e6Sjeremylt /// @file 41d7b241e6Sjeremylt /// Implementation of core components of Ceed library 42d7b241e6Sjeremylt /// 43dfdf5a53Sjeremylt /// @addtogroup Ceed 44d7b241e6Sjeremylt /// @{ 45d7b241e6Sjeremylt 46dfdf5a53Sjeremylt /** 47dfdf5a53Sjeremylt @brief Request immediate completion 48dfdf5a53Sjeremylt 49dfdf5a53Sjeremylt This predefined constant is passed as the \ref CeedRequest argument to 50dfdf5a53Sjeremylt interfaces when the caller wishes for the operation to be performed 51dfdf5a53Sjeremylt immediately. The code 52dfdf5a53Sjeremylt 53dfdf5a53Sjeremylt @code 54dfdf5a53Sjeremylt CeedOperatorApply(op, ..., CEED_REQUEST_IMMEDIATE); 55dfdf5a53Sjeremylt @endcode 56dfdf5a53Sjeremylt 57dfdf5a53Sjeremylt is semantically equivalent to 58dfdf5a53Sjeremylt 59dfdf5a53Sjeremylt @code 60dfdf5a53Sjeremylt CeedRequest request; 61dfdf5a53Sjeremylt CeedOperatorApply(op, ..., &request); 62dfdf5a53Sjeremylt CeedRequestWait(&request); 63dfdf5a53Sjeremylt @endcode 64dfdf5a53Sjeremylt 65dfdf5a53Sjeremylt @sa CEED_REQUEST_ORDERED 66dfdf5a53Sjeremylt **/ 67d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_IMMEDIATE = &ceed_request_immediate; 68d7b241e6Sjeremylt 69d7b241e6Sjeremylt /** 70b11c1e72Sjeremylt @brief Request ordered completion 71d7b241e6Sjeremylt 72d7b241e6Sjeremylt This predefined constant is passed as the \ref CeedRequest argument to 73d7b241e6Sjeremylt interfaces when the caller wishes for the operation to be completed in the 74d7b241e6Sjeremylt order that it is submitted to the device. It is typically used in a construct 75d7b241e6Sjeremylt such as 76d7b241e6Sjeremylt 77d7b241e6Sjeremylt @code 78d7b241e6Sjeremylt CeedRequest request; 79d7b241e6Sjeremylt CeedOperatorApply(op1, ..., CEED_REQUEST_ORDERED); 80d7b241e6Sjeremylt CeedOperatorApply(op2, ..., &request); 81d7b241e6Sjeremylt // other optional work 82d7b241e6Sjeremylt CeedWait(&request); 83d7b241e6Sjeremylt @endcode 84d7b241e6Sjeremylt 85d7b241e6Sjeremylt which allows the sequence to complete asynchronously but does not start 86d7b241e6Sjeremylt `op2` until `op1` has completed. 87d7b241e6Sjeremylt 88d7b241e6Sjeremylt @fixme The current implementation is overly strict, offering equivalent 89d7b241e6Sjeremylt semantics to CEED_REQUEST_IMMEDIATE. 90d7b241e6Sjeremylt 91d7b241e6Sjeremylt @sa CEED_REQUEST_IMMEDIATE 92d7b241e6Sjeremylt */ 93d7b241e6Sjeremylt CeedRequest *const CEED_REQUEST_ORDERED = &ceed_request_ordered; 94d7b241e6Sjeremylt 95b11c1e72Sjeremylt /** 96b11c1e72Sjeremylt @brief Error handling implementation; use \ref CeedError instead. 97dfdf5a53Sjeremylt 98dfdf5a53Sjeremylt @ref Developer 99b11c1e72Sjeremylt **/ 100d7b241e6Sjeremylt int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, 101d7b241e6Sjeremylt int ecode, const char *format, ...) { 102d7b241e6Sjeremylt va_list args; 103d7b241e6Sjeremylt va_start(args, format); 104d7b241e6Sjeremylt if (ceed) return ceed->Error(ceed, filename, lineno, func, ecode, format, args); 105d7b241e6Sjeremylt return CeedErrorAbort(ceed, filename, lineno, func, ecode, format, args); 106d7b241e6Sjeremylt } 107d7b241e6Sjeremylt 108b11c1e72Sjeremylt /** 109b11c1e72Sjeremylt @brief Error handler that returns without printing anything. 110b11c1e72Sjeremylt 111b11c1e72Sjeremylt Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 112dfdf5a53Sjeremylt 113dfdf5a53Sjeremylt @ref Developer 114b11c1e72Sjeremylt **/ 115d7b241e6Sjeremylt int CeedErrorReturn(Ceed ceed, const char *filename, int lineno, 116d7b241e6Sjeremylt const char *func, int ecode, const char *format, 117d7b241e6Sjeremylt va_list args) { 118d7b241e6Sjeremylt return ecode; 119d7b241e6Sjeremylt } 120d7b241e6Sjeremylt 121b11c1e72Sjeremylt /** 122b11c1e72Sjeremylt @brief Error handler that prints to stderr and aborts 123b11c1e72Sjeremylt 124b11c1e72Sjeremylt Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 125dfdf5a53Sjeremylt 126dfdf5a53Sjeremylt @ref Developer 127b11c1e72Sjeremylt **/ 128d7b241e6Sjeremylt int CeedErrorAbort(Ceed ceed, const char *filename, int lineno, 129d7b241e6Sjeremylt const char *func, int ecode, 130d7b241e6Sjeremylt const char *format, va_list args) { 131d7b241e6Sjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, lineno, func); 132d7b241e6Sjeremylt vfprintf(stderr, format, args); 133d7b241e6Sjeremylt fprintf(stderr, "\n"); 134d7b241e6Sjeremylt abort(); 135d7b241e6Sjeremylt return ecode; 136d7b241e6Sjeremylt } 137d7b241e6Sjeremylt 138b11c1e72Sjeremylt /** 13956e866f4SJed Brown @brief Error handler that prints to stderr and exits 14056e866f4SJed Brown 14156e866f4SJed Brown Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 14256e866f4SJed Brown 14356e866f4SJed Brown In contrast to CeedErrorAbort(), this exits without a signal, so atexit() 14456e866f4SJed Brown handlers (e.g., as used by gcov) are run. 14556e866f4SJed Brown 14656e866f4SJed Brown @ref Developer 14756e866f4SJed Brown **/ 14856e866f4SJed Brown int CeedErrorExit(Ceed ceed, const char *filename, int lineno, 14956e866f4SJed Brown const char *func, int ecode, 15056e866f4SJed Brown const char *format, va_list args) { 15156e866f4SJed Brown fprintf(stderr, "%s:%d in %s(): ", filename, lineno, func); 15256e866f4SJed Brown vfprintf(stderr, format, args); 15356e866f4SJed Brown fprintf(stderr, "\n"); 15456e866f4SJed Brown exit(ecode); 15556e866f4SJed Brown return ecode; 15656e866f4SJed Brown } 15756e866f4SJed Brown 15856e866f4SJed Brown /** 159dfdf5a53Sjeremylt @brief Set error handler 160b11c1e72Sjeremylt 161b11c1e72Sjeremylt A default error handler is set in CeedInit(). Use this function to change 162b11c1e72Sjeremylt the error handler to CeedErrorReturn(), CeedErrorAbort(), or a user-defined 163b11c1e72Sjeremylt error handler. 164dfdf5a53Sjeremylt 165dfdf5a53Sjeremylt @ref Developer 166b11c1e72Sjeremylt **/ 167d7b241e6Sjeremylt int CeedSetErrorHandler(Ceed ceed, 168d7b241e6Sjeremylt int (eh)(Ceed, const char *, int, const char *, 169d7b241e6Sjeremylt int, const char *, va_list)) { 170d7b241e6Sjeremylt ceed->Error = eh; 171d7b241e6Sjeremylt return 0; 172d7b241e6Sjeremylt } 173d7b241e6Sjeremylt 174d7b241e6Sjeremylt /** 175b11c1e72Sjeremylt @brief Register a Ceed backend 176d7b241e6Sjeremylt 177d7b241e6Sjeremylt @param prefix Prefix of resources for this backend to respond to. For 178d7b241e6Sjeremylt example, the reference backend responds to "/cpu/self". 179d7b241e6Sjeremylt @param init Initialization function called by CeedInit() when the backend 180d7b241e6Sjeremylt is selected to drive the requested resource. 181d7b241e6Sjeremylt @param priority Integer priority. Lower values are preferred in case the 182d7b241e6Sjeremylt resource requested by CeedInit() has non-unique best prefix 183d7b241e6Sjeremylt match. 184b11c1e72Sjeremylt 185b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 186dfdf5a53Sjeremylt 187dfdf5a53Sjeremylt @ref Advanced 188b11c1e72Sjeremylt **/ 189d7b241e6Sjeremylt int CeedRegister(const char *prefix, 190d7b241e6Sjeremylt int (*init)(const char *, Ceed), unsigned int priority) { 191d7b241e6Sjeremylt if (num_backends >= sizeof(backends) / sizeof(backends[0])) { 192d7b241e6Sjeremylt return CeedError(NULL, 1, "Too many backends"); 193d7b241e6Sjeremylt } 194d7b241e6Sjeremylt strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN); 195d7b241e6Sjeremylt backends[num_backends].init = init; 196d7b241e6Sjeremylt backends[num_backends].priority = priority; 197d7b241e6Sjeremylt num_backends++; 198d7b241e6Sjeremylt return 0; 199d7b241e6Sjeremylt } 200d7b241e6Sjeremylt 201b11c1e72Sjeremylt /** 202b11c1e72Sjeremylt @brief Allocate an array on the host; use CeedMalloc() 203b11c1e72Sjeremylt 204b11c1e72Sjeremylt Memory usage can be tracked by the library. This ensures sufficient 205b11c1e72Sjeremylt alignment for vectorization and should be used for large allocations. 206b11c1e72Sjeremylt 207b11c1e72Sjeremylt @param n Number of units to allocate 208b11c1e72Sjeremylt @param unit Size of each unit 209b11c1e72Sjeremylt @param p Address of pointer to hold the result. 210b11c1e72Sjeremylt 211b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 212b11c1e72Sjeremylt 213b11c1e72Sjeremylt @sa CeedFree() 214dfdf5a53Sjeremylt 215dfdf5a53Sjeremylt @ref Advanced 216b11c1e72Sjeremylt **/ 217d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 218d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n*unit); 219d7b241e6Sjeremylt if (ierr) 220d7b241e6Sjeremylt return CeedError(NULL, ierr, 221d7b241e6Sjeremylt "posix_memalign failed to allocate %zd members of size %zd\n", n, unit); 222d7b241e6Sjeremylt return 0; 223d7b241e6Sjeremylt } 224d7b241e6Sjeremylt 225b11c1e72Sjeremylt /** 226b11c1e72Sjeremylt @brief Allocate a cleared (zeroed) array on the host; use CeedCalloc() 227b11c1e72Sjeremylt 228b11c1e72Sjeremylt Memory usage can be tracked by the library. 229b11c1e72Sjeremylt 230b11c1e72Sjeremylt @param n Number of units to allocate 231b11c1e72Sjeremylt @param unit Size of each unit 232b11c1e72Sjeremylt @param p Address of pointer to hold the result. 233b11c1e72Sjeremylt 234b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 235b11c1e72Sjeremylt 236b11c1e72Sjeremylt @sa CeedFree() 237dfdf5a53Sjeremylt 238dfdf5a53Sjeremylt @ref Advanced 239b11c1e72Sjeremylt **/ 240d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 241d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 242d7b241e6Sjeremylt if (n && unit && !*(void **)p) 243d7b241e6Sjeremylt return CeedError(NULL, 1, "calloc failed to allocate %zd members of size %zd\n", 244d7b241e6Sjeremylt n, unit); 245d7b241e6Sjeremylt return 0; 246d7b241e6Sjeremylt } 247d7b241e6Sjeremylt 248b11c1e72Sjeremylt /** 249b11c1e72Sjeremylt @brief Reallocate an array on the host; use CeedRealloc() 250b11c1e72Sjeremylt 251b11c1e72Sjeremylt Memory usage can be tracked by the library. 252b11c1e72Sjeremylt 253b11c1e72Sjeremylt @param n Number of units to allocate 254b11c1e72Sjeremylt @param unit Size of each unit 255b11c1e72Sjeremylt @param p Address of pointer to hold the result. 256b11c1e72Sjeremylt 257b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 258b11c1e72Sjeremylt 259b11c1e72Sjeremylt @sa CeedFree() 260dfdf5a53Sjeremylt 261dfdf5a53Sjeremylt @ref Advanced 262b11c1e72Sjeremylt **/ 263d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 264d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n*unit); 265d7b241e6Sjeremylt if (n && unit && !*(void **)p) 266d7b241e6Sjeremylt return CeedError(NULL, 1, 267d7b241e6Sjeremylt "realloc failed to allocate %zd members of size %zd\n", 268d7b241e6Sjeremylt n, unit); 269d7b241e6Sjeremylt return 0; 270d7b241e6Sjeremylt } 271d7b241e6Sjeremylt 272d7b241e6Sjeremylt /// Free memory allocated using CeedMalloc() or CeedCalloc() 273d7b241e6Sjeremylt /// 274d7b241e6Sjeremylt /// @param p address of pointer to memory. This argument is of type void* to 275d7b241e6Sjeremylt /// avoid needing a cast, but is the address of the pointer (which is zeroed) 276d7b241e6Sjeremylt /// rather than the pointer. 277d7b241e6Sjeremylt int CeedFree(void *p) { 278d7b241e6Sjeremylt free(*(void **)p); 279d7b241e6Sjeremylt *(void **)p = NULL; 280d7b241e6Sjeremylt return 0; 281d7b241e6Sjeremylt } 282d7b241e6Sjeremylt 283d7b241e6Sjeremylt /** 284b11c1e72Sjeremylt @brief Wait for a CeedRequest to complete. 285d7b241e6Sjeremylt 286d7b241e6Sjeremylt Calling CeedRequestWait on a NULL request is a no-op. 287d7b241e6Sjeremylt 288d7b241e6Sjeremylt @param req Address of CeedRequest to wait for; zeroed on completion. 289b11c1e72Sjeremylt 290b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 291dfdf5a53Sjeremylt 292dfdf5a53Sjeremylt @ref Advanced 293b11c1e72Sjeremylt **/ 294d7b241e6Sjeremylt int CeedRequestWait(CeedRequest *req) { 295d7b241e6Sjeremylt if (!*req) return 0; 296d7b241e6Sjeremylt return CeedError(NULL, 2, "CeedRequestWait not implemented"); 297d7b241e6Sjeremylt } 298d7b241e6Sjeremylt 299b11c1e72Sjeremylt /** 300b11c1e72Sjeremylt @brief Initialize a \ref Ceed to use the specified resource. 301b11c1e72Sjeremylt 302b11c1e72Sjeremylt @param resource Resource to use, e.g., "/cpu/self" 303b11c1e72Sjeremylt @param ceed The library context 304b11c1e72Sjeremylt @sa CeedRegister() CeedDestroy() 305b11c1e72Sjeremylt 306b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 307dfdf5a53Sjeremylt 308dfdf5a53Sjeremylt @ref Basic 309b11c1e72Sjeremylt **/ 310d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 311d7b241e6Sjeremylt int ierr; 312d7b241e6Sjeremylt size_t matchlen = 0, matchidx; 313d7b241e6Sjeremylt unsigned int matchpriority = 100, priority; 314d7b241e6Sjeremylt 315*fe2413ffSjeremylt // Find matching backend 316d7b241e6Sjeremylt if (!resource) return CeedError(NULL, 1, "No resource provided"); 317d7b241e6Sjeremylt for (size_t i=0; i<num_backends; i++) { 318d7b241e6Sjeremylt size_t n; 319d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 320d7b241e6Sjeremylt for (n = 0; prefix[n] && prefix[n] == resource[n]; n++) {} 321d7b241e6Sjeremylt priority = backends[i].priority; 322d7b241e6Sjeremylt if (n > matchlen || (n == matchlen && matchpriority > priority)) { 323d7b241e6Sjeremylt matchlen = n; 324d7b241e6Sjeremylt matchpriority = priority; 325d7b241e6Sjeremylt matchidx = i; 326d7b241e6Sjeremylt } 327d7b241e6Sjeremylt } 328d7b241e6Sjeremylt if (!matchlen) return CeedError(NULL, 1, "No suitable backend"); 329*fe2413ffSjeremylt 330*fe2413ffSjeremylt // Setup Ceed 331d7b241e6Sjeremylt ierr = CeedCalloc(1,ceed); CeedChk(ierr); 332bc81ce41Sjeremylt const char * ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 333bc81ce41Sjeremylt if (!ceed_error_handler) ceed_error_handler = "abort"; 334bc81ce41Sjeremylt if (!strcmp(ceed_error_handler, "exit")) 33556e866f4SJed Brown (*ceed)->Error = CeedErrorExit; 33656e866f4SJed Brown else 337d7b241e6Sjeremylt (*ceed)->Error = CeedErrorAbort; 338d7b241e6Sjeremylt (*ceed)->refcount = 1; 339d7b241e6Sjeremylt (*ceed)->data = NULL; 340*fe2413ffSjeremylt 341*fe2413ffSjeremylt // Set lookup table 342*fe2413ffSjeremylt foffset foffsets[25] = { 343*fe2413ffSjeremylt {"Error", ceedoffsetof(Ceed, Error)}, 344*fe2413ffSjeremylt {"CeedDestroy", ceedoffsetof(Ceed, Destroy)}, 345*fe2413ffSjeremylt {"VecCreate", ceedoffsetof(Ceed, VecCreate)}, 346*fe2413ffSjeremylt {"ElemRestrictionCreate", ceedoffsetof(Ceed, ElemRestrictionCreate)}, 347*fe2413ffSjeremylt {"ElemRestrictionCreateBlocked", 348*fe2413ffSjeremylt ceedoffsetof(Ceed, ElemRestrictionCreateBlocked)}, 349*fe2413ffSjeremylt {"BasisCreateTensorH1", ceedoffsetof(Ceed, BasisCreateTensorH1)}, 350*fe2413ffSjeremylt {"BasisCreateH1", ceedoffsetof(Ceed, BasisCreateH1)}, 351*fe2413ffSjeremylt {"QFunctionCreate", ceedoffsetof(Ceed, QFunctionCreate)}, 352*fe2413ffSjeremylt {"OperatorCreate", ceedoffsetof(Ceed, OperatorCreate)}, 353*fe2413ffSjeremylt {"SetArray", ceedoffsetof(CeedVector, SetArray)}, 354*fe2413ffSjeremylt {"SetValue", ceedoffsetof(CeedVector, SetValue)}, 355*fe2413ffSjeremylt {"GetArray", ceedoffsetof(CeedVector, GetArray)}, 356*fe2413ffSjeremylt {"GetArrayRead", ceedoffsetof(CeedVector, GetArrayRead)}, 357*fe2413ffSjeremylt {"RestoreArray", ceedoffsetof(CeedVector, RestoreArray)}, 358*fe2413ffSjeremylt {"RestoreArrayRead", ceedoffsetof(CeedVector, RestoreArrayRead)}, 359*fe2413ffSjeremylt {"VectorDestroy", ceedoffsetof(CeedVector, Destroy)}, 360*fe2413ffSjeremylt {"ElemRestrictionApply", ceedoffsetof(CeedElemRestriction, Apply)}, 361*fe2413ffSjeremylt {"ElemRestrictionDestroy", ceedoffsetof(CeedElemRestriction, Destroy)}, 362*fe2413ffSjeremylt {"BasisApply", ceedoffsetof(CeedBasis, Apply)}, 363*fe2413ffSjeremylt {"BasisDestroy", ceedoffsetof(CeedBasis, Destroy)}, 364*fe2413ffSjeremylt {"QFunctionApply", ceedoffsetof(CeedQFunction, Apply)}, 365*fe2413ffSjeremylt {"QFunctionDestroy", ceedoffsetof(CeedQFunction, Destroy)}, 366*fe2413ffSjeremylt {"OperatorApply", ceedoffsetof(CeedOperator, Apply)}, 367*fe2413ffSjeremylt {"ApplyJacobian", ceedoffsetof(CeedOperator, ApplyJacobian)}, 368*fe2413ffSjeremylt {"OperatorDestroy", ceedoffsetof(CeedOperator, Destroy)} }; 369*fe2413ffSjeremylt 370*fe2413ffSjeremylt memcpy((*ceed)->foffsets, foffsets, 25*sizeof(foffset)); 371*fe2413ffSjeremylt 372*fe2413ffSjeremylt // Backend specific setup 373d7b241e6Sjeremylt ierr = backends[matchidx].init(resource, *ceed); CeedChk(ierr); 374*fe2413ffSjeremylt 375d7b241e6Sjeremylt return 0; 376d7b241e6Sjeremylt } 377d7b241e6Sjeremylt 378d7b241e6Sjeremylt /** 3795fe0d4faSjeremylt @brief Retrieve a delegate CEED 3805fe0d4faSjeremylt 3815fe0d4faSjeremylt @param ceed Ceed to retrieve delegate of 3825fe0d4faSjeremylt @param[out] delegate Address to save the delegate to 3835fe0d4faSjeremylt 3845fe0d4faSjeremylt @return An error code: 0 - success, otherwise - failure 3855fe0d4faSjeremylt 38623617272Sjeremylt @ref Developer 3875fe0d4faSjeremylt **/ 3885fe0d4faSjeremylt int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 3894ce2993fSjeremylt *delegate = ceed->delegate; 3904ce2993fSjeremylt return 0; 3914ce2993fSjeremylt } 3924ce2993fSjeremylt 3934ce2993fSjeremylt /** 3944ce2993fSjeremylt @brief Set a delegate CEED 3954ce2993fSjeremylt 3964ce2993fSjeremylt @param ceed Ceed to set delegate of 3974ce2993fSjeremylt @param[out] delegate Address to set the delegate to 3984ce2993fSjeremylt 3994ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 4004ce2993fSjeremylt 40123617272Sjeremylt @ref Advanced 4024ce2993fSjeremylt **/ 4034ce2993fSjeremylt int CeedSetDelegate(Ceed ceed, Ceed *delegate) { 4044ce2993fSjeremylt ceed->delegate = *delegate; 4054ce2993fSjeremylt return 0; 4064ce2993fSjeremylt } 4074ce2993fSjeremylt 4084ce2993fSjeremylt /** 409*fe2413ffSjeremylt @brief Set a backend function 410*fe2413ffSjeremylt 411*fe2413ffSjeremylt @param ceed Ceed for error handling 412*fe2413ffSjeremylt @param type Type of Ceed object to set function for 413*fe2413ffSjeremylt @param[out] object Ceed object to set function for 414*fe2413ffSjeremylt @param fname Name of function to set 415*fe2413ffSjeremylt @param f Function to set 416*fe2413ffSjeremylt 417*fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 418*fe2413ffSjeremylt 419*fe2413ffSjeremylt @ref Advanced 420*fe2413ffSjeremylt **/ 421*fe2413ffSjeremylt int CeedSetBackendFunction(Ceed ceed, 422*fe2413ffSjeremylt const char *type, void *object, 423*fe2413ffSjeremylt const char *fname, int (*f)()) { 424*fe2413ffSjeremylt char lookupname[100]; 425*fe2413ffSjeremylt strcpy(lookupname, ""); 426*fe2413ffSjeremylt 427*fe2413ffSjeremylt // Build lookup name 428*fe2413ffSjeremylt if (!strcmp(fname, "Apply") || !strcmp(fname, "Destroy")) { 429*fe2413ffSjeremylt strcat(strcat(lookupname, type), fname); 430*fe2413ffSjeremylt } else { 431*fe2413ffSjeremylt strcat(lookupname, fname); 432*fe2413ffSjeremylt } 433*fe2413ffSjeremylt 434*fe2413ffSjeremylt // Find and use offset 435*fe2413ffSjeremylt for (CeedInt i = 0; i < 25; i++) { 436*fe2413ffSjeremylt if (!strcmp(ceed->foffsets[i].fname, lookupname)) { 437*fe2413ffSjeremylt size_t offset = ceed->foffsets[i].offset; 438*fe2413ffSjeremylt size_t *fpointer; 439*fe2413ffSjeremylt fpointer = (size_t *)(object + offset); 440*fe2413ffSjeremylt *fpointer = (size_t) f; 441*fe2413ffSjeremylt return 0; 442*fe2413ffSjeremylt } 443*fe2413ffSjeremylt } 444*fe2413ffSjeremylt 445*fe2413ffSjeremylt return CeedError(ceed, 1, "Requested function '%s' was not found", fname); 446*fe2413ffSjeremylt } 447*fe2413ffSjeremylt 448*fe2413ffSjeremylt /** 4494ce2993fSjeremylt @brief Retrieve backend data for a CEED 4504ce2993fSjeremylt 451*fe2413ffSjeremylt @param ceed Ceed to retrieve data of 4524ce2993fSjeremylt @param[out] data Address to save data to 4534ce2993fSjeremylt 4544ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 4554ce2993fSjeremylt 45623617272Sjeremylt @ref Advanced 4574ce2993fSjeremylt **/ 4584ce2993fSjeremylt int CeedGetData(Ceed ceed, void* *data) { 4594ce2993fSjeremylt *data = ceed->data; 4605fe0d4faSjeremylt return 0; 4615fe0d4faSjeremylt } 4625fe0d4faSjeremylt 4635fe0d4faSjeremylt /** 464*fe2413ffSjeremylt @brief Set backend data for a CEED 465*fe2413ffSjeremylt 466*fe2413ffSjeremylt @param ceed Ceed to set data of 467*fe2413ffSjeremylt @param data Address of data to set 468*fe2413ffSjeremylt 469*fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 470*fe2413ffSjeremylt 471*fe2413ffSjeremylt @ref Advanced 472*fe2413ffSjeremylt **/ 473*fe2413ffSjeremylt int CeedSetData(Ceed ceed, void* *data) { 474*fe2413ffSjeremylt ceed->data = *data; 475*fe2413ffSjeremylt return 0; 476*fe2413ffSjeremylt } 477*fe2413ffSjeremylt 478*fe2413ffSjeremylt /** 479b11c1e72Sjeremylt @brief Destroy a Ceed context 480d7b241e6Sjeremylt 481d7b241e6Sjeremylt @param ceed Address of Ceed context to destroy 482b11c1e72Sjeremylt 483b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 484dfdf5a53Sjeremylt 485dfdf5a53Sjeremylt @ref Basic 486b11c1e72Sjeremylt **/ 487d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 488d7b241e6Sjeremylt int ierr; 489d7b241e6Sjeremylt 490d7b241e6Sjeremylt if (!*ceed || --(*ceed)->refcount > 0) return 0; 4915fe0d4faSjeremylt if ((*ceed)->delegate) { 4925fe0d4faSjeremylt ierr = CeedDestroy(&(*ceed)->delegate); CeedChk(ierr); 4935fe0d4faSjeremylt } 494d7b241e6Sjeremylt if ((*ceed)->Destroy) { 495d7b241e6Sjeremylt ierr = (*ceed)->Destroy(*ceed); CeedChk(ierr); 496d7b241e6Sjeremylt } 497d7b241e6Sjeremylt ierr = CeedFree(ceed); CeedChk(ierr); 498d7b241e6Sjeremylt return 0; 499d7b241e6Sjeremylt } 500d7b241e6Sjeremylt 501d7b241e6Sjeremylt /// @} 502