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 #include <ceed-impl.h> 18d863ab9bSjeremylt #include <ceed-backend.h> 19d7b241e6Sjeremylt #include <string.h> 20d7b241e6Sjeremylt 21dfdf5a53Sjeremylt /// @file 22dfdf5a53Sjeremylt /// Implementation of public CeedQFunction interfaces 23dfdf5a53Sjeremylt /// 24dfdf5a53Sjeremylt /// @addtogroup CeedQFunction 25dfdf5a53Sjeremylt /// @{ 26d7b241e6Sjeremylt 27d7b241e6Sjeremylt /** 28d7b241e6Sjeremylt @brief Create a CeedQFunction for evaluating interior (volumetric) terms. 29d7b241e6Sjeremylt 30b11c1e72Sjeremylt @param ceed A Ceed object where the CeedQFunction will be created 31d7b241e6Sjeremylt @param vlength Vector length. Caller must ensure that number of quadrature 32d7b241e6Sjeremylt points is a multiple of vlength. 33d7b241e6Sjeremylt @param f Function pointer to evaluate action at quadrature points. 34d7b241e6Sjeremylt See below. 35d7b241e6Sjeremylt @param focca OCCA identifier "file.c:function_name" for definition of `f` 36b11c1e72Sjeremylt @param[out] qf Address of the variable where the newly created 37b11c1e72Sjeremylt CeedQFunction will be stored 38b11c1e72Sjeremylt 39b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 40d7b241e6Sjeremylt 41d7b241e6Sjeremylt The arguments of the call-back 'function' are: 42d7b241e6Sjeremylt 43d7b241e6Sjeremylt 1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in 44d7b241e6Sjeremylt the CeedQFunction, set by calling CeedQFunctionSetContext 45d7b241e6Sjeremylt 46d7b241e6Sjeremylt 2. [CeedInt nq][in] - number of quadrature points to process 47d7b241e6Sjeremylt 48d7b241e6Sjeremylt 3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user 49d7b241e6Sjeremylt 50d7b241e6Sjeremylt 4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user 51d7b241e6Sjeremylt 52dfdf5a53Sjeremylt @ref Basic 53dfdf5a53Sjeremylt **/ 54d7b241e6Sjeremylt int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength, 55d7b241e6Sjeremylt int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*), 56d7b241e6Sjeremylt const char *focca, CeedQFunction *qf) { 57d7b241e6Sjeremylt int ierr; 58d7b241e6Sjeremylt char *focca_copy; 59d7b241e6Sjeremylt 605fe0d4faSjeremylt if (!ceed->QFunctionCreate) { 615fe0d4faSjeremylt Ceed delegate; 625fe0d4faSjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 635fe0d4faSjeremylt 645fe0d4faSjeremylt if (!delegate) 65d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 665fe0d4faSjeremylt 675fe0d4faSjeremylt ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr); 685fe0d4faSjeremylt return 0; 695fe0d4faSjeremylt } 705fe0d4faSjeremylt 71d7b241e6Sjeremylt ierr = CeedCalloc(1,qf); CeedChk(ierr); 72d7b241e6Sjeremylt (*qf)->ceed = ceed; 73d7b241e6Sjeremylt ceed->refcount++; 74d7b241e6Sjeremylt (*qf)->refcount = 1; 75d7b241e6Sjeremylt (*qf)->vlength = vlength; 76d7b241e6Sjeremylt (*qf)->function = f; 77d7b241e6Sjeremylt ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 78d7b241e6Sjeremylt strcpy(focca_copy, focca); 79d7b241e6Sjeremylt (*qf)->focca = focca_copy; 80d7b241e6Sjeremylt ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 81d7b241e6Sjeremylt return 0; 82d7b241e6Sjeremylt } 83d7b241e6Sjeremylt 84b11c1e72Sjeremylt /** 85a0a97fcfSJed Brown @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output 86b11c1e72Sjeremylt 87b11c1e72Sjeremylt @param f CeedQFunctionField 88b11c1e72Sjeremylt @param fieldname Name of QFunction field 89b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 90b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 91b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 92b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 93b11c1e72Sjeremylt 94b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 95dfdf5a53Sjeremylt 96dfdf5a53Sjeremylt @ref Developer 97b11c1e72Sjeremylt **/ 98d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f, 99d7b241e6Sjeremylt const char *fieldname, CeedInt ncomp, 100d7b241e6Sjeremylt CeedEvalMode emode) { 101d7b241e6Sjeremylt size_t len = strlen(fieldname); 102d7b241e6Sjeremylt char *tmp; 103d7b241e6Sjeremylt int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 104d7b241e6Sjeremylt memcpy(tmp, fieldname, len+1); 105d7b241e6Sjeremylt f->fieldname = tmp; 106d7b241e6Sjeremylt f->ncomp = ncomp; 107d7b241e6Sjeremylt f->emode = emode; 108d7b241e6Sjeremylt return 0; 109d7b241e6Sjeremylt } 110d7b241e6Sjeremylt 111b11c1e72Sjeremylt /** 112a0a97fcfSJed Brown @brief Add a CeedQFunction input 113b11c1e72Sjeremylt 114b11c1e72Sjeremylt @param qf CeedQFunction 115b11c1e72Sjeremylt @param fieldname Name of QFunction field 116b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 117b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 118b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 119b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 120b11c1e72Sjeremylt 121b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 122dfdf5a53Sjeremylt 123dfdf5a53Sjeremylt @ref Basic 124b11c1e72Sjeremylt **/ 125d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 126d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 127d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 128d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 129d7b241e6Sjeremylt return 0; 130d7b241e6Sjeremylt } 131d7b241e6Sjeremylt 132b11c1e72Sjeremylt /** 133a0a97fcfSJed Brown @brief Add a CeedQFunction output 134b11c1e72Sjeremylt 135b11c1e72Sjeremylt @param qf CeedQFunction 136b11c1e72Sjeremylt @param fieldname Name of QFunction field 137b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 138b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 139b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 140b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 141b11c1e72Sjeremylt 142b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 143dfdf5a53Sjeremylt 144dfdf5a53Sjeremylt @ref Basic 145b11c1e72Sjeremylt **/ 146d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 147d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 148d7b241e6Sjeremylt if (emode == CEED_EVAL_WEIGHT) 149d7b241e6Sjeremylt return CeedError(qf->ceed, 1, 150d7b241e6Sjeremylt "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 151d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 152d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 153d7b241e6Sjeremylt return 0; 154d7b241e6Sjeremylt } 155d7b241e6Sjeremylt 156dfdf5a53Sjeremylt /** 1574ce2993fSjeremylt @brief Get the Ceed associated with a CeedQFunction 1584ce2993fSjeremylt 1594ce2993fSjeremylt @param qf CeedQFunction 1604ce2993fSjeremylt @param[out] ceed Variable to store Ceed 1614ce2993fSjeremylt 1624ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 1634ce2993fSjeremylt 164*23617272Sjeremylt @ref Advanced 1654ce2993fSjeremylt **/ 1664ce2993fSjeremylt 1674ce2993fSjeremylt int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) { 1684ce2993fSjeremylt *ceed = qf->ceed; 1694ce2993fSjeremylt return 0; 1704ce2993fSjeremylt } 1714ce2993fSjeremylt 1724ce2993fSjeremylt /** 1734ce2993fSjeremylt @brief Get the vector length of a CeedQFunction 1744ce2993fSjeremylt 1754ce2993fSjeremylt @param qf CeedQFunction 1764ce2993fSjeremylt @param[out] veclength Variable to store vector length 1774ce2993fSjeremylt 1784ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 1794ce2993fSjeremylt 180*23617272Sjeremylt @ref Advanced 1814ce2993fSjeremylt **/ 1824ce2993fSjeremylt 1834ce2993fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) { 1844ce2993fSjeremylt *vlength = qf->vlength; 1854ce2993fSjeremylt return 0; 1864ce2993fSjeremylt } 1874ce2993fSjeremylt 1884ce2993fSjeremylt /** 189dfdf5a53Sjeremylt @brief Get the number of inputs and outputs to a CeedQFunction 190dfdf5a53Sjeremylt 191dfdf5a53Sjeremylt @param qf CeedQFunction 1924ce2993fSjeremylt @param[out] numinput Variable to store number of input fields 1934ce2993fSjeremylt @param[out] numoutput Variable to store number of output fields 194dfdf5a53Sjeremylt 195dfdf5a53Sjeremylt @return An error code: 0 - success, otherwise - failure 196dfdf5a53Sjeremylt 197*23617272Sjeremylt @ref Advanced 198dfdf5a53Sjeremylt **/ 199dfdf5a53Sjeremylt 200d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 201d7b241e6Sjeremylt CeedInt *numoutput) { 2021a4ead9bSjeremylt if (numinput) *numinput = qf->numinputfields; 2031a4ead9bSjeremylt if (numoutput) *numoutput = qf->numoutputfields; 204d7b241e6Sjeremylt return 0; 205d7b241e6Sjeremylt } 206d7b241e6Sjeremylt 207d7b241e6Sjeremylt /** 2084ce2993fSjeremylt @brief Get the FOCCA string for a CeedQFunction 2094ce2993fSjeremylt 2104ce2993fSjeremylt @param qf CeedQFunction 2114ce2993fSjeremylt @param[out] focca Variable to store focca string 2124ce2993fSjeremylt 2134ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2144ce2993fSjeremylt 215*23617272Sjeremylt @ref Advanced 2164ce2993fSjeremylt **/ 2174ce2993fSjeremylt 2184ce2993fSjeremylt int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) { 2194ce2993fSjeremylt *focca = (char*) qf->focca; 2204ce2993fSjeremylt return 0; 2214ce2993fSjeremylt } 2224ce2993fSjeremylt 2234ce2993fSjeremylt /** 2244ce2993fSjeremylt @brief Get global context size for a CeedQFunction 2254ce2993fSjeremylt 2264ce2993fSjeremylt @param qf CeedQFunction 2274ce2993fSjeremylt @param[out] ctxsize Variable to store size of context data values 2284ce2993fSjeremylt 2294ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2304ce2993fSjeremylt 231*23617272Sjeremylt @ref Advanced 2324ce2993fSjeremylt **/ 2334ce2993fSjeremylt 2344ce2993fSjeremylt int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) { 2354ce2993fSjeremylt *ctxsize = qf->ctxsize; 2364ce2993fSjeremylt return 0; 2374ce2993fSjeremylt } 2384ce2993fSjeremylt 2394ce2993fSjeremylt /** 2404ce2993fSjeremylt @brief Get global context for a CeedQFunction 2414ce2993fSjeremylt 2424ce2993fSjeremylt @param qf CeedQFunction 2434ce2993fSjeremylt @param[out] ctx Variable to store context data values 2444ce2993fSjeremylt 2454ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2464ce2993fSjeremylt 247*23617272Sjeremylt @ref Advanced 2484ce2993fSjeremylt **/ 2494ce2993fSjeremylt 2504ce2993fSjeremylt int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) { 2514ce2993fSjeremylt *ctx = qf->ctx; 2524ce2993fSjeremylt return 0; 2534ce2993fSjeremylt } 2544ce2993fSjeremylt 2554ce2993fSjeremylt /** 2564ce2993fSjeremylt @brief Get backend data of a CeedQFunction 2574ce2993fSjeremylt 2584ce2993fSjeremylt @param qf CeedQFunction 2594ce2993fSjeremylt @param[out] data Variable to store data 2604ce2993fSjeremylt 2614ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2624ce2993fSjeremylt 263*23617272Sjeremylt @ref Advanced 2644ce2993fSjeremylt **/ 2654ce2993fSjeremylt 2664ce2993fSjeremylt int CeedQFunctionGetData(CeedQFunction qf, void* *data) { 2674ce2993fSjeremylt *data = qf->data; 2684ce2993fSjeremylt return 0; 2694ce2993fSjeremylt } 2704ce2993fSjeremylt 2714ce2993fSjeremylt /** 2724ce2993fSjeremylt @brief Set global context for a CeedQFunction 273b11c1e72Sjeremylt 274b11c1e72Sjeremylt @param qf CeedQFunction 275b11c1e72Sjeremylt @param ctx Context data to set 276b11c1e72Sjeremylt @param ctxsize Size of context data values 277b11c1e72Sjeremylt 278b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 279dfdf5a53Sjeremylt 280dfdf5a53Sjeremylt @ref Basic 281b11c1e72Sjeremylt **/ 282d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 283d7b241e6Sjeremylt qf->ctx = ctx; 284d7b241e6Sjeremylt qf->ctxsize = ctxsize; 285d7b241e6Sjeremylt return 0; 286d7b241e6Sjeremylt } 287d7b241e6Sjeremylt 288b11c1e72Sjeremylt /** 289b11c1e72Sjeremylt @brief Apply the action of a CeedQFunction 290b11c1e72Sjeremylt 291b11c1e72Sjeremylt @param qf CeedQFunction 292b11c1e72Sjeremylt @param Q Number of quadrature points 293b11c1e72Sjeremylt @param[in] u Array of input data arrays 294b11c1e72Sjeremylt @param[out] v Array of output data arrays 295b11c1e72Sjeremylt 296b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 297dfdf5a53Sjeremylt 298dfdf5a53Sjeremylt @ref Advanced 299b11c1e72Sjeremylt **/ 300d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 301d7b241e6Sjeremylt const CeedScalar *const *u, 302d7b241e6Sjeremylt CeedScalar *const *v) { 303d7b241e6Sjeremylt int ierr; 304d7b241e6Sjeremylt if (!qf->Apply) 305d7b241e6Sjeremylt return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 306d7b241e6Sjeremylt if (Q % qf->vlength) 307d7b241e6Sjeremylt return CeedError(qf->ceed, 2, 308d7b241e6Sjeremylt "Number of quadrature points %d must be a multiple of %d", 309d7b241e6Sjeremylt Q, qf->vlength); 310d7b241e6Sjeremylt ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 311d7b241e6Sjeremylt return 0; 312d7b241e6Sjeremylt } 313d7b241e6Sjeremylt 314b11c1e72Sjeremylt /** 315b11c1e72Sjeremylt @brief Destroy a CeedQFunction 316b11c1e72Sjeremylt 317b11c1e72Sjeremylt @param qf CeedQFunction to destroy 318b11c1e72Sjeremylt 319b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 320dfdf5a53Sjeremylt 321dfdf5a53Sjeremylt @ref Basic 322b11c1e72Sjeremylt **/ 323d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) { 324d7b241e6Sjeremylt int ierr; 325d7b241e6Sjeremylt 326d7b241e6Sjeremylt if (!*qf || --(*qf)->refcount > 0) return 0; 327d7b241e6Sjeremylt // Free field names 328d7b241e6Sjeremylt for (int i=0; i<(*qf)->numinputfields; i++) { 329d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 330d7b241e6Sjeremylt } 331d7b241e6Sjeremylt for (int i=0; i<(*qf)->numoutputfields; i++) { 332d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 333d7b241e6Sjeremylt } 334d7b241e6Sjeremylt if ((*qf)->Destroy) { 335d7b241e6Sjeremylt ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 336d7b241e6Sjeremylt } 337d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 338d7b241e6Sjeremylt ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 339d7b241e6Sjeremylt ierr = CeedFree(qf); CeedChk(ierr); 340d7b241e6Sjeremylt return 0; 341d7b241e6Sjeremylt } 342d7b241e6Sjeremylt 343d7b241e6Sjeremylt /// @} 344