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