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 /** 75*a0a97fcfSJed 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 /** 102*a0a97fcfSJed 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 /** 123*a0a97fcfSJed 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) { 160d7b241e6Sjeremylt CeedInt nin = 0, nout = 0; 161d7b241e6Sjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 162d7b241e6Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 163d7b241e6Sjeremylt if (emode == CEED_EVAL_NONE) nin++; // Colocated field is input directly 164d7b241e6Sjeremylt if (emode & CEED_EVAL_INTERP) nin++; // Interpolate to quadrature points 165d7b241e6Sjeremylt if (emode & CEED_EVAL_GRAD) nin++; // Gradients at quadrature points 166d7b241e6Sjeremylt } 167d7b241e6Sjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 168d7b241e6Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 169d7b241e6Sjeremylt if (emode == CEED_EVAL_NONE) nout++; 170d7b241e6Sjeremylt if (emode & CEED_EVAL_INTERP) nout++; 171d7b241e6Sjeremylt if (emode & CEED_EVAL_GRAD) nout++; 172d7b241e6Sjeremylt } 173d7b241e6Sjeremylt if (numinput) *numinput = nin; 174d7b241e6Sjeremylt if (numoutput) *numoutput = nout; 175d7b241e6Sjeremylt return 0; 176d7b241e6Sjeremylt } 177d7b241e6Sjeremylt 178d7b241e6Sjeremylt /** 179b11c1e72Sjeremylt @brief Set global context for a quadrature function 180b11c1e72Sjeremylt 181b11c1e72Sjeremylt @param qf CeedQFunction 182b11c1e72Sjeremylt @param ctx Context data to set 183b11c1e72Sjeremylt @param ctxsize Size of context data values 184b11c1e72Sjeremylt 185b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 186dfdf5a53Sjeremylt 187dfdf5a53Sjeremylt @ref Basic 188b11c1e72Sjeremylt **/ 189d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 190d7b241e6Sjeremylt qf->ctx = ctx; 191d7b241e6Sjeremylt qf->ctxsize = ctxsize; 192d7b241e6Sjeremylt return 0; 193d7b241e6Sjeremylt } 194d7b241e6Sjeremylt 195b11c1e72Sjeremylt /** 196b11c1e72Sjeremylt @brief Apply the action of a CeedQFunction 197b11c1e72Sjeremylt 198b11c1e72Sjeremylt @param qf CeedQFunction 199b11c1e72Sjeremylt @param Q Number of quadrature points 200b11c1e72Sjeremylt @param[in] u Array of input data arrays 201b11c1e72Sjeremylt @param[out] v Array of output data arrays 202b11c1e72Sjeremylt 203b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 204dfdf5a53Sjeremylt 205dfdf5a53Sjeremylt @ref Advanced 206b11c1e72Sjeremylt **/ 207d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 208d7b241e6Sjeremylt const CeedScalar *const *u, 209d7b241e6Sjeremylt CeedScalar *const *v) { 210d7b241e6Sjeremylt int ierr; 211d7b241e6Sjeremylt if (!qf->Apply) 212d7b241e6Sjeremylt return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 213d7b241e6Sjeremylt if (Q % qf->vlength) 214d7b241e6Sjeremylt return CeedError(qf->ceed, 2, 215d7b241e6Sjeremylt "Number of quadrature points %d must be a multiple of %d", 216d7b241e6Sjeremylt Q, qf->vlength); 217d7b241e6Sjeremylt ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 218d7b241e6Sjeremylt return 0; 219d7b241e6Sjeremylt } 220d7b241e6Sjeremylt 221b11c1e72Sjeremylt /** 222b11c1e72Sjeremylt @brief Destroy a CeedQFunction 223b11c1e72Sjeremylt 224b11c1e72Sjeremylt @param qf CeedQFunction to destroy 225b11c1e72Sjeremylt 226b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 227dfdf5a53Sjeremylt 228dfdf5a53Sjeremylt @ref Basic 229b11c1e72Sjeremylt **/ 230d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) { 231d7b241e6Sjeremylt int ierr; 232d7b241e6Sjeremylt 233d7b241e6Sjeremylt if (!*qf || --(*qf)->refcount > 0) return 0; 234d7b241e6Sjeremylt // Free field names 235d7b241e6Sjeremylt for (int i=0; i<(*qf)->numinputfields; i++) { 236d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 237d7b241e6Sjeremylt } 238d7b241e6Sjeremylt for (int i=0; i<(*qf)->numoutputfields; i++) { 239d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 240d7b241e6Sjeremylt } 241d7b241e6Sjeremylt if ((*qf)->Destroy) { 242d7b241e6Sjeremylt ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 243d7b241e6Sjeremylt } 244d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 245d7b241e6Sjeremylt ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 246d7b241e6Sjeremylt ierr = CeedFree(qf); CeedChk(ierr); 247d7b241e6Sjeremylt return 0; 248d7b241e6Sjeremylt } 249d7b241e6Sjeremylt 250d7b241e6Sjeremylt /// @} 251