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 44d7b241e6Sjeremylt /// 45dfdf5a53Sjeremylt /// @addtogroup Ceed 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 90d7b241e6Sjeremylt @fixme 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 /** 98b11c1e72Sjeremylt @brief Error handling implementation; use \ref CeedError instead. 99dfdf5a53Sjeremylt 100dfdf5a53Sjeremylt @ref Developer 101b11c1e72Sjeremylt **/ 102d7b241e6Sjeremylt int CeedErrorImpl(Ceed ceed, const char *filename, int lineno, const char *func, 103d7b241e6Sjeremylt int ecode, const char *format, ...) { 104d7b241e6Sjeremylt va_list args; 105d7b241e6Sjeremylt va_start(args, format); 106d7b241e6Sjeremylt if (ceed) return ceed->Error(ceed, filename, lineno, func, ecode, format, args); 107d7b241e6Sjeremylt return CeedErrorAbort(ceed, filename, lineno, func, ecode, format, args); 108d7b241e6Sjeremylt } 109d7b241e6Sjeremylt 110b11c1e72Sjeremylt /** 111b11c1e72Sjeremylt @brief Error handler that returns without printing anything. 112b11c1e72Sjeremylt 113b11c1e72Sjeremylt Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 114dfdf5a53Sjeremylt 115dfdf5a53Sjeremylt @ref Developer 116b11c1e72Sjeremylt **/ 117d7b241e6Sjeremylt int CeedErrorReturn(Ceed ceed, const char *filename, int lineno, 118d7b241e6Sjeremylt const char *func, int ecode, const char *format, 119d7b241e6Sjeremylt va_list args) { 120d7b241e6Sjeremylt return ecode; 121d7b241e6Sjeremylt } 122d7b241e6Sjeremylt 123b11c1e72Sjeremylt /** 124b11c1e72Sjeremylt @brief Error handler that prints to stderr and aborts 125b11c1e72Sjeremylt 126b11c1e72Sjeremylt Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 127dfdf5a53Sjeremylt 128dfdf5a53Sjeremylt @ref Developer 129b11c1e72Sjeremylt **/ 130d7b241e6Sjeremylt int CeedErrorAbort(Ceed ceed, const char *filename, int lineno, 131d7b241e6Sjeremylt const char *func, int ecode, 132d7b241e6Sjeremylt const char *format, va_list args) { 133d7b241e6Sjeremylt fprintf(stderr, "%s:%d in %s(): ", filename, lineno, func); 134d7b241e6Sjeremylt vfprintf(stderr, format, args); 135d7b241e6Sjeremylt fprintf(stderr, "\n"); 136d7b241e6Sjeremylt abort(); 137d7b241e6Sjeremylt return ecode; 138d7b241e6Sjeremylt } 139d7b241e6Sjeremylt 140b11c1e72Sjeremylt /** 14156e866f4SJed Brown @brief Error handler that prints to stderr and exits 14256e866f4SJed Brown 14356e866f4SJed Brown Pass this to CeedSetErrorHandler() to obtain this error handling behavior. 14456e866f4SJed Brown 14556e866f4SJed Brown In contrast to CeedErrorAbort(), this exits without a signal, so atexit() 14656e866f4SJed Brown handlers (e.g., as used by gcov) are run. 14756e866f4SJed Brown 14856e866f4SJed Brown @ref Developer 14956e866f4SJed Brown **/ 15056e866f4SJed Brown int CeedErrorExit(Ceed ceed, const char *filename, int lineno, 15156e866f4SJed Brown const char *func, int ecode, 15256e866f4SJed Brown const char *format, va_list args) { 15356e866f4SJed Brown fprintf(stderr, "%s:%d in %s(): ", filename, lineno, func); 15456e866f4SJed Brown vfprintf(stderr, format, args); 15556e866f4SJed Brown fprintf(stderr, "\n"); 15656e866f4SJed Brown exit(ecode); 15756e866f4SJed Brown return ecode; 15856e866f4SJed Brown } 15956e866f4SJed Brown 16056e866f4SJed Brown /** 161dfdf5a53Sjeremylt @brief Set error handler 162b11c1e72Sjeremylt 163b11c1e72Sjeremylt A default error handler is set in CeedInit(). Use this function to change 164b11c1e72Sjeremylt the error handler to CeedErrorReturn(), CeedErrorAbort(), or a user-defined 165b11c1e72Sjeremylt error handler. 166dfdf5a53Sjeremylt 167dfdf5a53Sjeremylt @ref Developer 168b11c1e72Sjeremylt **/ 169d7b241e6Sjeremylt int CeedSetErrorHandler(Ceed ceed, 170d7b241e6Sjeremylt int (eh)(Ceed, const char *, int, const char *, 171d7b241e6Sjeremylt int, const char *, va_list)) { 172d7b241e6Sjeremylt ceed->Error = eh; 173d7b241e6Sjeremylt return 0; 174d7b241e6Sjeremylt } 175d7b241e6Sjeremylt 176d7b241e6Sjeremylt /** 177b11c1e72Sjeremylt @brief Register a Ceed backend 178d7b241e6Sjeremylt 179d7b241e6Sjeremylt @param prefix Prefix of resources for this backend to respond to. For 180d7b241e6Sjeremylt example, the reference backend responds to "/cpu/self". 181d7b241e6Sjeremylt @param init Initialization function called by CeedInit() when the backend 182d7b241e6Sjeremylt is selected to drive the requested resource. 183d7b241e6Sjeremylt @param priority Integer priority. Lower values are preferred in case the 184d7b241e6Sjeremylt resource requested by CeedInit() has non-unique best prefix 185d7b241e6Sjeremylt match. 186b11c1e72Sjeremylt 187b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 188dfdf5a53Sjeremylt 189dfdf5a53Sjeremylt @ref Advanced 190b11c1e72Sjeremylt **/ 191d7b241e6Sjeremylt int CeedRegister(const char *prefix, 192d7b241e6Sjeremylt int (*init)(const char *, Ceed), unsigned int priority) { 193d7b241e6Sjeremylt if (num_backends >= sizeof(backends) / sizeof(backends[0])) { 194d7b241e6Sjeremylt return CeedError(NULL, 1, "Too many backends"); 195d7b241e6Sjeremylt } 196d7b241e6Sjeremylt strncpy(backends[num_backends].prefix, prefix, CEED_MAX_RESOURCE_LEN); 197d7b241e6Sjeremylt backends[num_backends].init = init; 198d7b241e6Sjeremylt backends[num_backends].priority = priority; 199d7b241e6Sjeremylt num_backends++; 200d7b241e6Sjeremylt return 0; 201d7b241e6Sjeremylt } 202d7b241e6Sjeremylt 203b11c1e72Sjeremylt /** 204b11c1e72Sjeremylt @brief Allocate an array on the host; use CeedMalloc() 205b11c1e72Sjeremylt 206b11c1e72Sjeremylt Memory usage can be tracked by the library. This ensures sufficient 207b11c1e72Sjeremylt alignment for vectorization and should be used for large allocations. 208b11c1e72Sjeremylt 209b11c1e72Sjeremylt @param n Number of units to allocate 210b11c1e72Sjeremylt @param unit Size of each unit 211b11c1e72Sjeremylt @param p Address of pointer to hold the result. 212b11c1e72Sjeremylt 213b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 214b11c1e72Sjeremylt 215b11c1e72Sjeremylt @sa CeedFree() 216dfdf5a53Sjeremylt 217dfdf5a53Sjeremylt @ref Advanced 218b11c1e72Sjeremylt **/ 219d7b241e6Sjeremylt int CeedMallocArray(size_t n, size_t unit, void *p) { 220d7b241e6Sjeremylt int ierr = posix_memalign((void **)p, CEED_ALIGN, n*unit); 221d7b241e6Sjeremylt if (ierr) 222d7b241e6Sjeremylt return CeedError(NULL, ierr, 223d7b241e6Sjeremylt "posix_memalign failed to allocate %zd members of size %zd\n", n, unit); 224d7b241e6Sjeremylt return 0; 225d7b241e6Sjeremylt } 226d7b241e6Sjeremylt 227b11c1e72Sjeremylt /** 228b11c1e72Sjeremylt @brief Allocate a cleared (zeroed) array on the host; use CeedCalloc() 229b11c1e72Sjeremylt 230b11c1e72Sjeremylt Memory usage can be tracked by the library. 231b11c1e72Sjeremylt 232b11c1e72Sjeremylt @param n Number of units to allocate 233b11c1e72Sjeremylt @param unit Size of each unit 234b11c1e72Sjeremylt @param p Address of pointer to hold the result. 235b11c1e72Sjeremylt 236b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 237b11c1e72Sjeremylt 238b11c1e72Sjeremylt @sa CeedFree() 239dfdf5a53Sjeremylt 240dfdf5a53Sjeremylt @ref Advanced 241b11c1e72Sjeremylt **/ 242d7b241e6Sjeremylt int CeedCallocArray(size_t n, size_t unit, void *p) { 243d7b241e6Sjeremylt *(void **)p = calloc(n, unit); 244d7b241e6Sjeremylt if (n && unit && !*(void **)p) 245d7b241e6Sjeremylt return CeedError(NULL, 1, "calloc failed to allocate %zd members of size %zd\n", 246d7b241e6Sjeremylt n, unit); 247d7b241e6Sjeremylt return 0; 248d7b241e6Sjeremylt } 249d7b241e6Sjeremylt 250b11c1e72Sjeremylt /** 251b11c1e72Sjeremylt @brief Reallocate an array on the host; use CeedRealloc() 252b11c1e72Sjeremylt 253b11c1e72Sjeremylt Memory usage can be tracked by the library. 254b11c1e72Sjeremylt 255b11c1e72Sjeremylt @param n Number of units to allocate 256b11c1e72Sjeremylt @param unit Size of each unit 257b11c1e72Sjeremylt @param p Address of pointer to hold the result. 258b11c1e72Sjeremylt 259b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 260b11c1e72Sjeremylt 261b11c1e72Sjeremylt @sa CeedFree() 262dfdf5a53Sjeremylt 263dfdf5a53Sjeremylt @ref Advanced 264b11c1e72Sjeremylt **/ 265d7b241e6Sjeremylt int CeedReallocArray(size_t n, size_t unit, void *p) { 266d7b241e6Sjeremylt *(void **)p = realloc(*(void **)p, n*unit); 267d7b241e6Sjeremylt if (n && unit && !*(void **)p) 268d7b241e6Sjeremylt return CeedError(NULL, 1, 269d7b241e6Sjeremylt "realloc failed to allocate %zd members of size %zd\n", 270d7b241e6Sjeremylt n, unit); 271d7b241e6Sjeremylt return 0; 272d7b241e6Sjeremylt } 273d7b241e6Sjeremylt 274d7b241e6Sjeremylt /// Free memory allocated using CeedMalloc() or CeedCalloc() 275d7b241e6Sjeremylt /// 276d7b241e6Sjeremylt /// @param p address of pointer to memory. This argument is of type void* to 277d7b241e6Sjeremylt /// avoid needing a cast, but is the address of the pointer (which is zeroed) 278d7b241e6Sjeremylt /// rather than the pointer. 279d7b241e6Sjeremylt int CeedFree(void *p) { 280d7b241e6Sjeremylt free(*(void **)p); 281d7b241e6Sjeremylt *(void **)p = NULL; 282d7b241e6Sjeremylt return 0; 283d7b241e6Sjeremylt } 284d7b241e6Sjeremylt 285d7b241e6Sjeremylt /** 286b11c1e72Sjeremylt @brief Wait for a CeedRequest to complete. 287d7b241e6Sjeremylt 288d7b241e6Sjeremylt Calling CeedRequestWait on a NULL request is a no-op. 289d7b241e6Sjeremylt 290d7b241e6Sjeremylt @param req Address of CeedRequest to wait for; zeroed on completion. 291b11c1e72Sjeremylt 292b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 293dfdf5a53Sjeremylt 294dfdf5a53Sjeremylt @ref Advanced 295b11c1e72Sjeremylt **/ 296d7b241e6Sjeremylt int CeedRequestWait(CeedRequest *req) { 297d7b241e6Sjeremylt if (!*req) return 0; 298d7b241e6Sjeremylt return CeedError(NULL, 2, "CeedRequestWait not implemented"); 299d7b241e6Sjeremylt } 300d7b241e6Sjeremylt 301b11c1e72Sjeremylt /** 302b11c1e72Sjeremylt @brief Initialize a \ref Ceed to use the specified resource. 303b11c1e72Sjeremylt 304b11c1e72Sjeremylt @param resource Resource to use, e.g., "/cpu/self" 305b11c1e72Sjeremylt @param ceed The library context 306b11c1e72Sjeremylt @sa CeedRegister() CeedDestroy() 307b11c1e72Sjeremylt 308b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 309dfdf5a53Sjeremylt 310dfdf5a53Sjeremylt @ref Basic 311b11c1e72Sjeremylt **/ 312d7b241e6Sjeremylt int CeedInit(const char *resource, Ceed *ceed) { 313d7b241e6Sjeremylt int ierr; 314aedaa0e5Sjeremylt size_t matchlen = 0, matchidx = UINT_MAX, matchpriority = UINT_MAX, priority; 315d7b241e6Sjeremylt 316fe2413ffSjeremylt // Find matching backend 317d7b241e6Sjeremylt if (!resource) return CeedError(NULL, 1, "No resource provided"); 318d7b241e6Sjeremylt for (size_t i=0; i<num_backends; i++) { 319d7b241e6Sjeremylt size_t n; 320d7b241e6Sjeremylt const char *prefix = backends[i].prefix; 321d7b241e6Sjeremylt for (n = 0; prefix[n] && prefix[n] == resource[n]; n++) {} 322d7b241e6Sjeremylt priority = backends[i].priority; 323d7b241e6Sjeremylt if (n > matchlen || (n == matchlen && matchpriority > priority)) { 324d7b241e6Sjeremylt matchlen = n; 325d7b241e6Sjeremylt matchpriority = priority; 326d7b241e6Sjeremylt matchidx = i; 327d7b241e6Sjeremylt } 328d7b241e6Sjeremylt } 329d7b241e6Sjeremylt if (!matchlen) return CeedError(NULL, 1, "No suitable backend"); 330fe2413ffSjeremylt 331fe2413ffSjeremylt // Setup Ceed 332d7b241e6Sjeremylt ierr = CeedCalloc(1,ceed); CeedChk(ierr); 333bc81ce41Sjeremylt const char *ceed_error_handler = getenv("CEED_ERROR_HANDLER"); 334bc81ce41Sjeremylt if (!ceed_error_handler) ceed_error_handler = "abort"; 335bc81ce41Sjeremylt if (!strcmp(ceed_error_handler, "exit")) 33656e866f4SJed Brown (*ceed)->Error = CeedErrorExit; 33756e866f4SJed Brown else 338d7b241e6Sjeremylt (*ceed)->Error = CeedErrorAbort; 339d7b241e6Sjeremylt (*ceed)->refcount = 1; 340d7b241e6Sjeremylt (*ceed)->data = NULL; 341fe2413ffSjeremylt 342fe2413ffSjeremylt // Set lookup table 3436e79d475Sjeremylt foffset foffsets[] = { 3446e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Error), 3456e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, GetPreferredMemType), 3466e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, Destroy), 347*f8902d9eSjeremylt CEED_FTABLE_ENTRY(Ceed, VectorCreate), 3486e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreate), 3496e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, ElemRestrictionCreateBlocked), 3506e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateTensorH1), 3516e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, BasisCreateH1), 3526e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, TensorContractCreate), 3536e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, QFunctionCreate), 3546e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, OperatorCreate), 3556e79d475Sjeremylt CEED_FTABLE_ENTRY(Ceed, CompositeOperatorCreate), 3566e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetArray), 3576e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, SetValue), 3586e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArray), 3596e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, GetArrayRead), 3606e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArray), 3616e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, RestoreArrayRead), 3626e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedVector, Destroy), 3636e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Apply), 3646e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, ApplyBlock), 3656e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedElemRestriction, Destroy), 3666e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Apply), 3676e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedBasis, Destroy), 3686e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Apply), 3696e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedTensorContract, Destroy), 3706e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Apply), 3716e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedQFunction, Destroy), 3726e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Apply), 3736e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, ApplyJacobian), 3746e79d475Sjeremylt CEED_FTABLE_ENTRY(CeedOperator, Destroy), 3756e79d475Sjeremylt {NULL, 0} // End of lookup table - used in SetBackendFunction loop 3761dfeef1dSjeremylt }; 377fe2413ffSjeremylt 3786e79d475Sjeremylt ierr = CeedCalloc(sizeof(foffsets), &(*ceed)->foffsets); CeedChk(ierr); 3796e79d475Sjeremylt memcpy((*ceed)->foffsets, foffsets, sizeof(foffsets)); 380fe2413ffSjeremylt 381fe2413ffSjeremylt // Backend specific setup 382d7b241e6Sjeremylt ierr = backends[matchidx].init(resource, *ceed); CeedChk(ierr); 383fe2413ffSjeremylt 384d7b241e6Sjeremylt return 0; 385d7b241e6Sjeremylt } 386d7b241e6Sjeremylt 387d7b241e6Sjeremylt /** 3882f86a920SJeremy L Thompson @brief Retrieve a parent CEED 3892f86a920SJeremy L Thompson 3902f86a920SJeremy L Thompson @param ceed Ceed to retrieve parent of 3912f86a920SJeremy L Thompson @param[out] parent Address to save the parent to 3922f86a920SJeremy L Thompson 3932f86a920SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 3942f86a920SJeremy L Thompson 3952f86a920SJeremy L Thompson @ref Developer 3962f86a920SJeremy L Thompson **/ 3972f86a920SJeremy L Thompson int CeedGetParent(Ceed ceed, Ceed *parent) { 3982f86a920SJeremy L Thompson int ierr; 3992f86a920SJeremy L Thompson if (ceed->parent) { 4002f86a920SJeremy L Thompson ierr = CeedGetParent(ceed->parent, parent); CeedChk(ierr); 4012f86a920SJeremy L Thompson return 0; 4022f86a920SJeremy L Thompson } 4032f86a920SJeremy L Thompson *parent = ceed; 4042f86a920SJeremy L Thompson return 0; 4052f86a920SJeremy L Thompson } 4062f86a920SJeremy L Thompson 4072f86a920SJeremy L Thompson /** 4085fe0d4faSjeremylt @brief Retrieve a delegate CEED 4095fe0d4faSjeremylt 4105fe0d4faSjeremylt @param ceed Ceed to retrieve delegate of 4115fe0d4faSjeremylt @param[out] delegate Address to save the delegate to 4125fe0d4faSjeremylt 4135fe0d4faSjeremylt @return An error code: 0 - success, otherwise - failure 4145fe0d4faSjeremylt 41523617272Sjeremylt @ref Developer 4165fe0d4faSjeremylt **/ 4175fe0d4faSjeremylt int CeedGetDelegate(Ceed ceed, Ceed *delegate) { 4184ce2993fSjeremylt *delegate = ceed->delegate; 4194ce2993fSjeremylt return 0; 4204ce2993fSjeremylt } 4214ce2993fSjeremylt 4224ce2993fSjeremylt /** 4234ce2993fSjeremylt @brief Set a delegate CEED 4244ce2993fSjeremylt 4254ce2993fSjeremylt @param ceed Ceed to set delegate of 4264ce2993fSjeremylt @param[out] delegate Address to set the delegate to 4274ce2993fSjeremylt 4284ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 4294ce2993fSjeremylt 43023617272Sjeremylt @ref Advanced 4314ce2993fSjeremylt **/ 4324ce2993fSjeremylt int CeedSetDelegate(Ceed ceed, Ceed *delegate) { 4334ce2993fSjeremylt ceed->delegate = *delegate; 4342f86a920SJeremy L Thompson (*delegate)->parent = ceed; 4354ce2993fSjeremylt return 0; 4364ce2993fSjeremylt } 4374ce2993fSjeremylt 4384ce2993fSjeremylt /** 439c907536fSjeremylt @brief Return Ceed perferred memory type 440c907536fSjeremylt 441c907536fSjeremylt @param ceed Ceed to get preferred memory type of 442c907536fSjeremylt @param[out] delegate Address to save preferred memory type to 443c907536fSjeremylt 444c907536fSjeremylt @return An error code: 0 - success, otherwise - failure 445c907536fSjeremylt 446c907536fSjeremylt @ref Basic 447c907536fSjeremylt **/ 448c907536fSjeremylt int CeedGetPreferredMemType(Ceed ceed, CeedMemType *type) { 449c907536fSjeremylt int ierr; 450c907536fSjeremylt if (ceed->GetPreferredMemType) { 451c907536fSjeremylt ierr = ceed->GetPreferredMemType(type); CeedChk(ierr); 452c907536fSjeremylt } else { 453c907536fSjeremylt *type = CEED_MEM_HOST; 454c907536fSjeremylt } 455c907536fSjeremylt 456c907536fSjeremylt return 0; 457c907536fSjeremylt } 458c907536fSjeremylt 459c907536fSjeremylt /** 460fe2413ffSjeremylt @brief Set a backend function 461fe2413ffSjeremylt 462cb37edd8Sjeremylt This function is used for a backend to set the function associated with 463cb37edd8Sjeremylt the CEED objects. For example, 464*f8902d9eSjeremylt CeedSetBackendFunction(ceed, "Ceed", ceed, "VectorCreate", BackendVectorCreate) 465cb37edd8Sjeremylt sets the backend implementation of 'CeedVectorCreate' and 466cb37edd8Sjeremylt CeedSetBackendFunction(ceed, "Basis", basis, "Apply", BackendBasisApply) 467cb37edd8Sjeremylt sets the backend implementation of 'CeedBasisApply'. Note, the prefix 'Ceed' 468cb37edd8Sjeremylt is not required for the object type ("Basis" vs "CeedBasis"). 469cb37edd8Sjeremylt 470fe2413ffSjeremylt @param ceed Ceed for error handling 471fe2413ffSjeremylt @param type Type of Ceed object to set function for 472fe2413ffSjeremylt @param[out] object Ceed object to set function for 473fe2413ffSjeremylt @param fname Name of function to set 474fe2413ffSjeremylt @param f Function to set 475fe2413ffSjeremylt 476fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 477fe2413ffSjeremylt 478fe2413ffSjeremylt @ref Advanced 479fe2413ffSjeremylt **/ 480fe2413ffSjeremylt int CeedSetBackendFunction(Ceed ceed, 481fe2413ffSjeremylt const char *type, void *object, 482fe2413ffSjeremylt const char *fname, int (*f)()) { 483409ab9adSjeremylt char lookupname[CEED_MAX_RESOURCE_LEN+1] = ""; 484fe2413ffSjeremylt 485fe2413ffSjeremylt // Build lookup name 4866e79d475Sjeremylt if (strcmp(type, "Ceed")) 4876e79d475Sjeremylt strncat (lookupname, "Ceed", CEED_MAX_RESOURCE_LEN); 488409ab9adSjeremylt strncat(lookupname, type, CEED_MAX_RESOURCE_LEN); 489409ab9adSjeremylt strncat(lookupname, fname, CEED_MAX_RESOURCE_LEN); 490fe2413ffSjeremylt 491fe2413ffSjeremylt // Find and use offset 4926e79d475Sjeremylt for (CeedInt i = 0; ceed->foffsets[i].fname; i++) { 493fe2413ffSjeremylt if (!strcmp(ceed->foffsets[i].fname, lookupname)) { 494fe2413ffSjeremylt size_t offset = ceed->foffsets[i].offset; 495a7a2e802Sjeremylt int (**fpointer)(void) = (int (**)(void))((char*)object + offset); 496a7a2e802Sjeremylt *fpointer = f; 497fe2413ffSjeremylt return 0; 498fe2413ffSjeremylt } 499fe2413ffSjeremylt } 500fe2413ffSjeremylt 5011dfeef1dSjeremylt return CeedError(ceed, 1, 5021dfeef1dSjeremylt "Requested function '%s' was not found for CEED object '%s'", fname, type); 503fe2413ffSjeremylt } 504fe2413ffSjeremylt 505fe2413ffSjeremylt /** 5064ce2993fSjeremylt @brief Retrieve backend data for a CEED 5074ce2993fSjeremylt 508fe2413ffSjeremylt @param ceed Ceed to retrieve data of 5094ce2993fSjeremylt @param[out] data Address to save data to 5104ce2993fSjeremylt 5114ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 5124ce2993fSjeremylt 51323617272Sjeremylt @ref Advanced 5144ce2993fSjeremylt **/ 5154ce2993fSjeremylt int CeedGetData(Ceed ceed, void* *data) { 5164ce2993fSjeremylt *data = ceed->data; 5175fe0d4faSjeremylt return 0; 5185fe0d4faSjeremylt } 5195fe0d4faSjeremylt 5205fe0d4faSjeremylt /** 521fe2413ffSjeremylt @brief Set backend data for a CEED 522fe2413ffSjeremylt 523fe2413ffSjeremylt @param ceed Ceed to set data of 524fe2413ffSjeremylt @param data Address of data to set 525fe2413ffSjeremylt 526fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 527fe2413ffSjeremylt 528fe2413ffSjeremylt @ref Advanced 529fe2413ffSjeremylt **/ 530fe2413ffSjeremylt int CeedSetData(Ceed ceed, void* *data) { 531fe2413ffSjeremylt ceed->data = *data; 532fe2413ffSjeremylt return 0; 533fe2413ffSjeremylt } 534fe2413ffSjeremylt 535fe2413ffSjeremylt /** 536b11c1e72Sjeremylt @brief Destroy a Ceed context 537d7b241e6Sjeremylt 538d7b241e6Sjeremylt @param ceed Address of Ceed context to destroy 539b11c1e72Sjeremylt 540b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 541dfdf5a53Sjeremylt 542dfdf5a53Sjeremylt @ref Basic 543b11c1e72Sjeremylt **/ 544d7b241e6Sjeremylt int CeedDestroy(Ceed *ceed) { 545d7b241e6Sjeremylt int ierr; 546d7b241e6Sjeremylt 547d7b241e6Sjeremylt if (!*ceed || --(*ceed)->refcount > 0) return 0; 5485fe0d4faSjeremylt if ((*ceed)->delegate) { 5495fe0d4faSjeremylt ierr = CeedDestroy(&(*ceed)->delegate); CeedChk(ierr); 5505fe0d4faSjeremylt } 551d7b241e6Sjeremylt if ((*ceed)->Destroy) { 552d7b241e6Sjeremylt ierr = (*ceed)->Destroy(*ceed); CeedChk(ierr); 553d7b241e6Sjeremylt } 5546e79d475Sjeremylt ierr = CeedFree(&(*ceed)->foffsets); CeedChk(ierr); 555d7b241e6Sjeremylt ierr = CeedFree(ceed); CeedChk(ierr); 556d7b241e6Sjeremylt return 0; 557d7b241e6Sjeremylt } 558d7b241e6Sjeremylt 559d7b241e6Sjeremylt /// @} 560