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 59d7b241e6Sjeremylt if (!ceed->QFunctionCreate) 60d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 61d7b241e6Sjeremylt ierr = CeedCalloc(1,qf); CeedChk(ierr); 62d7b241e6Sjeremylt (*qf)->ceed = ceed; 63d7b241e6Sjeremylt ceed->refcount++; 64d7b241e6Sjeremylt (*qf)->refcount = 1; 65d7b241e6Sjeremylt (*qf)->vlength = vlength; 66d7b241e6Sjeremylt (*qf)->function = f; 67d7b241e6Sjeremylt ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 68d7b241e6Sjeremylt strcpy(focca_copy, focca); 69d7b241e6Sjeremylt (*qf)->focca = focca_copy; 70d7b241e6Sjeremylt ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 71d7b241e6Sjeremylt return 0; 72d7b241e6Sjeremylt } 73d7b241e6Sjeremylt 74b11c1e72Sjeremylt /** 75a0a97fcfSJed Brown @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output 76b11c1e72Sjeremylt 77b11c1e72Sjeremylt @param f CeedQFunctionField 78b11c1e72Sjeremylt @param fieldname Name of QFunction field 79b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 80b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 81b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 82b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 83b11c1e72Sjeremylt 84b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 85dfdf5a53Sjeremylt 86dfdf5a53Sjeremylt @ref Developer 87b11c1e72Sjeremylt **/ 88d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f, 89d7b241e6Sjeremylt const char *fieldname, CeedInt ncomp, 90d7b241e6Sjeremylt CeedEvalMode emode) { 91d7b241e6Sjeremylt size_t len = strlen(fieldname); 92d7b241e6Sjeremylt char *tmp; 93d7b241e6Sjeremylt int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 94d7b241e6Sjeremylt memcpy(tmp, fieldname, len+1); 95d7b241e6Sjeremylt f->fieldname = tmp; 96d7b241e6Sjeremylt f->ncomp = ncomp; 97d7b241e6Sjeremylt f->emode = emode; 98d7b241e6Sjeremylt return 0; 99d7b241e6Sjeremylt } 100d7b241e6Sjeremylt 101b11c1e72Sjeremylt /** 102a0a97fcfSJed Brown @brief Add a CeedQFunction input 103b11c1e72Sjeremylt 104b11c1e72Sjeremylt @param qf CeedQFunction 105b11c1e72Sjeremylt @param fieldname Name of QFunction field 106b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 107b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 108b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 109b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 110b11c1e72Sjeremylt 111b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 112dfdf5a53Sjeremylt 113dfdf5a53Sjeremylt @ref Basic 114b11c1e72Sjeremylt **/ 115d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 116d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 117d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 118d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 119d7b241e6Sjeremylt return 0; 120d7b241e6Sjeremylt } 121d7b241e6Sjeremylt 122b11c1e72Sjeremylt /** 123a0a97fcfSJed Brown @brief Add a CeedQFunction output 124b11c1e72Sjeremylt 125b11c1e72Sjeremylt @param qf CeedQFunction 126b11c1e72Sjeremylt @param fieldname Name of QFunction field 127b11c1e72Sjeremylt @param ncomp Number of components per quadrature node 128b11c1e72Sjeremylt @param emode \ref CEED_EVAL_NONE to use values directly, 129b11c1e72Sjeremylt \ref CEED_EVAL_INTERP to use interpolated values, 130b11c1e72Sjeremylt \ref CEED_EVAL_GRAD to use gradients. 131b11c1e72Sjeremylt 132b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 133dfdf5a53Sjeremylt 134dfdf5a53Sjeremylt @ref Basic 135b11c1e72Sjeremylt **/ 136d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 137d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 138d7b241e6Sjeremylt if (emode == CEED_EVAL_WEIGHT) 139d7b241e6Sjeremylt return CeedError(qf->ceed, 1, 140d7b241e6Sjeremylt "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 141d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 142d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 143d7b241e6Sjeremylt return 0; 144d7b241e6Sjeremylt } 145d7b241e6Sjeremylt 146dfdf5a53Sjeremylt /** 147dfdf5a53Sjeremylt @brief Get the number of inputs and outputs to a CeedQFunction 148dfdf5a53Sjeremylt 149dfdf5a53Sjeremylt @param qf CeedQFunction 150dfdf5a53Sjeremylt @param[out] numinput Number of input fields 151dfdf5a53Sjeremylt @param[out] numoutput Number of output fields 152dfdf5a53Sjeremylt 153dfdf5a53Sjeremylt @return An error code: 0 - success, otherwise - failure 154dfdf5a53Sjeremylt 155dfdf5a53Sjeremylt @ref Utility 156dfdf5a53Sjeremylt **/ 157dfdf5a53Sjeremylt 158d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 159d7b241e6Sjeremylt CeedInt *numoutput) { 160*1a4ead9bSjeremylt if (numinput) *numinput = qf->numinputfields; 161*1a4ead9bSjeremylt if (numoutput) *numoutput = qf->numoutputfields; 162d7b241e6Sjeremylt return 0; 163d7b241e6Sjeremylt } 164d7b241e6Sjeremylt 165d7b241e6Sjeremylt /** 166b11c1e72Sjeremylt @brief Set global context for a quadrature function 167b11c1e72Sjeremylt 168b11c1e72Sjeremylt @param qf CeedQFunction 169b11c1e72Sjeremylt @param ctx Context data to set 170b11c1e72Sjeremylt @param ctxsize Size of context data values 171b11c1e72Sjeremylt 172b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 173dfdf5a53Sjeremylt 174dfdf5a53Sjeremylt @ref Basic 175b11c1e72Sjeremylt **/ 176d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 177d7b241e6Sjeremylt qf->ctx = ctx; 178d7b241e6Sjeremylt qf->ctxsize = ctxsize; 179d7b241e6Sjeremylt return 0; 180d7b241e6Sjeremylt } 181d7b241e6Sjeremylt 182b11c1e72Sjeremylt /** 183b11c1e72Sjeremylt @brief Apply the action of a CeedQFunction 184b11c1e72Sjeremylt 185b11c1e72Sjeremylt @param qf CeedQFunction 186b11c1e72Sjeremylt @param Q Number of quadrature points 187b11c1e72Sjeremylt @param[in] u Array of input data arrays 188b11c1e72Sjeremylt @param[out] v Array of output data arrays 189b11c1e72Sjeremylt 190b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 191dfdf5a53Sjeremylt 192dfdf5a53Sjeremylt @ref Advanced 193b11c1e72Sjeremylt **/ 194d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 195d7b241e6Sjeremylt const CeedScalar *const *u, 196d7b241e6Sjeremylt CeedScalar *const *v) { 197d7b241e6Sjeremylt int ierr; 198d7b241e6Sjeremylt if (!qf->Apply) 199d7b241e6Sjeremylt return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 200d7b241e6Sjeremylt if (Q % qf->vlength) 201d7b241e6Sjeremylt return CeedError(qf->ceed, 2, 202d7b241e6Sjeremylt "Number of quadrature points %d must be a multiple of %d", 203d7b241e6Sjeremylt Q, qf->vlength); 204d7b241e6Sjeremylt ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 205d7b241e6Sjeremylt return 0; 206d7b241e6Sjeremylt } 207d7b241e6Sjeremylt 208b11c1e72Sjeremylt /** 209b11c1e72Sjeremylt @brief Destroy a CeedQFunction 210b11c1e72Sjeremylt 211b11c1e72Sjeremylt @param qf CeedQFunction to destroy 212b11c1e72Sjeremylt 213b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 214dfdf5a53Sjeremylt 215dfdf5a53Sjeremylt @ref Basic 216b11c1e72Sjeremylt **/ 217d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) { 218d7b241e6Sjeremylt int ierr; 219d7b241e6Sjeremylt 220d7b241e6Sjeremylt if (!*qf || --(*qf)->refcount > 0) return 0; 221d7b241e6Sjeremylt // Free field names 222d7b241e6Sjeremylt for (int i=0; i<(*qf)->numinputfields; i++) { 223d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 224d7b241e6Sjeremylt } 225d7b241e6Sjeremylt for (int i=0; i<(*qf)->numoutputfields; i++) { 226d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 227d7b241e6Sjeremylt } 228d7b241e6Sjeremylt if ((*qf)->Destroy) { 229d7b241e6Sjeremylt ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 230d7b241e6Sjeremylt } 231d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 232d7b241e6Sjeremylt ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 233d7b241e6Sjeremylt ierr = CeedFree(qf); CeedChk(ierr); 234d7b241e6Sjeremylt return 0; 235d7b241e6Sjeremylt } 236d7b241e6Sjeremylt 237d7b241e6Sjeremylt /// @} 238