121617c04Sjeremylt // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 221617c04Sjeremylt // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 321617c04Sjeremylt // All Rights reserved. See files LICENSE and NOTICE for details. 421617c04Sjeremylt // 521617c04Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 621617c04Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 721617c04Sjeremylt // element discretizations for exascale applications. For more information and 821617c04Sjeremylt // source code availability see http://github.com/ceed. 921617c04Sjeremylt // 1021617c04Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 1121617c04Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 1221617c04Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 1321617c04Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 1421617c04Sjeremylt // software, applications, hardware, advanced system engineering and early 1521617c04Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 1621617c04Sjeremylt 1721617c04Sjeremylt #include <string.h> 1821617c04Sjeremylt #include "ceed-ref.h" 1921617c04Sjeremylt 2021617c04Sjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 2121617c04Sjeremylt int ierr; 224ce2993fSjeremylt CeedOperator_Ref *impl; 234ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 2421617c04Sjeremylt 25885ac19cSjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 26885ac19cSjeremylt ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 27885ac19cSjeremylt } 28885ac19cSjeremylt ierr = CeedFree(&impl->evecs); CeedChk(ierr); 29885ac19cSjeremylt ierr = CeedFree(&impl->edata); CeedChk(ierr); 30885ac19cSjeremylt 31885ac19cSjeremylt for (CeedInt i=0; i<impl->numqin+impl->numqout; i++) { 32885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc[i]); CeedChk(ierr); 33885ac19cSjeremylt } 34885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc); CeedChk(ierr); 35885ac19cSjeremylt ierr = CeedFree(&impl->qdata); CeedChk(ierr); 36885ac19cSjeremylt 37885ac19cSjeremylt ierr = CeedFree(&impl->indata); CeedChk(ierr); 38885ac19cSjeremylt ierr = CeedFree(&impl->outdata); CeedChk(ierr); 39885ac19cSjeremylt 40*fe2413ffSjeremylt ierr = CeedFree(&impl); CeedChk(ierr); 4121617c04Sjeremylt return 0; 4221617c04Sjeremylt } 4321617c04Sjeremylt 44885ac19cSjeremylt /* 45885ac19cSjeremylt Setup infields or outfields 46885ac19cSjeremylt */ 47*fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 48*fe2413ffSjeremylt bool inOrOut, 49885ac19cSjeremylt CeedVector *evecs, CeedScalar **qdata, 50885ac19cSjeremylt CeedScalar **qdata_alloc, CeedScalar **indata, 51135a076eSjeremylt CeedInt starti, CeedInt startq, 52135a076eSjeremylt CeedInt numfields, CeedInt Q) { 53135a076eSjeremylt CeedInt dim, ierr, iq=startq, ncomp; 54d1bcdac9Sjeremylt CeedBasis basis; 55d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 56*fe2413ffSjeremylt CeedOperatorField *ofields; 57*fe2413ffSjeremylt CeedQFunctionField *qfields; 58*fe2413ffSjeremylt if (inOrOut) { 59*fe2413ffSjeremylt ierr = CeedOperatorGetFields(op, NULL, &ofields); 60*fe2413ffSjeremylt CeedChk(ierr); 61*fe2413ffSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qfields); 62*fe2413ffSjeremylt CeedChk(ierr); 63*fe2413ffSjeremylt } else { 64*fe2413ffSjeremylt ierr = CeedOperatorGetFields(op, &ofields, NULL); 65*fe2413ffSjeremylt CeedChk(ierr); 66*fe2413ffSjeremylt ierr = CeedQFunctionGetFields(qf, &qfields, NULL); 67*fe2413ffSjeremylt CeedChk(ierr); 68*fe2413ffSjeremylt } 6921617c04Sjeremylt 70885ac19cSjeremylt // Loop over fields 71885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 72d1bcdac9Sjeremylt CeedEvalMode emode; 73d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfields[i], &emode); CeedChk(ierr); 74135a076eSjeremylt 75135a076eSjeremylt if (emode != CEED_EVAL_WEIGHT) { 76d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(ofields[i], &Erestrict); 77d1bcdac9Sjeremylt CeedChk(ierr); 78d1bcdac9Sjeremylt ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 794b8bea3bSJed Brown &evecs[i+starti]); 80135a076eSjeremylt CeedChk(ierr); 81135a076eSjeremylt } 82135a076eSjeremylt 83885ac19cSjeremylt switch(emode) { 84885ac19cSjeremylt case CEED_EVAL_NONE: 85885ac19cSjeremylt break; // No action 86885ac19cSjeremylt case CEED_EVAL_INTERP: 87d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfields[i], &ncomp); 88d1bcdac9Sjeremylt CeedChk(ierr); 89885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp, &qdata_alloc[iq]); CeedChk(ierr); 90885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 91885ac19cSjeremylt iq++; 92885ac19cSjeremylt break; 93885ac19cSjeremylt case CEED_EVAL_GRAD: 94d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(ofields[i], &basis); CeedChk(ierr); 95d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfields[i], &ncomp); 96d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 97885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp*dim, &qdata_alloc[iq]); CeedChk(ierr); 98885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 99885ac19cSjeremylt iq++; 100885ac19cSjeremylt break; 101885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 102d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(ofields[i], &basis); CeedChk(ierr); 103885ac19cSjeremylt ierr = CeedMalloc(Q, &qdata_alloc[iq]); CeedChk(ierr); 104d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 105885ac19cSjeremylt NULL, qdata_alloc[iq]); CeedChk(ierr); 106885ac19cSjeremylt qdata[i] = qdata_alloc[iq]; 107885ac19cSjeremylt indata[i] = qdata[i]; 108885ac19cSjeremylt iq++; 109885ac19cSjeremylt break; 110885ac19cSjeremylt case CEED_EVAL_DIV: 111885ac19cSjeremylt break; // Not implimented 112885ac19cSjeremylt case CEED_EVAL_CURL: 113885ac19cSjeremylt break; // Not implimented 11421617c04Sjeremylt } 115885ac19cSjeremylt } 11621617c04Sjeremylt return 0; 11721617c04Sjeremylt } 11821617c04Sjeremylt 119885ac19cSjeremylt /* 120885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 121885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 122885ac19cSjeremylt */ 123885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 12421617c04Sjeremylt int ierr; 1254ce2993fSjeremylt bool setupdone; 1264ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1274ce2993fSjeremylt if (setupdone) return 0; 1284ce2993fSjeremylt CeedOperator_Ref *impl; 1294ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1304ce2993fSjeremylt CeedQFunction qf; 1314ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1324ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1334ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 134a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 135a8de75f0Sjeremylt CeedChk(ierr); 136d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 137d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 138d1bcdac9Sjeremylt CeedChk(ierr); 139d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 140d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 141d1bcdac9Sjeremylt CeedChk(ierr); 142d1bcdac9Sjeremylt CeedEvalMode emode; 1434ce2993fSjeremylt 1444ce2993fSjeremylt // Count infield and outfield array sizes and evectors 1451a4ead9bSjeremylt impl->numein = numinputfields; 1461a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 147d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 148d1bcdac9Sjeremylt CeedChk(ierr); 1498d94b059Sjeremylt impl->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + 1508d94b059Sjeremylt !!(emode & CEED_EVAL_WEIGHT); 15121617c04Sjeremylt } 1521a4ead9bSjeremylt impl->numeout = numoutputfields; 1531a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 154d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 155d1bcdac9Sjeremylt CeedChk(ierr); 156a2b73c81Sjeremylt impl->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 157885ac19cSjeremylt } 158885ac19cSjeremylt 159885ac19cSjeremylt // Allocate 160a2b73c81Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->evecs); CeedChk(ierr); 161a2b73c81Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->edata); 162885ac19cSjeremylt CeedChk(ierr); 163885ac19cSjeremylt 164a2b73c81Sjeremylt ierr = CeedCalloc(impl->numqin + impl->numqout, &impl->qdata_alloc); 165885ac19cSjeremylt CeedChk(ierr); 1661a4ead9bSjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->qdata); 167885ac19cSjeremylt CeedChk(ierr); 168885ac19cSjeremylt 169a2b73c81Sjeremylt ierr = CeedCalloc(16, &impl->indata); CeedChk(ierr); 170a2b73c81Sjeremylt ierr = CeedCalloc(16, &impl->outdata); CeedChk(ierr); 171885ac19cSjeremylt 172885ac19cSjeremylt // Set up infield and outfield pointer arrays 173885ac19cSjeremylt // Infields 174*fe2413ffSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, 175a2b73c81Sjeremylt impl->evecs, impl->qdata, impl->qdata_alloc, 176a2b73c81Sjeremylt impl->indata, 0, 0, 1771a4ead9bSjeremylt numinputfields, Q); CeedChk(ierr); 178885ac19cSjeremylt 179885ac19cSjeremylt // Outfields 180*fe2413ffSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, 181a2b73c81Sjeremylt impl->evecs, impl->qdata, impl->qdata_alloc, 1821a4ead9bSjeremylt impl->indata, numinputfields, 183d1bcdac9Sjeremylt impl->numqin, numoutputfields, Q); 184d1bcdac9Sjeremylt CeedChk(ierr); 185885ac19cSjeremylt 1868d94b059Sjeremylt // Input Qvecs 1871a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 188d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 189d1bcdac9Sjeremylt CeedChk(ierr); 1908d94b059Sjeremylt if ((emode != CEED_EVAL_NONE) && (emode != CEED_EVAL_WEIGHT)) 1918d94b059Sjeremylt impl->indata[i] = impl->qdata[i]; 1928d94b059Sjeremylt } 1937ca8db16Sjeremylt // Output Qvecs 1941a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 195d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 196d1bcdac9Sjeremylt CeedChk(ierr); 1978d94b059Sjeremylt if (emode != CEED_EVAL_NONE) 1981a4ead9bSjeremylt impl->outdata[i] = impl->qdata[i + numinputfields]; 1997ca8db16Sjeremylt } 2007ca8db16Sjeremylt 2014ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 202885ac19cSjeremylt 203885ac19cSjeremylt return 0; 204885ac19cSjeremylt } 205885ac19cSjeremylt 206885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 207885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 208885ac19cSjeremylt int ierr; 2094ce2993fSjeremylt CeedOperator_Ref *impl; 2104ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 2114ce2993fSjeremylt CeedQFunction qf; 2124ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 213d1bcdac9Sjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 2144ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 2154ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 2164ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 2174ce2993fSjeremylt CeedChk(ierr); 2184dccadb6Sjeremylt CeedTransposeMode lmode; 219d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 220d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 221d1bcdac9Sjeremylt CeedChk(ierr); 222d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 223d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 224d1bcdac9Sjeremylt CeedChk(ierr); 225d1bcdac9Sjeremylt CeedEvalMode emode; 226d1bcdac9Sjeremylt CeedVector vec; 227d1bcdac9Sjeremylt CeedBasis basis; 228d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 229885ac19cSjeremylt 230885ac19cSjeremylt // Setup 231885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 232885ac19cSjeremylt 233885ac19cSjeremylt // Input Evecs and Restriction 2341a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 235d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 236d1bcdac9Sjeremylt CeedChk(ierr); 237135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 238668048e2SJed Brown } else { 239d1bcdac9Sjeremylt // Get input vector 240d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 241d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 242d1bcdac9Sjeremylt vec = invec; 243668048e2SJed Brown // Restrict 244d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 245d1bcdac9Sjeremylt CeedChk(ierr); 2464dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 247d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 248d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 249668048e2SJed Brown request); CeedChk(ierr); 250668048e2SJed Brown // Get evec 251a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 252d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 253d1bcdac9Sjeremylt CeedChk(ierr); 254885ac19cSjeremylt } 255885ac19cSjeremylt } 256885ac19cSjeremylt 257885ac19cSjeremylt // Output Evecs 2581a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 259a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2601a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 261885ac19cSjeremylt } 262885ac19cSjeremylt 263885ac19cSjeremylt // Loop through elements 2644ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 265885ac19cSjeremylt // Input basis apply if needed 2661a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 267135a076eSjeremylt // Get elemsize, emode, ncomp 268d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 269d1bcdac9Sjeremylt CeedChk(ierr); 270d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 271d1bcdac9Sjeremylt CeedChk(ierr); 272d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 273d1bcdac9Sjeremylt CeedChk(ierr); 274d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 275d1bcdac9Sjeremylt CeedChk(ierr); 276885ac19cSjeremylt // Basis action 277885ac19cSjeremylt switch(emode) { 278885ac19cSjeremylt case CEED_EVAL_NONE: 279a2b73c81Sjeremylt impl->indata[i] = &impl->edata[i][e*Q*ncomp]; 280885ac19cSjeremylt break; 281885ac19cSjeremylt case CEED_EVAL_INTERP: 282d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 283d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 284d1bcdac9Sjeremylt CEED_EVAL_INTERP, &impl->edata[i][e*elemsize*ncomp], 285d1bcdac9Sjeremylt impl->qdata[i]); CeedChk(ierr); 286885ac19cSjeremylt break; 287885ac19cSjeremylt case CEED_EVAL_GRAD: 288d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 289d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 290d1bcdac9Sjeremylt CEED_EVAL_GRAD, &impl->edata[i][e*elemsize*ncomp], 291d1bcdac9Sjeremylt impl->qdata[i]); CeedChk(ierr); 292885ac19cSjeremylt break; 293885ac19cSjeremylt case CEED_EVAL_WEIGHT: 294885ac19cSjeremylt break; // No action 295885ac19cSjeremylt case CEED_EVAL_DIV: 296885ac19cSjeremylt break; // Not implimented 297885ac19cSjeremylt case CEED_EVAL_CURL: 298885ac19cSjeremylt break; // Not implimented 299885ac19cSjeremylt } 300885ac19cSjeremylt } 301885ac19cSjeremylt // Output pointers 3021a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 303d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 304d1bcdac9Sjeremylt CeedChk(ierr); 305885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 306d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 307d1bcdac9Sjeremylt CeedChk(ierr); 3081a4ead9bSjeremylt impl->outdata[i] = &impl->edata[i + numinputfields][e*Q*ncomp]; 309885ac19cSjeremylt } 310885ac19cSjeremylt } 311885ac19cSjeremylt // Q function 3124ce2993fSjeremylt ierr = CeedQFunctionApply(qf, Q, (const CeedScalar * const*) impl->indata, 313a2b73c81Sjeremylt impl->outdata); CeedChk(ierr); 314885ac19cSjeremylt 315885ac19cSjeremylt // Output basis apply if needed 3161a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 317135a076eSjeremylt // Get elemsize, emode, ncomp 318d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 319d1bcdac9Sjeremylt CeedChk(ierr); 320d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 321d1bcdac9Sjeremylt CeedChk(ierr); 322d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 323d1bcdac9Sjeremylt CeedChk(ierr); 324d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 325d1bcdac9Sjeremylt CeedChk(ierr); 326885ac19cSjeremylt // Basis action 327885ac19cSjeremylt switch(emode) { 328885ac19cSjeremylt case CEED_EVAL_NONE: 329885ac19cSjeremylt break; // No action 330885ac19cSjeremylt case CEED_EVAL_INTERP: 331d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 332d1bcdac9Sjeremylt CeedChk(ierr); 333d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 334a2b73c81Sjeremylt CEED_EVAL_INTERP, impl->outdata[i], 3351a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 3368d94b059Sjeremylt CeedChk(ierr); 337885ac19cSjeremylt break; 338885ac19cSjeremylt case CEED_EVAL_GRAD: 339d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 340d1bcdac9Sjeremylt CeedChk(ierr); 341d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 342d1bcdac9Sjeremylt CEED_EVAL_GRAD, impl->outdata[i], 343d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 344885ac19cSjeremylt CeedChk(ierr); 345885ac19cSjeremylt break; 3464ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 3474ce2993fSjeremylt Ceed ceed; 3484ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3494ce2993fSjeremylt return CeedError(ceed, 1, 3508d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 351885ac19cSjeremylt break; // Should not occur 3524ce2993fSjeremylt } 353885ac19cSjeremylt case CEED_EVAL_DIV: 354885ac19cSjeremylt break; // Not implimented 355885ac19cSjeremylt case CEED_EVAL_CURL: 356885ac19cSjeremylt break; // Not implimented 357885ac19cSjeremylt } 358885ac19cSjeremylt } 359885ac19cSjeremylt } 360885ac19cSjeremylt 36142ecf959Sjeremylt // Zero lvecs 362d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 363d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 364d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 365d1bcdac9Sjeremylt vec = outvec; 366d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 36742ecf959Sjeremylt } 36842ecf959Sjeremylt 369885ac19cSjeremylt // Output restriction 3701a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 371a2b73c81Sjeremylt // Restore evec 372a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 373d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 374d1bcdac9Sjeremylt CeedChk(ierr); 375d1bcdac9Sjeremylt // Get output vector 376d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 377668048e2SJed Brown // Active 378d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 379d1bcdac9Sjeremylt vec = outvec; 3807ca8db16Sjeremylt // Restrict 381d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 382d1bcdac9Sjeremylt CeedChk(ierr); 3834dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 384d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 385d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 386668048e2SJed Brown request); CeedChk(ierr); 387885ac19cSjeremylt } 388885ac19cSjeremylt 3897ca8db16Sjeremylt // Restore input arrays 3901a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 391d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 392d1bcdac9Sjeremylt CeedChk(ierr); 393135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 3947ca8db16Sjeremylt } else { 395a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 396d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 397d1bcdac9Sjeremylt CeedChk(ierr); 3987ca8db16Sjeremylt } 3997ca8db16Sjeremylt } 4007ca8db16Sjeremylt 40121617c04Sjeremylt return 0; 40221617c04Sjeremylt } 40321617c04Sjeremylt 40421617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 40521617c04Sjeremylt int ierr; 406*fe2413ffSjeremylt Ceed ceed; 407*fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 4084ce2993fSjeremylt CeedOperator_Ref *impl; 40921617c04Sjeremylt 41021617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 411*fe2413ffSjeremylt ierr = CeedOperatorSetData(op, (void*)&impl); 412*fe2413ffSjeremylt 413*fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 414*fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 415*fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 416*fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 41721617c04Sjeremylt return 0; 41821617c04Sjeremylt } 419