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 4021617c04Sjeremylt ierr = CeedFree(&op->data); CeedChk(ierr); 4121617c04Sjeremylt return 0; 4221617c04Sjeremylt } 4321617c04Sjeremylt 44885ac19cSjeremylt /* 45885ac19cSjeremylt Setup infields or outfields 46885ac19cSjeremylt */ 47*d1bcdac9Sjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunctionField qfields[16], 48*d1bcdac9Sjeremylt CeedOperatorField ofields[16], 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; 54*d1bcdac9Sjeremylt CeedBasis basis; 55*d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 5621617c04Sjeremylt 57885ac19cSjeremylt // Loop over fields 58885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 59*d1bcdac9Sjeremylt CeedEvalMode emode; 60*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfields[i], &emode); CeedChk(ierr); 61135a076eSjeremylt 62135a076eSjeremylt if (emode != CEED_EVAL_WEIGHT) { 63*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(ofields[i], &Erestrict); 64*d1bcdac9Sjeremylt CeedChk(ierr); 65*d1bcdac9Sjeremylt ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 664b8bea3bSJed Brown &evecs[i+starti]); 67135a076eSjeremylt CeedChk(ierr); 68135a076eSjeremylt } 69135a076eSjeremylt 70885ac19cSjeremylt switch(emode) { 71885ac19cSjeremylt case CEED_EVAL_NONE: 72885ac19cSjeremylt break; // No action 73885ac19cSjeremylt case CEED_EVAL_INTERP: 74*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfields[i], &ncomp); 75*d1bcdac9Sjeremylt CeedChk(ierr); 76885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp, &qdata_alloc[iq]); CeedChk(ierr); 77885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 78885ac19cSjeremylt iq++; 79885ac19cSjeremylt break; 80885ac19cSjeremylt case CEED_EVAL_GRAD: 81*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(ofields[i], &basis); CeedChk(ierr); 82*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfields[i], &ncomp); 83*d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 84885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp*dim, &qdata_alloc[iq]); CeedChk(ierr); 85885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 86885ac19cSjeremylt iq++; 87885ac19cSjeremylt break; 88885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 89*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(ofields[i], &basis); CeedChk(ierr); 90885ac19cSjeremylt ierr = CeedMalloc(Q, &qdata_alloc[iq]); CeedChk(ierr); 91*d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 92885ac19cSjeremylt NULL, qdata_alloc[iq]); CeedChk(ierr); 93885ac19cSjeremylt qdata[i] = qdata_alloc[iq]; 94885ac19cSjeremylt indata[i] = qdata[i]; 95885ac19cSjeremylt iq++; 96885ac19cSjeremylt break; 97885ac19cSjeremylt case CEED_EVAL_DIV: 98885ac19cSjeremylt break; // Not implimented 99885ac19cSjeremylt case CEED_EVAL_CURL: 100885ac19cSjeremylt break; // Not implimented 10121617c04Sjeremylt } 102885ac19cSjeremylt } 10321617c04Sjeremylt return 0; 10421617c04Sjeremylt } 10521617c04Sjeremylt 106885ac19cSjeremylt /* 107885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 108885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 109885ac19cSjeremylt */ 110885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 11121617c04Sjeremylt int ierr; 1124ce2993fSjeremylt bool setupdone; 1134ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1144ce2993fSjeremylt if (setupdone) return 0; 1154ce2993fSjeremylt CeedOperator_Ref *impl; 1164ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1174ce2993fSjeremylt CeedQFunction qf; 1184ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1194ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1204ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 121a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 122a8de75f0Sjeremylt CeedChk(ierr); 123*d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 124*d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 125*d1bcdac9Sjeremylt CeedChk(ierr); 126*d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 127*d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 128*d1bcdac9Sjeremylt CeedChk(ierr); 129*d1bcdac9Sjeremylt CeedEvalMode emode; 1304ce2993fSjeremylt 1314ce2993fSjeremylt // Count infield and outfield array sizes and evectors 1321a4ead9bSjeremylt impl->numein = numinputfields; 1331a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 134*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 135*d1bcdac9Sjeremylt CeedChk(ierr); 1368d94b059Sjeremylt impl->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + 1378d94b059Sjeremylt !!(emode & CEED_EVAL_WEIGHT); 13821617c04Sjeremylt } 1391a4ead9bSjeremylt impl->numeout = numoutputfields; 1401a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 141*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 142*d1bcdac9Sjeremylt CeedChk(ierr); 143a2b73c81Sjeremylt impl->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 144885ac19cSjeremylt } 145885ac19cSjeremylt 146885ac19cSjeremylt // Allocate 147a2b73c81Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->evecs); CeedChk(ierr); 148a2b73c81Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->edata); 149885ac19cSjeremylt CeedChk(ierr); 150885ac19cSjeremylt 151a2b73c81Sjeremylt ierr = CeedCalloc(impl->numqin + impl->numqout, &impl->qdata_alloc); 152885ac19cSjeremylt CeedChk(ierr); 1531a4ead9bSjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->qdata); 154885ac19cSjeremylt CeedChk(ierr); 155885ac19cSjeremylt 156a2b73c81Sjeremylt ierr = CeedCalloc(16, &impl->indata); CeedChk(ierr); 157a2b73c81Sjeremylt ierr = CeedCalloc(16, &impl->outdata); CeedChk(ierr); 158885ac19cSjeremylt 159885ac19cSjeremylt // Set up infield and outfield pointer arrays 160885ac19cSjeremylt // Infields 161*d1bcdac9Sjeremylt ierr = CeedOperatorSetupFields_Ref(qfinputfields, opinputfields, 162a2b73c81Sjeremylt impl->evecs, impl->qdata, impl->qdata_alloc, 163a2b73c81Sjeremylt impl->indata, 0, 0, 1641a4ead9bSjeremylt numinputfields, Q); CeedChk(ierr); 165885ac19cSjeremylt 166885ac19cSjeremylt // Outfields 167*d1bcdac9Sjeremylt ierr = CeedOperatorSetupFields_Ref(qfoutputfields, opoutputfields, 168a2b73c81Sjeremylt impl->evecs, impl->qdata, impl->qdata_alloc, 1691a4ead9bSjeremylt impl->indata, numinputfields, 170*d1bcdac9Sjeremylt impl->numqin, numoutputfields, Q); 171*d1bcdac9Sjeremylt CeedChk(ierr); 172885ac19cSjeremylt 1738d94b059Sjeremylt // Input Qvecs 1741a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 175*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 176*d1bcdac9Sjeremylt CeedChk(ierr); 1778d94b059Sjeremylt if ((emode != CEED_EVAL_NONE) && (emode != CEED_EVAL_WEIGHT)) 1788d94b059Sjeremylt impl->indata[i] = impl->qdata[i]; 1798d94b059Sjeremylt } 1807ca8db16Sjeremylt // Output Qvecs 1811a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 182*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 183*d1bcdac9Sjeremylt CeedChk(ierr); 1848d94b059Sjeremylt if (emode != CEED_EVAL_NONE) 1851a4ead9bSjeremylt impl->outdata[i] = impl->qdata[i + numinputfields]; 1867ca8db16Sjeremylt } 1877ca8db16Sjeremylt 1884ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 189885ac19cSjeremylt 190885ac19cSjeremylt return 0; 191885ac19cSjeremylt } 192885ac19cSjeremylt 193885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 194885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 195885ac19cSjeremylt int ierr; 1964ce2993fSjeremylt CeedOperator_Ref *impl; 1974ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1984ce2993fSjeremylt CeedQFunction qf; 1994ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 200*d1bcdac9Sjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 2014ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 2024ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 2034ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 2044ce2993fSjeremylt CeedChk(ierr); 205885ac19cSjeremylt CeedTransposeMode lmode = CEED_NOTRANSPOSE; 206*d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 207*d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 208*d1bcdac9Sjeremylt CeedChk(ierr); 209*d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 210*d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 211*d1bcdac9Sjeremylt CeedChk(ierr); 212*d1bcdac9Sjeremylt CeedEvalMode emode; 213*d1bcdac9Sjeremylt CeedVector vec; 214*d1bcdac9Sjeremylt CeedBasis basis; 215*d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 216885ac19cSjeremylt 217885ac19cSjeremylt // Setup 218885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 219885ac19cSjeremylt 220885ac19cSjeremylt // Input Evecs and Restriction 2211a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 222*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 223*d1bcdac9Sjeremylt CeedChk(ierr); 224135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 225668048e2SJed Brown } else { 226*d1bcdac9Sjeremylt // Get input vector 227*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 228*d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 229*d1bcdac9Sjeremylt vec = invec; 230668048e2SJed Brown // Restrict 231*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 232*d1bcdac9Sjeremylt CeedChk(ierr); 233*d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 234*d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 235668048e2SJed Brown request); CeedChk(ierr); 236668048e2SJed Brown // Get evec 237a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 238*d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 239*d1bcdac9Sjeremylt CeedChk(ierr); 240885ac19cSjeremylt } 241885ac19cSjeremylt } 242885ac19cSjeremylt 243885ac19cSjeremylt // Output Evecs 2441a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 245a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2461a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 247885ac19cSjeremylt } 248885ac19cSjeremylt 249885ac19cSjeremylt // Loop through elements 2504ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 251885ac19cSjeremylt // Input basis apply if needed 2521a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 253135a076eSjeremylt // Get elemsize, emode, ncomp 254*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 255*d1bcdac9Sjeremylt CeedChk(ierr); 256*d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 257*d1bcdac9Sjeremylt CeedChk(ierr); 258*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 259*d1bcdac9Sjeremylt CeedChk(ierr); 260*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 261*d1bcdac9Sjeremylt CeedChk(ierr); 262885ac19cSjeremylt // Basis action 263885ac19cSjeremylt switch(emode) { 264885ac19cSjeremylt case CEED_EVAL_NONE: 265a2b73c81Sjeremylt impl->indata[i] = &impl->edata[i][e*Q*ncomp]; 266885ac19cSjeremylt break; 267885ac19cSjeremylt case CEED_EVAL_INTERP: 268*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 269*d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 270*d1bcdac9Sjeremylt CEED_EVAL_INTERP, &impl->edata[i][e*elemsize*ncomp], 271*d1bcdac9Sjeremylt impl->qdata[i]); CeedChk(ierr); 272885ac19cSjeremylt break; 273885ac19cSjeremylt case CEED_EVAL_GRAD: 274*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 275*d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 276*d1bcdac9Sjeremylt CEED_EVAL_GRAD, &impl->edata[i][e*elemsize*ncomp], 277*d1bcdac9Sjeremylt impl->qdata[i]); CeedChk(ierr); 278885ac19cSjeremylt break; 279885ac19cSjeremylt case CEED_EVAL_WEIGHT: 280885ac19cSjeremylt break; // No action 281885ac19cSjeremylt case CEED_EVAL_DIV: 282885ac19cSjeremylt break; // Not implimented 283885ac19cSjeremylt case CEED_EVAL_CURL: 284885ac19cSjeremylt break; // Not implimented 285885ac19cSjeremylt } 286885ac19cSjeremylt } 287885ac19cSjeremylt // Output pointers 2881a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 289*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 290*d1bcdac9Sjeremylt CeedChk(ierr); 291885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 292*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 293*d1bcdac9Sjeremylt CeedChk(ierr); 2941a4ead9bSjeremylt impl->outdata[i] = &impl->edata[i + numinputfields][e*Q*ncomp]; 295885ac19cSjeremylt } 296885ac19cSjeremylt } 297885ac19cSjeremylt // Q function 2984ce2993fSjeremylt ierr = CeedQFunctionApply(qf, Q, (const CeedScalar * const*) impl->indata, 299a2b73c81Sjeremylt impl->outdata); CeedChk(ierr); 300885ac19cSjeremylt 301885ac19cSjeremylt // Output basis apply if needed 3021a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 303135a076eSjeremylt // Get elemsize, emode, ncomp 304*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 305*d1bcdac9Sjeremylt CeedChk(ierr); 306*d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 307*d1bcdac9Sjeremylt CeedChk(ierr); 308*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 309*d1bcdac9Sjeremylt CeedChk(ierr); 310*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 311*d1bcdac9Sjeremylt CeedChk(ierr); 312885ac19cSjeremylt // Basis action 313885ac19cSjeremylt switch(emode) { 314885ac19cSjeremylt case CEED_EVAL_NONE: 315885ac19cSjeremylt break; // No action 316885ac19cSjeremylt case CEED_EVAL_INTERP: 317*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 318*d1bcdac9Sjeremylt CeedChk(ierr); 319*d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 320a2b73c81Sjeremylt CEED_EVAL_INTERP, impl->outdata[i], 3211a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 3228d94b059Sjeremylt CeedChk(ierr); 323885ac19cSjeremylt break; 324885ac19cSjeremylt case CEED_EVAL_GRAD: 325*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 326*d1bcdac9Sjeremylt CeedChk(ierr); 327*d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 328*d1bcdac9Sjeremylt CEED_EVAL_GRAD, impl->outdata[i], 329*d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 330885ac19cSjeremylt CeedChk(ierr); 331885ac19cSjeremylt break; 3324ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 3334ce2993fSjeremylt Ceed ceed; 3344ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3354ce2993fSjeremylt return CeedError(ceed, 1, 3368d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 337885ac19cSjeremylt break; // Should not occur 3384ce2993fSjeremylt } 339885ac19cSjeremylt case CEED_EVAL_DIV: 340885ac19cSjeremylt break; // Not implimented 341885ac19cSjeremylt case CEED_EVAL_CURL: 342885ac19cSjeremylt break; // Not implimented 343885ac19cSjeremylt } 344885ac19cSjeremylt } 345885ac19cSjeremylt } 346885ac19cSjeremylt 34742ecf959Sjeremylt // Zero lvecs 348*d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 349*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 350*d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 351*d1bcdac9Sjeremylt vec = outvec; 352*d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 35342ecf959Sjeremylt } 35442ecf959Sjeremylt 355885ac19cSjeremylt // Output restriction 3561a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 357a2b73c81Sjeremylt // Restore evec 358a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 359*d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 360*d1bcdac9Sjeremylt CeedChk(ierr); 361*d1bcdac9Sjeremylt // Get output vector 362*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 363668048e2SJed Brown // Active 364*d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 365*d1bcdac9Sjeremylt vec = outvec; 3667ca8db16Sjeremylt // Restrict 367*d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 368*d1bcdac9Sjeremylt CeedChk(ierr); 369*d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 370*d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 371668048e2SJed Brown request); CeedChk(ierr); 372885ac19cSjeremylt } 373885ac19cSjeremylt 3747ca8db16Sjeremylt // Restore input arrays 3751a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 376*d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 377*d1bcdac9Sjeremylt CeedChk(ierr); 378135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 3797ca8db16Sjeremylt } else { 380a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 381*d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 382*d1bcdac9Sjeremylt CeedChk(ierr); 3837ca8db16Sjeremylt } 3847ca8db16Sjeremylt } 3857ca8db16Sjeremylt 38621617c04Sjeremylt return 0; 38721617c04Sjeremylt } 38821617c04Sjeremylt 38921617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 39021617c04Sjeremylt int ierr; 3914ce2993fSjeremylt CeedOperator_Ref *impl; 39221617c04Sjeremylt 39321617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 39421617c04Sjeremylt op->data = impl; 39521617c04Sjeremylt op->Destroy = CeedOperatorDestroy_Ref; 39621617c04Sjeremylt op->Apply = CeedOperatorApply_Ref; 39721617c04Sjeremylt return 0; 39821617c04Sjeremylt } 399