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> 18d7b241e6Sjeremylt #include <string.h> 19d7b241e6Sjeremylt 20dfdf5a53Sjeremylt /// @file 21dfdf5a53Sjeremylt /// Implementation of public CeedQFunction interfaces 22dfdf5a53Sjeremylt /// 23dfdf5a53Sjeremylt /// @addtogroup CeedQFunction 24dfdf5a53Sjeremylt /// @{ 25d7b241e6Sjeremylt 26d7b241e6Sjeremylt /** 27d7b241e6Sjeremylt @brief Create a CeedQFunction for evaluating interior (volumetric) terms. 28d7b241e6Sjeremylt 29b11c1e72Sjeremylt @param ceed A Ceed object where the CeedQFunction will be created 30d7b241e6Sjeremylt @param vlength Vector length. Caller must ensure that number of quadrature 31d7b241e6Sjeremylt points is a multiple of vlength. 32d7b241e6Sjeremylt @param f Function pointer to evaluate action at quadrature points. 33d7b241e6Sjeremylt See below. 34d7b241e6Sjeremylt @param focca OCCA identifier "file.c:function_name" for definition of `f` 35b11c1e72Sjeremylt @param[out] qf Address of the variable where the newly created 36b11c1e72Sjeremylt CeedQFunction will be stored 37b11c1e72Sjeremylt 38b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 39d7b241e6Sjeremylt 40d7b241e6Sjeremylt The arguments of the call-back 'function' are: 41d7b241e6Sjeremylt 42d7b241e6Sjeremylt 1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in 43d7b241e6Sjeremylt the CeedQFunction, set by calling CeedQFunctionSetContext 44d7b241e6Sjeremylt 45d7b241e6Sjeremylt 2. [CeedInt nq][in] - number of quadrature points to process 46d7b241e6Sjeremylt 47d7b241e6Sjeremylt 3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user 48d7b241e6Sjeremylt 49d7b241e6Sjeremylt 4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user 50d7b241e6Sjeremylt 51dfdf5a53Sjeremylt @ref Basic 52dfdf5a53Sjeremylt **/ 53d7b241e6Sjeremylt int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength, 54d7b241e6Sjeremylt int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*), 55d7b241e6Sjeremylt const char *focca, CeedQFunction *qf) { 56d7b241e6Sjeremylt int ierr; 57d7b241e6Sjeremylt char *focca_copy; 58d7b241e6Sjeremylt 595fe0d4faSjeremylt if (!ceed->QFunctionCreate) { 605fe0d4faSjeremylt Ceed delegate; 615fe0d4faSjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 625fe0d4faSjeremylt 635fe0d4faSjeremylt if (!delegate) 64d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 655fe0d4faSjeremylt 665fe0d4faSjeremylt ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr); 675fe0d4faSjeremylt return 0; 685fe0d4faSjeremylt } 695fe0d4faSjeremylt 70d7b241e6Sjeremylt ierr = CeedCalloc(1,qf); CeedChk(ierr); 71d7b241e6Sjeremylt (*qf)->ceed = ceed; 72d7b241e6Sjeremylt ceed->refcount++; 73d7b241e6Sjeremylt (*qf)->refcount = 1; 74d7b241e6Sjeremylt (*qf)->vlength = vlength; 75d7b241e6Sjeremylt (*qf)->function = f; 76d7b241e6Sjeremylt ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 77d7b241e6Sjeremylt strcpy(focca_copy, focca); 78d7b241e6Sjeremylt (*qf)->focca = focca_copy; 79d7b241e6Sjeremylt ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 80d7b241e6Sjeremylt return 0; 81d7b241e6Sjeremylt } 82d7b241e6Sjeremylt 83b11c1e72Sjeremylt /** 84a0a97fcfSJed Brown @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output 85b11c1e72Sjeremylt 86b11c1e72Sjeremylt @param f CeedQFunctionField 87b11c1e72Sjeremylt @param fieldname Name of QFunction field 88b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 89b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 90b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 91b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 92b11c1e72Sjeremylt 93b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 94dfdf5a53Sjeremylt 95dfdf5a53Sjeremylt @ref Developer 96b11c1e72Sjeremylt **/ 97d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f, 98d7b241e6Sjeremylt const char *fieldname, CeedInt ncomp, 99d7b241e6Sjeremylt CeedEvalMode emode) { 100d7b241e6Sjeremylt size_t len = strlen(fieldname); 101d7b241e6Sjeremylt char *tmp; 102d7b241e6Sjeremylt int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 103d7b241e6Sjeremylt memcpy(tmp, fieldname, len+1); 104d7b241e6Sjeremylt f->fieldname = tmp; 105d7b241e6Sjeremylt f->ncomp = ncomp; 106d7b241e6Sjeremylt f->emode = emode; 107d7b241e6Sjeremylt return 0; 108d7b241e6Sjeremylt } 109d7b241e6Sjeremylt 110b11c1e72Sjeremylt /** 111a0a97fcfSJed Brown @brief Add a CeedQFunction input 112b11c1e72Sjeremylt 113b11c1e72Sjeremylt @param qf CeedQFunction 114b11c1e72Sjeremylt @param fieldname Name of QFunction field 115b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 116b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 117b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 118b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 119b11c1e72Sjeremylt 120b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 121dfdf5a53Sjeremylt 122dfdf5a53Sjeremylt @ref Basic 123b11c1e72Sjeremylt **/ 124d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 125d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 126d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 127d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 128d7b241e6Sjeremylt return 0; 129d7b241e6Sjeremylt } 130d7b241e6Sjeremylt 131b11c1e72Sjeremylt /** 132a0a97fcfSJed Brown @brief Add a CeedQFunction output 133b11c1e72Sjeremylt 134b11c1e72Sjeremylt @param qf CeedQFunction 135b11c1e72Sjeremylt @param fieldname Name of QFunction field 136b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 137b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 138b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 139b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 140b11c1e72Sjeremylt 141b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 142dfdf5a53Sjeremylt 143dfdf5a53Sjeremylt @ref Basic 144b11c1e72Sjeremylt **/ 145d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 146d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 147d7b241e6Sjeremylt if (emode == CEED_EVAL_WEIGHT) 148d7b241e6Sjeremylt return CeedError(qf->ceed, 1, 149d7b241e6Sjeremylt "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 150d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 151d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 152d7b241e6Sjeremylt return 0; 153d7b241e6Sjeremylt } 154d7b241e6Sjeremylt 155dfdf5a53Sjeremylt /** 156*4ce2993fSjeremylt @brief Get the Ceed associated with a CeedQFunction 157*4ce2993fSjeremylt 158*4ce2993fSjeremylt @param qf CeedQFunction 159*4ce2993fSjeremylt @param[out] ceed Variable to store Ceed 160*4ce2993fSjeremylt 161*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 162*4ce2993fSjeremylt 163*4ce2993fSjeremylt @ref Utility 164*4ce2993fSjeremylt **/ 165*4ce2993fSjeremylt 166*4ce2993fSjeremylt int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) { 167*4ce2993fSjeremylt *ceed = qf->ceed; 168*4ce2993fSjeremylt return 0; 169*4ce2993fSjeremylt } 170*4ce2993fSjeremylt 171*4ce2993fSjeremylt /** 172*4ce2993fSjeremylt @brief Get the vector length of a CeedQFunction 173*4ce2993fSjeremylt 174*4ce2993fSjeremylt @param qf CeedQFunction 175*4ce2993fSjeremylt @param[out] veclength Variable to store vector length 176*4ce2993fSjeremylt 177*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 178*4ce2993fSjeremylt 179*4ce2993fSjeremylt @ref Utility 180*4ce2993fSjeremylt **/ 181*4ce2993fSjeremylt 182*4ce2993fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) { 183*4ce2993fSjeremylt *vlength = qf->vlength; 184*4ce2993fSjeremylt return 0; 185*4ce2993fSjeremylt } 186*4ce2993fSjeremylt 187*4ce2993fSjeremylt /** 188dfdf5a53Sjeremylt @brief Get the number of inputs and outputs to a CeedQFunction 189dfdf5a53Sjeremylt 190dfdf5a53Sjeremylt @param qf CeedQFunction 191*4ce2993fSjeremylt @param[out] numinput Variable to store number of input fields 192*4ce2993fSjeremylt @param[out] numoutput Variable to store number of output fields 193dfdf5a53Sjeremylt 194dfdf5a53Sjeremylt @return An error code: 0 - success, otherwise - failure 195dfdf5a53Sjeremylt 196dfdf5a53Sjeremylt @ref Utility 197dfdf5a53Sjeremylt **/ 198dfdf5a53Sjeremylt 199d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 200d7b241e6Sjeremylt CeedInt *numoutput) { 2011a4ead9bSjeremylt if (numinput) *numinput = qf->numinputfields; 2021a4ead9bSjeremylt if (numoutput) *numoutput = qf->numoutputfields; 203d7b241e6Sjeremylt return 0; 204d7b241e6Sjeremylt } 205d7b241e6Sjeremylt 206d7b241e6Sjeremylt /** 207*4ce2993fSjeremylt @brief Get the FOCCA string for a CeedQFunction 208*4ce2993fSjeremylt 209*4ce2993fSjeremylt @param qf CeedQFunction 210*4ce2993fSjeremylt @param[out] focca Variable to store focca string 211*4ce2993fSjeremylt 212*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 213*4ce2993fSjeremylt 214*4ce2993fSjeremylt @ref Utility 215*4ce2993fSjeremylt **/ 216*4ce2993fSjeremylt 217*4ce2993fSjeremylt int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) { 218*4ce2993fSjeremylt *focca = (char*) qf->focca; 219*4ce2993fSjeremylt return 0; 220*4ce2993fSjeremylt } 221*4ce2993fSjeremylt 222*4ce2993fSjeremylt /** 223*4ce2993fSjeremylt @brief Get global context size for a CeedQFunction 224*4ce2993fSjeremylt 225*4ce2993fSjeremylt @param qf CeedQFunction 226*4ce2993fSjeremylt @param[out] ctxsize Variable to store size of context data values 227*4ce2993fSjeremylt 228*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 229*4ce2993fSjeremylt 230*4ce2993fSjeremylt @ref Utility 231*4ce2993fSjeremylt **/ 232*4ce2993fSjeremylt 233*4ce2993fSjeremylt int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) { 234*4ce2993fSjeremylt *ctxsize = qf->ctxsize; 235*4ce2993fSjeremylt return 0; 236*4ce2993fSjeremylt } 237*4ce2993fSjeremylt 238*4ce2993fSjeremylt /** 239*4ce2993fSjeremylt @brief Get global context for a CeedQFunction 240*4ce2993fSjeremylt 241*4ce2993fSjeremylt @param qf CeedQFunction 242*4ce2993fSjeremylt @param[out] ctx Variable to store context data values 243*4ce2993fSjeremylt 244*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 245*4ce2993fSjeremylt 246*4ce2993fSjeremylt @ref Utility 247*4ce2993fSjeremylt **/ 248*4ce2993fSjeremylt 249*4ce2993fSjeremylt int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) { 250*4ce2993fSjeremylt *ctx = qf->ctx; 251*4ce2993fSjeremylt return 0; 252*4ce2993fSjeremylt } 253*4ce2993fSjeremylt 254*4ce2993fSjeremylt /** 255*4ce2993fSjeremylt @brief Get backend data of a CeedQFunction 256*4ce2993fSjeremylt 257*4ce2993fSjeremylt @param qf CeedQFunction 258*4ce2993fSjeremylt @param[out] data Variable to store data 259*4ce2993fSjeremylt 260*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 261*4ce2993fSjeremylt 262*4ce2993fSjeremylt @ref Utility 263*4ce2993fSjeremylt **/ 264*4ce2993fSjeremylt 265*4ce2993fSjeremylt int CeedQFunctionGetData(CeedQFunction qf, void* *data) { 266*4ce2993fSjeremylt *data = qf->data; 267*4ce2993fSjeremylt return 0; 268*4ce2993fSjeremylt } 269*4ce2993fSjeremylt 270*4ce2993fSjeremylt /** 271*4ce2993fSjeremylt @brief Set global context for a CeedQFunction 272b11c1e72Sjeremylt 273b11c1e72Sjeremylt @param qf CeedQFunction 274b11c1e72Sjeremylt @param ctx Context data to set 275b11c1e72Sjeremylt @param ctxsize Size of context data values 276b11c1e72Sjeremylt 277b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 278dfdf5a53Sjeremylt 279dfdf5a53Sjeremylt @ref Basic 280b11c1e72Sjeremylt **/ 281d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 282d7b241e6Sjeremylt qf->ctx = ctx; 283d7b241e6Sjeremylt qf->ctxsize = ctxsize; 284d7b241e6Sjeremylt return 0; 285d7b241e6Sjeremylt } 286d7b241e6Sjeremylt 287b11c1e72Sjeremylt /** 288b11c1e72Sjeremylt @brief Apply the action of a CeedQFunction 289b11c1e72Sjeremylt 290b11c1e72Sjeremylt @param qf CeedQFunction 291b11c1e72Sjeremylt @param Q Number of quadrature points 292b11c1e72Sjeremylt @param[in] u Array of input data arrays 293b11c1e72Sjeremylt @param[out] v Array of output data arrays 294b11c1e72Sjeremylt 295b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 296dfdf5a53Sjeremylt 297dfdf5a53Sjeremylt @ref Advanced 298b11c1e72Sjeremylt **/ 299d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 300d7b241e6Sjeremylt const CeedScalar *const *u, 301d7b241e6Sjeremylt CeedScalar *const *v) { 302d7b241e6Sjeremylt int ierr; 303d7b241e6Sjeremylt if (!qf->Apply) 304d7b241e6Sjeremylt return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 305d7b241e6Sjeremylt if (Q % qf->vlength) 306d7b241e6Sjeremylt return CeedError(qf->ceed, 2, 307d7b241e6Sjeremylt "Number of quadrature points %d must be a multiple of %d", 308d7b241e6Sjeremylt Q, qf->vlength); 309d7b241e6Sjeremylt ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 310d7b241e6Sjeremylt return 0; 311d7b241e6Sjeremylt } 312d7b241e6Sjeremylt 313b11c1e72Sjeremylt /** 314b11c1e72Sjeremylt @brief Destroy a CeedQFunction 315b11c1e72Sjeremylt 316b11c1e72Sjeremylt @param qf CeedQFunction to destroy 317b11c1e72Sjeremylt 318b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 319dfdf5a53Sjeremylt 320dfdf5a53Sjeremylt @ref Basic 321b11c1e72Sjeremylt **/ 322d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) { 323d7b241e6Sjeremylt int ierr; 324d7b241e6Sjeremylt 325d7b241e6Sjeremylt if (!*qf || --(*qf)->refcount > 0) return 0; 326d7b241e6Sjeremylt // Free field names 327d7b241e6Sjeremylt for (int i=0; i<(*qf)->numinputfields; i++) { 328d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 329d7b241e6Sjeremylt } 330d7b241e6Sjeremylt for (int i=0; i<(*qf)->numoutputfields; i++) { 331d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 332d7b241e6Sjeremylt } 333d7b241e6Sjeremylt if ((*qf)->Destroy) { 334d7b241e6Sjeremylt ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 335d7b241e6Sjeremylt } 336d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 337d7b241e6Sjeremylt ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 338d7b241e6Sjeremylt ierr = CeedFree(qf); CeedChk(ierr); 339d7b241e6Sjeremylt return 0; 340d7b241e6Sjeremylt } 341d7b241e6Sjeremylt 342d7b241e6Sjeremylt /// @} 343