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 59*5fe0d4faSjeremylt if (!ceed->QFunctionCreate) { 60*5fe0d4faSjeremylt Ceed delegate; 61*5fe0d4faSjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 62*5fe0d4faSjeremylt 63*5fe0d4faSjeremylt if (!delegate) 64d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 65*5fe0d4faSjeremylt 66*5fe0d4faSjeremylt ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr); 67*5fe0d4faSjeremylt return 0; 68*5fe0d4faSjeremylt } 69*5fe0d4faSjeremylt 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 /** 156dfdf5a53Sjeremylt @brief Get the number of inputs and outputs to a CeedQFunction 157dfdf5a53Sjeremylt 158dfdf5a53Sjeremylt @param qf CeedQFunction 159dfdf5a53Sjeremylt @param[out] numinput Number of input fields 160dfdf5a53Sjeremylt @param[out] numoutput Number of output fields 161dfdf5a53Sjeremylt 162dfdf5a53Sjeremylt @return An error code: 0 - success, otherwise - failure 163dfdf5a53Sjeremylt 164dfdf5a53Sjeremylt @ref Utility 165dfdf5a53Sjeremylt **/ 166dfdf5a53Sjeremylt 167d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 168d7b241e6Sjeremylt CeedInt *numoutput) { 1691a4ead9bSjeremylt if (numinput) *numinput = qf->numinputfields; 1701a4ead9bSjeremylt if (numoutput) *numoutput = qf->numoutputfields; 171d7b241e6Sjeremylt return 0; 172d7b241e6Sjeremylt } 173d7b241e6Sjeremylt 174d7b241e6Sjeremylt /** 175b11c1e72Sjeremylt @brief Set global context for a quadrature function 176b11c1e72Sjeremylt 177b11c1e72Sjeremylt @param qf CeedQFunction 178b11c1e72Sjeremylt @param ctx Context data to set 179b11c1e72Sjeremylt @param ctxsize Size of context data values 180b11c1e72Sjeremylt 181b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 182dfdf5a53Sjeremylt 183dfdf5a53Sjeremylt @ref Basic 184b11c1e72Sjeremylt **/ 185d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 186d7b241e6Sjeremylt qf->ctx = ctx; 187d7b241e6Sjeremylt qf->ctxsize = ctxsize; 188d7b241e6Sjeremylt return 0; 189d7b241e6Sjeremylt } 190d7b241e6Sjeremylt 191b11c1e72Sjeremylt /** 192b11c1e72Sjeremylt @brief Apply the action of a CeedQFunction 193b11c1e72Sjeremylt 194b11c1e72Sjeremylt @param qf CeedQFunction 195b11c1e72Sjeremylt @param Q Number of quadrature points 196b11c1e72Sjeremylt @param[in] u Array of input data arrays 197b11c1e72Sjeremylt @param[out] v Array of output data arrays 198b11c1e72Sjeremylt 199b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 200dfdf5a53Sjeremylt 201dfdf5a53Sjeremylt @ref Advanced 202b11c1e72Sjeremylt **/ 203d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 204d7b241e6Sjeremylt const CeedScalar *const *u, 205d7b241e6Sjeremylt CeedScalar *const *v) { 206d7b241e6Sjeremylt int ierr; 207d7b241e6Sjeremylt if (!qf->Apply) 208d7b241e6Sjeremylt return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 209d7b241e6Sjeremylt if (Q % qf->vlength) 210d7b241e6Sjeremylt return CeedError(qf->ceed, 2, 211d7b241e6Sjeremylt "Number of quadrature points %d must be a multiple of %d", 212d7b241e6Sjeremylt Q, qf->vlength); 213d7b241e6Sjeremylt ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 214d7b241e6Sjeremylt return 0; 215d7b241e6Sjeremylt } 216d7b241e6Sjeremylt 217b11c1e72Sjeremylt /** 218b11c1e72Sjeremylt @brief Destroy a CeedQFunction 219b11c1e72Sjeremylt 220b11c1e72Sjeremylt @param qf CeedQFunction to destroy 221b11c1e72Sjeremylt 222b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 223dfdf5a53Sjeremylt 224dfdf5a53Sjeremylt @ref Basic 225b11c1e72Sjeremylt **/ 226d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) { 227d7b241e6Sjeremylt int ierr; 228d7b241e6Sjeremylt 229d7b241e6Sjeremylt if (!*qf || --(*qf)->refcount > 0) return 0; 230d7b241e6Sjeremylt // Free field names 231d7b241e6Sjeremylt for (int i=0; i<(*qf)->numinputfields; i++) { 232d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 233d7b241e6Sjeremylt } 234d7b241e6Sjeremylt for (int i=0; i<(*qf)->numoutputfields; i++) { 235d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 236d7b241e6Sjeremylt } 237d7b241e6Sjeremylt if ((*qf)->Destroy) { 238d7b241e6Sjeremylt ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 239d7b241e6Sjeremylt } 240d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 241d7b241e6Sjeremylt ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 242d7b241e6Sjeremylt ierr = CeedFree(qf); CeedChk(ierr); 243d7b241e6Sjeremylt return 0; 244d7b241e6Sjeremylt } 245d7b241e6Sjeremylt 246d7b241e6Sjeremylt /// @} 247