1*d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2*d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3*d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4*d7b241e6Sjeremylt // 5*d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6*d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7*d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8*d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9*d7b241e6Sjeremylt // 10*d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11*d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12*d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13*d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14*d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15*d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16*d7b241e6Sjeremylt 17*d7b241e6Sjeremylt #include <ceed-impl.h> 18*d7b241e6Sjeremylt #include <string.h> 19*d7b241e6Sjeremylt 20*d7b241e6Sjeremylt /** 21*d7b241e6Sjeremylt @file 22*d7b241e6Sjeremylt Implementation of public CeedQFunction interfaces 23*d7b241e6Sjeremylt 24*d7b241e6Sjeremylt @defgroup CeedQFunction CeedQFunction: independent operations at quadrature points 25*d7b241e6Sjeremylt @{ 26*d7b241e6Sjeremylt */ 27*d7b241e6Sjeremylt 28*d7b241e6Sjeremylt /** 29*d7b241e6Sjeremylt @brief Create a CeedQFunction for evaluating interior (volumetric) terms. 30*d7b241e6Sjeremylt 31*d7b241e6Sjeremylt @param ceed Ceed library context 32*d7b241e6Sjeremylt @param vlength Vector length. Caller must ensure that number of quadrature 33*d7b241e6Sjeremylt points is a multiple of vlength. 34*d7b241e6Sjeremylt @param f Function pointer to evaluate action at quadrature points. 35*d7b241e6Sjeremylt See below. 36*d7b241e6Sjeremylt @param focca OCCA identifier "file.c:function_name" for definition of `f` 37*d7b241e6Sjeremylt @param qf constructed QFunction 38*d7b241e6Sjeremylt @return 0 on success, otherwise failure 39*d7b241e6Sjeremylt 40*d7b241e6Sjeremylt The arguments of the call-back 'function' are: 41*d7b241e6Sjeremylt 42*d7b241e6Sjeremylt 1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in 43*d7b241e6Sjeremylt the CeedQFunction, set by calling CeedQFunctionSetContext 44*d7b241e6Sjeremylt 45*d7b241e6Sjeremylt 2. [CeedInt nq][in] - number of quadrature points to process 46*d7b241e6Sjeremylt 47*d7b241e6Sjeremylt 3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user 48*d7b241e6Sjeremylt 49*d7b241e6Sjeremylt 4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user 50*d7b241e6Sjeremylt 51*d7b241e6Sjeremylt */ 52*d7b241e6Sjeremylt int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength, 53*d7b241e6Sjeremylt int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*), 54*d7b241e6Sjeremylt const char *focca, CeedQFunction *qf) { 55*d7b241e6Sjeremylt int ierr; 56*d7b241e6Sjeremylt char *focca_copy; 57*d7b241e6Sjeremylt 58*d7b241e6Sjeremylt if (!ceed->QFunctionCreate) 59*d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 60*d7b241e6Sjeremylt ierr = CeedCalloc(1,qf); CeedChk(ierr); 61*d7b241e6Sjeremylt (*qf)->ceed = ceed; 62*d7b241e6Sjeremylt ceed->refcount++; 63*d7b241e6Sjeremylt (*qf)->refcount = 1; 64*d7b241e6Sjeremylt (*qf)->vlength = vlength; 65*d7b241e6Sjeremylt (*qf)->function = f; 66*d7b241e6Sjeremylt ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 67*d7b241e6Sjeremylt strcpy(focca_copy, focca); 68*d7b241e6Sjeremylt (*qf)->focca = focca_copy; 69*d7b241e6Sjeremylt ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 70*d7b241e6Sjeremylt return 0; 71*d7b241e6Sjeremylt } 72*d7b241e6Sjeremylt 73*d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f, 74*d7b241e6Sjeremylt const char *fieldname, CeedInt ncomp, 75*d7b241e6Sjeremylt CeedEvalMode emode) { 76*d7b241e6Sjeremylt size_t len = strlen(fieldname); 77*d7b241e6Sjeremylt char *tmp; 78*d7b241e6Sjeremylt int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 79*d7b241e6Sjeremylt memcpy(tmp, fieldname, len+1); 80*d7b241e6Sjeremylt f->fieldname = tmp; 81*d7b241e6Sjeremylt f->ncomp = ncomp; 82*d7b241e6Sjeremylt f->emode = emode; 83*d7b241e6Sjeremylt return 0; 84*d7b241e6Sjeremylt } 85*d7b241e6Sjeremylt 86*d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 87*d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 88*d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 89*d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 90*d7b241e6Sjeremylt return 0; 91*d7b241e6Sjeremylt } 92*d7b241e6Sjeremylt 93*d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 94*d7b241e6Sjeremylt CeedInt ncomp, CeedEvalMode emode) { 95*d7b241e6Sjeremylt if (emode == CEED_EVAL_WEIGHT) 96*d7b241e6Sjeremylt return CeedError(qf->ceed, 1, 97*d7b241e6Sjeremylt "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 98*d7b241e6Sjeremylt int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 99*d7b241e6Sjeremylt fieldname, ncomp, emode); CeedChk(ierr); 100*d7b241e6Sjeremylt return 0; 101*d7b241e6Sjeremylt } 102*d7b241e6Sjeremylt 103*d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 104*d7b241e6Sjeremylt CeedInt *numoutput) { 105*d7b241e6Sjeremylt CeedInt nin = 0, nout = 0; 106*d7b241e6Sjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 107*d7b241e6Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 108*d7b241e6Sjeremylt if (emode == CEED_EVAL_NONE) nin++; // Colocated field is input directly 109*d7b241e6Sjeremylt if (emode & CEED_EVAL_INTERP) nin++; // Interpolate to quadrature points 110*d7b241e6Sjeremylt if (emode & CEED_EVAL_GRAD) nin++; // Gradients at quadrature points 111*d7b241e6Sjeremylt } 112*d7b241e6Sjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 113*d7b241e6Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 114*d7b241e6Sjeremylt if (emode == CEED_EVAL_NONE) nout++; 115*d7b241e6Sjeremylt if (emode & CEED_EVAL_INTERP) nout++; 116*d7b241e6Sjeremylt if (emode & CEED_EVAL_GRAD) nout++; 117*d7b241e6Sjeremylt } 118*d7b241e6Sjeremylt if (numinput) *numinput = nin; 119*d7b241e6Sjeremylt if (numoutput) *numoutput = nout; 120*d7b241e6Sjeremylt return 0; 121*d7b241e6Sjeremylt } 122*d7b241e6Sjeremylt 123*d7b241e6Sjeremylt /** 124*d7b241e6Sjeremylt Set global context for a quadrature function 125*d7b241e6Sjeremylt */ 126*d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 127*d7b241e6Sjeremylt qf->ctx = ctx; 128*d7b241e6Sjeremylt qf->ctxsize = ctxsize; 129*d7b241e6Sjeremylt return 0; 130*d7b241e6Sjeremylt } 131*d7b241e6Sjeremylt 132*d7b241e6Sjeremylt /** Apply the action of a CeedQFunction 133*d7b241e6Sjeremylt */ 134*d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 135*d7b241e6Sjeremylt const CeedScalar *const *u, 136*d7b241e6Sjeremylt CeedScalar *const *v) { 137*d7b241e6Sjeremylt int ierr; 138*d7b241e6Sjeremylt if (!qf->Apply) 139*d7b241e6Sjeremylt return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 140*d7b241e6Sjeremylt if (Q % qf->vlength) 141*d7b241e6Sjeremylt return CeedError(qf->ceed, 2, 142*d7b241e6Sjeremylt "Number of quadrature points %d must be a multiple of %d", 143*d7b241e6Sjeremylt Q, qf->vlength); 144*d7b241e6Sjeremylt ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 145*d7b241e6Sjeremylt return 0; 146*d7b241e6Sjeremylt } 147*d7b241e6Sjeremylt 148*d7b241e6Sjeremylt /** Destroy a CeedQFunction 149*d7b241e6Sjeremylt */ 150*d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) { 151*d7b241e6Sjeremylt int ierr; 152*d7b241e6Sjeremylt 153*d7b241e6Sjeremylt if (!*qf || --(*qf)->refcount > 0) return 0; 154*d7b241e6Sjeremylt // Free field names 155*d7b241e6Sjeremylt for (int i=0; i<(*qf)->numinputfields; i++) { 156*d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 157*d7b241e6Sjeremylt } 158*d7b241e6Sjeremylt for (int i=0; i<(*qf)->numoutputfields; i++) { 159*d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 160*d7b241e6Sjeremylt } 161*d7b241e6Sjeremylt if ((*qf)->Destroy) { 162*d7b241e6Sjeremylt ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 163*d7b241e6Sjeremylt } 164*d7b241e6Sjeremylt ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 165*d7b241e6Sjeremylt ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 166*d7b241e6Sjeremylt ierr = CeedFree(qf); CeedChk(ierr); 167*d7b241e6Sjeremylt return 0; 168*d7b241e6Sjeremylt } 169*d7b241e6Sjeremylt 170*d7b241e6Sjeremylt /// @} 171