1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3 // reserved. See files LICENSE and NOTICE for details. 4 // 5 // This file is part of CEED, a collection of benchmarks, miniapps, software 6 // libraries and APIs for efficient high-order finite element and spectral 7 // element discretizations for exascale applications. For more information and 8 // source code availability see http://github.com/ceed. 9 // 10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11 // a collaborative effort of two U.S. Department of Energy organizations (Office 12 // of Science and the National Nuclear Security Administration) responsible for 13 // the planning and preparation of a capable exascale ecosystem, including 14 // software, applications, hardware, advanced system engineering and early 15 // testbed platforms, in support of the nation's exascale computing imperative. 16 17 #include <ceed-impl.h> 18 #include <string.h> 19 20 /// @file 21 /// Implementation of public CeedQFunction interfaces 22 /// 23 /// @addtogroup CeedQFunction 24 /// @{ 25 26 /** 27 @brief Create a CeedQFunction for evaluating interior (volumetric) terms. 28 29 @param ceed A Ceed object where the CeedQFunction will be created 30 @param vlength Vector length. Caller must ensure that number of quadrature 31 points is a multiple of vlength. 32 @param f Function pointer to evaluate action at quadrature points. 33 See below. 34 @param focca OCCA identifier "file.c:function_name" for definition of `f` 35 @param[out] qf Address of the variable where the newly created 36 CeedQFunction will be stored 37 38 @return An error code: 0 - success, otherwise - failure 39 40 The arguments of the call-back 'function' are: 41 42 1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in 43 the CeedQFunction, set by calling CeedQFunctionSetContext 44 45 2. [CeedInt nq][in] - number of quadrature points to process 46 47 3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user 48 49 4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user 50 51 @ref Basic 52 **/ 53 int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength, 54 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*), 55 const char *focca, CeedQFunction *qf) { 56 int ierr; 57 char *focca_copy; 58 59 if (!ceed->QFunctionCreate) { 60 Ceed delegate; 61 ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 62 63 if (!delegate) 64 return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 65 66 ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr); 67 return 0; 68 } 69 70 ierr = CeedCalloc(1,qf); CeedChk(ierr); 71 (*qf)->ceed = ceed; 72 ceed->refcount++; 73 (*qf)->refcount = 1; 74 (*qf)->vlength = vlength; 75 (*qf)->function = f; 76 ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 77 strcpy(focca_copy, focca); 78 (*qf)->focca = focca_copy; 79 ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 80 return 0; 81 } 82 83 /** 84 @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output 85 86 @param f CeedQFunctionField 87 @param fieldname Name of QFunction field 88 @param ncomp Number of components per quadrature node 89 @param emode \ref CEED_EVAL_NONE to use values directly, 90 \ref CEED_EVAL_INTERP to use interpolated values, 91 \ref CEED_EVAL_GRAD to use gradients. 92 93 @return An error code: 0 - success, otherwise - failure 94 95 @ref Developer 96 **/ 97 static int CeedQFunctionFieldSet(struct CeedQFunctionField *f, 98 const char *fieldname, CeedInt ncomp, 99 CeedEvalMode emode) { 100 size_t len = strlen(fieldname); 101 char *tmp; 102 int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 103 memcpy(tmp, fieldname, len+1); 104 f->fieldname = tmp; 105 f->ncomp = ncomp; 106 f->emode = emode; 107 return 0; 108 } 109 110 /** 111 @brief Add a CeedQFunction input 112 113 @param qf CeedQFunction 114 @param fieldname Name of QFunction field 115 @param ncomp Number of components per quadrature node 116 @param emode \ref CEED_EVAL_NONE to use values directly, 117 \ref CEED_EVAL_INTERP to use interpolated values, 118 \ref CEED_EVAL_GRAD to use gradients. 119 120 @return An error code: 0 - success, otherwise - failure 121 122 @ref Basic 123 **/ 124 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 125 CeedInt ncomp, CeedEvalMode emode) { 126 int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 127 fieldname, ncomp, emode); CeedChk(ierr); 128 return 0; 129 } 130 131 /** 132 @brief Add a CeedQFunction output 133 134 @param qf CeedQFunction 135 @param fieldname Name of QFunction field 136 @param ncomp Number of components per quadrature node 137 @param emode \ref CEED_EVAL_NONE to use values directly, 138 \ref CEED_EVAL_INTERP to use interpolated values, 139 \ref CEED_EVAL_GRAD to use gradients. 140 141 @return An error code: 0 - success, otherwise - failure 142 143 @ref Basic 144 **/ 145 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 146 CeedInt ncomp, CeedEvalMode emode) { 147 if (emode == CEED_EVAL_WEIGHT) 148 return CeedError(qf->ceed, 1, 149 "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 150 int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 151 fieldname, ncomp, emode); CeedChk(ierr); 152 return 0; 153 } 154 155 /** 156 @brief Get the number of inputs and outputs to a CeedQFunction 157 158 @param qf CeedQFunction 159 @param[out] numinput Number of input fields 160 @param[out] numoutput Number of output fields 161 162 @return An error code: 0 - success, otherwise - failure 163 164 @ref Utility 165 **/ 166 167 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 168 CeedInt *numoutput) { 169 if (numinput) *numinput = qf->numinputfields; 170 if (numoutput) *numoutput = qf->numoutputfields; 171 return 0; 172 } 173 174 /** 175 @brief Set global context for a quadrature function 176 177 @param qf CeedQFunction 178 @param ctx Context data to set 179 @param ctxsize Size of context data values 180 181 @return An error code: 0 - success, otherwise - failure 182 183 @ref Basic 184 **/ 185 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 186 qf->ctx = ctx; 187 qf->ctxsize = ctxsize; 188 return 0; 189 } 190 191 /** 192 @brief Apply the action of a CeedQFunction 193 194 @param qf CeedQFunction 195 @param Q Number of quadrature points 196 @param[in] u Array of input data arrays 197 @param[out] v Array of output data arrays 198 199 @return An error code: 0 - success, otherwise - failure 200 201 @ref Advanced 202 **/ 203 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 204 const CeedScalar *const *u, 205 CeedScalar *const *v) { 206 int ierr; 207 if (!qf->Apply) 208 return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 209 if (Q % qf->vlength) 210 return CeedError(qf->ceed, 2, 211 "Number of quadrature points %d must be a multiple of %d", 212 Q, qf->vlength); 213 ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 214 return 0; 215 } 216 217 /** 218 @brief Destroy a CeedQFunction 219 220 @param qf CeedQFunction to destroy 221 222 @return An error code: 0 - success, otherwise - failure 223 224 @ref Basic 225 **/ 226 int CeedQFunctionDestroy(CeedQFunction *qf) { 227 int ierr; 228 229 if (!*qf || --(*qf)->refcount > 0) return 0; 230 // Free field names 231 for (int i=0; i<(*qf)->numinputfields; i++) { 232 ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 233 } 234 for (int i=0; i<(*qf)->numoutputfields; i++) { 235 ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 236 } 237 if ((*qf)->Destroy) { 238 ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 239 } 240 ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 241 ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 242 ierr = CeedFree(qf); CeedChk(ierr); 243 return 0; 244 } 245 246 /// @} 247