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 /** 21 @file 22 Implementation of public CeedQFunction interfaces 23 24 @defgroup CeedQFunction CeedQFunction: independent operations at quadrature points 25 @{ 26 */ 27 28 /** 29 @brief Create a CeedQFunction for evaluating interior (volumetric) terms. 30 31 @param ceed Ceed library context 32 @param vlength Vector length. Caller must ensure that number of quadrature 33 points is a multiple of vlength. 34 @param f Function pointer to evaluate action at quadrature points. 35 See below. 36 @param focca OCCA identifier "file.c:function_name" for definition of `f` 37 @param qf constructed QFunction 38 @return 0 on 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 */ 52 int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength, 53 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*), 54 const char *focca, CeedQFunction *qf) { 55 int ierr; 56 char *focca_copy; 57 58 if (!ceed->QFunctionCreate) 59 return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 60 ierr = CeedCalloc(1,qf); CeedChk(ierr); 61 (*qf)->ceed = ceed; 62 ceed->refcount++; 63 (*qf)->refcount = 1; 64 (*qf)->vlength = vlength; 65 (*qf)->function = f; 66 ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 67 strcpy(focca_copy, focca); 68 (*qf)->focca = focca_copy; 69 ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 70 return 0; 71 } 72 73 static int CeedQFunctionFieldSet(struct CeedQFunctionField *f, 74 const char *fieldname, CeedInt ncomp, 75 CeedEvalMode emode) { 76 size_t len = strlen(fieldname); 77 char *tmp; 78 int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 79 memcpy(tmp, fieldname, len+1); 80 f->fieldname = tmp; 81 f->ncomp = ncomp; 82 f->emode = emode; 83 return 0; 84 } 85 86 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 87 CeedInt ncomp, CeedEvalMode emode) { 88 int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 89 fieldname, ncomp, emode); CeedChk(ierr); 90 return 0; 91 } 92 93 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 94 CeedInt ncomp, CeedEvalMode emode) { 95 if (emode == CEED_EVAL_WEIGHT) 96 return CeedError(qf->ceed, 1, 97 "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 98 int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 99 fieldname, ncomp, emode); CeedChk(ierr); 100 return 0; 101 } 102 103 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 104 CeedInt *numoutput) { 105 CeedInt nin = 0, nout = 0; 106 for (CeedInt i=0; i<qf->numinputfields; i++) { 107 CeedEvalMode emode = qf->inputfields[i].emode; 108 if (emode == CEED_EVAL_NONE) nin++; // Colocated field is input directly 109 if (emode & CEED_EVAL_INTERP) nin++; // Interpolate to quadrature points 110 if (emode & CEED_EVAL_GRAD) nin++; // Gradients at quadrature points 111 } 112 for (CeedInt i=0; i<qf->numoutputfields; i++) { 113 CeedEvalMode emode = qf->outputfields[i].emode; 114 if (emode == CEED_EVAL_NONE) nout++; 115 if (emode & CEED_EVAL_INTERP) nout++; 116 if (emode & CEED_EVAL_GRAD) nout++; 117 } 118 if (numinput) *numinput = nin; 119 if (numoutput) *numoutput = nout; 120 return 0; 121 } 122 123 /** 124 Set global context for a quadrature function 125 */ 126 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 127 qf->ctx = ctx; 128 qf->ctxsize = ctxsize; 129 return 0; 130 } 131 132 /** Apply the action of a CeedQFunction 133 */ 134 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 135 const CeedScalar *const *u, 136 CeedScalar *const *v) { 137 int ierr; 138 if (!qf->Apply) 139 return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 140 if (Q % qf->vlength) 141 return CeedError(qf->ceed, 2, 142 "Number of quadrature points %d must be a multiple of %d", 143 Q, qf->vlength); 144 ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 145 return 0; 146 } 147 148 /** Destroy a CeedQFunction 149 */ 150 int CeedQFunctionDestroy(CeedQFunction *qf) { 151 int ierr; 152 153 if (!*qf || --(*qf)->refcount > 0) return 0; 154 // Free field names 155 for (int i=0; i<(*qf)->numinputfields; i++) { 156 ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 157 } 158 for (int i=0; i<(*qf)->numoutputfields; i++) { 159 ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 160 } 161 if ((*qf)->Destroy) { 162 ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 163 } 164 ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 165 ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 166 ierr = CeedFree(qf); CeedChk(ierr); 167 return 0; 168 } 169 170 /// @} 171